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