From c3b0503f8e2ecf955d0e8e4ca9294e6cd5199c0b Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期四, 27 八月 2026 11:02:30 +0800
Subject: [PATCH] HRM: 员工台账岗位支持多选并同步系统用户岗位
---
docs/hrm_employee_post_multiselect.md | 107 +++++++++++++++++
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/HrmEmployeeController.java | 25 ++-
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeRespVO.java | 8
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserUpdateReqDTO.java | 40 ++++++
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java | 75 +++++++++---
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/employee/HrmEmployeeDO.java | 6
docs/hrm_employee_import.md | 5
sql/mysql/hrm_employee_post_multiselect_deploy.sql | 20 +++
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeSaveReqVO.java | 6
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java | 14 ++
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java | 8 +
sql/mysql/hrm_employee_post_multi.sql | 15 ++
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmOvertimeApplicationServiceImpl.java | 16 ++
13 files changed, 303 insertions(+), 42 deletions(-)
diff --git a/docs/hrm_employee_import.md b/docs/hrm_employee_import.md
index 25fbea1..0f26f8f 100644
--- a/docs/hrm_employee_import.md
+++ b/docs/hrm_employee_import.md
@@ -10,7 +10,7 @@
## 涓氬姟娴佺▼涓庢暟鎹甫鍏�
1. **涓嬭浇妯℃澘** -> 鍓嶇璋冪敤 `GET /hrm/employee/import-template` 涓嬭浇 Excel 妯℃澘锛屾ā鏉垮寘鍚ず渚嬭渚涘弬鑰冦��
-2. **濉啓妯℃澘** -> 鐢ㄦ埛鎸夋ā鏉垮~鍐欏憳宸ヤ俊鎭紝鍏朵腑"閮ㄩ棬鍚嶇О/宀椾綅鍚嶇О/鐢ㄦ埛瑙掕壊"涓夊垪濉�**鍚嶇О**锛堢敤鎴疯鑹插涓敤涓枃閫楀彿鍒嗛殧锛夛紝鐢卞悗绔嚜鍔ㄨ浆鎹负 ID銆�
+2. **濉啓妯℃澘** -> 鐢ㄦ埛鎸夋ā鏉垮~鍐欏憳宸ヤ俊鎭紝鍏朵腑"閮ㄩ棬鍚嶇О/宀椾綅鍚嶇О/鐢ㄦ埛瑙掕壊"涓夊垪濉�**鍚嶇О**锛堝矖浣嶅悕绉般�佺敤鎴疯鑹插涓敤涓枃鎴栬嫳鏂囬�楀彿鍒嗛殧锛夛紝鐢卞悗绔嚜鍔ㄨ浆鎹负 ID銆�
3. **涓婁紶瀵煎叆** -> 鍓嶇璋冪敤 `POST /hrm/employee/import`锛坢ultipart 琛ㄥ崟锛宖ile + updateSupport锛変笂浼犳枃浠躲��
4. **灞曠ず缁撴灉** -> 鍚庣杩斿洖瀵煎叆缁撴灉锛堝垱寤烘垚鍔熷悕鍗� / 鏇存柊鎴愬姛鍚嶅崟 / 澶辫触鍚嶅崟鍙婂師鍥狅級锛屽墠绔�愭潯灞曠ず銆�
@@ -30,6 +30,7 @@
- 鎬у埆锛氬~"鐢�"/"濂�"锛堝瓧鍏� `hrm_gender`锛屽�� 1/2锛�
- 鍛樺伐鐘舵�侊細濉�"鍦ㄨ亴"/"璇曠敤"/"绂昏亴"锛堝瓧鍏� `hrm_employee_status`锛屽�� 1/2/3锛�
+- 宀椾綅鍚嶇О锛氬~宀椾綅鍚嶇О锛�**鏀寔澶氫釜**锛屽涓敤鑻辨枃閫楀彿锛坄,`锛夋垨涓枃閫楀彿锛坄锛宍锛夊垎闅旓紙濡�"閮ㄩ棬缁忕悊,椤圭洰缁忕悊"锛�
- 鐢ㄦ埛瑙掕壊锛氬~瑙掕壊鍚嶇О锛屽涓敤**涓枃閫楀彿**鍒嗛殧锛堝"鏅�氱鐞嗗憳,鏅�氬憳宸�"锛�
### 瀵煎叆鍛樺伐
@@ -75,7 +76,7 @@
| 鎬у埆 | 妯℃澘鍒� | 蹇呭~锛岄粯璁ょ敺 |
| 鎵嬫満鍙� | 妯℃澘鍒� | 蹇呭~锛屽皢浣滀负绯荤粺鐧诲綍璐﹀彿 |
| 閮ㄩ棬鍚嶇О | 妯℃澘鍒� | 蹇呭~锛屽~鍚嶇О锛屽悗绔浆 ID |
-| 宀椾綅鍚嶇О | 妯℃澘鍒� | 蹇呭~锛屽~鍚嶇О锛屽悗绔浆 ID |
+| 宀椾綅鍚嶇О | 妯℃澘鍒� | 蹇呭~锛屽~鍚嶇О锛屾敮鎸佸涓紙鐢ㄩ�楀彿鍒嗛殧锛夛紝鍚庣杞� ID |
| 鐢ㄦ埛瑙掕壊 | 妯℃澘鍒� | 閫夊~锛屽~鍚嶇О锛屽涓敤涓枃閫楀彿鍒嗛殧 |
| 鍏ヨ亴鏃ユ湡 | 妯℃澘鍒� | 蹇呭~锛屾牸寮� YYYY-MM-DD |
| 鍛樺伐鐘舵�� | 妯℃澘鍒� | 蹇呭~锛岄粯璁ゅ湪鑱� |
diff --git a/docs/hrm_employee_post_multiselect.md b/docs/hrm_employee_post_multiselect.md
new file mode 100644
index 0000000..b643e66
--- /dev/null
+++ b/docs/hrm_employee_post_multiselect.md
@@ -0,0 +1,107 @@
+# 鍛樺伐鍙拌处宀椾綅澶氶�� - 鍓嶇鑱旇皟鏂规
+
+## 鑳屾櫙
+
+浜哄姏璧勬簮 > 鍛樺伐绠$悊锛堝憳宸ュ彴璐︼級鐨�"宀椾綅"鐢卞崟閫夋敼涓�**澶氶��**锛屼笌绯荤粺"鐢ㄦ埛绠$悊"鐨勫宀椾綅鑳藉姏淇濇寔涓�鑷淬�傚瓨鍌ㄤ笂閲囩敤 JSON 鏁扮粍锛坄post_ids` 鍒楋級锛屽悓"瑙掕壊"瀛楁鐨勬棦鏈夋ā寮忋��
+
+## 娑夊強椤甸潰
+
+- 浜哄姏璧勬簮 > 鍛樺伐绠$悊 鍒楄〃椤碉紙`src/views/hrm/employee/index.vue`锛�
+- 鍛樺伐鏂板/缂栬緫琛ㄥ崟锛坄src/views/hrm/employee/modules/form.vue`銆乣data.ts`锛�
+- 鍛樺伐璇︽儏锛坄src/views/hrm/employee/modules/detail.vue`锛�
+- 鍛樺伐瀵煎叆寮圭獥锛堝惈涓嬭浇妯℃澘銆佷笂浼犳枃浠讹級
+- 鍛樺伐瀵煎嚭 Excel
+
+## API 鍙樻洿璇存槑
+
+| 鏂规硶 | 璺緞 | 鍙樻洿 |
+|------|------|------|
+| POST | `/hrm/employee/create` | 璇锋眰瀛楁 `postId` 鈫� `postIds`锛堟暟缁勶級 |
+| PUT | `/hrm/employee/update` | 璇锋眰瀛楁 `postId` 鈫� `postIds`锛堟暟缁勶級 |
+| GET | `/hrm/employee/get` | 鍝嶅簲瀛楁 `postId/postName` 鈫� `postIds/postNames` |
+| GET | `/hrm/employee/page` | 鍝嶅簲瀛楁 `postId/postName` 鈫� `postIds/postNames` |
+| GET | `/hrm/employee/export-excel` | "宀椾綅鍚嶇О"鍒楁敮鎸佸鍊硷紙閫楀彿鎷兼帴锛� |
+| GET | `/hrm/employee/import-template` | "宀椾綅鍚嶇О"鍒楃ず渚嬫敼涓哄宀椾綅 |
+| POST | `/hrm/employee/import` | "宀椾綅鍚嶇О"鍒楁敮鎸佸~鍐欏涓矖浣嶅悕 |
+
+### 1. 鏂板鍛樺伐 `POST /hrm/employee/create`
+
+**璇锋眰鍙傛暟锛堝瓧娈靛彉鏇达級锛�**
+
+| 鍙傛暟 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|------|------|------|------|
+| postIds | List\<Long\> | 鏄� | 宀椾綅ID鏁扮粍锛岃嚦灏戜竴涓紙鍘� `postId` 鍗曞�煎瓧娈靛凡绉婚櫎锛� |
+
+```json
+{
+ "name": "寮犱笁",
+ "phone": "13800138000",
+ "deptId": 103,
+ "postIds": [2, 4],
+ "roleIds": [1],
+ "hireDate": "2026-08-01",
+ "employeeStatus": 1,
+ "gender": 1
+}
+```
+
+### 2. 鏇存柊鍛樺伐 `PUT /hrm/employee/update`
+
+鍚� create锛岃姹備綋涓殑 `postIds` 涓哄憳宸ユ渶缁堢殑宀椾綅闆嗗悎锛堝叏閲忚鐩栵紝闈炲閲忥級銆�
+
+### 3. 鍛樺伐璇︽儏 / 鍒嗛〉 `GET /hrm/employee/get`銆乣GET /hrm/employee/page`
+
+**鍝嶅簲瀛楁鍙樻洿锛�**
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| postIds | List\<Long\> | 宀椾綅ID鏁扮粍锛堝師 `postId` 宸茬Щ闄わ級 |
+| postNames | String | 宀椾綅鍚嶇О锛屽涓敤鑻辨枃閫楀彿鎷兼帴锛屽"閮ㄩ棬缁忕悊,椤圭洰缁忕悊"锛堝師 `postName` 宸茬Щ闄わ級 |
+
+```json
+{
+ "code": 0,
+ "data": {
+ "id": 6,
+ "name": "寮犱笁",
+ "deptName": "鐮斿彂閮�",
+ "postIds": [2, 4],
+ "postNames": "閮ㄩ棬缁忕悊,椤圭洰缁忕悊",
+ "roleNames": "鏅�氱鐞嗗憳"
+ }
+}
+```
+
+### 4. 瀵煎嚭 Excel `GET /hrm/employee/export-excel`
+
+- "宀椾綅鍚嶇О"鍒楀睍绀哄涓矖浣嶅悕锛岃嫳鏂囬�楀彿鎷兼帴锛堜笌鍒嗛〉杩斿洖鐨� `postNames` 涓�鑷达級銆�
+
+### 5. 瀵煎叆妯℃澘 / 瀵煎叆 `GET /hrm/employee/import-template`銆乣POST /hrm/employee/import`
+
+- 妯℃澘"宀椾綅鍚嶇О"鍒楃敱鍗曚釜宀椾綅鍚嶆敼涓烘敮鎸�**澶氫釜宀椾綅鍚�**锛屽涓敤**鑻辨枃閫楀彿锛坄,`锛夋垨涓枃閫楀彿锛坄锛宍锛�**鍒嗛殧銆�
+- 妯℃澘绀轰緥琛岋細`閮ㄩ棬缁忕悊,椤圭洰缁忕悊`銆�
+- 浠讳竴宀椾綅鍚嶄笉瀛樺湪锛岃琛屽鍏ュけ璐ワ紝鍘熷洜"宀椾綅銆恱x銆戜笉瀛樺湪"銆�
+- 宀椾綅鍚嶇О鍒椾笉鍏佽涓虹┖锛堝矖浣嶅繀濉級銆�
+
+## 瀛楁灞曠ず瑙勫垯
+
+| 瀛楁 | 灞曠ず浣嶇疆 | 璇存槑 |
+|------|----------|------|
+| postIds | 琛ㄥ崟锛堟柊澧�/缂栬緫锛夈�佽鎯� | 琛ㄥ崟宀椾綅鏀逛负澶氶�変笅鎷夋锛岀紪杈戝洖鏄惧嬀閫夊涓� |
+| postNames | 鍒楄〃銆佽鎯呫�佸鍑� | 灞曠ず涓洪�楀彿鎷兼帴鐨勫涓矖浣嶅悕 |
+
+## 涓氬姟瑙勫垯璇存槑
+
+| 鍦烘櫙 | 瑙勫垯 |
+|------|------|
+| 琛ㄥ崟淇濆瓨 | `postIds` 蹇呭~锛岃嚦灏戜竴涓矖浣� |
+| 缂栬緫淇濆瓨 | `postIds` 鍏ㄩ噺瑕嗙洊璇ュ憳宸ュ矖浣� |
+| 瀵煎叆 | "宀椾綅鍚嶇О"鍒楀涓悕绉扮敤閫楀彿鍒嗛殧锛屼换涓�涓嶅瓨鍦ㄥ垯鏁磋澶辫触 |
+| 宸叉湁鏁版嵁 | 瀛橀噺鍛樺伐鐨勫崟宀椾綅鏁版嵁宸茶縼绉讳负 `postIds`锛岃�佹暟鎹笉涓㈠け |
+
+## 娉ㄦ剰浜嬮」
+
+- **鍓嶇闇�鍚屾淇敼**锛氭柊澧�/缂栬緫琛ㄥ崟鐨勫矖浣嶅瓧娈典粠鍗曢�夋敼涓哄閫変笅鎷夛紝鎻愪氦瀛楁鍚嶄粠 `postId` 鏀逛负 `postIds`锛涘垪琛�/璇︽儏灞曠ず瀛楁浠� `postName` 鏀逛负 `postNames`銆�
+- **缂栬緫鍛樺伐鏃跺悓姝ユ洿鏂�**鍏宠仈绯荤粺鐧诲綍鐢ㄦ埛锛堢敤鎴风鐞嗛〉锛夌殑宀椾綅/閮ㄩ棬/鏄电О/瑙掕壊/閭/澶囨敞锛屼袱杈逛繚鎸佷竴鑷淬��
+- 宀椾綅涓嬫媺鏁版嵁浠嶄粠绯荤粺宀椾綅鎺ュ彛鑾峰彇锛堜笌涔嬪墠涓�鑷达級銆�
+- 宀椾綅鍚嶇О瑙f瀽涓虹簿纭尮閰嶏紝涓嶆敮鎸佹ā绯娿��
diff --git a/sql/mysql/hrm_employee_post_multi.sql b/sql/mysql/hrm_employee_post_multi.sql
new file mode 100644
index 0000000..8e24d60
--- /dev/null
+++ b/sql/mysql/hrm_employee_post_multi.sql
@@ -0,0 +1,15 @@
+-- =============================================
+-- HRM 鍛樺伐琛細宀椾綅澶氶�夋敼閫� SQL
+-- 1. 娣诲姞 post_ids 瀛楁锛圝SON 鏍煎紡锛屼笌 role_ids 瀛樺偍鏂瑰紡涓�鑷达級
+-- 2. 杩佺Щ宸叉湁 post_id 鏁版嵁鍒� post_ids
+-- 3. 淇濈暀 post_id 瀛楁锛堝吋瀹规棫鑴氭湰/澶栭儴寮曠敤锛屽凡搴熷純涓嶅啀鍐欏叆锛�
+-- =============================================
+
+-- 1. 娣诲姞宀椾綅ID鍒楄〃瀛楁锛圝SON鏍煎紡瀛樺偍锛�
+ALTER TABLE `hrm_employee` ADD COLUMN `post_ids` varchar(500) DEFAULT NULL COMMENT '宀椾綅ID鍒楄〃锛圝SON鏍煎紡锛�' AFTER `post_id`;
+
+-- 2. 杩佺Щ宸叉湁 post_id 鏁版嵁鍒� post_ids
+UPDATE `hrm_employee` SET `post_ids` = CONCAT('[', `post_id`, ']') WHERE `post_id` IS NOT NULL AND (`post_ids` IS NULL OR `post_ids` = '');
+
+-- 鎵ц瀹屾垚鎻愮ず
+SELECT 'HRM 鍛樺伐琛ㄥ矖浣嶅閫夋敼閫犲畬鎴愶紒' AS result;
diff --git a/sql/mysql/hrm_employee_post_multiselect_deploy.sql b/sql/mysql/hrm_employee_post_multiselect_deploy.sql
new file mode 100644
index 0000000..786e944
--- /dev/null
+++ b/sql/mysql/hrm_employee_post_multiselect_deploy.sql
@@ -0,0 +1,20 @@
+-- =============================================
+-- HRM 鍛樺伐鍙拌处宀椾綅澶氶�� - 鏁版嵁搴撳彉鏇存眹鎬昏剼鏈�
+-- 閫傜敤锛歵est / prod 绛夐渶瑕佹墜宸ユ墽琛岀殑鐜
+-- 鍖呭惈锛�
+-- 1. hrm_employee 琛ㄦ柊澧炲矖浣岻D鍒楄〃(post_ids)鍒楋紝骞惰縼绉绘棫 post_id 鏁版嵁
+-- 2. hrm_salary_structure 琛ㄦ柊澧炰紤鎭棩/娉曞畾鑺傚亣鏃ュ姞鐝伐璧勫�嶇巼鍒楋紙淇鍛樺伐缂栬緫椤佃柂閰粨鏋勪笅鎷夋姤閿欙級
+-- 娉ㄦ剰锛歁ySQL 8 鐨� ALTER TABLE ADD COLUMN 涓嶆敮鎸� IF NOT EXISTS锛�
+-- 鑻ユ煇鍒楀凡瀛樺湪锛屽搴� ALTER 璇彞浼氭姤"Duplicate column"锛屽拷鐣ヨ鏉″嵆鍙户缁��
+-- =============================================
+
+-- ---------- 1. hrm_employee锛氭柊澧炲矖浣岻D鍒楄〃(JSON)锛屽苟杩佺Щ鏃� post_id ----------
+ALTER TABLE `hrm_employee` ADD COLUMN `post_ids` varchar(500) DEFAULT NULL COMMENT '宀椾綅ID鍒楄〃锛圝SON鏍煎紡锛�' AFTER `post_id`;
+UPDATE `hrm_employee` SET `post_ids` = CONCAT('[', `post_id`, ']') WHERE `post_id` IS NOT NULL AND (`post_ids` IS NULL OR `post_ids` = '');
+
+-- ---------- 2. hrm_salary_structure锛氭柊澧炰紤鎭棩/娉曞畾鑺傚亣鏃ュ姞鐝�嶇巼 ----------
+ALTER TABLE `hrm_salary_structure` ADD COLUMN `rest_day_overtime_pay_ratio` decimal(4,2) DEFAULT 2.00 COMMENT '浼戞伅鏃ュ姞鐝伐璧勫�嶇巼' AFTER `overtime_pay_ratio`;
+ALTER TABLE `hrm_salary_structure` ADD COLUMN `legal_holiday_overtime_pay_ratio` decimal(4,2) DEFAULT 3.00 COMMENT '娉曞畾鑺傚亣鏃ュ姞鐝伐璧勫�嶇巼' AFTER `rest_day_overtime_pay_ratio`;
+
+-- ---------- 瀹屾垚鎻愮ず ----------
+SELECT 'HRM 鍛樺伐鍙拌处宀椾綅澶氶�夋暟鎹簱鍙樻洿瀹屾垚锛�' AS result;
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/HrmEmployeeController.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/HrmEmployeeController.java
index 989e1ce..4d4829a 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/HrmEmployeeController.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/HrmEmployeeController.java
@@ -115,10 +115,12 @@
Map<Long, DeptRespDTO> deptMap = CollUtil.isEmpty(deptIds) ? Collections.emptyMap() : deptApi.getDeptMap(deptIds);
// 2. 鎵归噺鑾峰彇宀椾綅淇℃伅
- Set<Long> postIds = employeeList.stream()
- .map(HrmEmployeeDO::getPostId)
- .filter(Objects::nonNull)
- .collect(Collectors.toSet());
+ Set<Long> postIds = new HashSet<>();
+ for (HrmEmployeeDO employee : employeeList) {
+ if (StrUtil.isNotBlank(employee.getPostIds())) {
+ postIds.addAll(JSONUtil.toList(employee.getPostIds(), Long.class));
+ }
+ }
Map<Long, PostRespDTO> postMap = CollUtil.isEmpty(postIds) ? Collections.emptyMap() : postApi.getPostMap(postIds);
// 3. 鏀堕泦鎵�鏈夎鑹睮D
@@ -143,9 +145,16 @@
respVO.setDeptName(deptMap.get(employee.getDeptId()).getName());
}
- // 濉厖宀椾綅鍚嶇О
- if (employee.getPostId() != null && postMap.containsKey(employee.getPostId())) {
- respVO.setPostName(postMap.get(employee.getPostId()).getName());
+ // 濉厖宀椾綅淇℃伅
+ if (StrUtil.isNotBlank(employee.getPostIds())) {
+ List<Long> employeePostIds = JSONUtil.toList(employee.getPostIds(), Long.class);
+ respVO.setPostIds(employeePostIds);
+ if (CollUtil.isNotEmpty(employeePostIds)) {
+ respVO.setPostNames(employeePostIds.stream()
+ .filter(postMap::containsKey)
+ .map(id -> postMap.get(id).getName())
+ .collect(Collectors.joining(",")));
+ }
}
// 瑙f瀽 roleIds 骞跺~鍏呰鑹插悕绉�
@@ -195,7 +204,7 @@
// 杈撳嚭绀轰緥鏁版嵁锛屾柟渚夸娇鐢ㄨ�呭弬鑰�
List<HrmEmployeeImportExcelVO> list = Arrays.asList(
HrmEmployeeImportExcelVO.builder().name("寮犱笁").gender(1).phone("13800138000")
- .deptName("鐮斿彂閮�").postName("閮ㄩ棬缁忕悊").roleNames("鏅�氱鐞嗗憳")
+ .deptName("鐮斿彂閮�").postName("閮ㄩ棬缁忕悊,椤圭洰缁忕悊").roleNames("鏅�氱鐞嗗憳")
.hireDate(LocalDate.of(2020, 3, 1)).employeeStatus(1)
.idCard("320102199001150011").birthday(LocalDate.of(1990, 1, 15))
.nation("姹夋棌").marriageStatus("宸插").age(36).education("鏈").politicalStatus("涓叡鍏氬憳")
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeRespVO.java
index 262364a..8706fc4 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeRespVO.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeRespVO.java
@@ -32,12 +32,12 @@
@ExcelProperty("閮ㄩ棬鍚嶇О")
private String deptName;
- @Schema(description = "宀椾綅ID")
- private Long postId;
+ @Schema(description = "宀椾綅ID鍒楄〃")
+ private List<Long> postIds;
- @Schema(description = "宀椾綅鍚嶇О")
+ @Schema(description = "宀椾綅鍚嶇О鍒楄〃")
@ExcelProperty("宀椾綅鍚嶇О")
- private String postName;
+ private String postNames;
@Schema(description = "鍛樺伐濮撳悕")
@ExcelProperty("鍛樺伐濮撳悕")
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeSaveReqVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeSaveReqVO.java
index 35fe0a2..f0f0231 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeSaveReqVO.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeSaveReqVO.java
@@ -23,9 +23,9 @@
@NotNull(message = "閮ㄩ棬涓嶈兘涓虹┖")
private Long deptId;
- @Schema(description = "宀椾綅ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
- @NotNull(message = "宀椾綅涓嶈兘涓虹┖")
- private Long postId;
+ @Schema(description = "宀椾綅ID鍒楄〃", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]")
+ @NotEmpty(message = "宀椾綅涓嶈兘涓虹┖")
+ private List<Long> postIds;
@Schema(description = "鍛樺伐濮撳悕", requiredMode = Schema.RequiredMode.REQUIRED, example = "寮犱笁")
@NotEmpty(message = "鍛樺伐濮撳悕涓嶈兘涓虹┖")
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/employee/HrmEmployeeDO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/employee/HrmEmployeeDO.java
index 3207b95..b784f3d 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/employee/HrmEmployeeDO.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/employee/HrmEmployeeDO.java
@@ -45,11 +45,11 @@
private Long deptId;
/**
- * 宀椾綅ID
+ * 宀椾綅ID鍒楄〃
*
- * 鍏宠仈 PostDO#getId()
+ * 鍏宠仈 PostDO#getId()锛孞SON 鏍煎紡瀛樺偍
*/
- private Long postId;
+ private String postIds;
/**
* 鍛樺伐缂栧彿
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmOvertimeApplicationServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmOvertimeApplicationServiceImpl.java
index aa9449d..a044fba 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmOvertimeApplicationServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmOvertimeApplicationServiceImpl.java
@@ -2,6 +2,8 @@
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
@@ -255,9 +257,17 @@
resp.setEmployeeName(employee.getName()); resp.setEmployeeNo(employee.getEmployeeNo());
resp.setDeptId(employee.getDeptId());
DeptRespDTO dept = employee.getDeptId() == null ? null : deptApi.getDept(employee.getDeptId());
- PostRespDTO post = employee.getPostId() == null ? null
- : postApi.getPostMap(Collections.singleton(employee.getPostId())).get(employee.getPostId());
resp.setDeptName(dept == null ? null : dept.getName());
- resp.setPostName(post == null ? null : post.getName());
+ // 宀椾綅澶氶�夛細瑙f瀽 postIds JSON锛屾嫾鎺ュ矖浣嶅悕绉�
+ if (StrUtil.isNotBlank(employee.getPostIds())) {
+ List<Long> postIds = JSONUtil.toList(employee.getPostIds(), Long.class);
+ if (CollUtil.isNotEmpty(postIds)) {
+ Map<Long, PostRespDTO> postMap = postApi.getPostMap(postIds);
+ resp.setPostName(postIds.stream()
+ .filter(postMap::containsKey)
+ .map(id -> postMap.get(id).getName())
+ .collect(Collectors.joining(",")));
+ }
+ }
}
}
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
index c538b8c..c326a89 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
@@ -33,6 +33,7 @@
import cn.iocoder.yudao.module.system.api.permission.dto.RoleRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserCreateReqDTO;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserUpdateReqDTO;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
@@ -91,7 +92,7 @@
// 1. 鏍¢獙閮ㄩ棬
deptApi.validateDeptList(Collections.singleton(createReqVO.getDeptId()));
// 2. 鏍¢獙宀椾綅
- postApi.validPostList(Collections.singleton(createReqVO.getPostId()));
+ postApi.validPostList(createReqVO.getPostIds());
// 3. 鏍¢獙鎵嬫満鍙锋槸鍚﹀凡瀛樺湪
if (employeeMapper.selectByPhone(createReqVO.getPhone()) != null) {
throw exception(EMPLOYEE_PHONE_EXISTS);
@@ -101,7 +102,7 @@
userCreateReqDTO.setUsername(createReqVO.getPhone());
userCreateReqDTO.setNickname(createReqVO.getName());
userCreateReqDTO.setDeptId(createReqVO.getDeptId());
- userCreateReqDTO.setPostIds(Collections.singleton(createReqVO.getPostId()));
+ userCreateReqDTO.setPostIds(new LinkedHashSet<>(createReqVO.getPostIds()));
userCreateReqDTO.setMobile(createReqVO.getPhone());
userCreateReqDTO.setPassword(createReqVO.getPhone());
userCreateReqDTO.setSex(createReqVO.getGender());
@@ -121,6 +122,10 @@
// roleIds 瀛樺偍涓� JSON
if (CollUtil.isNotEmpty(createReqVO.getRoleIds())) {
employee.setRoleIds(JSONUtil.toJsonStr(createReqVO.getRoleIds()));
+ }
+ // postIds 瀛樺偍涓� JSON
+ if (CollUtil.isNotEmpty(createReqVO.getPostIds())) {
+ employee.setPostIds(JSONUtil.toJsonStr(createReqVO.getPostIds()));
}
employeeMapper.insert(employee);
Long employeeId = employee.getId();
@@ -167,7 +172,7 @@
// 鏍¢獙閮ㄩ棬
deptApi.validateDeptList(Collections.singleton(updateReqVO.getDeptId()));
// 鏍¢獙宀椾綅
- postApi.validPostList(Collections.singleton(updateReqVO.getPostId()));
+ postApi.validPostList(updateReqVO.getPostIds());
// 鏍¢獙鎵嬫満鍙锋槸鍚﹀凡瀛樺湪锛堝鏋滄墜鏈哄彿鏈夊彉鏇达級
if (!Objects.equals(employee.getPhone(), updateReqVO.getPhone())
&& employeeMapper.selectByPhone(updateReqVO.getPhone()) != null) {
@@ -179,7 +184,24 @@
if (CollUtil.isNotEmpty(updateReqVO.getRoleIds())) {
updateObj.setRoleIds(JSONUtil.toJsonStr(updateReqVO.getRoleIds()));
}
+ // postIds 瀛樺偍涓� JSON
+ if (CollUtil.isNotEmpty(updateReqVO.getPostIds())) {
+ updateObj.setPostIds(JSONUtil.toJsonStr(updateReqVO.getPostIds()));
+ }
employeeMapper.updateById(updateObj);
+ // 鍚屾鏇存柊鍏宠仈绯荤粺鐢ㄦ埛锛堝矖浣�/閮ㄩ棬/鏄电О/瑙掕壊/閭/澶囨敞锛夛紝淇濇寔涓庣敤鎴风鐞嗕竴鑷�
+ if (employee.getUserId() != null) {
+ AdminUserUpdateReqDTO userUpdateReqDTO = new AdminUserUpdateReqDTO();
+ userUpdateReqDTO.setId(employee.getUserId());
+ userUpdateReqDTO.setNickname(updateReqVO.getName());
+ userUpdateReqDTO.setDeptId(updateReqVO.getDeptId());
+ userUpdateReqDTO.setPostIds(new LinkedHashSet<>(updateReqVO.getPostIds()));
+ userUpdateReqDTO.setRoleIds(CollUtil.isEmpty(updateReqVO.getRoleIds()) ? null
+ : new LinkedHashSet<>(updateReqVO.getRoleIds()));
+ userUpdateReqDTO.setEmail(updateReqVO.getEmail());
+ userUpdateReqDTO.setRemark(updateReqVO.getRemark());
+ adminUserApi.updateUser(userUpdateReqDTO);
+ }
Long employeeId = updateReqVO.getId();
// 鍚屾鏁欒偛缁忓巻
@@ -270,12 +292,16 @@
respVO.setDeptName(dept.getName());
}
}
- // 濉厖宀椾綅鍚嶇О
- if (employee.getPostId() != null) {
- Map<Long, PostRespDTO> postMap = postApi.getPostMap(Collections.singleton(employee.getPostId()));
- PostRespDTO post = postMap.get(employee.getPostId());
- if (post != null) {
- respVO.setPostName(post.getName());
+ // 濉厖宀椾綅淇℃伅
+ if (StrUtil.isNotBlank(employee.getPostIds())) {
+ List<Long> postIds = JSONUtil.toList(employee.getPostIds(), Long.class);
+ respVO.setPostIds(postIds);
+ if (CollUtil.isNotEmpty(postIds)) {
+ Map<Long, PostRespDTO> postMap = postApi.getPostMap(postIds);
+ respVO.setPostNames(postIds.stream()
+ .filter(postMap::containsKey)
+ .map(postId -> postMap.get(postId).getName())
+ .collect(Collectors.joining(",")));
}
}
// 濉厖瑙掕壊鍚嶇О
@@ -370,10 +396,10 @@
try {
// 3.1 鍚嶇О杞� ID
Long deptId = parseDeptId(importEmployee.getDeptName(), deptMap);
- Long postId = parsePostId(importEmployee.getPostName(), postMap);
+ Set<Long> postIds = parsePostIds(importEmployee.getPostName(), postMap);
Set<Long> roleIds = parseRoleIds(importEmployee.getRoleNames(), roleMap);
// 3.2 鏋勫缓淇濆瓨璇锋眰
- HrmEmployeeSaveReqVO saveReqVO = buildImportSaveReqVO(importEmployee, deptId, postId, roleIds);
+ HrmEmployeeSaveReqVO saveReqVO = buildImportSaveReqVO(importEmployee, deptId, postIds, roleIds);
// 3.3 鍒ゆ柇瀛樺湪鎬э細鎸夋墜鏈哄彿
HrmEmployeeDO existEmployee = employeeMapper.selectByPhone(importEmployee.getPhone());
if (existEmployee == null) {
@@ -398,7 +424,7 @@
}
private HrmEmployeeSaveReqVO buildImportSaveReqVO(HrmEmployeeImportExcelVO importEmployee,
- Long deptId, Long postId, Set<Long> roleIds) {
+ Long deptId, Set<Long> postIds, Set<Long> roleIds) {
if (StrUtil.isBlank(importEmployee.getName())) {
throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "鍛樺伐濮撳悕");
}
@@ -413,7 +439,7 @@
reqVO.setGender(importEmployee.getGender() != null ? importEmployee.getGender() : 1); // 榛樿鐢�
reqVO.setPhone(importEmployee.getPhone());
reqVO.setDeptId(deptId);
- reqVO.setPostId(postId);
+ reqVO.setPostIds(CollUtil.isEmpty(postIds) ? null : new ArrayList<>(postIds));
reqVO.setRoleIds(CollUtil.isEmpty(roleIds) ? null : new ArrayList<>(roleIds));
reqVO.setHireDate(importEmployee.getHireDate());
reqVO.setEmployeeStatus(importEmployee.getEmployeeStatus() != null
@@ -441,15 +467,26 @@
return dept.getId();
}
- private Long parsePostId(String postName, Map<String, PostRespDTO> postMap) {
- if (StrUtil.isBlank(postName)) {
+ private Set<Long> parsePostIds(String postNames, Map<String, PostRespDTO> postMap) {
+ if (StrUtil.isBlank(postNames)) {
throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "宀椾綅鍚嶇О");
}
- PostRespDTO post = postMap.get(postName.trim());
- if (post == null) {
- throw exception(EMPLOYEE_POST_NAME_NOT_EXISTS, postName.trim());
+ Set<Long> postIds = new LinkedHashSet<>();
+ for (String postName : postNames.split("[,锛宂")) {
+ String trimmed = postName.trim();
+ if (StrUtil.isBlank(trimmed)) {
+ continue;
+ }
+ PostRespDTO post = postMap.get(trimmed);
+ if (post == null) {
+ throw exception(EMPLOYEE_POST_NAME_NOT_EXISTS, trimmed);
+ }
+ postIds.add(post.getId());
}
- return post.getId();
+ if (CollUtil.isEmpty(postIds)) {
+ throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "宀椾綅鍚嶇О");
+ }
+ return postIds;
}
private Set<Long> parseRoleIds(String roleNames, Map<String, RoleRespDTO> roleMap) {
diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java
index 4445377..8019b02 100644
--- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java
+++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java
@@ -3,6 +3,7 @@
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserCreateReqDTO;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserUpdateReqDTO;
import java.util.Collection;
import java.util.Collections;
@@ -25,6 +26,13 @@
Long createUser(AdminUserCreateReqDTO createReqDTO);
/**
+ * 鏇存柊鐢ㄦ埛锛堜緵鍏朵粬妯″潡鍚屾鏇存柊绯荤粺鐢ㄦ埛閮ㄥ垎淇℃伅锛屽宀椾綅/閮ㄩ棬/鏄电О绛夛級
+ *
+ * @param updateReqDTO 鐢ㄦ埛鏇存柊淇℃伅
+ */
+ void updateUser(AdminUserUpdateReqDTO updateReqDTO);
+
+ /**
* 閫氳繃鐢ㄦ埛 ID 鏌ヨ鐢ㄦ埛
*
* @param id 鐢ㄦ埛ID
diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java
index f68064a..d0a0c68 100644
--- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java
+++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java
@@ -7,6 +7,7 @@
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserCreateReqDTO;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserUpdateReqDTO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
@@ -53,6 +54,19 @@
}
@Override
+ public void updateUser(AdminUserUpdateReqDTO updateReqDTO) {
+ UserSaveReqVO updateReqVO = new UserSaveReqVO();
+ updateReqVO.setId(updateReqDTO.getId());
+ updateReqVO.setNickname(updateReqDTO.getNickname());
+ updateReqVO.setDeptId(updateReqDTO.getDeptId());
+ updateReqVO.setPostIds(updateReqDTO.getPostIds());
+ updateReqVO.setRoleIds(updateReqDTO.getRoleIds());
+ updateReqVO.setEmail(updateReqDTO.getEmail());
+ updateReqVO.setRemark(updateReqDTO.getRemark());
+ userService.updateUser(updateReqVO);
+ }
+
+ @Override
@DataPermission(enable = false) // 蹇界暐鏁版嵁鏉冮檺锛岄伩鍏嶅洜涓鸿繃婊わ紝瀵艰嚧鏃犳硶鏌ヨ鐢ㄦ埛銆傜被浼硷細https://github.com/YunaiV/ruoyi-vue-pro/issues/1051
public AdminUserRespDTO getUser(Long id) {
AdminUserDO user = userService.getUser(id);
diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserUpdateReqDTO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserUpdateReqDTO.java
new file mode 100644
index 0000000..e3a21ac
--- /dev/null
+++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserUpdateReqDTO.java
@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.module.system.api.user.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.util.Set;
+
+/**
+ * Admin 鐢ㄦ埛鏇存柊 Request DTO
+ *
+ * 渚涘叾浠栨ā鍧楀悓姝ユ洿鏂扮郴缁熺敤鎴风殑閮ㄥ垎淇℃伅锛堝 HRM 鍛樺伐缂栬緫鏃跺悓姝ュ矖浣�/閮ㄩ棬绛夛級
+ */
+@Schema(description = "绠$悊鍚庡彴 - 鐢ㄦ埛鏇存柊 Request DTO")
+@Data
+public class AdminUserUpdateReqDTO {
+
+ @Schema(description = "鐢ㄦ埛缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @NotNull(message = "鐢ㄦ埛缂栧彿涓嶈兘涓虹┖")
+ private Long id;
+
+ @Schema(description = "鐢ㄦ埛鏄电О", example = "寮犱笁")
+ private String nickname;
+
+ @Schema(description = "閮ㄩ棬缂栧彿", example = "1")
+ private Long deptId;
+
+ @Schema(description = "宀椾綅缂栧彿鏁扮粍", example = "[1, 2]")
+ private Set<Long> postIds;
+
+ @Schema(description = "瑙掕壊缂栧彿鏁扮粍", example = "[1, 2]")
+ private Set<Long> roleIds;
+
+ @Schema(description = "鐢ㄦ埛閭", example = "zhangsan@example.com")
+ private String email;
+
+ @Schema(description = "澶囨敞", example = "澶囨敞淇℃伅")
+ private String remark;
+
+}
--
Gitblit v1.9.3