ソースを参照

feat(s8): default manual report occurrence department

YY968XX 1 週間 前
コミット
331ca3e4e2

+ 19 - 6
Web/src/views/aidop/s8/report/S8ManualReportPage.vue

@@ -36,13 +36,26 @@ const form = reactive({
 });
 
 async function loadOptions() {
-	const result = (await s8ReportApi.formOptions({ tenantId: 1, factoryId: 1 })) as Record<string, any[]>;
-	formOptions.scenes = (result.scenes ?? []).map((item) => ({ value: item.value, label: item.label }));
-	formOptions.severities = (result.severities ?? []).map((item) => ({ value: item.value, label: item.label }));
-	formOptions.departments = (result.departments ?? []).map((item) => ({ value: item.value, label: item.label }));
-	formOptions.lines = (result.lines ?? []).map((item) => ({ value: item.value, label: item.label }));
+	const result = (await s8ReportApi.formOptions({ tenantId: 1, factoryId: 1 })) as Record<string, any> & {
+		defaultOccurrenceDeptId?: number | null;
+		defaultOccurrenceDeptName?: string | null;
+	};
+	formOptions.scenes = (result.scenes ?? []).map((item: any) => ({ value: item.value, label: item.label }));
+	formOptions.severities = (result.severities ?? []).map((item: any) => ({ value: item.value, label: item.label }));
+	formOptions.departments = (result.departments ?? []).map((item: any) => ({ value: item.value, label: item.label }));
+	formOptions.lines = (result.lines ?? []).map((item: any) => ({ value: item.value, label: item.label }));
 	if (!form.sceneCode && formOptions.scenes[0]) form.sceneCode = formOptions.scenes[0].value;
-	if (!form.occurrenceDeptId && formOptions.departments[0]) form.occurrenceDeptId = formOptions.departments[0].value;
+	// S8-MANUAL-REPORT-DEFAULT-OCCURRENCE-DEPT-1(P1):发生部门默认 = 当前登录员工部门(后端解析)。
+	// 仅当后端给出 defaultOccurrenceDeptId 且该 ID 存在于 departments 选项中时采用;否则继续兜底首项。
+	// 用户仍可改;不联动 responsibleDeptId 的默认值。
+	if (!form.occurrenceDeptId) {
+		const defaultId = result.defaultOccurrenceDeptId ?? null;
+		if (defaultId != null && formOptions.departments.some((d) => d.value === defaultId)) {
+			form.occurrenceDeptId = defaultId;
+		} else if (formOptions.departments[0]) {
+			form.occurrenceDeptId = formOptions.departments[0].value;
+		}
+	}
 	if (!form.responsibleDeptId && formOptions.departments[0]) form.responsibleDeptId = formOptions.departments[0].value;
 }
 

+ 59 - 1
server/Plugins/Admin.NET.Plugin.AiDOP/Service/S8/S8ManualReportService.cs

@@ -150,6 +150,55 @@ public class S8ManualReportService : ITransient
         return emp?.Id;
     }
 
+    // S8-MANUAL-REPORT-DEFAULT-OCCURRENCE-DEPT-1(P1):取当前登录员工的业务部门作为默认发生部门。
+    // 链路:SysUser.Id → EmployeeMaster.sys_user_id → EmployeeMaster.Department(string)
+    //        + EmployeeMaster.FactoryRefId → DepartmentMaster.Department + FactoryRefId → RecID。
+    // 不绑定 / 部门为空 / 部门未匹配 / 命中多条:均返回 (null,null) + warning,绝不报错也不阻断页面。
+    // 仅作为前端 form 默认初值;用户仍可改,CreateAsync 的 dept=0 guard 不变。
+    private async Task<(long? DeptId, string? DeptName)> ResolveCurrentEmployeeDefaultDeptAsync(long factoryId, long sysUserId)
+    {
+        if (sysUserId <= 0 || factoryId <= 0) return (null, null);
+        var emp = await _empRep.AsQueryable().ClearFilter()
+            .Where(x => x.SysUserId == sysUserId && x.FactoryRefId == factoryId && x.IsActive)
+            .Select(x => new { x.Id, x.Department, x.FactoryRefId })
+            .FirstAsync();
+        if (emp == null)
+        {
+            _logger.LogWarning(
+                "s8_manual_report_default_dept_unbound_employee sysUserId={SysUserId} factoryId={FactoryId}",
+                sysUserId, factoryId);
+            return (null, null);
+        }
+        if (string.IsNullOrWhiteSpace(emp.Department))
+        {
+            _logger.LogWarning(
+                "s8_manual_report_default_dept_employee_dept_empty sysUserId={SysUserId} factoryId={FactoryId} employeeId={EmployeeId}",
+                sysUserId, factoryId, emp.Id);
+            return (null, null);
+        }
+        var depts = await _deptRep.AsQueryable().ClearFilter()
+            .Where(x => x.Department == emp.Department && x.FactoryRefId == emp.FactoryRefId && x.IsActive)
+            .Select(x => new { x.Id, x.Department, x.Descr })
+            .Take(2)
+            .ToListAsync();
+        if (depts.Count == 0)
+        {
+            _logger.LogWarning(
+                "s8_manual_report_default_dept_unmatched sysUserId={SysUserId} factoryId={FactoryId} employeeId={EmployeeId} departmentCode={DeptCode}",
+                sysUserId, factoryId, emp.Id, emp.Department);
+            return (null, null);
+        }
+        if (depts.Count > 1)
+        {
+            _logger.LogWarning(
+                "s8_manual_report_default_dept_ambiguous sysUserId={SysUserId} factoryId={FactoryId} employeeId={EmployeeId} departmentCode={DeptCode} matchedCount={Count}",
+                sysUserId, factoryId, emp.Id, emp.Department, depts.Count);
+            return (null, null);
+        }
+        var d = depts[0];
+        return (d.Id, string.IsNullOrWhiteSpace(d.Descr) ? d.Department : d.Descr);
+    }
+
     /// <summary>
     /// 主动提报推断 ExceptionTypeCode:场景下取启用且 SortNo 最小的一条。
     /// baseline 异常类型当前 tenant_id=0/factory_id=0(全局基线),所以匹配条件为
@@ -218,6 +267,13 @@ public class S8ManualReportService : ITransient
             .Select(x => new { value = x.Id, label = x.Describe ?? x.Line })
             .ToListAsync();
 
+        // S8-MANUAL-REPORT-DEFAULT-OCCURRENCE-DEPT-1(P1):默认发生部门 = 当前登录员工的业务部门。
+        // 未登录 / 未绑定 / 部门不可解析 → 返回 null,前端继续要求用户手动选择。
+        var sysUserId = _userManager.UserId;
+        var (defaultOccDeptId, defaultOccDeptName) = sysUserId > 0
+            ? await ResolveCurrentEmployeeDefaultDeptAsync(factoryId, sysUserId)
+            : (null, null);
+
         return new
         {
             scenes,
@@ -225,7 +281,9 @@ public class S8ManualReportService : ITransient
             severities = S8SeverityCode.Options(),
             departments,
             lines,
-            materials = Array.Empty<object>()
+            materials = Array.Empty<object>(),
+            defaultOccurrenceDeptId = defaultOccDeptId,
+            defaultOccurrenceDeptName = defaultOccDeptName,
         };
     }