From ce841ddf85c48bae32f9e3068403fdfe98ac8711 Mon Sep 17 00:00:00 2001
From: zzw <228544128@qq.com>
Date: 星期三, 07 十月 2026 12:35:09 +0800
Subject: [PATCH] feat: add extension defaults for fault reporting
---
emergency-repair-server/src/main/java/com/emergencyrepair/system/controller/SystemController.java | 22 ++
emergency-repair-server/src/main/java/com/emergencyrepair/auth/AuthController.java | 28 ++
emergency-repair-web/src/views/Login.vue | 6
emergency-repair-web/src/views/fault/FaultReport.vue | 25 +-
HANDOFF.md | 54 ++++++
emergency-repair-server/src/main/java/com/emergencyrepair/system/service/ButtonPermissionCatalog.java | 3
requirement/交接文件_2026.10.3.md | 54 ++++++
emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DatabaseBootstrap.java | 4
emergency-repair-web/src/views/system/UserManage.vue | 65 +++++++
emergency-repair-server/src/main/java/com/emergencyrepair/business/dto/Requests.java | 12 +
requirement/改进20261003.txt | 10 +
emergency-repair-server/src/main/java/com/emergencyrepair/system/service/SystemService.java | 150 ++++++++++++++++
emergency-repair-web/src/views/system/OrganizationManage.vue | 60 ++++++
13 files changed, 474 insertions(+), 19 deletions(-)
diff --git a/HANDOFF.md b/HANDOFF.md
index b08a22f..e2335ac 100644
--- a/HANDOFF.md
+++ b/HANDOFF.md
@@ -938,3 +938,57 @@
- 浣跨敤鏂� jar 閲嶅惎鍚庡啀娆℃煡璇紝鍥涘紶涓氬姟琛ㄤ粛鍧囦负 `0` 琛岋紱鐧诲綍鎺ュ彛 `200`锛屽墠绔椤� `200`銆�
- 褰撳墠鍚庣 PID `21528`锛岀洃鍚� `8091`锛涙棩蹇楋細`.codex-run/backend-20261007-cleared.out.log`銆乣.codex-run/backend-20261007-cleared.err.log`銆�
- 濡傞渶閲嶆柊鐏屽叆婕旂ず涓氬姟鏁版嵁锛屽皢 `app.seed-demo-data` 涓存椂璁句负 `true` 鍚庨噸鍚��
+
+## 26. 鏀跺熬蹇収锛�2026-10-07 鍛ㄤ笁锛岄渶姹� 28-30 鎵╁睍灞炴�т笌鏂板鏁呴殰榛樿鍊硷級
+
+**闇�姹傚彛寰�**
+- 闇�姹� 30 缂栧彿宸茬‘璁わ紱鏂板鏁呴殰閲岀殑鈥滆矗浠烩�濆氨鏄�滆礋璐d汉鈥濄��
+- 閮ㄩ棬鎵╁睍灞炴�р�滆礋璐k_T鈥濈殑鍊煎氨鏄� `rk_X鍙穈锛屽�煎繀椤绘槸浜у搧缁撴瀯鏍� `side` 绫诲瀷鑺傜偣锛屽崟閫夈��
+- 鏂板鏁呴殰鐨� `rk_X鍙穈 榛樿鍊煎彧鍙栫櫥褰曠敤鎴锋墍灞為儴闂ㄧ殑鎵╁睍灞炴�э紱鍗充娇鐢ㄦ埛鎵╁睍灞炴�т篃璁剧疆浜嗏�滆礋璐k_T鈥濓紝浠嶄互閮ㄩ棬璁剧疆涓哄噯銆�
+- 鈥渞k_TD涓撲笟鈥濅笌鐜版湁鈥渞k_T闃熶笓涓氣�濇槸鍚屼竴瀛楁锛屼唬鐮佸瓧娈典负 `teamMajor`锛屽綋鍓嶇晫闈㈡殏鏃舵部鐢ㄢ�渞k_T闃熶笓涓氣�濄��
+- 澶栭儴 `CSICZB_ZB.SYS_DEPT`銆乣CSICZB_ZB.SYS_USER` 鐢卞叾浠栫郴缁熺淮鎶わ紝鏈」鐩彧璇伙紱鎵╁睍灞炴�т繚瀛樺埌鏈湴鏂拌〃銆�
+
+**鏈疆瀹屾垚鍐呭**
+- `DatabaseBootstrap` 鑷姩鍒涘缓 `LX.T_SYS_DEPT_EXT`锛坄DEPT_ID`銆乣RESPONSIBLE_X_NO` 鍙婂璁″瓧娈碉級鍜� `LX.T_SYS_USER_EXT`锛坄USER_ID`銆乣ENGINEERING_MAJOR`銆乣TEAM_MAJOR`銆乣RESPONSIBLE_X_NO` 鍙婂璁″瓧娈碉級銆�
+- 缁勭粐鏈烘瀯椤甸潰澧炲姞鈥滄墿灞曞睘鎬р�濇寜閽拰寮圭獥锛屽彲璁剧疆閮ㄩ棬鈥滆礋璐k_T鈥濓紱鍒楄〃鏄剧ず宸茶缃�笺��
+- 鐢ㄦ埛绠$悊椤甸潰澧炲姞鈥滄墿灞曞睘鎬р�濇寜閽拰寮圭獥锛屽彲璁剧疆宸ョ▼涓撲笟銆乺k_T闃熶笓涓氥�佽礋璐k_T锛涘垪琛ㄦ樉绀烘墿灞曞睘鎬ф槸鍚﹀凡璁剧疆銆�
+- 鏂板鏁呴殰寮圭獥榛樿甯﹀嚭锛氫笂鎶ュ崟浣嶄负褰撳墠鐧诲綍浜虹殑鍗曚綅銆佽礋璐d汉涓哄綋鍓嶇櫥褰曚汉銆乣rk_X鍙穈涓哄綋鍓嶉儴闂ㄦ墿灞曞睘鎬с�佸伐绋嬩笓涓氬拰 rk_T闃熶笓涓氫负褰撳墠鐢ㄦ埛鎵╁睍灞炴�с��
+- 鐢ㄦ埛鎵╁睍灞炴�т负绌烘椂锛屽伐绋嬩笓涓氬拰 rk_T闃熶笓涓氫笉鍐嶉粯璁ら�夋嫨閰嶇疆鍒楄〃绗竴椤广��
+
+**鎺ュ彛涓庢潈闄�**
+- `GET/PUT /api/system/depts/{deptId}/ext`锛氭煡璇㈠拰淇濆瓨閮ㄩ棬鎵╁睍灞炴�с��
+- `GET/PUT /api/system/users/{userId}/ext`锛氭煡璇㈠拰淇濆瓨鐢ㄦ埛鎵╁睍灞炴�с��
+- `/api/auth/login`銆乣/api/auth/me` 杩斿洖 `userId`銆乣deptId`銆乣engineeringMajor`銆乣teamMajor`銆乣deptResponsibleXNo`銆乣responsibleXNo`銆�
+- 鎸夐挳鏉冮檺鏂板 `system:organization:ext`锛堟墿灞曞睘鎬ц缃級銆乣system:users:ext`锛堟墿灞曞睘鎬ц缃級銆�
+
+**涓昏鍙樻洿鏂囦欢**
+- `emergency-repair-server/src/main/java/com/emergencyrepair/auth/AuthController.java`
+- `emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DatabaseBootstrap.java`
+- `emergency-repair-server/src/main/java/com/emergencyrepair/business/dto/Requests.java`
+- `emergency-repair-server/src/main/java/com/emergencyrepair/system/controller/SystemController.java`
+- `emergency-repair-server/src/main/java/com/emergencyrepair/system/service/ButtonPermissionCatalog.java`
+- `emergency-repair-server/src/main/java/com/emergencyrepair/system/service/SystemService.java`
+- `emergency-repair-web/src/views/Login.vue`
+- `emergency-repair-web/src/views/fault/FaultReport.vue`
+- `emergency-repair-web/src/views/system/OrganizationManage.vue`
+- `emergency-repair-web/src/views/system/UserManage.vue`
+- `requirement/鏀硅繘20261003.txt`锛堣ˉ鍏呴渶姹� 28-30锛�
+
+**楠岃瘉缁撴灉**
+- 鍚庣 `mvn -B -DskipTests clean package` 閫氳繃锛涘墠绔� `npm run build` 閫氳繃锛屼粎鏈夋棦鏈夊寘浣撶Н鍛婅銆�
+- `node .codex-run/verify-req28-30.js` 杩斿洖 `pass: true`銆�
+- 閮ㄩ棬 `1390477009348739073 / sy鍖哄煙` 璁剧疆 `rk_X鍙�=201`锛岀敤鎴� `123 / yszl` 璁剧疆宸ョ▼涓撲笟 `鍔ㄥ姏涓撲笟`銆乺k_T闃熶笓涓� `娑插帇涓撲笟`銆佽礋璐� `202`銆�
+- 鏂板鏁呴殰瀹為檯榛樿鍊间负锛氫笂鎶ュ崟浣� `sy鍖哄煙`銆佽礋璐d汉 `鍔╃悊鐢ㄦ埛锛堟紨绀猴級`銆乣rk_X鍙�=201`銆乺k_T闃熶笓涓� `娑插帇涓撲笟`銆佸伐绋嬩笓涓� `鍔ㄥ姏涓撲笟`銆�
+- 鎴浘锛歚.codex-run/req28-org-ext.png`銆乣.codex-run/req29-user-ext.png`銆乣.codex-run/req30-fault-defaults.png`銆�
+- 楠岃瘉鍚庡凡娓呴櫎涓存椂閮ㄩ棬銆佺敤鎴锋墿灞曞睘鎬э紝鏌ヨ纭 `configured=false` 涓斿瓧娈典负绌恒��
+
+**褰撳墠杩愯鐘舵�侊紙2026-10-07锛�**
+- 鍚庣 PID `56124`锛岀洃鍚� `http://127.0.0.1:8091`锛涘墠绔� PID `57312`锛岀洃鍚� `http://localhost:8082`銆�
+- 涓� UI 楠岃瘉鍚姩鐨� headless Edge PID `95756`锛孋DP 绔彛 `9222`锛涢厤缃洰褰� `.codex-run/edge-profile-req28-30`銆�
+- 鍚庣鏃ュ織锛歚.codex-run/backend-20261007-req28-30-final.out.log`銆乣.codex-run/backend-20261007-req28-30-final.err.log`銆�
+- 鐧诲綍 `admin / admin123`锛涙暟鎹簱 `SYSDBA/SYSDBA`锛屼笟鍔� schema `LX`銆�
+
+**鎺ユ墜娉ㄦ剰**
+- 寮�鍙戠幆澧冩晱鎰熻瘝閰嶇疆浼氭妸 `rk_T` 鏄剧ず涓衡�滄鈥濓紝鍥犳椤甸潰鎴浘涓彲鑳芥樉绀衡�滆礋璐f鈥濓紱浠g爜鍜屽悗绔瓧娈典粛鏄� `rk_T`銆�
+- 涓嶈鎻愪氦 `.codex-run`銆丱ffice 閿佹枃浠舵垨 `emergency-repair-web/public/鏂板缓 鏂囨湰鏂囨。.txt`銆�
+- 鏈疆浠g爜銆侀渶姹傛枃浠跺拰浜ゆ帴璁板綍涓�骞舵彁浜ゅ苟鎺ㄩ�佸叕鍙� Git 浠撳簱 `main` 鍒嗘敮銆�
diff --git a/emergency-repair-server/src/main/java/com/emergencyrepair/auth/AuthController.java b/emergency-repair-server/src/main/java/com/emergencyrepair/auth/AuthController.java
index 3da7330..3348937 100644
--- a/emergency-repair-server/src/main/java/com/emergencyrepair/auth/AuthController.java
+++ b/emergency-repair-server/src/main/java/com/emergencyrepair/auth/AuthController.java
@@ -58,6 +58,12 @@
data.put("realName", StringUtils.hasText(stringValue(user.get("nickName")))
? stringValue(user.get("nickName")) : username);
data.put("deptName", stringValue(user.get("deptName")));
+ data.put("userId", String.valueOf(user.get("userId")));
+ data.put("deptId", user.get("deptId") == null ? "" : String.valueOf(user.get("deptId")));
+ data.put("engineeringMajor", stringValue(user.get("engineeringMajor")));
+ data.put("teamMajor", stringValue(user.get("teamMajor")));
+ data.put("deptResponsibleXNo", stringValue(user.get("deptResponsibleXNo")));
+ data.put("responsibleXNo", stringValue(user.get("responsibleXNo")));
data.put("roles", systemService.roleCodes(username));
data.put("permissions", systemService.permissionCodes(username));
return Result.ok(data);
@@ -76,6 +82,12 @@
data.put("realName", StringUtils.hasText(stringValue(user.get("nickName")))
? stringValue(user.get("nickName")) : username);
data.put("deptName", stringValue(user.get("deptName")));
+ data.put("userId", String.valueOf(user.get("userId")));
+ data.put("deptId", user.get("deptId") == null ? "" : String.valueOf(user.get("deptId")));
+ data.put("engineeringMajor", stringValue(user.get("engineeringMajor")));
+ data.put("teamMajor", stringValue(user.get("teamMajor")));
+ data.put("deptResponsibleXNo", stringValue(user.get("deptResponsibleXNo")));
+ data.put("responsibleXNo", stringValue(user.get("responsibleXNo")));
data.put("roles", systemService.roleCodes(username));
data.put("permissions", systemService.permissionCodes(username));
return Result.ok(data);
@@ -87,9 +99,13 @@
}
try {
List<Map<String, Object>> rows = jdbcTemplate.query(
- "SELECT u.USER_ID, u.USER_NAME, u.NICK_NAME, u.PASSWORD, u.STATUS, d.DEPT_NAME " +
- "FROM LX.SYS_USER u LEFT JOIN LX.SYS_DEPT d ON d.DEPT_ID = u.DEPT_ID " +
- "WHERE u.USER_NAME = ? AND (u.DEL_FLAG = '0' OR u.DEL_FLAG IS NULL)",
+ "SELECT u.USER_ID, u.USER_NAME, u.NICK_NAME, u.PASSWORD, u.STATUS, u.DEPT_ID, d.DEPT_NAME, "
+ + "ue.ENGINEERING_MAJOR, ue.TEAM_MAJOR, ue.RESPONSIBLE_X_NO AS USER_RESPONSIBLE_X_NO, "
+ + "de.RESPONSIBLE_X_NO AS DEPT_RESPONSIBLE_X_NO "
+ + "FROM LX.SYS_USER u LEFT JOIN LX.SYS_DEPT d ON d.DEPT_ID = u.DEPT_ID "
+ + "LEFT JOIN LX.T_SYS_USER_EXT ue ON ue.USER_ID = u.USER_ID AND (ue.DEL_FLAG = 0 OR ue.DEL_FLAG IS NULL) "
+ + "LEFT JOIN LX.T_SYS_DEPT_EXT de ON de.DEPT_ID = u.DEPT_ID AND (de.DEL_FLAG = 0 OR de.DEL_FLAG IS NULL) "
+ + "WHERE u.USER_NAME = ? AND (u.DEL_FLAG = '0' OR u.DEL_FLAG IS NULL)",
new Object[]{username},
(rs, rowNum) -> {
Map<String, Object> row = new LinkedHashMap<>();
@@ -98,6 +114,12 @@
row.put("nickName", rs.getString("NICK_NAME"));
row.put("password", rs.getString("PASSWORD"));
row.put("status", rs.getString("STATUS"));
+ Object deptId = rs.getObject("DEPT_ID");
+ row.put("deptId", deptId == null ? null : rs.getLong("DEPT_ID"));
+ row.put("engineeringMajor", rs.getString("ENGINEERING_MAJOR"));
+ row.put("teamMajor", rs.getString("TEAM_MAJOR"));
+ row.put("responsibleXNo", rs.getString("USER_RESPONSIBLE_X_NO"));
+ row.put("deptResponsibleXNo", rs.getString("DEPT_RESPONSIBLE_X_NO"));
row.put("deptName", rs.getString("DEPT_NAME"));
return row;
});
diff --git a/emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DatabaseBootstrap.java b/emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DatabaseBootstrap.java
index 4797f5e..1814e1f 100644
--- a/emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DatabaseBootstrap.java
+++ b/emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DatabaseBootstrap.java
@@ -18,7 +18,7 @@
"T_BASE_EQUIPMENT", "T_PRODUCT_TREE", "T_WORK_ORDER", "T_COMPLETION_INFO",
"T_ACCEPTANCE", "T_SYS_MENU", "T_SYS_ROLE", "T_SYS_ROLE_MENU",
"T_SYS_TENANT_MENU", "T_SYS_ROLE_USER", "T_SYS_LOGIN_LOG", "T_SYS_OPERATION_LOG",
- "T_SYS_ERROR_LOG"
+ "T_SYS_ERROR_LOG", "T_SYS_DEPT_EXT", "T_SYS_USER_EXT"
};
private final JdbcTemplate jdbcTemplate;
@@ -122,6 +122,8 @@
ddl.put("T_SYS_ROLE_MENU", "CREATE TABLE LX.T_SYS_ROLE_MENU (ID BIGINT NOT NULL PRIMARY KEY, ROLE_ID BIGINT, MENU_ID BIGINT, CREATE_TIME TIMESTAMP)");
ddl.put("T_SYS_TENANT_MENU", "CREATE TABLE LX.T_SYS_TENANT_MENU (ID BIGINT NOT NULL PRIMARY KEY, TENANT_ID BIGINT, MENU_ID BIGINT, CREATE_TIME TIMESTAMP)");
ddl.put("T_SYS_ROLE_USER", "CREATE TABLE LX.T_SYS_ROLE_USER (ID BIGINT NOT NULL PRIMARY KEY, ROLE_ID BIGINT, USER_ID BIGINT, CREATE_TIME TIMESTAMP)");
+ ddl.put("T_SYS_DEPT_EXT", "CREATE TABLE LX.T_SYS_DEPT_EXT (DEPT_ID BIGINT NOT NULL PRIMARY KEY, RESPONSIBLE_X_NO VARCHAR(40), CREATE_BY VARCHAR(120), UPDATE_BY VARCHAR(120), DEL_FLAG INT DEFAULT 0, CREATE_TIME TIMESTAMP, UPDATE_TIME TIMESTAMP)");
+ ddl.put("T_SYS_USER_EXT", "CREATE TABLE LX.T_SYS_USER_EXT (USER_ID BIGINT NOT NULL PRIMARY KEY, ENGINEERING_MAJOR VARCHAR(100), TEAM_MAJOR VARCHAR(100), RESPONSIBLE_X_NO VARCHAR(40), CREATE_BY VARCHAR(120), UPDATE_BY VARCHAR(120), DEL_FLAG INT DEFAULT 0, CREATE_TIME TIMESTAMP, UPDATE_TIME TIMESTAMP)");
ddl.put("T_SYS_LOGIN_LOG", "CREATE TABLE LX.T_SYS_LOGIN_LOG (ID BIGINT NOT NULL PRIMARY KEY, USER_ID BIGINT, USER_NAME VARCHAR(120), NICK_NAME VARCHAR(120), DEPT_NAME VARCHAR(120), LOGIN_IP VARCHAR(200), STATUS VARCHAR(20), MESSAGE VARCHAR(500), LOGIN_TIME TIMESTAMP)");
ddl.put("T_SYS_OPERATION_LOG", "CREATE TABLE LX.T_SYS_OPERATION_LOG (ID BIGINT NOT NULL PRIMARY KEY, USER_ID BIGINT, USER_NAME VARCHAR(120), NICK_NAME VARCHAR(120), MODULE VARCHAR(100), OPERATION_TYPE VARCHAR(40), TARGET_TYPE VARCHAR(100), TARGET_ID VARCHAR(80), DESCRIPTION VARCHAR(500), REQUEST_METHOD VARCHAR(10), REQUEST_URI VARCHAR(300), RESULT VARCHAR(20), CREATE_TIME TIMESTAMP)");
ddl.put("T_SYS_ERROR_LOG", "CREATE TABLE LX.T_SYS_ERROR_LOG (ID BIGINT NOT NULL PRIMARY KEY, USER_ID BIGINT, USER_NAME VARCHAR(120), NICK_NAME VARCHAR(120), MODULE VARCHAR(100), REQUEST_METHOD VARCHAR(10), REQUEST_URI VARCHAR(500), EXCEPTION_TYPE VARCHAR(300), MESSAGE VARCHAR(2000), STACK_TRACE CLOB, ERROR_TIME TIMESTAMP)");
diff --git a/emergency-repair-server/src/main/java/com/emergencyrepair/business/dto/Requests.java b/emergency-repair-server/src/main/java/com/emergencyrepair/business/dto/Requests.java
index 321c475..ce7c2e6 100644
--- a/emergency-repair-server/src/main/java/com/emergencyrepair/business/dto/Requests.java
+++ b/emergency-repair-server/src/main/java/com/emergencyrepair/business/dto/Requests.java
@@ -128,6 +128,18 @@
}
@Data
+ public static class DeptExtRequest {
+ private String responsibleXNo;
+ }
+
+ @Data
+ public static class UserExtRequest {
+ private String engineeringMajor;
+ private String teamMajor;
+ private String responsibleXNo;
+ }
+
+ @Data
public static class ButtonSyncRequest {
private Long menuId;
private List<String> codes = new ArrayList<>();
diff --git a/emergency-repair-server/src/main/java/com/emergencyrepair/system/controller/SystemController.java b/emergency-repair-server/src/main/java/com/emergencyrepair/system/controller/SystemController.java
index 09f271c..2f1e564 100644
--- a/emergency-repair-server/src/main/java/com/emergencyrepair/system/controller/SystemController.java
+++ b/emergency-repair-server/src/main/java/com/emergencyrepair/system/controller/SystemController.java
@@ -80,6 +80,17 @@
return Result.ok();
}
+ @GetMapping("/users/{userId}/ext")
+ public Result<Map<String, Object>> userExt(@PathVariable Long userId) {
+ return Result.ok(systemService.userExt(userId));
+ }
+
+ @PutMapping("/users/{userId}/ext")
+ public Result<Void> saveUserExt(@PathVariable Long userId, @RequestBody Requests.UserExtRequest request) {
+ systemService.saveUserExt(userId, request.getEngineeringMajor(), request.getTeamMajor(), request.getResponsibleXNo());
+ return Result.ok();
+ }
+
@PutMapping("/users/roles/batch")
public Result<Void> saveBatchUserRoles(@RequestBody Requests.BatchUserRoleRequest request) {
systemService.saveUserRolesBatch(request.getUserIds(), request.getRoleIds(), request.getMode());
@@ -91,6 +102,17 @@
return Result.ok(systemService.depts());
}
+ @GetMapping("/depts/{deptId}/ext")
+ public Result<Map<String, Object>> deptExt(@PathVariable Long deptId) {
+ return Result.ok(systemService.deptExt(deptId));
+ }
+
+ @PutMapping("/depts/{deptId}/ext")
+ public Result<Void> saveDeptExt(@PathVariable Long deptId, @RequestBody Requests.DeptExtRequest request) {
+ systemService.saveDeptExt(deptId, request.getResponsibleXNo());
+ return Result.ok();
+ }
+
@GetMapping("/login-logs")
public Result<Page<SysLoginLog>> loginLogs(@RequestParam(defaultValue = "1") int current,
@RequestParam(defaultValue = "20") int size,
diff --git a/emergency-repair-server/src/main/java/com/emergencyrepair/system/service/ButtonPermissionCatalog.java b/emergency-repair-server/src/main/java/com/emergencyrepair/system/service/ButtonPermissionCatalog.java
index 7e6b6fa..bd2bd90 100644
--- a/emergency-repair-server/src/main/java/com/emergencyrepair/system/service/ButtonPermissionCatalog.java
+++ b/emergency-repair-server/src/main/java/com/emergencyrepair/system/service/ButtonPermissionCatalog.java
@@ -84,10 +84,11 @@
put("/reports/contractors", def("report:common:query", "\u67e5\u8be2"), def("report:common:export", "\u5bfc\u51fa"));
put("/reports/trend", def("report:common:query", "\u67e5\u8be2"), def("report:common:export", "\u5bfc\u51fa"));
put("/system/product-tree", def("system:tree:add", "\u65b0\u589e"), def("system:tree:edit", "\u7f16\u8f91"), def("system:tree:delete", "\u5220\u9664"));
+ put("/system/organization", def("system:organization:query", "\u67e5\u8be2"), def("system:organization:ext", "\u6269\u5c55\u5c5e\u6027\u8bbe\u7f6e"));
put("/system/base-equipment", def("system:tree:add", "\u65b0\u589e"), def("system:tree:edit", "\u7f16\u8f91"), def("system:tree:delete", "\u5220\u9664"));
put("/system/engineering-majors", def("system:major:add", "\u65b0\u589e"), def("system:major:edit", "\u7f16\u8f91"), def("system:major:delete", "\u5220\u9664"));
put("/system/team-majors", def("system:major:add", "\u65b0\u589e"), def("system:major:edit", "\u7f16\u8f91"), def("system:major:delete", "\u5220\u9664"));
- put("/system/users", def("system:users:query", "\u67e5\u8be2"), def("system:users:assign", "\u89d2\u8272\u6388\u6743"));
+ put("/system/users", def("system:users:query", "\u67e5\u8be2"), def("system:users:assign", "\u89d2\u8272\u6388\u6743"), def("system:users:ext", "\u6269\u5c55\u5c5e\u6027\u8bbe\u7f6e"));
put("/system/roles", def("system:roles:add", "\u65b0\u589e"), def("system:roles:edit", "\u7f16\u8f91"), def("system:roles:delete", "\u5220\u9664"), def("system:roles:assign", "\u7528\u6237\u8bbe\u7f6e"), def("system:roles:permission", "\u6743\u9650\u8bbe\u7f6e"));
put("/system/menus", def("system:menus:add", "\u65b0\u589e"), def("system:menus:edit", "\u7f16\u8f91"), def("system:menus:delete", "\u5220\u9664"), def("system:menus:buttons", "\u83dc\u5355\u6309\u94ae\u540c\u6b65"));
put("/system/login-logs", def("system:login-logs:query", "\u67e5\u8be2"), def("system:login-logs:export", "\u5bfc\u51fa"));
diff --git a/emergency-repair-server/src/main/java/com/emergencyrepair/system/service/SystemService.java b/emergency-repair-server/src/main/java/com/emergencyrepair/system/service/SystemService.java
index 1775f6e..e14467e 100644
--- a/emergency-repair-server/src/main/java/com/emergencyrepair/system/service/SystemService.java
+++ b/emergency-repair-server/src/main/java/com/emergencyrepair/system/service/SystemService.java
@@ -13,6 +13,7 @@
import com.emergencyrepair.business.mapper.ProductNodeMapper;
import com.emergencyrepair.business.mapper.TeamMajorMapper;
import com.emergencyrepair.common.BusinessException;
+import com.emergencyrepair.common.audit.CurrentUserContext;
import com.emergencyrepair.system.entity.SysMenu;
import com.emergencyrepair.system.entity.SysErrorLog;
import com.emergencyrepair.system.entity.SysLoginLog;
@@ -601,8 +602,10 @@
public Map<String, Object> userPage(String keyword, Long deptId, Long roleId, int current, int size) {
List<Object> args = new ArrayList<>();
StringBuilder sql = new StringBuilder();
- sql.append("SELECT u.USER_ID, u.USER_NAME, u.NICK_NAME, u.DEPT_ID, d.DEPT_NAME, u.PHONENUMBER, u.STATUS, u.LOGIN_DATE ");
+ sql.append("SELECT u.USER_ID, u.USER_NAME, u.NICK_NAME, u.DEPT_ID, d.DEPT_NAME, u.PHONENUMBER, u.STATUS, u.LOGIN_DATE, ");
+ sql.append("ue.ENGINEERING_MAJOR, ue.TEAM_MAJOR, ue.RESPONSIBLE_X_NO, CASE WHEN ue.USER_ID IS NULL THEN 0 ELSE 1 END AS EXT_CONFIGURED ");
sql.append("FROM CSICZB_ZB.SYS_USER u LEFT JOIN CSICZB_ZB.SYS_DEPT d ON d.DEPT_ID = u.DEPT_ID ");
+ sql.append("LEFT JOIN LX.T_SYS_USER_EXT ue ON ue.USER_ID = u.USER_ID AND (ue.DEL_FLAG = 0 OR ue.DEL_FLAG IS NULL) ");
sql.append("WHERE (u.DEL_FLAG = '0' OR u.DEL_FLAG IS NULL) ");
if (StringUtils.hasText(keyword)) {
sql.append("AND (u.USER_NAME LIKE ? OR u.NICK_NAME LIKE ?) ");
@@ -631,6 +634,10 @@
row.put("status", rs.getString("STATUS"));
java.sql.Timestamp loginDate = rs.getTimestamp("LOGIN_DATE");
row.put("loginDate", loginDate == null ? null : loginDate.toLocalDateTime().toString().replace('T', ' '));
+ row.put("engineeringMajor", rs.getString("ENGINEERING_MAJOR"));
+ row.put("teamMajor", rs.getString("TEAM_MAJOR"));
+ row.put("responsibleXNo", rs.getString("RESPONSIBLE_X_NO"));
+ row.put("extConfigured", rs.getInt("EXT_CONFIGURED") == 1);
row.put("roles", new ArrayList<Map<String, Object>>());
return row;
});
@@ -675,7 +682,11 @@
public List<Map<String, Object>> depts() {
return jdbcTemplate.query(
- "SELECT DEPT_ID, DEPT_NAME, PARENT_ID, ORDER_NUM, DEPT_TYPE, LEADER, PHONE, STATUS, DEPT_CODE FROM CSICZB_ZB.SYS_DEPT WHERE (DEL_FLAG = '0' OR DEL_FLAG IS NULL) ORDER BY ORDER_NUM, DEPT_ID",
+ "SELECT d.DEPT_ID, d.DEPT_NAME, d.PARENT_ID, d.ORDER_NUM, d.DEPT_TYPE, d.LEADER, d.PHONE, d.STATUS, d.DEPT_CODE, "
+ + "e.RESPONSIBLE_X_NO, CASE WHEN e.DEPT_ID IS NULL THEN 0 ELSE 1 END AS EXT_CONFIGURED "
+ + "FROM CSICZB_ZB.SYS_DEPT d "
+ + "LEFT JOIN LX.T_SYS_DEPT_EXT e ON e.DEPT_ID = d.DEPT_ID AND (e.DEL_FLAG = 0 OR e.DEL_FLAG IS NULL) "
+ + "WHERE (d.DEL_FLAG = '0' OR d.DEL_FLAG IS NULL) ORDER BY d.ORDER_NUM, d.DEPT_ID",
(rs, rowNum) -> {
Map<String, Object> row = new LinkedHashMap<>();
row.put("id", String.valueOf(rs.getLong("DEPT_ID")));
@@ -688,10 +699,145 @@
row.put("phone", rs.getString("PHONE"));
row.put("status", rs.getString("STATUS"));
row.put("deptCode", rs.getString("DEPT_CODE"));
+ row.put("responsibleXNo", rs.getString("RESPONSIBLE_X_NO"));
+ row.put("extConfigured", rs.getInt("EXT_CONFIGURED") == 1);
return row;
});
}
+ public Map<String, Object> deptExt(Long deptId) {
+ List<Map<String, Object>> rows = jdbcTemplate.query(
+ "SELECT d.DEPT_NAME, e.RESPONSIBLE_X_NO FROM CSICZB_ZB.SYS_DEPT d "
+ + "LEFT JOIN LX.T_SYS_DEPT_EXT e ON e.DEPT_ID = d.DEPT_ID AND (e.DEL_FLAG = 0 OR e.DEL_FLAG IS NULL) "
+ + "WHERE d.DEPT_ID = ? AND (d.DEL_FLAG = '0' OR d.DEL_FLAG IS NULL)",
+ new Object[]{deptId}, (rs, rowNum) -> {
+ Map<String, Object> row = new LinkedHashMap<>();
+ row.put("deptId", String.valueOf(deptId));
+ row.put("deptName", rs.getString("DEPT_NAME"));
+ row.put("responsibleXNo", rs.getString("RESPONSIBLE_X_NO"));
+ row.put("configured", StringUtils.hasText(rs.getString("RESPONSIBLE_X_NO")));
+ return row;
+ });
+ if (rows.isEmpty()) {
+ throw new BusinessException("閮ㄩ棬涓嶅瓨鍦�");
+ }
+ return rows.get(0);
+ }
+
+ @Transactional
+ public void saveDeptExt(Long deptId, String responsibleXNo) {
+ assertExternalDept(deptId);
+ String xNo = normalizeExtValue(responsibleXNo);
+ assertKnownXNo(xNo);
+ String username = CurrentUserContext.get();
+ LocalDateTime now = LocalDateTime.now();
+ int delFlag = xNo == null ? 1 : 0;
+ int updated = jdbcTemplate.update(
+ "UPDATE LX.T_SYS_DEPT_EXT SET RESPONSIBLE_X_NO = ?, DEL_FLAG = ?, UPDATE_BY = ?, UPDATE_TIME = ? WHERE DEPT_ID = ?",
+ xNo, delFlag, username, now, deptId);
+ if (updated == 0) {
+ jdbcTemplate.update(
+ "INSERT INTO LX.T_SYS_DEPT_EXT (DEPT_ID, RESPONSIBLE_X_NO, CREATE_BY, UPDATE_BY, DEL_FLAG, CREATE_TIME, UPDATE_TIME) VALUES (?, ?, ?, ?, ?, ?, ?)",
+ deptId, xNo, username, username, delFlag, now, now);
+ }
+ }
+
+ public Map<String, Object> userExt(Long userId) {
+ List<Map<String, Object>> rows = jdbcTemplate.query(
+ "SELECT u.USER_NAME, u.NICK_NAME, e.ENGINEERING_MAJOR, e.TEAM_MAJOR, e.RESPONSIBLE_X_NO "
+ + "FROM CSICZB_ZB.SYS_USER u "
+ + "LEFT JOIN LX.T_SYS_USER_EXT e ON e.USER_ID = u.USER_ID AND (e.DEL_FLAG = 0 OR e.DEL_FLAG IS NULL) "
+ + "WHERE u.USER_ID = ? AND (u.DEL_FLAG = '0' OR u.DEL_FLAG IS NULL)",
+ new Object[]{userId}, (rs, rowNum) -> {
+ Map<String, Object> row = new LinkedHashMap<>();
+ row.put("userId", String.valueOf(userId));
+ row.put("userName", rs.getString("USER_NAME"));
+ row.put("nickName", rs.getString("NICK_NAME"));
+ row.put("engineeringMajor", rs.getString("ENGINEERING_MAJOR"));
+ row.put("teamMajor", rs.getString("TEAM_MAJOR"));
+ row.put("responsibleXNo", rs.getString("RESPONSIBLE_X_NO"));
+ boolean configured = StringUtils.hasText(rs.getString("ENGINEERING_MAJOR"))
+ || StringUtils.hasText(rs.getString("TEAM_MAJOR"))
+ || StringUtils.hasText(rs.getString("RESPONSIBLE_X_NO"));
+ row.put("configured", configured);
+ return row;
+ });
+ if (rows.isEmpty()) {
+ throw new BusinessException("鐢ㄦ埛涓嶅瓨鍦�");
+ }
+ return rows.get(0);
+ }
+
+ @Transactional
+ public void saveUserExt(Long userId, String engineeringMajor, String teamMajor, String responsibleXNo) {
+ assertExternalUser(userId);
+ String engineering = normalizeExtValue(engineeringMajor);
+ String team = normalizeExtValue(teamMajor);
+ String xNo = normalizeExtValue(responsibleXNo);
+ assertKnownEngineeringMajor(engineering);
+ assertKnownTeamMajor(team);
+ assertKnownXNo(xNo);
+ boolean configured = engineering != null || team != null || xNo != null;
+ String username = CurrentUserContext.get();
+ LocalDateTime now = LocalDateTime.now();
+ int updated = jdbcTemplate.update(
+ "UPDATE LX.T_SYS_USER_EXT SET ENGINEERING_MAJOR = ?, TEAM_MAJOR = ?, RESPONSIBLE_X_NO = ?, DEL_FLAG = ?, UPDATE_BY = ?, UPDATE_TIME = ? WHERE USER_ID = ?",
+ engineering, team, xNo, configured ? 0 : 1, username, now, userId);
+ if (updated == 0) {
+ jdbcTemplate.update(
+ "INSERT INTO LX.T_SYS_USER_EXT (USER_ID, ENGINEERING_MAJOR, TEAM_MAJOR, RESPONSIBLE_X_NO, CREATE_BY, UPDATE_BY, DEL_FLAG, CREATE_TIME, UPDATE_TIME) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ userId, engineering, team, xNo, username, username, configured ? 0 : 1, now, now);
+ }
+ }
+
+ private void assertExternalDept(Long deptId) {
+ if (deptId == null) {
+ throw new BusinessException("璇烽�夋嫨閮ㄩ棬");
+ }
+ Integer count = jdbcTemplate.queryForObject(
+ "SELECT COUNT(*) FROM CSICZB_ZB.SYS_DEPT WHERE DEPT_ID = ? AND (DEL_FLAG = '0' OR DEL_FLAG IS NULL)",
+ Integer.class, deptId);
+ if (count == null || count == 0) {
+ throw new BusinessException("閮ㄩ棬涓嶅瓨鍦�");
+ }
+ }
+
+ private void assertExternalUser(Long userId) {
+ if (userId == null) {
+ throw new BusinessException("璇烽�夋嫨鐢ㄦ埛");
+ }
+ Integer count = jdbcTemplate.queryForObject(
+ "SELECT COUNT(*) FROM CSICZB_ZB.SYS_USER WHERE USER_ID = ? AND (DEL_FLAG = '0' OR DEL_FLAG IS NULL)",
+ Integer.class, userId);
+ if (count == null || count == 0) {
+ throw new BusinessException("鐢ㄦ埛涓嶅瓨鍦�");
+ }
+ }
+
+ private void assertKnownXNo(String xNo) {
+ if (xNo != null && !productXNumbers().contains(xNo)) {
+ throw new BusinessException("rk_X鍙峰繀椤讳粠浜у搧缁撴瀯鏍戠殑side鑺傜偣涓�夋嫨");
+ }
+ }
+
+ private void assertKnownEngineeringMajor(String value) {
+ if (value != null && listEngineeringMajors().stream().map(EngineeringMajor::getName)
+ .filter(StringUtils::hasText).noneMatch(item -> value.equals(item.trim()))) {
+ throw new BusinessException("宸ョ▼涓撲笟涓嶅湪鍙�夎寖鍥村唴");
+ }
+ }
+
+ private void assertKnownTeamMajor(String value) {
+ if (value != null && listTeamMajors().stream().map(TeamMajor::getName)
+ .filter(StringUtils::hasText).noneMatch(item -> value.equals(item.trim()))) {
+ throw new BusinessException("rk_T闃熶笓涓氫笉鍦ㄥ彲閫夎寖鍥村唴");
+ }
+ }
+
+ private String normalizeExtValue(String value) {
+ return StringUtils.hasText(value) ? value.trim() : null;
+ }
+
public List<String> userRoleIds(Long userId) {
if (userId == null) {
return new ArrayList<>();
diff --git a/emergency-repair-web/src/views/Login.vue b/emergency-repair-web/src/views/Login.vue
index a12939a..6e4b37f 100644
--- a/emergency-repair-web/src/views/Login.vue
+++ b/emergency-repair-web/src/views/Login.vue
@@ -48,6 +48,12 @@
sessionStorage.setItem('username', res.data.username)
sessionStorage.setItem('realName', res.data.realName)
sessionStorage.setItem('deptName', res.data.deptName || '')
+ sessionStorage.setItem('userId', res.data.userId || '')
+ sessionStorage.setItem('deptId', res.data.deptId || '')
+ sessionStorage.setItem('engineeringMajor', res.data.engineeringMajor || '')
+ sessionStorage.setItem('teamMajor', res.data.teamMajor || '')
+ sessionStorage.setItem('deptResponsibleXNo', res.data.deptResponsibleXNo || '')
+ sessionStorage.setItem('responsibleXNo', res.data.responsibleXNo || '')
sessionStorage.setItem('roles', JSON.stringify(res.data.roles || []))
sessionStorage.setItem('permissions', JSON.stringify(res.data.permissions || []))
this.$router.push('/dashboard')
diff --git a/emergency-repair-web/src/views/fault/FaultReport.vue b/emergency-repair-web/src/views/fault/FaultReport.vue
index 3b06b6b..778314b 100644
--- a/emergency-repair-web/src/views/fault/FaultReport.vue
+++ b/emergency-repair-web/src/views/fault/FaultReport.vue
@@ -193,22 +193,24 @@
taskMeta(value) { return statusMeta(taskStatuses, value) },
yesNo(value) { return Number(value) === 1 ? '\u662f' : '\u5426' },
loadAccountInfo() {
- if (sessionStorage.getItem('deptName') !== null) return
- api.get('/auth/me').then(res => {
+ return api.get('/auth/me').then(res => {
const info = res.data || {}
sessionStorage.setItem('realName', info.realName || sessionStorage.getItem('realName') || '')
sessionStorage.setItem('deptName', info.deptName || '')
- if (this.form && !this.form.id && !this.form.reportUnit) this.form.reportUnit = info.deptName || ''
+ sessionStorage.setItem('userId', info.userId || '')
+ sessionStorage.setItem('deptId', info.deptId || '')
+ sessionStorage.setItem('engineeringMajor', info.engineeringMajor || '')
+ sessionStorage.setItem('teamMajor', info.teamMajor || '')
+ sessionStorage.setItem('deptResponsibleXNo', info.deptResponsibleXNo || '')
+ sessionStorage.setItem('responsibleXNo', info.responsibleXNo || '')
})
},
loadMajors() {
api.get('/system/team-majors').then(res => {
this.teamMajors = res.data || []
- if (!this.form.teamMajor && this.teamMajors.length) this.form.teamMajor = this.teamMajors[0].name
})
api.get('/system/engineering-majors').then(res => {
this.engineeringMajors = res.data || []
- if (!this.form.engineeringMajor && this.engineeringMajors.length) this.form.engineeringMajor = this.engineeringMajors[0].name
})
},
loadXNumbers() {
@@ -270,10 +272,10 @@
faultCode: '',
reportUnit: sessionStorage.getItem('deptName') || '',
reportDate: today,
- xNo: '',
- owner: sessionStorage.getItem('realName') || 'rk_T鍛�',
- teamMajor: (this.teamMajors[0] || {}).name || '',
- engineeringMajor: (this.engineeringMajors[0] || {}).name || '',
+ xNo: sessionStorage.getItem('deptResponsibleXNo') || '',
+ owner: sessionStorage.getItem('realName') || '',
+ teamMajor: sessionStorage.getItem('teamMajor') || '',
+ engineeringMajor: sessionStorage.getItem('engineeringMajor') || '',
equipmentIds: '',
equipmentName: '',
parentSystem: '',
@@ -290,7 +292,10 @@
remark: ''
}
},
- openCreate() {
+ async openCreate() {
+ try {
+ await this.loadAccountInfo()
+ } catch (e) {}
this.form = this.blankForm()
this.dialogVisible = true
},
diff --git a/emergency-repair-web/src/views/system/OrganizationManage.vue b/emergency-repair-web/src/views/system/OrganizationManage.vue
index 519eb3c..0b455e3 100644
--- a/emergency-repair-web/src/views/system/OrganizationManage.vue
+++ b/emergency-repair-web/src/views/system/OrganizationManage.vue
@@ -39,14 +39,40 @@
</el-table-column>
<el-table-column prop="leader" label="璐熻矗浜�" width="120"></el-table-column>
<el-table-column prop="phone" label="鑱旂郴鐢佃瘽" width="150"></el-table-column>
+ <el-table-column prop="responsibleXNo" label="璐熻矗rk_T" width="110" align="center">
+ <template slot-scope="{ row }">
+ <el-tag v-if="row.responsibleXNo" size="mini" type="success">{{ row.responsibleXNo }}</el-tag>
+ <span v-else class="muted">鏈缃�</span>
+ </template>
+ </el-table-column>
<el-table-column prop="orderNum" label="鎺掑簭" width="80" align="center"></el-table-column>
<el-table-column label="鐘舵��" width="90" align="center">
<template slot-scope="{ row }">
<el-tag size="mini" :type="row.status === '1' ? 'info' : 'success'">{{ row.status === '1' ? '鍋滅敤' : '姝e父' }}</el-tag>
</template>
</el-table-column>
+ <el-table-column label="鎿嶄綔" width="120" align="center" fixed="right">
+ <template slot-scope="{ row }">
+ <el-button type="text" icon="el-icon-setting" v-permission="'system:organization:ext'" @click="openExt(row)">鎵╁睍灞炴��</el-button>
+ </template>
+ </el-table-column>
</el-table>
</div>
+
+ <el-dialog :title="'鎵╁睍灞炴�ц缃� - ' + (currentDept.name || '')" :visible.sync="extVisible" width="520px" append-to-body :close-on-click-modal="false">
+ <el-form label-width="105px" v-loading="extLoading">
+ <el-form-item label="璐熻矗rk_T">
+ <el-select v-model="extForm.responsibleXNo" clearable filterable placeholder="璇烽�夋嫨rk_X鍙�" style="width:100%">
+ <el-option v-for="item in xNumbers" :key="item" :label="item" :value="item"></el-option>
+ </el-select>
+ <div class="field-tip">璇ュ�兼柊澧炴晠闅滄椂浣滀负rk_X鍙烽粯璁ゅ�硷紝浠ラ儴闂ㄨ缃负鍑嗐��</div>
+ </el-form-item>
+ </el-form>
+ <template slot="footer">
+ <el-button @click="extVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" :loading="extSaving" @click="saveExt">淇濆瓨</el-button>
+ </template>
+ </el-dialog>
</div>
</template>
<script>
@@ -58,7 +84,13 @@
loading: false,
rows: [],
keyword: '',
- deptType: ''
+ deptType: '',
+ extVisible: false,
+ extLoading: false,
+ extSaving: false,
+ currentDept: {},
+ extForm: { responsibleXNo: '' },
+ xNumbers: []
}
},
computed: {
@@ -91,13 +123,35 @@
return walk(this.tree)
}
},
- created() { this.load() },
+ created() { this.load(); this.loadXNumbers() },
methods: {
load() {
this.loading = true
api.get('/system/depts').then(res => {
this.rows = res.data || []
}).finally(() => { this.loading = false })
+ },
+ loadXNumbers() {
+ api.get('/system/tree/product/x-numbers').then(res => { this.xNumbers = res.data || [] })
+ },
+ openExt(row) {
+ this.currentDept = { ...row }
+ this.extForm = { responsibleXNo: row.responsibleXNo || '' }
+ this.extVisible = true
+ this.extLoading = true
+ api.get('/system/depts/' + row.id + '/ext').then(res => {
+ const data = res.data || {}
+ this.extForm = { responsibleXNo: data.responsibleXNo || '' }
+ }).finally(() => { this.extLoading = false })
+ },
+ saveExt() {
+ if (!this.currentDept.id) return
+ this.extSaving = true
+ api.put('/system/depts/' + this.currentDept.id + '/ext', this.extForm).then(() => {
+ this.$message.success('鎵╁睍灞炴�ц缃垚鍔�')
+ this.extVisible = false
+ this.load()
+ }).finally(() => { this.extSaving = false })
},
buildTree(rows) {
const nodes = rows.map(row => ({ ...row, children: [] }))
@@ -124,4 +178,6 @@
</script>
<style scoped>
.summary { color: #6d7f91; font-size: 13px; }
+.muted { color: #a3afbc; font-size: 12px; }
+.field-tip { margin-top: 4px; color: #7b8a99; font-size: 12px; line-height: 18px; }
</style>
diff --git a/emergency-repair-web/src/views/system/UserManage.vue b/emergency-repair-web/src/views/system/UserManage.vue
index 2e3c9a5..0cc4acf 100644
--- a/emergency-repair-web/src/views/system/UserManage.vue
+++ b/emergency-repair-web/src/views/system/UserManage.vue
@@ -39,6 +39,11 @@
</template>
</el-table-column>
<el-table-column prop="phoneNumber" label="鎵嬫満鍙�" width="130"></el-table-column>
+ <el-table-column label="鎵╁睍灞炴��" width="100" align="center">
+ <template slot-scope="{ row }">
+ <el-button type="text" v-permission="'system:users:ext'" @click="openExt(row)">{{ row.extConfigured ? '缂栬緫' : '璁剧疆' }}</el-button>
+ </template>
+ </el-table-column>
<el-table-column label="鐘舵��" width="80" align="center">
<template slot-scope="{ row }">
<el-tag size="mini" :type="isDisabled(row) ? 'info' : 'success'">{{ isDisabled(row) ? '鍋滅敤' : '姝e父' }}</el-tag>
@@ -99,6 +104,29 @@
<el-button type="primary" :loading="batchSaving" v-permission="'system:users:assign'" @click="saveBatchRoles">淇濆瓨</el-button>
</span>
</el-dialog>
+ <el-dialog :title="'鐢ㄦ埛鎵╁睍灞炴�ц缃� - ' + ((currentExtUser.nickName || currentExtUser.userName) || '')" :visible.sync="extVisible" width="560px" append-to-body :close-on-click-modal="false">
+ <el-form label-width="105px" v-loading="extLoading">
+ <el-form-item label="宸ョ▼涓撲笟">
+ <el-select v-model="extForm.engineeringMajor" clearable filterable placeholder="璇烽�夋嫨宸ョ▼涓撲笟" style="width:100%">
+ <el-option v-for="item in engineeringMajors" :key="item.id" :label="item.name" :value="item.name"></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="rk_T闃熶笓涓�">
+ <el-select v-model="extForm.teamMajor" clearable filterable placeholder="璇烽�夋嫨rk_T闃熶笓涓�" style="width:100%">
+ <el-option v-for="item in teamMajors" :key="item.id" :label="item.name" :value="item.name"></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="璐熻矗rk_T">
+ <el-select v-model="extForm.responsibleXNo" clearable filterable placeholder="璇烽�夋嫨rk_X鍙�" style="width:100%">
+ <el-option v-for="item in xNumbers" :key="item" :label="item" :value="item"></el-option>
+ </el-select>
+ </el-form-item>
+ </el-form>
+ <template slot="footer">
+ <el-button @click="extVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" :loading="extSaving" @click="saveExt">淇濆瓨</el-button>
+ </template>
+ </el-dialog>
</div>
</template>
<script>
@@ -122,12 +150,21 @@
roles: [],
selected: null,
checkedRoleIds: [],
+ extVisible: false,
+ extLoading: false,
+ extSaving: false,
+ currentExtUser: {},
+ extForm: { engineeringMajor: '', teamMajor: '', responsibleXNo: '' },
+ engineeringMajors: [],
+ teamMajors: [],
+ xNumbers: [],
filters: { keyword: '', deptId: null, roleId: null }
}
},
created() {
this.loadRoles()
this.loadDepts()
+ this.loadExtOptions()
this.load()
},
methods: {
@@ -159,6 +196,34 @@
loadDepts() {
api.get('/system/depts').then(res => { this.depts = res.data || [] })
},
+ loadExtOptions() {
+ api.get('/system/engineering-majors').then(res => { this.engineeringMajors = res.data || [] })
+ api.get('/system/team-majors').then(res => { this.teamMajors = res.data || [] })
+ api.get('/system/tree/product/x-numbers').then(res => { this.xNumbers = res.data || [] })
+ },
+ openExt(row) {
+ this.currentExtUser = { ...row }
+ this.extForm = { engineeringMajor: '', teamMajor: '', responsibleXNo: '' }
+ this.extVisible = true
+ this.extLoading = true
+ api.get('/system/users/' + row.userId + '/ext').then(res => {
+ const data = res.data || {}
+ this.extForm = {
+ engineeringMajor: data.engineeringMajor || '',
+ teamMajor: data.teamMajor || '',
+ responsibleXNo: data.responsibleXNo || ''
+ }
+ }).finally(() => { this.extLoading = false })
+ },
+ saveExt() {
+ if (!this.currentExtUser.userId) return
+ this.extSaving = true
+ api.put('/system/users/' + this.currentExtUser.userId + '/ext', this.extForm).then(() => {
+ this.$message.success('鎵╁睍灞炴�ц缃垚鍔�')
+ this.extVisible = false
+ this.load()
+ }).finally(() => { this.extSaving = false })
+ },
search() {
this.current = 1
this.load()
diff --git "a/requirement/\344\272\244\346\216\245\346\226\207\344\273\266_2026.10.3.md" "b/requirement/\344\272\244\346\216\245\346\226\207\344\273\266_2026.10.3.md"
index fc0995c..b1698db 100644
--- "a/requirement/\344\272\244\346\216\245\346\226\207\344\273\266_2026.10.3.md"
+++ "b/requirement/\344\272\244\346\216\245\346\226\207\344\273\266_2026.10.3.md"
@@ -735,3 +735,57 @@
- 娓呯┖鍓嶏細鏁呴殰 `23`銆佹淳宸ュ崟 `8`銆佸畬宸ヤ俊鎭� `6`銆侀獙鏀� `6`锛涙竻绌哄悗鍧� `0`銆�
- 鍚庣 `mvn -B -DskipTests clean package` 閫氳繃锛涙柊 jar 閲嶅惎鍚庡洓琛ㄤ粛鍧囦负 `0`銆�
- 褰撳墠鍚庣 PID `21528`锛岀洃鍚� `8091`锛涘墠绔� PID `57312`锛岀洃鍚� `8082`锛涘悗绔敊璇棩蹇椾负绌恒��
+
+## 浜屽崄銆�2026-10-07 鑱旇皟鏀跺熬锛堥渶姹� 28-30锛�
+
+| 搴忓彿 | 闇�姹� | 鐘舵�� | 瀹炵幇涓庨獙璇� |
+| --- | --- | --- | --- |
+| 28 | 缁勭粐鏈烘瀯澧炲姞鎵╁睍灞炴�ц缃紝璁剧疆閮ㄩ棬璐熻矗rk_T | 宸插畬鎴� | 缁勭粐鏈烘瀯鍒楄〃澧炲姞鈥滄墿灞曞睘鎬р�濇寜閽拰寮圭獥锛屼粠浜у搧缁撴瀯鏍� `side` 鑺傜偣涓崟閫� `rk_X鍙穈锛屼繚瀛樺埌 `LX.T_SYS_DEPT_EXT`锛屼笉淇敼澶栭儴 `SYS_DEPT` |
+| 29 | 鐢ㄦ埛绠$悊澧炲姞鎵╁睍灞炴�ц缃� | 宸插畬鎴� | 鍙缃伐绋嬩笓涓氥�乺k_T闃熶笓涓氥�佽礋璐k_T锛屼繚瀛樺埌 `LX.T_SYS_USER_EXT`锛屼笉淇敼澶栭儴 `SYS_USER`锛況k_TD涓撲笟涓庣幇鏈� `teamMajor` 涓哄悓涓�瀛楁 |
+| 30 | 鏂板鏁呴殰榛樿鍊� | 宸插畬鎴� | 涓婃姤鍗曚綅鍙栫櫥褰曠敤鎴峰崟浣嶏紝璐熻矗浜哄彇鐧诲綍鐢ㄦ埛锛宍rk_X鍙穈鍙彇閮ㄩ棬鎵╁睍灞炴�э紝宸ョ▼涓撲笟鍜宺k_T闃熶笓涓氬彇鐢ㄦ埛鎵╁睍灞炴�э紱鏈厤缃椂鐣欑┖锛屼笉鍐嶅彇鍒楄〃绗竴椤� |
+
+### 20.1 纭鍙e緞
+
+- 闇�姹� 30 缂栧彿姝g‘锛涙柊澧炴晠闅滈噷鐨勨�滆矗浠烩�濆氨鏄�滆礋璐d汉鈥濄��
+- 閮ㄩ棬鎵╁睍灞炴�р�滆礋璐k_T鈥濆氨鏄� `rk_X鍙穈锛屽崟閫夛紱鏂板鏁呴殰鐨� `rk_X鍙穈 鍙互閮ㄩ棬璁剧疆涓哄噯锛屽嵆浣跨敤鎴蜂篃璁剧疆浜嗏�滆礋璐k_T鈥濅篃涓嶅弬涓庤榛樿鍊笺��
+- `rk_TD涓撲笟`灏辨槸鐜版湁椤甸潰閲岀殑鈥渞k_T闃熶笓涓氣�濓紝鍚庣画鏆傜粺涓�娌跨敤鐜版湁鏄剧ず锛屽瓧娈典负 `teamMajor`銆�
+- 澶栭儴 `CSICZB_ZB.SYS_DEPT`銆乣CSICZB_ZB.SYS_USER` 鐢卞叾浠栫郴缁熺淮鎶わ紝鎵╁睍灞炴�у潎瀛樻湰鍦版墿灞曡〃銆�
+
+### 20.2 鎺ュ彛涓庢暟鎹〃
+
+- `LX.T_SYS_DEPT_EXT`锛歚DEPT_ID`銆乣RESPONSIBLE_X_NO`銆佸璁″瓧娈点��
+- `LX.T_SYS_USER_EXT`锛歚USER_ID`銆乣ENGINEERING_MAJOR`銆乣TEAM_MAJOR`銆乣RESPONSIBLE_X_NO`銆佸璁″瓧娈点��
+- `GET/PUT /api/system/depts/{deptId}/ext`锛氭煡璇€�佷繚瀛橀儴闂ㄦ墿灞曞睘鎬с��
+- `GET/PUT /api/system/users/{userId}/ext`锛氭煡璇€�佷繚瀛樼敤鎴锋墿灞曞睘鎬с��
+- `/api/auth/login`銆乣/api/auth/me`杩斿洖鐢ㄦ埛銆侀儴闂ㄥ拰涓撲笟鎵╁睍淇℃伅锛屼緵鏂板鏁呴殰榛樿鍊间娇鐢ㄣ��
+- 鏂板鎸夐挳鏉冮檺 `system:organization:ext`銆乣system:users:ext`銆�
+
+### 20.3 涓昏鍙樻洿鏂囦欢
+
+- `emergency-repair-server/src/main/java/com/emergencyrepair/auth/AuthController.java`
+- `emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DatabaseBootstrap.java`
+- `emergency-repair-server/src/main/java/com/emergencyrepair/business/dto/Requests.java`
+- `emergency-repair-server/src/main/java/com/emergencyrepair/system/controller/SystemController.java`
+- `emergency-repair-server/src/main/java/com/emergencyrepair/system/service/ButtonPermissionCatalog.java`
+- `emergency-repair-server/src/main/java/com/emergencyrepair/system/service/SystemService.java`
+- `emergency-repair-web/src/views/Login.vue`
+- `emergency-repair-web/src/views/fault/FaultReport.vue`
+- `emergency-repair-web/src/views/system/OrganizationManage.vue`
+- `emergency-repair-web/src/views/system/UserManage.vue`
+- `requirement/鏀硅繘20261003.txt`銆乣HANDOFF.md`锛堣ˉ鍏呴渶姹� 28-30 鍜屼氦鎺ヨ褰曪級
+
+### 20.4 楠岃瘉缁撴灉
+
+- 鍚庣 `mvn -B -DskipTests clean package` 閫氳繃锛涘墠绔� `npm run build` 閫氳繃锛屼粎鏈夋棦鏈夊寘浣撶Н鍛婅銆�
+- `node .codex-run/verify-req28-30.js` 杩斿洖 `pass: true`銆�
+- 閮ㄩ棬 `sy鍖哄煙` 璁剧疆 `rk_X鍙�=201`锛涚敤鎴� `yszl` 璁剧疆宸ョ▼涓撲笟 `鍔ㄥ姏涓撲笟`銆乺k_T闃熶笓涓� `娑插帇涓撲笟`銆佽礋璐� `202`銆�
+- 鏂板鏁呴殰榛樿鍊煎疄娴嬶細涓婃姤鍗曚綅 `sy鍖哄煙`銆佽礋璐d汉 `鍔╃悊鐢ㄦ埛锛堟紨绀猴級`銆乣rk_X鍙�=201`銆乺k_T闃熶笓涓� `娑插帇涓撲笟`銆佸伐绋嬩笓涓� `鍔ㄥ姏涓撲笟`銆�
+- 鎴浘锛歚.codex-run/req28-org-ext.png`銆乣.codex-run/req29-user-ext.png`銆乣.codex-run/req30-fault-defaults.png`銆�
+- 楠岃瘉鍚庡凡娓呯┖涓存椂鎵╁睍灞炴�э紝鏌ヨ纭 `configured=false` 涓斿瓧娈典负绌恒��
+
+### 20.5 鎺ユ墜娉ㄦ剰
+
+- 褰撳墠鍚庣 PID `56124`锛岀洃鍚� `http://127.0.0.1:8091`锛涘墠绔� PID `57312`锛岀洃鍚� `http://localhost:8082`锛汥M8 `127.0.0.1:5236`锛汦dge CDP `9222`銆傜櫥褰� `admin / admin123`銆�
+- 寮�鍙戠幆澧冩晱鎰熻瘝浼氭妸 `rk_T` 鏄剧ず鎴愨�滄鈥濓紝鎴浘涓殑鈥滆礋璐f鈥濆搴斾唬鐮�/鍚庣瀛楁 `rk_T`銆�
+- `.codex-run`銆丱ffice 閿佹枃浠跺強 `emergency-repair-web/public/鏂板缓 鏂囨湰鏂囨。.txt` 浠嶄负鏈湴涓存椂鏂囦欢锛屼笉搴旀彁浜ゃ��
+- 鏈疆浠g爜銆侀渶姹傛枃浠跺拰浜ゆ帴璁板綍涓�骞舵彁浜ゅ苟鎺ㄩ�佸叕鍙� Git 浠撳簱 `main` 鍒嗘敮銆�
diff --git "a/requirement/\346\224\271\350\277\23320261003.txt" "b/requirement/\346\224\271\350\277\23320261003.txt"
index ea44d46..c22cfd3 100644
--- "a/requirement/\346\224\271\350\277\23320261003.txt"
+++ "b/requirement/\346\224\271\350\277\23320261003.txt"
@@ -40,3 +40,13 @@
26銆佹棩蹇楃鐞嗙殑鏃ユ湡缁勪欢2涓棩鏈熶腑闂撮偅涓�滆嚦鈥濇樉绀轰笉瀹屾暣
27銆佹柊澧炴晠闅滈偅閲岄�変簡rk_X鍙凤紙瀵瑰簲浜у搧缁撴瀯鏍戠殑side绫诲瀷锛夊悗锛屽啀閫夎澶囩殑鏃跺�欒繕鏄樉绀烘暣涓骇鍝佺粨鏋勬爲锛屽簲璇ユ樉绀洪攣閫夎妭鐐圭殑涓嬬骇鑺傜偣
+28锛岀粍缁囨満鏋勶紙閮ㄩ棬鏍戣〃锛夛紝澧炲姞鎵╁睍灞炴�ц缃紝鐩墠涓昏鍖呮嫭璐熻矗rk_T
+29锛岀敤鎴风鐞嗭紝澧炲姞鎵╁睍灞炴�ц缃紝鐩墠涓昏鏈夊伐绋嬩笓涓氥�乺k_TD涓撲笟锛岃礋璐k_T
+30銆佹柊澧炴晠闅滐紝榛樿鍊硷紝鏁呴殰涓婃姤鍗曚綅榛樿濉啓褰撳墠鐧诲綍浜虹殑鍗曚綅锛岃矗浠婚粯璁ゅ~鍐欏綋鍓嶇櫥褰曚汉锛宺k_X鍙烽粯璁ゅ~鍐欏綋鍓嶇櫥褰曚汉鐨勫崟浣嶇殑鎵╁紶灞炴�ц礋璐k_T锛屽伐绋嬩笓涓氥�乺k_TD涓撲笟鍒嗗埆涓哄綋鍓嶇敤鎴风殑鎵╁睍灞炴�у伐绋嬩笓涓氥�乺k_TD涓撲笟
+
+
+
+绗笁鏉″簲璇ョ紪鍙蜂负 30 鍚э紵鍙﹀鈥滆矗浠烩�濇槸鍚﹀氨鏄�滆礋璐d汉鈥濓紵鏄殑
+鈥滆礋璐k_T鈥濆叿浣撴槸閫� rk_X鍙凤紝杩樻槸閫夋煇涓粍缁�/涓撲笟锛熷崟閫夎繕鏄閫夛紵濡傛灉閮ㄩ棬鍜岀敤鎴烽兘璁剧疆浜嗭紝rk_X鍙锋槸鍚﹀彧浠ラ儴闂ㄨ缃负鍑嗭紵閫� rk_X鍙凤紝瑕佹眰鎵╁睍灞炴�у拰鏁呴殰琛ㄩ噷瀛樼殑涓�鑷达紝鍗曢�夛紝閫夐儴闂ㄧ殑
+浣犺鐨勨�渞k_TD涓撲笟鈥濇槸鍚﹀氨鏄幇鏈夐〉闈㈤噷鐨勨�渞k_T闃熶笓涓氣�濓紵鍚庣画缁熶竴鏄剧ず鍝竴涓悕绉帮紵鏄殑
+鎵╁睍灞炴�у缓璁柊寤烘湰鍦版墿灞曡〃淇濆瓨锛屼緥濡傞儴闂ㄦ墿灞曡〃鍜岀敤鎴锋墿灞曡〃锛屼笉鐩存帴淇敼澶栭儴鏉ユ簮鐨� SYS_DEPT銆丼YS_USER 琛ㄣ�傛槸鍚︽寜杩欎釜鏂瑰紡瀹炵幇锛熸槸鐨勶紝鍥犱负閭�2涓〃鏄埆鐨勭郴缁熺淮鎶ょ殑
--
Gitblit v1.9.1