From f1fad2d27d5d180132c334febcc9c62f460c603b Mon Sep 17 00:00:00 2001 From: zlwu <704541015@qq.com> Date: Thu, 6 Aug 2026 15:19:32 +0800 Subject: [PATCH] feat(oa): add dept_contains_match for condition id intersection Co-authored-by: Cursor --- backend/app/services/oa_dept_select.py | 25 ++++++++++++++++++- backend/tests/test_oa_dept_select.py | 34 +++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/backend/app/services/oa_dept_select.py b/backend/app/services/oa_dept_select.py index ff302c2e..82a69497 100644 --- a/backend/app/services/oa_dept_select.py +++ b/backend/app/services/oa_dept_select.py @@ -1,7 +1,7 @@ """OA 表单设计器:部门选择控件 form_data 校验""" from __future__ import annotations -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Optional, Set def _walk_rules(rules: Any, out: List[dict]) -> None: @@ -139,3 +139,26 @@ def validate_dept_form_values(schema: Any, form_data: Optional[Dict[str, Any]]) forced["props"] = props errors.extend(_validate_dept_rule(forced, data)) return errors + + +def extract_dept_ids(raw: Any) -> Set[str]: + ids: Set[str] = set() + items = raw if isinstance(raw, list) else ([raw] if isinstance(raw, dict) else []) + for item in items: + if not isinstance(item, dict): + continue + did = str(item.get("id") or "").strip() + if did: + ids.add(did) + return ids + + +def dept_contains_match(form_value: Any, cond_ids: Any) -> bool: + form_ids = extract_dept_ids(form_value) + if isinstance(cond_ids, str): + want = {cond_ids.strip()} if cond_ids.strip() else set() + elif isinstance(cond_ids, list): + want = {str(x).strip() for x in cond_ids if str(x).strip()} + else: + want = set() + return bool(form_ids & want) diff --git a/backend/tests/test_oa_dept_select.py b/backend/tests/test_oa_dept_select.py index fa16c50c..346f932f 100644 --- a/backend/tests/test_oa_dept_select.py +++ b/backend/tests/test_oa_dept_select.py @@ -1,6 +1,10 @@ import unittest -from app.services.oa_dept_select import validate_dept_form_values +from app.services.oa_dept_select import ( + dept_contains_match, + extract_dept_ids, + validate_dept_form_values, +) class TestValidateDeptFormValues(unittest.TestCase): @@ -113,5 +117,33 @@ class TestValidateDeptFormValues(unittest.TestCase): self.assertEqual(validate_dept_form_values(schema, {"t": "x"}), []) +class TestOaDeptSelect(unittest.TestCase): + def test_extract_and_contains(self): + self.assertEqual(extract_dept_ids({"id": "d1", "name": "研发"}), {"d1"}) + self.assertEqual( + extract_dept_ids([{"id": "d1", "name": "A"}, {"id": "d2", "name": "B"}]), + {"d1", "d2"}, + ) + self.assertTrue( + dept_contains_match( + [{"id": "d1", "name": "A"}], + ["d1", "d9"], + ) + ) + self.assertFalse( + dept_contains_match( + [{"id": "d3", "name": "C"}], + ["d1", "d2"], + ) + ) + # 精确匹配:下级 id 不等于上级 id + self.assertFalse( + dept_contains_match( + {"id": "d1-child", "name": "前端组"}, + ["d1"], + ) + ) + + if __name__ == "__main__": unittest.main()