diff --git a/backend/app/services/oa_dept_select.py b/backend/app/services/oa_dept_select.py index da6a57fb..947f9c5e 100644 --- a/backend/app/services/oa_dept_select.py +++ b/backend/app/services/oa_dept_select.py @@ -28,27 +28,45 @@ def _schema_rules(schema: Any) -> List[dict]: return out +def _rule_props(rule: dict) -> dict: + props = rule.get("props") + return props if isinstance(props, dict) else {} + + def _field_label(rule: dict) -> str: return str(rule.get("title") or rule.get("label") or rule.get("field") or "部门") def _is_required(rule: dict) -> bool: - props = rule.get("props") or {} - if rule.get("$required"): + props = _rule_props(rule) + if rule.get("$required") is True: return True - if rule.get("required"): + if rule.get("required") is True: return True - if props.get("required"): + if props.get("required") is True: return True return False def _is_multiple(rule: dict) -> bool: - props = rule.get("props") or {} + props = _rule_props(rule) multiple = props.get("multiple") if multiple is None: return True - return bool(multiple) + return multiple is True + + +def _max_count(rule: dict) -> Optional[int]: + raw = _rule_props(rule).get("max") + if raw is None or raw == "": + return None + try: + value = int(raw) + except (TypeError, ValueError): + return None + if value <= 0: + return None + return value def _is_valid_dept_item(item: Any) -> bool: @@ -71,8 +89,7 @@ def _validate_dept_rule(rule: dict, data: Dict[str, Any]) -> List[str]: label = _field_label(rule) required = _is_required(rule) multiple = _is_multiple(rule) - props = rule.get("props") or {} - max_count = props.get("max") + max_count = _max_count(rule) value = data.get(field) errors: List[str] = [] @@ -91,7 +108,7 @@ def _validate_dept_rule(rule: dict, data: Dict[str, Any]) -> List[str]: if not _is_valid_dept_item(item): errors.append(f"「{label}」部门项格式不正确,需包含有效的 id 与 name") break - if max_count is not None and isinstance(max_count, int) and len(value) > max_count: + if max_count is not None and len(value) > max_count: errors.append(f"「{label}」选择部门数量超过最大上限 {max_count} 个") return errors diff --git a/backend/tests/test_oa_dept_select.py b/backend/tests/test_oa_dept_select.py index 7958028e..fa16c50c 100644 --- a/backend/tests/test_oa_dept_select.py +++ b/backend/tests/test_oa_dept_select.py @@ -70,6 +70,25 @@ class TestValidateDeptFormValues(unittest.TestCase): errs = validate_dept_form_values(schema, data) self.assertTrue(any("最大" in e or "上限" in e for e in errs)) + def test_max_exceeded_string_max(self): + schema = { + "rule": [ + { + "type": "dept", + "field": "depts", + "props": {"multiple": True, "max": "1"}, + } + ] + } + data = { + "depts": [ + {"id": "d1", "name": "A"}, + {"id": "d2", "name": "B"}, + ] + } + errs = validate_dept_form_values(schema, data) + self.assertTrue(any("最大" in e or "上限" in e for e in errs)) + def test_nested_fc_row(self): schema = { "rule": [