pipeline_core/wwwroot/api/my_pipelines.dspy

91 lines
4.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# my_pipelines.dspy - 当前用户可用产线列表 → ChipBar 数据手机端「产线」Tab 胶囊条)
# 口径2026-09-07 用户定夺):客户只显示购买过且未到期的产线;
# 平台侧owner./reseller. 角色)显示全部 published 产线。
# 数据链product_subscription(status='1', end_date>=今天) × product(product_type='pipeline',
# resource_ref_id=pipelines.id) × pipelines(status='published')。
import json as _json
uid = await get_user()
if not uid:
return _json.dumps({"items": [], "error": "未登录"}, ensure_ascii=False)
orgid = await get_userorgid()
dbname = get_module_dbname('pipeline_core')
# mode=full桌面侧边栏/管理场景):不过滤订阅,返回全部 published 产线;
# 默认(手机端 ChipBar客户只见已购未到期产线2026-09-07 用户定夺)
_mode = ((params_kw or {}).get('mode') or '').strip()
# fmt=more底部 TabBar「更多」菜单返回 MobileSheet 项格式
# [{name,label,icon,desc,url}]url 直达该产线会话页2026-09-08
_fmt = ((params_kw or {}).get('fmt') or '').strip()
items = []
try:
# 平台侧角色owner./reseller.)看全部 published 产线;客户只看已购未到期。
# get_user_roles 由 rbac.init 注册到 ServerEnvdspy run_ns 会带入;
# 探测失败/不可用时默认按客户处理(只显示已购,安全侧,不放大可见面)。
is_ops = _mode == 'full'
if not is_ops:
try:
roles = await get_user_roles(uid)
for r in (roles or []):
rs = str(r)
if rs.startswith('owner.') or rs.startswith('reseller.'):
is_ops = True
break
except Exception:
is_ops = False
async with DBPools().sqlorContext(dbname) as sor:
if is_ops:
recs = await sor.sqlExe(
"SELECT id, name FROM pipelines WHERE status='published' ORDER BY id", {})
await sor.sqlExe("COMMIT", {})
ids = [(getattr(r, 'id', ''), getattr(r, 'name', '')) for r in (recs or [])]
else:
srecs = await sor.sqlExe(
"SELECT DISTINCT pr.resource_ref_id AS rid FROM product_subscription ps"
" JOIN product pr ON ps.product_id = pr.id"
" WHERE ps.user_org_id=${org}$ AND ps.status='1'"
" AND ps.end_date >= CURDATE()"
" AND pr.product_type='pipeline'", {"org": orgid})
await sor.sqlExe("COMMIT", {})
rids = []
for r in (srecs or []):
v = getattr(r, 'rid', '')
if v and v not in rids:
rids.append(v)
ids = []
if rids:
# sqlor IN 列表必须展开占位符(传 list 会崩)
ph = {}
marks = []
for i, rid in enumerate(rids):
k = 'k%d' % i
ph[k] = rid
marks.append('${%s}$' % k)
prec = await sor.sqlExe(
"SELECT id, name FROM pipelines WHERE status='published'"
" AND id IN (" + ','.join(marks) + ") ORDER BY id", ph)
await sor.sqlExe("COMMIT", {})
ids = [(getattr(r, 'id', ''), getattr(r, 'name', '')) for r in (prec or [])]
for pid, pname in ids:
if _fmt == 'more':
# 底部 TabBar「更多」菜单项2026-09-08点击 → 内容区直达该产线
# 会话页embed=1隐藏胶囊条/门禁,锁定产线,会话区最大化)。
# url 不预 urlencode前端 url_parse 会再编码一次,双重编码坑)
items.append({"name": "m_pl_" + pid, "label": pname or pid,
"icon": "⚡", "desc": "已购产线",
"url": entire_url("/pipeline_core/mobile_agent.ui")
+ "?pipeline_id=" + pid + "&embed=1"})
else:
items.append({"id": pid, "pipeline_id": pid,
"name": pname or pid, "session_id": "m_" + pid})
except Exception:
items = []
return _json.dumps({"items": items}, ensure_ascii=False)