feat: ship OA drafts/badges, role dual-track, and test-env deploy tooling.

Add approval instance drafts with menu badges, dual-track user/role read model and role bound names, form-designer outline docs, and bare-metal test deploy scripts. Ignore local test-server credential file.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-08-06 13:58:47 +08:00
1 parent 7af53fc344
commit de22678c87
56 files changed
+11861 -6082

No files matched your search

+18 -24
View File
@@ -26,8 +26,11 @@ from app.crud import menu as menu_svc
from app.crud import role as role_svc
from app.crud import user as user_svc
from app.crud.collection_protocol import _lookup_attachment_by_url
from app.models.models import BizAttachment, SysDept, SysRole, SysUser, SysUserRole
from app.services.web_auth_roles import _map_role_name_to_web
from app.models.models import BizAttachment, SysDept, SysRole, SysUser
from app.services.web_auth_roles import (
_map_role_name_to_web,
list_user_ids_with_effective_role_name,
)
router = APIRouter(prefix="/web/admin", tags=["运营端管理"])
@@ -77,7 +80,7 @@ async def list_users_for_select(
):
"""返回用户下拉选项(label=昵称,value=用户ID),供流程设计器审批人选择使用。
可选 roleName:按 sys_role.role_name 精确过滤拥有该角色的用户。
可选 roleName:按有效角色(直接绑定 ∪ 职位继承)精确过滤。
"""
tenant_no = _user.get("tenant_no", "")
q = db.query(SysUser).filter(SysUser.del_flag == 0, SysUser.status == "1")
@@ -85,18 +88,12 @@ async def list_users_for_select(
q = q.filter(SysUser.tenant_no == tenant_no)
rn = (roleName or "").strip()
if rn:
q = (
q.join(SysUserRole, SysUserRole.user_id == SysUser.id)
.join(SysRole, SysRole.id == SysUserRole.role_id)
.filter(
SysUserRole.del_flag == 0,
SysRole.del_flag == 0,
SysRole.status == "1",
SysRole.role_name == rn,
)
matched_ids = list_user_ids_with_effective_role_name(
db, tenant_no=tenant_no or settings.DEFAULT_TENANT_NO, role_name=rn
)
if tenant_no:
q = q.filter(SysUserRole.tenant_no == tenant_no, SysRole.tenant_no == tenant_no)
if not matched_ids:
return success_response([])
q = q.filter(SysUser.id.in_(matched_ids))
rows = q.order_by(SysUser.create_time.desc()).distinct().all()
out = [{"label": (r.nick_name or r.user_no or ""), "value": r.id} for r in rows]
return success_response(out)
@@ -317,17 +314,14 @@ async def list_users(
query = query.filter(SysUser.status == status)
rn = (roleName or "").strip()
if rn:
query = (
query.join(SysUserRole, SysUserRole.user_id == SysUser.id)
.join(SysRole, SysRole.id == SysUserRole.role_id)
.filter(
SysUserRole.del_flag == 0,
SysRole.del_flag == 0,
SysRole.status == "1",
SysRole.role_name == rn,
)
matched_ids = list_user_ids_with_effective_role_name(
db, tenant_no=tenant_no, role_name=rn
)
query = query.filter(SysUserRole.tenant_no == tenant_no, SysRole.tenant_no == tenant_no)
if not matched_ids:
return success_response(
{"list": [], "total": 0, "page": page, "pageSize": pageSize, "totalPages": 0}
)
query = query.filter(SysUser.id.in_(matched_ids))
query = apply_data_scope(query, SysUser, user, db, tenant_no)
total = query.distinct().count()
items = (