diff --git a/backend/apps/material/importers.py b/backend/apps/material/importers.py
index bba15ef..d8fe82a 100644
--- a/backend/apps/material/importers.py
+++ b/backend/apps/material/importers.py
@@ -2,6 +2,7 @@ import re
from typing import Any, Dict, List, Optional, Tuple
import openpyxl
+from django.contrib.auth import get_user_model
from apps.factory.models import Factory
from apps.material.models import Material
@@ -18,6 +19,7 @@ MAJOR_CATEGORY_MAP = {
STAGE_VALUES = {choice[0] for choice in Material.STAGE_CHOICES}
IMPORTANCE_LEVEL_VALUES = {choice[0] for choice in Material.IMPORTANCE_LEVEL_CHOICES}
UNIT_SPLIT_RE = re.compile(r"[\s,,、/;;]+")
+INITIAL_PASSWORD = "abc!0000"
def _cell(value: Any) -> str:
@@ -41,6 +43,33 @@ def _parse_choice(value: Any, allowed_values: set) -> Optional[str]:
return text if text in allowed_values else None
+def _unique_username(user_model, base: str) -> str:
+ if not user_model.objects.filter(username=base).exists():
+ return base
+ for index in range(2, 10000):
+ candidate = f"{base}{index}"
+ if not user_model.objects.filter(username=candidate).exists():
+ return candidate
+ raise RuntimeError(f"无法为账号分配唯一用户名: {base}")
+
+
+def _ensure_factory_user(factory: Factory, unit_name: str) -> bool:
+ user_model = get_user_model()
+ existing_user = user_model.objects.filter(role="user", factory_id=factory.id).order_by("id").first()
+ if existing_user:
+ return False
+
+ username_base = _single_line(unit_name, max_len=150) or f"factory{factory.id}"
+ username = _unique_username(user_model, username_base)
+ user_model.objects.create_user(
+ username=username,
+ password=INITIAL_PASSWORD,
+ role="user",
+ factory=factory,
+ )
+ return True
+
+
def _resolve_factory(unit_name: str, factory_cache: Dict[str, Optional[Factory]], unrecognized_factory: Factory) -> Tuple[Factory, bool, bool]:
if not unit_name:
return unrecognized_factory, True, False
@@ -79,6 +108,7 @@ def _resolve_factory(unit_name: str, factory_cache: Dict[str, Optional[Factory]]
city="北京",
district="北京",
)
+ _ensure_factory_user(created_factory, unit_name)
factory_cache[unit_name] = created_factory
return created_factory, False, True
@@ -120,6 +150,7 @@ def import_materials_plan_excel(file_obj) -> Dict[str, int]:
skipped = 0
unresolved_factory = 0
created_factory = 0
+ created_user = 0
factory_cache: Dict[str, Optional[Factory]] = {}
current_major_category = ""
@@ -147,6 +178,7 @@ def import_materials_plan_excel(file_obj) -> Dict[str, int]:
unresolved_factory += 1
if is_created_factory:
created_factory += 1
+ created_user += 1
defaults = {
"stage": _parse_choice(get(row, "阶段"), STAGE_VALUES),
@@ -179,4 +211,5 @@ def import_materials_plan_excel(file_obj) -> Dict[str, int]:
"skipped": skipped,
"unresolved_factory": unresolved_factory,
"created_factory": created_factory,
+ "created_user": created_user,
}
diff --git a/frontend/src/views/MaterialManage.vue b/frontend/src/views/MaterialManage.vue
index cc41fbc..b1b1e97 100644
--- a/frontend/src/views/MaterialManage.vue
+++ b/frontend/src/views/MaterialManage.vue
@@ -26,7 +26,7 @@
-
+