From 8438d50aef0bb78e5e6c41ca1c1bc09b4e61add1 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 29 七月 2026 09:18:29 +0800
Subject: [PATCH] feat(customer): 添加公海客户归属查看权限控制
---
docs/customer_view_all_permission.md | 78 ++++++++++++++++++++++++++
src/main/resources/mapper/basic/CustomerMapper.xml | 22 ++++++-
src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java | 4
sql/migration_customer_view_all_permission.sql | 42 ++++++++++++++
src/main/java/com/ruoyi/ai/tools/SalesAgentTools.java | 3
src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java | 25 +++++++-
6 files changed, 163 insertions(+), 11 deletions(-)
diff --git a/docs/customer_view_all_permission.md b/docs/customer_view_all_permission.md
new file mode 100644
index 0000000..5c307b5
--- /dev/null
+++ b/docs/customer_view_all_permission.md
@@ -0,0 +1,78 @@
+# 鍏捣瀹㈡埛褰掑睘鏌ョ湅鏉冮檺
+
+## 娑夊強椤甸潰
+
+- 瀹㈡埛妗f - 鍏捣瀹㈡埛鍒楄〃 (`/customer/publicSea`)
+- 瀹㈡埛妗f - 绉佹捣瀹㈡埛鍒楄〃 (`/customer/privateSea`)
+- AI 閿�鍞姪鎵� - 瀹㈡埛鍒楄〃鏌ヨ
+
+## API
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| GET | /basic/customer/list | 鏌ヨ瀹㈡埛鍒楄〃锛坱ype=1 鍏捣锛宼ype=0 绉佹捣锛� |
+
+**璇锋眰鍙傛暟锛�** 涓嶅彉锛屽弬鑰冪幇鏈夋帴鍙f枃妗c��
+
+**鍝嶅簲鍙樻洿锛�** `usageUserName` 瀛楁鐨勫�煎彈鏉冮檺鎺у埗锛�
+
+- **鏈� `customer:viewAll` 鏉冮檺**锛歚usageUserName` 杩斿洖璇ュ鎴峰搴旂殑閿�鍞汉鍚嶇О锛堜笌涔嬪墠琛屼负涓�鑷达級
+- **鏃� `customer:viewAll` 鏉冮檺**锛氫粎褰撳鎴风敱褰撳墠鐢ㄦ埛棰嗙敤锛坄usage_user`锛夋垨鍒涘缓锛坄create_user`锛夋椂杩斿洖閿�鍞汉鍚嶇О锛屽叾浠栨儏鍐佃繑鍥炵┖瀛楃涓� `""`
+
+鍝嶅簲缁撴瀯涓嶅彉锛屼粛涓猴細
+
+```json
+{
+ "code": 200,
+ "data": {
+ "records": [
+ {
+ "id": 1,
+ "customerName": "xxx鍏徃",
+ "usageUserName": "寮犱笁",
+ "type": 1,
+ "isAssigned": 1
+ }
+ ]
+ }
+}
+```
+
+## 鍓嶇淇敼鐐�
+
+### 1. 鍏捣瀹㈡埛鍒楄〃琛ㄦ牸 鈥� 澶勭悊绌虹殑 usageUserName
+
+鍏捣鍒楄〃鐨�"褰掑睘閿�鍞�"鍒楅渶澶勭悊 `usageUserName` 涓虹┖鐨勬儏鍐碉細
+
+```html
+<el-table-column prop="usageUserName" label="褰掑睘閿�鍞�" width="120">
+ <template slot-scope="scope">
+ <span>{{ scope.row.usageUserName || '-' }}</span>
+ </template>
+</el-table-column>
+```
+
+### 2. 鏉冮檺鎺у埗 鈥� 椤甸潰鎸夐挳/鍔熻兘鍙鎬�
+
+閫氳繃 `v-hasPermi` 鎸囦护鎴� `@ss.hasPermi('customer:viewAll')` 鎺у埗绠$悊绫诲姛鑳界殑鍙鎬э紙渚嬪瀵煎嚭鍚攢鍞汉淇℃伅鐨勬姤琛ㄧ瓑锛夛細
+
+```html
+<el-button v-hasPermi="['customer:viewAll']" @click="exportWithSalesperson">
+ 瀵煎嚭锛堝惈褰掑睘閿�鍞級
+</el-button>
+```
+
+### 3. 鏉冮檺鏍囪瘑
+
+鍦ㄦ潈闄愮鐞嗭紙瑙掕壊绠$悊 > 鑿滃崟鏉冮檺锛変腑鏂板鎸夐挳绾ф潈闄愶細
+
+| 鏉冮檺鏍囪瘑 | 鏉冮檺鍚嶇О | 璇存槑 |
+|----------|----------|------|
+| `customer:viewAll` | 鍏捣瀹㈡埛褰掑睘鏌ョ湅 | 鍏佽鏌ョ湅鍏捣涓墍鏈夊鎴风殑褰掑睘閿�鍞汉淇℃伅 |
+
+## 娉ㄦ剰浜嬮」
+
+- 璇ユ潈闄愪笉褰卞搷瀹㈡埛鏁版嵁鐨勫彲瑙佽寖鍥达紙鍏捣瀹㈡埛浠嶅鎵�鏈夌櫥褰曠敤鎴峰彲瑙侊級锛屽彧鎺у埗"褰掑睘閿�鍞汉"淇℃伅鐨勫睍绀恒��
+- 绉佹捣鍒楄〃涓紝鐢ㄦ埛鍘熸湰灏卞彧鑳界湅鍒拌嚜宸辩殑瀹㈡埛锛宍usageUserName` 濮嬬粓鏄嚜宸辩殑鍚嶇О锛屼笉鍙楁鏉冮檺褰卞搷銆�
+- 鍓嶇涓嬫媺閫夋嫨瀹㈡埛鍒楄〃 (`/basic/customer/customerList`) 涔熷彈姝ゆ潈闄愬奖鍝嶏紝鏃犳潈闄愭椂 `usageUserName` 鍙兘涓虹┖銆�
+- AI 閿�鍞姪鎵嬬殑瀹㈡埛鏌ヨ鍚屾牱閬靛惊姝ゆ潈闄愯鍒欍��
diff --git a/sql/migration_customer_view_all_permission.sql b/sql/migration_customer_view_all_permission.sql
new file mode 100644
index 0000000..c5ca5c8
--- /dev/null
+++ b/sql/migration_customer_view_all_permission.sql
@@ -0,0 +1,42 @@
+-- ----------------------------
+-- 瀹㈡埛妗f - 鍏捣瀹㈡埛褰掑睘鏌ョ湅鏉冮檺
+-- 璇存槑锛氬湪"瀹㈡埛妗f"鑿滃崟涓嬫柊澧炴寜閽潈闄愶紝鏈夎鏉冮檺鐨勭敤鎴峰彲鍦ㄥ叕娴锋煡鐪嬫墍鏈夊鎴风殑褰掑睘閿�鍞汉淇℃伅
+-- 鎵ц鏂瑰紡锛氱洿鎺ユ墽琛屾湰 SQL 鎴栭�氳繃绯荤粺鑿滃崟绠$悊鐣岄潰鎵嬪姩娣诲姞
+-- ----------------------------
+
+-- 鏌ユ壘"瀹㈡埛妗f"鑿滃崟鐨� ID 浣滀负鐖惰彍鍗�
+SET @parent_menu_name = '瀹㈡埛妗f(鍏捣)';
+
+SELECT @parent_id := menu_id
+FROM sys_menu
+WHERE menu_name = @parent_menu_name
+ AND menu_type IN ('C', 'M')
+LIMIT 1;
+
+-- 浠呭綋鎵惧埌鐖惰彍鍗曚笖璇ユ潈闄愭爣璇嗕笉瀛樺湪鏃舵墠鎻掑叆
+INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark, app_component)
+SELECT '鍏捣瀹㈡埛褰掑睘鏌ョ湅',
+ @parent_id,
+ 9,
+ '',
+ NULL,
+ NULL,
+ '',
+ 1,
+ 0,
+ 'F',
+ '0',
+ '0',
+ 'customer:viewAll',
+ '#',
+ 'admin',
+ NOW(),
+ '',
+ NULL,
+ '鎺у埗鍏捣瀹㈡埛鍒楄〃涓綊灞為攢鍞汉鍚嶇О鐨勫彲瑙佹��',
+ NULL
+FROM DUAL
+WHERE @parent_id IS NOT NULL
+ AND NOT EXISTS (
+ SELECT 1 FROM sys_menu WHERE perms = 'customer:viewAll'
+ );
diff --git a/src/main/java/com/ruoyi/ai/tools/SalesAgentTools.java b/src/main/java/com/ruoyi/ai/tools/SalesAgentTools.java
index 0f7e586..ec7c4e0 100644
--- a/src/main/java/com/ruoyi/ai/tools/SalesAgentTools.java
+++ b/src/main/java/com/ruoyi/ai/tools/SalesAgentTools.java
@@ -81,7 +81,8 @@
customerDto.setType(normalizeSeaType(seaType));
customerDto.setUsageStatus(1L);
- List<CustomerVo> rows = defaultList(customerMapper.list(customerDto, loginUser.getUserId()));
+ boolean isAdmin = SecurityUtils.hasPermi("customer:viewAll");
+ List<CustomerVo> rows = defaultList(customerMapper.list(customerDto, loginUser.getUserId(), isAdmin));
List<CustomerVo> filtered = rows.stream()
.filter(item -> matchCustomerKeyword(item, keyword))
.sorted(Comparator.comparing(CustomerVo::getId, Comparator.nullsLast(Comparator.reverseOrder())))
diff --git a/src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java b/src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java
index f871b91..c3cf7ea 100644
--- a/src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java
+++ b/src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java
@@ -70,9 +70,9 @@
*/
int deleteCustomerByIds(Long[] ids);
- IPage<CustomerVo> listPage(Page<CustomerDto> page, @Param("c") CustomerDto customer, @Param("loginUserId") Long loginUserId);
+ IPage<CustomerVo> listPage(Page<CustomerDto> page, @Param("c") CustomerDto customer, @Param("loginUserId") Long loginUserId, @Param("isAdmin") Boolean isAdmin);
- List<CustomerVo> list(@Param("c") CustomerDto customer, @Param("loginUserId") Long loginUserId);
+ List<CustomerVo> list(@Param("c") CustomerDto customer, @Param("loginUserId") Long loginUserId, @Param("isAdmin") Boolean isAdmin);
IPage<CustomerTransactionsVo> customewTransactions(Page page, @Param("customerName") String customerName);
diff --git a/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
index 5a4d19a..4404387 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
@@ -130,7 +130,8 @@
public IPage<CustomerVo> selectCustomerList(Page<CustomerDto> page, CustomerDto customer) {
LoginUser loginUser = SecurityUtils.getLoginUser();
Long loginUserId = loginUser.getUserId();
- IPage<CustomerVo> customerPage = customerMapper.listPage(page, customer, loginUserId);
+ boolean isAdmin = SecurityUtils.hasPermi("customer:viewAll");
+ IPage<CustomerVo> customerPage = customerMapper.listPage(page, customer, loginUserId, isAdmin);
List<CustomerVo> records = customerPage.getRecords();
if (CollectionUtils.isEmpty(records)) {
@@ -199,7 +200,21 @@
LoginUser loginUser = SecurityUtils.getLoginUser();
Long tenantId = loginUser.getTenantId();
customer.setTenantId(tenantId);
- return customerMapper.insert(customer);
+ int result = customerMapper.insert(customer);
+
+ // 绉佹捣鏂板鏃跺悓姝ヤ竴鏉″埌鍏捣
+ if (customer.getType() != null && customer.getType() == 0) {
+ Customer publicSeaCustomer = new Customer();
+ BeanUtils.copyProperties(customer, publicSeaCustomer);
+ publicSeaCustomer.setId(null);
+ publicSeaCustomer.setType(1);
+ publicSeaCustomer.setIsAssigned(0);
+ publicSeaCustomer.setUsageUser(loginUser.getUserId());
+ publicSeaCustomer.setUsageStatus(1L);
+ customerMapper.insert(publicSeaCustomer);
+ }
+
+ return result;
}
/**
@@ -281,7 +296,8 @@
public List<CustomerVo> selectCustomerLists(CustomerDto customer) {
LoginUser loginUser = SecurityUtils.getLoginUser();
Long loginUserId = loginUser.getUserId();
- return customerMapper.list(customer, loginUserId);
+ boolean isAdmin = SecurityUtils.hasPermi("customer:viewAll");
+ return customerMapper.list(customer, loginUserId, isAdmin);
}
@Override
@@ -312,13 +328,14 @@
public List<Map<String, Object>> customerList(Customer customer) {
LoginUser loginUser = SecurityUtils.getLoginUser();
Long loginUserId = loginUser.getUserId();
+ boolean isAdmin = SecurityUtils.hasPermi("customer:viewAll");
CustomerDto query = new CustomerDto();
if (customer != null) {
BeanUtils.copyProperties(customer, query);
}
// 澶嶇敤瀹㈡埛鍒楄〃鐨勫彲瑙佹�ц鍒欙紝閬垮厤鎶婂埆浜虹殑绉佹捣瀹㈡埛鏆撮湶缁欏綋鍓嶈处鍙�
- List<CustomerVo> visibleCustomers = customerMapper.list(query, loginUserId);
+ List<CustomerVo> visibleCustomers = customerMapper.list(query, loginUserId, isAdmin);
if (CollectionUtils.isEmpty(visibleCustomers)) {
return Collections.emptyList();
}
diff --git a/src/main/resources/mapper/basic/CustomerMapper.xml b/src/main/resources/mapper/basic/CustomerMapper.xml
index ffaff4e..c69d89c 100644
--- a/src/main/resources/mapper/basic/CustomerMapper.xml
+++ b/src/main/resources/mapper/basic/CustomerMapper.xml
@@ -9,9 +9,16 @@
<select id="listPage" resultType="com.ruoyi.basic.vo.CustomerVo">
select
c.*,
- u.user_name usage_user_name,
+ <choose>
+ <when test="isAdmin">
+ u.nick_name usage_user_name,
+ </when>
+ <otherwise>
+ CASE WHEN c.usage_user = #{loginUserId} OR c.create_user = #{loginUserId} THEN u.nick_name ELSE '' END as usage_user_name,
+ </otherwise>
+ </choose>
(
- select group_concat(u2.user_name separator ', ')
+ select group_concat(u2.nick_name separator ', ')
from customer_user cu
left join sys_user u2 on cu.user_id = u2.user_id
where cu.customer_id = c.id
@@ -65,9 +72,16 @@
<select id="list" resultType="com.ruoyi.basic.vo.CustomerVo">
select
c.*,
- u.user_name usage_user_name,
+ <choose>
+ <when test="isAdmin">
+ u.nick_name usage_user_name,
+ </when>
+ <otherwise>
+ CASE WHEN c.usage_user = #{loginUserId} OR c.create_user = #{loginUserId} THEN u.nick_name ELSE '' END as usage_user_name,
+ </otherwise>
+ </choose>
(
- select group_concat(u2.user_name separator ', ')
+ select group_concat(u2.nick_name separator ', ')
from customer_user cu
left join sys_user u2 on cu.user_id = u2.user_id
where cu.customer_id = c.id
--
Gitblit v1.9.3