feat(mobile): 手机端产线工作界面——mobile_agent.ui(ChipBar已购产线胶囊+AgentIO全屏,mobile_opts压margin)+my_pipelines.dspy(客户按product_subscription未到期×pipelines published过滤,平台角色看全部,get_user_roles失败降级按客户安全侧)(2026-09-07手机端适配:只有购买过的产线可见)
This commit is contained in:
parent
01bfd01619
commit
c7b766e1c1
72
wwwroot/api/my_pipelines.dspy
Normal file
72
wwwroot/api/my_pipelines.dspy
Normal file
@ -0,0 +1,72 @@
|
||||
# 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')
|
||||
|
||||
items = []
|
||||
try:
|
||||
# 平台侧角色(owner./reseller.)看全部 published 产线;客户只看已购未到期。
|
||||
# get_user_roles 由 rbac.init 注册到 ServerEnv,dspy run_ns 会带入;
|
||||
# 探测失败/不可用时默认按客户处理(只显示已购,安全侧,不放大可见面)。
|
||||
is_ops = False
|
||||
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:
|
||||
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)
|
||||
52
wwwroot/mobile_agent.ui
Normal file
52
wwwroot/mobile_agent.ui
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"widgettype": "VBox",
|
||||
"options": {"width": "100%", "height": "100%", "padding": "0"},
|
||||
"subwidgets": [
|
||||
{
|
||||
"widgettype": "ChipBar",
|
||||
"id": "mobile_pipeline_chips",
|
||||
"options": {
|
||||
"width": "100%",
|
||||
"height": "auto",
|
||||
"dataurl": "/pipeline_core/api/my_pipelines.dspy",
|
||||
"valueField": "id",
|
||||
"textField": "name",
|
||||
"empty_text": "暂无已购产线 · 请到「我的 → 产品商城」购买"
|
||||
},
|
||||
"binds": [
|
||||
{
|
||||
"wid": "self",
|
||||
"event": "select",
|
||||
"actiontype": "method",
|
||||
"target": "app.mobile_agent_io",
|
||||
"method": "set_pipeline"
|
||||
},
|
||||
{
|
||||
"wid": "self",
|
||||
"event": "select",
|
||||
"actiontype": "urlwidget",
|
||||
"target": "app.mobile_menus_wrap",
|
||||
"options": {"url": "/pipeline_core/api/agent_menus.dspy", "method": "GET"}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"widgettype": "VBox",
|
||||
"id": "mobile_menus_wrap",
|
||||
"options": {"width": "100%", "height": "auto"}
|
||||
},
|
||||
{
|
||||
"widgettype": "AgentIO",
|
||||
"id": "mobile_agent_io",
|
||||
"options": {
|
||||
"css": "filler",
|
||||
"margin": "0 24px 24px 24px",
|
||||
"mobile_opts": {"margin": "0 8px 8px 8px"},
|
||||
"url": "/pipeline_core/api/agent_chat.dspy",
|
||||
"model_dataurl": "/pipeline_core/api/agent_model_options.dspy?capabilities=chat",
|
||||
"model_cwidth": 14,
|
||||
"placeholder": "输入你的需求..."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user