feat(bidding): 6张CRUD表当前项目强制过滤——get_*.dspy注入会话级解析(get_session_project_id含产线隔离),强制覆盖project_id传值,无项目报错提示选择或新建;bid_task_tree删「最近进行中项目」第三级兜底(会把别人项目当当前项目),统一走会话级解析;知识库入口加require_project门禁
This commit is contained in:
parent
e5516bedf3
commit
d0e2ab89a8
@ -517,7 +517,7 @@ def register_bid_ability():
|
||||
{"label": "🎯 资质", "icon": "", "url": "/pipeline-bidding/bid_qualifications/index.ui",
|
||||
"type": "popup", "width": "88%", "height": "82%", "require_project": True},
|
||||
{"label": "📚 投标知识库", "icon": "", "url": "/pipeline-bidding/bid_kb_docs/index.ui",
|
||||
"type": "popup", "width": "88%", "height": "82%"},
|
||||
"type": "popup", "width": "88%", "height": "82%", "require_project": True},
|
||||
{"label": "📦 标书", "icon": "", "url": "/pipeline-bidding/bid_documents/index.ui",
|
||||
"type": "popup", "width": "88%", "height": "82%", "require_project": True},
|
||||
{"label": "📋 任务树", "icon": "", "url": "/pipeline-bidding/bid_task_tree_popup.ui",
|
||||
|
||||
@ -42,31 +42,20 @@ _ROLE_GROUPS = [
|
||||
_ROLE_SET = set(r for r, _ in _ROLE_GROUPS)
|
||||
|
||||
async with DBPools().sqlorContext(dbname) as sor:
|
||||
# ── 解析当前投标项目(三级兜底) ──
|
||||
# ── 解析当前投标项目(2026-09-11 收敛:统一走 get_session_project_id,
|
||||
# 含悬空自愈+产线隔离;删掉「最近一个进行中的投标项目」第三级兜底——
|
||||
# 把别人的项目当当前项目违反「没项目要提示选择或新建」)──
|
||||
_sid = (params_kw or {}).get('session_id', '') or ''
|
||||
pid = ''
|
||||
# 1) 投标产线默认会话的项目绑定
|
||||
recs = await sor.sqlExe(
|
||||
"SELECT current_project_id FROM pipeline_session_settings "
|
||||
"WHERE user_id=${u}$ AND session_id='default_bidding_general' LIMIT 1", {"u": uid})
|
||||
if recs:
|
||||
pid = getattr(recs[0], 'current_project_id', '') or ''
|
||||
# 2) agent 全局设置
|
||||
if not pid:
|
||||
recs = await sor.sqlExe(
|
||||
"SELECT current_project_id FROM pipeline_agent_settings WHERE user_id=${u}$", {"u": uid})
|
||||
if recs:
|
||||
pid = getattr(recs[0], 'current_project_id', '') or ''
|
||||
# 3) 最近一个进行中的投标项目
|
||||
if not pid:
|
||||
recs = await sor.sqlExe(
|
||||
"SELECT id FROM sd_projects WHERE pipeline_id='bidding_general' "
|
||||
"AND status='in_progress' ORDER BY updated_at DESC LIMIT 1")
|
||||
if recs:
|
||||
pid = getattr(recs[0], 'id', '') or ''
|
||||
try:
|
||||
from pipeline_service.workspace import get_session_project_id
|
||||
pid = await get_session_project_id(sor, uid, _sid, 'bidding_general') or ''
|
||||
except Exception:
|
||||
pid = ''
|
||||
|
||||
if not pid:
|
||||
if not node_id:
|
||||
return json.dumps([{"id": "__root__", "label": "请先在会话中切换/创建投标项目", "is_leaf": True}], ensure_ascii=False)
|
||||
return json.dumps([{"id": "__root__", "label": "请先选择或新建投标项目", "is_leaf": True}], ensure_ascii=False)
|
||||
return json.dumps([], ensure_ascii=False)
|
||||
|
||||
pname = ''
|
||||
|
||||
@ -1,6 +1,26 @@
|
||||
|
||||
ns = params_kw.copy()
|
||||
|
||||
# 会话当前项目强制过滤(2026-09-11 用户要求):会话级解析(session→全局兜底+产线隔离+悬空自愈),
|
||||
# 无项目报错提示;强制覆盖前端 project_id 传值(含搜索框),列表只显示当前项目数据。
|
||||
_uid = await get_user()
|
||||
if not _uid:
|
||||
_uid = 'user-01'
|
||||
_sid = (params_kw or {}).get('session_id', '') or ''
|
||||
_pl = (params_kw or {}).get('pipeline_id', '') or 'bidding_general'
|
||||
_cur_pid = ''
|
||||
try:
|
||||
from pipeline_service.workspace import get_session_project_id
|
||||
async with DBPools().sqlorContext(get_module_dbname('pipeline_bidding')) as _sor:
|
||||
_cur_pid = await get_session_project_id(_sor, _uid, _sid, _pl) or ''
|
||||
except Exception:
|
||||
_cur_pid = ''
|
||||
if not _cur_pid:
|
||||
return {"widgettype":"Error","options":{"title":"错误","timeout":3,"cwidth":22,"cheight":9,"message":"当前会话没有项目,请先选择或新建项目"}}
|
||||
ns['_cur_pid'] = _cur_pid
|
||||
ns['project_id'] = _cur_pid
|
||||
|
||||
|
||||
|
||||
debug(f'get_bid_chapters.dspy:{ns=}')
|
||||
if not ns.get('page'):
|
||||
@ -13,7 +33,7 @@ if not ns.get('sort'):
|
||||
|
||||
|
||||
sql = '''select a.*, b.status_text, c.section_text
|
||||
from (select * from bid_chapters where 1=1 [[filterstr]]) a left join (select k as status,
|
||||
from (select * from bid_chapters where project_id = ${_cur_pid}$ [[filterstr]]) a left join (select k as status,
|
||||
v as status_text from appcodes_kv where parentid='bid_chapter_status') b on a.status = b.status left join (select k as section,
|
||||
v as section_text from appcodes_kv where parentid='bid_scoring_section') c on a.section = c.section'''
|
||||
|
||||
|
||||
@ -1,6 +1,26 @@
|
||||
|
||||
ns = params_kw.copy()
|
||||
|
||||
# 会话当前项目强制过滤(2026-09-11 用户要求):会话级解析(session→全局兜底+产线隔离+悬空自愈),
|
||||
# 无项目报错提示;强制覆盖前端 project_id 传值(含搜索框),列表只显示当前项目数据。
|
||||
_uid = await get_user()
|
||||
if not _uid:
|
||||
_uid = 'user-01'
|
||||
_sid = (params_kw or {}).get('session_id', '') or ''
|
||||
_pl = (params_kw or {}).get('pipeline_id', '') or 'bidding_general'
|
||||
_cur_pid = ''
|
||||
try:
|
||||
from pipeline_service.workspace import get_session_project_id
|
||||
async with DBPools().sqlorContext(get_module_dbname('pipeline_bidding')) as _sor:
|
||||
_cur_pid = await get_session_project_id(_sor, _uid, _sid, _pl) or ''
|
||||
except Exception:
|
||||
_cur_pid = ''
|
||||
if not _cur_pid:
|
||||
return {"widgettype":"Error","options":{"title":"错误","timeout":3,"cwidth":22,"cheight":9,"message":"当前会话没有项目,请先选择或新建项目"}}
|
||||
ns['_cur_pid'] = _cur_pid
|
||||
ns['project_id'] = _cur_pid
|
||||
|
||||
|
||||
|
||||
debug(f'get_bid_documents.dspy:{ns=}')
|
||||
if not ns.get('page'):
|
||||
@ -13,7 +33,7 @@ if not ns.get('sort'):
|
||||
|
||||
|
||||
sql = '''select a.*, b.status_text
|
||||
from (select * from bid_documents where 1=1 [[filterstr]]) a left join (select k as status,
|
||||
from (select * from bid_documents where project_id = ${_cur_pid}$ [[filterstr]]) a left join (select k as status,
|
||||
v as status_text from appcodes_kv where parentid='bid_doc_status') b on a.status = b.status'''
|
||||
|
||||
|
||||
|
||||
@ -1,6 +1,26 @@
|
||||
|
||||
ns = params_kw.copy()
|
||||
|
||||
# 会话当前项目强制过滤(2026-09-11 用户要求):会话级解析(session→全局兜底+产线隔离+悬空自愈),
|
||||
# 无项目报错提示;强制覆盖前端 project_id 传值(含搜索框),列表只显示当前项目数据。
|
||||
_uid = await get_user()
|
||||
if not _uid:
|
||||
_uid = 'user-01'
|
||||
_sid = (params_kw or {}).get('session_id', '') or ''
|
||||
_pl = (params_kw or {}).get('pipeline_id', '') or 'bidding_general'
|
||||
_cur_pid = ''
|
||||
try:
|
||||
from pipeline_service.workspace import get_session_project_id
|
||||
async with DBPools().sqlorContext(get_module_dbname('pipeline_bidding')) as _sor:
|
||||
_cur_pid = await get_session_project_id(_sor, _uid, _sid, _pl) or ''
|
||||
except Exception:
|
||||
_cur_pid = ''
|
||||
if not _cur_pid:
|
||||
return {"widgettype":"Error","options":{"title":"错误","timeout":3,"cwidth":22,"cheight":9,"message":"当前会话没有项目,请先选择或新建项目"}}
|
||||
ns['_cur_pid'] = _cur_pid
|
||||
ns['project_id'] = _cur_pid
|
||||
|
||||
|
||||
|
||||
debug(f'get_bid_qc_reviews.dspy:{ns=}')
|
||||
if not ns.get('page'):
|
||||
@ -13,7 +33,7 @@ if not ns.get('sort'):
|
||||
|
||||
|
||||
sql = '''select a.*, b.qc_type_text
|
||||
from (select * from bid_qc_reviews where 1=1 [[filterstr]]) a left join (select k as qc_type,
|
||||
from (select * from bid_qc_reviews where project_id = ${_cur_pid}$ [[filterstr]]) a left join (select k as qc_type,
|
||||
v as qc_type_text from appcodes_kv where parentid='bid_qc_type') b on a.qc_type = b.qc_type'''
|
||||
|
||||
filterjson = params_kw.get('data_filter')
|
||||
|
||||
@ -1,6 +1,26 @@
|
||||
|
||||
ns = params_kw.copy()
|
||||
|
||||
# 会话当前项目强制过滤(2026-09-11 用户要求):会话级解析(session→全局兜底+产线隔离+悬空自愈),
|
||||
# 无项目报错提示;强制覆盖前端 project_id 传值(含搜索框),列表只显示当前项目数据。
|
||||
_uid = await get_user()
|
||||
if not _uid:
|
||||
_uid = 'user-01'
|
||||
_sid = (params_kw or {}).get('session_id', '') or ''
|
||||
_pl = (params_kw or {}).get('pipeline_id', '') or 'bidding_general'
|
||||
_cur_pid = ''
|
||||
try:
|
||||
from pipeline_service.workspace import get_session_project_id
|
||||
async with DBPools().sqlorContext(get_module_dbname('pipeline_bidding')) as _sor:
|
||||
_cur_pid = await get_session_project_id(_sor, _uid, _sid, _pl) or ''
|
||||
except Exception:
|
||||
_cur_pid = ''
|
||||
if not _cur_pid:
|
||||
return {"widgettype":"Error","options":{"title":"错误","timeout":3,"cwidth":22,"cheight":9,"message":"当前会话没有项目,请先选择或新建项目"}}
|
||||
ns['_cur_pid'] = _cur_pid
|
||||
ns['project_id'] = _cur_pid
|
||||
|
||||
|
||||
|
||||
debug(f'get_bid_qualifications.dspy:{ns=}')
|
||||
if not ns.get('page'):
|
||||
@ -13,7 +33,7 @@ if not ns.get('sort'):
|
||||
|
||||
|
||||
sql = '''select a.*, b.match_status_text, c.owner_text
|
||||
from (select * from bid_qualifications where 1=1 [[filterstr]]) a left join (select k as match_status,
|
||||
from (select * from bid_qualifications where project_id = ${_cur_pid}$ [[filterstr]]) a left join (select k as match_status,
|
||||
v as match_status_text from appcodes_kv where parentid='bid_qual_match_status') b on a.match_status = b.match_status left join (select k as owner,
|
||||
v as owner_text from appcodes_kv where parentid='bid_qual_owner') c on a.owner = c.owner'''
|
||||
|
||||
|
||||
@ -1,6 +1,26 @@
|
||||
|
||||
ns = params_kw.copy()
|
||||
|
||||
# 会话当前项目强制过滤(2026-09-11 用户要求):会话级解析(session→全局兜底+产线隔离+悬空自愈),
|
||||
# 无项目报错提示;强制覆盖前端 project_id 传值(含搜索框),列表只显示当前项目数据。
|
||||
_uid = await get_user()
|
||||
if not _uid:
|
||||
_uid = 'user-01'
|
||||
_sid = (params_kw or {}).get('session_id', '') or ''
|
||||
_pl = (params_kw or {}).get('pipeline_id', '') or 'bidding_general'
|
||||
_cur_pid = ''
|
||||
try:
|
||||
from pipeline_service.workspace import get_session_project_id
|
||||
async with DBPools().sqlorContext(get_module_dbname('pipeline_bidding')) as _sor:
|
||||
_cur_pid = await get_session_project_id(_sor, _uid, _sid, _pl) or ''
|
||||
except Exception:
|
||||
_cur_pid = ''
|
||||
if not _cur_pid:
|
||||
return {"widgettype":"Error","options":{"title":"错误","timeout":3,"cwidth":22,"cheight":9,"message":"当前会话没有项目,请先选择或新建项目"}}
|
||||
ns['_cur_pid'] = _cur_pid
|
||||
ns['project_id'] = _cur_pid
|
||||
|
||||
|
||||
|
||||
debug(f'get_bid_scoring_items.dspy:{ns=}')
|
||||
if not ns.get('page'):
|
||||
@ -13,7 +33,7 @@ if not ns.get('sort'):
|
||||
|
||||
|
||||
sql = '''select a.*, b.section_text
|
||||
from (select * from bid_scoring_items where 1=1 [[filterstr]]) a left join (select k as section,
|
||||
from (select * from bid_scoring_items where project_id = ${_cur_pid}$ [[filterstr]]) a left join (select k as section,
|
||||
v as section_text from appcodes_kv where parentid='bid_scoring_section') b on a.section = b.section'''
|
||||
|
||||
|
||||
|
||||
@ -1,6 +1,26 @@
|
||||
|
||||
ns = params_kw.copy()
|
||||
|
||||
# 会话当前项目强制过滤(2026-09-11 用户要求):会话级解析(session→全局兜底+产线隔离+悬空自愈),
|
||||
# 无项目报错提示;强制覆盖前端 project_id 传值(含搜索框),列表只显示当前项目数据。
|
||||
_uid = await get_user()
|
||||
if not _uid:
|
||||
_uid = 'user-01'
|
||||
_sid = (params_kw or {}).get('session_id', '') or ''
|
||||
_pl = (params_kw or {}).get('pipeline_id', '') or 'bidding_general'
|
||||
_cur_pid = ''
|
||||
try:
|
||||
from pipeline_service.workspace import get_session_project_id
|
||||
async with DBPools().sqlorContext(get_module_dbname('pipeline_bidding')) as _sor:
|
||||
_cur_pid = await get_session_project_id(_sor, _uid, _sid, _pl) or ''
|
||||
except Exception:
|
||||
_cur_pid = ''
|
||||
if not _cur_pid:
|
||||
return {"widgettype":"Error","options":{"title":"错误","timeout":3,"cwidth":22,"cheight":9,"message":"当前会话没有项目,请先选择或新建项目"}}
|
||||
ns['_cur_pid'] = _cur_pid
|
||||
ns['project_id'] = _cur_pid
|
||||
|
||||
|
||||
|
||||
debug(f'get_bid_tender_files.dspy:{ns=}')
|
||||
if not ns.get('page'):
|
||||
@ -13,7 +33,7 @@ if not ns.get('sort'):
|
||||
|
||||
|
||||
sql = '''select a.*, b.file_type_text
|
||||
from (select * from bid_tender_files where 1=1 [[filterstr]]) a left join (select k as file_type,
|
||||
from (select * from bid_tender_files where project_id = ${_cur_pid}$ [[filterstr]]) a left join (select k as file_type,
|
||||
v as file_type_text from appcodes_kv where parentid='bid_file_type') b on a.file_type = b.file_type'''
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user