新增 club_recharge_page_copy 表与小程序/后台读写接口,kefu 菜单挂「充值页文案」。 Co-authored-by: Cursor <cursoragent@cursor.com>
205 lines
6.3 KiB
Python
205 lines
6.3 KiB
Python
"""会员/履约金充值页文案按俱乐部读写。"""
|
||
import json
|
||
|
||
from jituan.models import ClubRechargePageCopy
|
||
from jituan.services.club_context import resolve_club_id_from_request, resolve_effective_club_id
|
||
|
||
PAGE_HUIYUAN = 'huiyuan'
|
||
PAGE_YAJIN = 'yajin'
|
||
PAGE_KEYS = {PAGE_HUIYUAN, PAGE_YAJIN}
|
||
|
||
REGIONS_BY_PAGE = {
|
||
PAGE_HUIYUAN: ('rules', 'benefits', 'advantages'),
|
||
PAGE_YAJIN: ('rules', 'benefits'),
|
||
}
|
||
|
||
REGION_SORT = {
|
||
'rules': 10,
|
||
'benefits': 20,
|
||
'advantages': 30,
|
||
}
|
||
|
||
|
||
def normalize_page_key(page_key):
|
||
key = (page_key or '').strip().lower()
|
||
return key if key in PAGE_KEYS else ''
|
||
|
||
|
||
def normalize_region_key(page_key, region_key):
|
||
key = (region_key or '').strip().lower()
|
||
allowed = REGIONS_BY_PAGE.get(page_key) or ()
|
||
return key if key in allowed else ''
|
||
|
||
|
||
def _as_items_list(raw):
|
||
if raw is None:
|
||
return []
|
||
if isinstance(raw, str):
|
||
try:
|
||
raw = json.loads(raw)
|
||
except (TypeError, ValueError):
|
||
return []
|
||
if not isinstance(raw, list):
|
||
return []
|
||
out = []
|
||
for item in raw:
|
||
if isinstance(item, dict):
|
||
out.append(item)
|
||
elif isinstance(item, str) and item.strip():
|
||
out.append({'text': item.strip()})
|
||
return out
|
||
|
||
|
||
def _normalize_items_for_region(region_key, items):
|
||
"""按区域清洗条目字段,去掉空条目。"""
|
||
cleaned = []
|
||
for item in _as_items_list(items):
|
||
if region_key == 'rules':
|
||
text = (item.get('text') or '').strip()
|
||
if text:
|
||
cleaned.append({'text': text})
|
||
elif region_key == 'benefits':
|
||
# 会员权益:title/desc;履约金权益:label
|
||
title = (item.get('title') or '').strip()
|
||
label = (item.get('label') or '').strip()
|
||
desc = (item.get('desc') or '').strip()
|
||
icon_url = (item.get('icon_url') or '').strip()
|
||
accent = (item.get('accent_color') or '').strip()
|
||
row = {}
|
||
if title:
|
||
row['title'] = title
|
||
if label:
|
||
row['label'] = label
|
||
if desc:
|
||
row['desc'] = desc
|
||
if icon_url:
|
||
row['icon_url'] = icon_url
|
||
if accent:
|
||
row['accent_color'] = accent
|
||
if row.get('title') or row.get('label') or row.get('desc'):
|
||
cleaned.append(row)
|
||
elif region_key == 'advantages':
|
||
title = (item.get('title') or '').strip()
|
||
desc = (item.get('desc') or '').strip()
|
||
icon_url = (item.get('icon_url') or '').strip()
|
||
if not (title or desc):
|
||
continue
|
||
row = {}
|
||
if title:
|
||
row['title'] = title
|
||
if desc:
|
||
row['desc'] = desc
|
||
if icon_url:
|
||
row['icon_url'] = icon_url
|
||
cleaned.append(row)
|
||
return cleaned
|
||
|
||
|
||
def _row_to_region_payload(row, for_admin=False):
|
||
items = _as_items_list(row.items_json)
|
||
payload = {
|
||
'title': (row.title or '').strip(),
|
||
'items': items,
|
||
'enabled': bool(row.enabled),
|
||
'sort_order': int(row.sort_order or 0),
|
||
}
|
||
if for_admin:
|
||
payload['region_key'] = row.region_key
|
||
payload['page_key'] = row.page_key
|
||
return payload
|
||
|
||
|
||
def get_public_regions(club_id, page_key):
|
||
"""小程序只读:仅返回 enabled 且 items 非空的区域。"""
|
||
page_key = normalize_page_key(page_key)
|
||
if not page_key or not club_id:
|
||
return {}
|
||
rows = (
|
||
ClubRechargePageCopy.query
|
||
.filter(club_id=club_id, page_key=page_key, enabled=True)
|
||
.order_by('sort_order', 'id')
|
||
)
|
||
regions = {}
|
||
for row in rows:
|
||
items = _as_items_list(row.items_json)
|
||
if not items:
|
||
continue
|
||
regions[row.region_key] = {
|
||
'title': (row.title or '').strip(),
|
||
'items': items,
|
||
}
|
||
return regions
|
||
|
||
|
||
def get_admin_regions(club_id, page_key):
|
||
"""后台:返回该页全部区域(含未启用/空),缺省区域补空壳。"""
|
||
page_key = normalize_page_key(page_key)
|
||
if not page_key or not club_id:
|
||
return {}
|
||
allowed = REGIONS_BY_PAGE[page_key]
|
||
existing = {
|
||
row.region_key: row
|
||
for row in ClubRechargePageCopy.query.filter(club_id=club_id, page_key=page_key)
|
||
}
|
||
regions = {}
|
||
for rk in allowed:
|
||
row = existing.get(rk)
|
||
if row:
|
||
regions[rk] = _row_to_region_payload(row, for_admin=True)
|
||
else:
|
||
regions[rk] = {
|
||
'region_key': rk,
|
||
'page_key': page_key,
|
||
'title': '',
|
||
'items': [],
|
||
'enabled': False,
|
||
'sort_order': REGION_SORT.get(rk, 0),
|
||
}
|
||
return regions
|
||
|
||
|
||
def save_region(club_id, page_key, region_key, *, title='', items=None, enabled=True, sort_order=None):
|
||
page_key = normalize_page_key(page_key)
|
||
region_key = normalize_region_key(page_key, region_key)
|
||
if not club_id or not page_key or not region_key:
|
||
return None, 'page_key 或 region_key 无效'
|
||
|
||
items_clean = _normalize_items_for_region(region_key, items)
|
||
title = (title or '').strip()[:64]
|
||
enabled = bool(enabled)
|
||
if sort_order is None:
|
||
sort_order = REGION_SORT.get(region_key, 0)
|
||
try:
|
||
sort_order = int(sort_order)
|
||
except (TypeError, ValueError):
|
||
sort_order = REGION_SORT.get(region_key, 0)
|
||
|
||
row = ClubRechargePageCopy.query.filter(
|
||
club_id=club_id, page_key=page_key, region_key=region_key,
|
||
).first()
|
||
if row:
|
||
row.title = title
|
||
row.items_json = items_clean
|
||
row.enabled = enabled
|
||
row.sort_order = sort_order
|
||
row.save(update_fields=['title', 'items_json', 'enabled', 'sort_order', 'UpdateTime'])
|
||
else:
|
||
row = ClubRechargePageCopy.query.create(
|
||
club_id=club_id,
|
||
page_key=page_key,
|
||
region_key=region_key,
|
||
title=title,
|
||
items_json=items_clean,
|
||
enabled=enabled,
|
||
sort_order=sort_order,
|
||
)
|
||
return _row_to_region_payload(row, for_admin=True), None
|
||
|
||
|
||
def club_id_for_mini(request):
|
||
return resolve_club_id_from_request(request)
|
||
|
||
|
||
def club_id_for_admin(request, user):
|
||
return resolve_effective_club_id(request, user)
|