87 lines
3.5 KiB
Plaintext
87 lines
3.5 KiB
Plaintext
# opp_references_items.dspy - 某软件主题的分项列表(references 可查证)
|
||
# 入参:category=<主题名>。每条分项:标题+时间+预算+地区 + 「公告原文」「来源页」按钮(新窗口)
|
||
|
||
import json as _json
|
||
|
||
uid = await get_user()
|
||
if not uid:
|
||
return {"widgettype": "Message", "options": {"title": "未登录", "message": "请先登录"}}
|
||
|
||
category = ((params_kw or {}).get("category") or "").strip()
|
||
days = int((params_kw or {}).get("days") or 30)
|
||
if not category:
|
||
return {"widgettype": "Message", "options": {"title": "缺少参数", "message": "缺少 category"}}
|
||
|
||
dbname = get_module_dbname('pipeline-opportunity')
|
||
|
||
async with DBPools().sqlorContext(dbname) as sor:
|
||
from pipeline_opportunity.opp_data_capability import category_references
|
||
from pipeline_opportunity.opp_common import source_button_widget
|
||
ok, res = await category_references(sor, category, days=days, limit=500)
|
||
await sor.sqlExe("COMMIT", {})
|
||
|
||
rows = []
|
||
if not ok:
|
||
rows.append({"widgettype": "Text", "options": {
|
||
"text": "查询失败:" + str(res)[:200],
|
||
"color": "#dc2626", "padding": "12px", "halign": "left"}})
|
||
else:
|
||
items = res.get("items") or []
|
||
if not items:
|
||
rows.append({"widgettype": "Text", "options": {
|
||
"text": "该主题近 %d 天无分项" % days, "color": "#64748b", "padding": "12px", "halign": "left"}})
|
||
for it in items:
|
||
url = str(it.get("url") or "")
|
||
src = str(it.get("source_url") or "")
|
||
sub_btns = []
|
||
if url:
|
||
sub_btns.append({"widgettype": "Button", "options": {"label": "公告原文", "css": "small"},
|
||
"binds": [{"wid": "self", "event": "click", "actiontype": "script",
|
||
"target": "self",
|
||
"script": "window.open(" + _json.dumps(url) + ",'_blank','noopener');"}]})
|
||
# 来源:显示来源名称,点击直跳来源 url(2026-09-08 用户定夺)
|
||
_sb = source_button_widget(str(it.get("source") or ""), src)
|
||
if _sb:
|
||
sub_btns.append(_sb)
|
||
budget = it.get("budget_wan") or 0
|
||
meta = "%s | %s | %s" % (
|
||
str(it.get("publish_time") or "")[:10],
|
||
str(it.get("region") or "—"),
|
||
(("预算 %.0f 万" % budget) if budget else "预算未公开"))
|
||
rows.append({
|
||
"widgettype": "VBox",
|
||
"options": {"width": "100%", "padding": "8px 12px", "gap": "4px",
|
||
"border": "1px solid #e2e8f0", "borderRadius": "8px",
|
||
"margin": "0 0 6px 0", "bgcolor": "#ffffff"},
|
||
"subwidgets": [
|
||
{"widgettype": "Text", "options": {
|
||
"text": str(it.get("title") or ""), "cfontsize": 0.95,
|
||
"color": "#0f172a", "halign": "left", "wrap": True}},
|
||
{"widgettype": "HBox", "options": {"width": "100%", "gap": "10px",
|
||
"alignItems": "center"},
|
||
"subwidgets": [
|
||
{"widgettype": "Text", "options": {"text": meta,
|
||
"cfontsize": 0.75, "color": "#94a3b8", "halign": "left"}},
|
||
{"widgettype": "Filler"}
|
||
] + sub_btns}
|
||
]
|
||
})
|
||
|
||
total = res.get("count", len(rows)) if ok else 0
|
||
return {
|
||
"widgettype": "PopupWindow",
|
||
"id": "opp_refs_items_pw",
|
||
"options": {"title": "分项明细:%s(%d 条)" % (category, total),
|
||
"width": "80%", "height": "82%", "auto_open": True, "resizable": True},
|
||
"subwidgets": [{
|
||
"widgettype": "VBox",
|
||
"options": {"css": "filler", "width": "100%", "height": "100%",
|
||
"padding": "12px 16px", "gap": "0px", "overflow": "auto"},
|
||
"subwidgets": [
|
||
{"widgettype": "Text", "options": {
|
||
"text": "每条「公告原文」为招标公告原链接;来源按钮显示数据来源名称、点击直达该条采集来源页,均在新窗口打开,可逐条查证。",
|
||
"cfontsize": 0.78, "color": "#64748b", "halign": "left", "margin": "0 0 8px 0"}}
|
||
] + rows
|
||
}]
|
||
}
|