diff --git a/easyflow-api/easyflow-api-admin/src/main/java/tech/easyflow/admin/controller/system/SysAccountController.java b/easyflow-api/easyflow-api-admin/src/main/java/tech/easyflow/admin/controller/system/SysAccountController.java
index 9afeb2d0..2ae99304 100644
--- a/easyflow-api/easyflow-api-admin/src/main/java/tech/easyflow/admin/controller/system/SysAccountController.java
+++ b/easyflow-api/easyflow-api-admin/src/main/java/tech/easyflow/admin/controller/system/SysAccountController.java
@@ -67,9 +67,7 @@ public class SysAccountController extends BaseCurdController账号部门由管理端表单指定;只有未提交部门时才沿用通用创建流程的默认部门。
+ *
+ * @param entity 待创建的账号
+ * @param loginAccount 当前登录账号
+ */
+ @Override
+ protected void fillCreateCommonFields(SysAccount entity, LoginAccount loginAccount) {
+ BigInteger selectedDeptId = entity.getDeptId();
+ super.fillCreateCommonFields(entity, loginAccount);
+ if (selectedDeptId != null) {
+ entity.setDeptId(selectedDeptId);
+ }
+ }
+
@Override
protected void onSaveOrUpdateAfter(SysAccount entity, boolean isSave) {
service.syncRelations(entity);
diff --git a/easyflow-api/easyflow-api-admin/src/test/java/tech/easyflow/admin/controller/system/SysAccountControllerTest.java b/easyflow-api/easyflow-api-admin/src/test/java/tech/easyflow/admin/controller/system/SysAccountControllerTest.java
new file mode 100644
index 00000000..3c2963db
--- /dev/null
+++ b/easyflow-api/easyflow-api-admin/src/test/java/tech/easyflow/admin/controller/system/SysAccountControllerTest.java
@@ -0,0 +1,100 @@
+package tech.easyflow.admin.controller.system;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.mybatisflex.core.query.QueryWrapper;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockedStatic;
+import org.testng.annotations.Test;
+import tech.easyflow.auth.service.AuthCredentialKeyService;
+import tech.easyflow.common.domain.Result;
+import tech.easyflow.common.entity.LoginAccount;
+import tech.easyflow.common.satoken.util.SaTokenUtil;
+import tech.easyflow.system.entity.SysAccount;
+import tech.easyflow.system.service.SysAccountService;
+
+import java.math.BigInteger;
+import java.util.Map;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * {@link SysAccountController} 创建账号测试。
+ */
+public class SysAccountControllerTest {
+
+ /**
+ * 验证创建用户时保留表单选择的部门,而不是替换为操作者部门。
+ */
+ @Test
+ public void saveShouldKeepSubmittedDepartment() {
+ BigInteger selectedDeptId = BigInteger.valueOf(200);
+ BigInteger operatorDeptId = BigInteger.valueOf(100);
+ BigInteger tenantId = BigInteger.valueOf(300);
+ BigInteger operatorId = BigInteger.valueOf(400);
+ SysAccountService accountService = mock(SysAccountService.class);
+ AuthCredentialKeyService credentialKeyService = mock(AuthCredentialKeyService.class);
+ SysAccountController controller = new SysAccountController(accountService, credentialKeyService);
+ SysAccount entity = createAccount(selectedDeptId);
+ LoginAccount loginAccount = createLoginAccount(operatorId, tenantId, operatorDeptId);
+
+ when(accountService.count(any(QueryWrapper.class))).thenReturn(0L);
+ when(accountService.save(any(SysAccount.class))).thenAnswer(invocation -> {
+ invocation.getArgument(0, SysAccount.class).setId(BigInteger.valueOf(500));
+ return true;
+ });
+ when(credentialKeyService.decryptPayload(any()))
+ .thenReturn(JSONObject.parseObject("{\"password\":\"Valid123!\"}"));
+
+ try (MockedStatic saToken = mockStatic(SaTokenUtil.class)) {
+ saToken.when(SaTokenUtil::getLoginAccount).thenReturn(loginAccount);
+
+ Result> result = controller.save(entity);
+
+ assertEquals(result.getErrorCode(), 0);
+ }
+
+ ArgumentCaptor accountCaptor = ArgumentCaptor.forClass(SysAccount.class);
+ verify(accountService).save(accountCaptor.capture());
+ SysAccount savedAccount = accountCaptor.getValue();
+ assertEquals(savedAccount.getDeptId(), selectedDeptId);
+ assertEquals(savedAccount.getTenantId(), tenantId);
+ assertEquals(savedAccount.getCreatedBy(), operatorId);
+ assertEquals(savedAccount.getModifiedBy(), operatorId);
+ }
+
+ /**
+ * 构造待创建账号。
+ *
+ * @param deptId 表单选择的部门 ID
+ * @return 待创建账号
+ */
+ private SysAccount createAccount(BigInteger deptId) {
+ SysAccount account = new SysAccount();
+ account.setDeptId(deptId);
+ account.setLoginName("department_test_user");
+ account.setNickname("部门测试用户");
+ account.setPasswordCredential(Map.of("keyId", "test-key"));
+ return account;
+ }
+
+ /**
+ * 构造当前登录账号。
+ *
+ * @param id 操作人 ID
+ * @param tenantId 租户 ID
+ * @param deptId 操作人部门 ID
+ * @return 当前登录账号
+ */
+ private LoginAccount createLoginAccount(BigInteger id, BigInteger tenantId, BigInteger deptId) {
+ LoginAccount account = new LoginAccount();
+ account.setId(id);
+ account.setTenantId(tenantId);
+ account.setDeptId(deptId);
+ return account;
+ }
+}
diff --git a/easyflow-commons/easyflow-common-web/src/main/java/tech/easyflow/common/web/controller/BaseCurdController.java b/easyflow-commons/easyflow-common-web/src/main/java/tech/easyflow/common/web/controller/BaseCurdController.java
index b355ab1a..bac9fb9c 100644
--- a/easyflow-commons/easyflow-common-web/src/main/java/tech/easyflow/common/web/controller/BaseCurdController.java
+++ b/easyflow-commons/easyflow-common-web/src/main/java/tech/easyflow/common/web/controller/BaseCurdController.java
@@ -52,7 +52,7 @@ public class BaseCurdController, M> extends BaseController
throw new NullPointerException("entity is null");
}
LoginAccount loginAccount = SaTokenUtil.getLoginAccount();
- commonFiled(entity, loginAccount.getId(), loginAccount.getTenantId(), loginAccount.getDeptId());
+ fillCreateCommonFields(entity, loginAccount);
service.save(entity);
onSaveOrUpdateAfter(entity, true);
TableInfo tableInfo = TableInfoFactory.ofEntityClass(entity.getClass());
@@ -271,6 +271,19 @@ public class BaseCurdController, M> extends BaseController
return service.page(page, queryWrapper);
}
+ /**
+ * 填充创建记录的公共审计与归属字段。
+ *
+ * 默认将部门归属设置为当前登录用户所属部门。若业务实体的部门字段具有独立业务含义,
+ * 子类可覆写此方法以保留业务侧传入的部门。
+ *
+ * @param entity 待创建的实体
+ * @param loginAccount 当前登录账号
+ */
+ protected void fillCreateCommonFields(M entity, LoginAccount loginAccount) {
+ commonFiled(entity, loginAccount.getId(), loginAccount.getTenantId(), loginAccount.getDeptId());
+ }
+
protected Result> onSaveOrUpdateBefore(M entity, boolean isSave) {
return null;
}