Эх сурвалжийг харах

feat(T31): 服务商「我的团队」多团队管理(顶部切换器,一人多团队)

后端:
- 新增 POST /api/admin/supply-system/my-teams:按当前登录 userId 返回其作为 admin/active 成员的供应体系列表(supply_system_member + admin_id 并集),鉴权不泄露他人团队
- supply-system/my-system 支持可选 systemId(显式指定时校验 admin/成员权限,缺省取默认团队:优先管理员体系,回退所属第一个团队)
- supply-hierarchy/my 改为 @RequestAttribute userId 鉴权(消除原 params.userId 越权),支持可选 systemId,返回 totalChildren(团队规模)
- supply-team/members、supply-team/customers 增加 systemId 空值与越权校验;listCustomers parentId 为空时返回整个体系客户(团队维度)

小程序前端:
- team-system.vue 顶部团队切换器(横向标签页,vif 单团队退化单列),data 维护 teamList/currentSystemId,切换联动刷新 getVendorSystemInfo/getVendorHierarchyInfo/getVendorTeamMembers/getVendorTeamCustomers,增加 _teamLoadSeq 竞态防护
- utils/api.js 新增 getVendorTeamList;getVendorSystemInfo/getVendorHierarchyInfo 增 systemId 参数透传

验证:mvn clean compile BUILD SUCCESS;verify-vue-compile PASS;audit-mp-antipatterns ERROR 0;audit-duplicate-api-calls 0 error
Agnes Agent 1 долоо хоног өмнө
parent
commit
dd7c1391d0

+ 29 - 6
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/SupplyHierarchyController.java

@@ -3,6 +3,7 @@ package com.etotem.cfc.controller.admin;
 import com.etotem.cfc.common.Result;
 import com.etotem.cfc.common.Result;
 import com.etotem.cfc.entity.SupplyHierarchy;
 import com.etotem.cfc.entity.SupplyHierarchy;
 import com.etotem.cfc.entity.SupplyHierarchyChangeRequest;
 import com.etotem.cfc.entity.SupplyHierarchyChangeRequest;
+import com.etotem.cfc.entity.SupplySystem;
 import com.etotem.cfc.entity.SupplySystemMember;
 import com.etotem.cfc.entity.SupplySystemMember;
 import com.etotem.cfc.entity.User;
 import com.etotem.cfc.entity.User;
 import com.etotem.cfc.mapper.SupplySystemMemberMapper;
 import com.etotem.cfc.mapper.SupplySystemMemberMapper;
@@ -10,6 +11,7 @@ import com.etotem.cfc.mapper.UserMapper;
 import com.etotem.cfc.service.SupplyHierarchyService;
 import com.etotem.cfc.service.SupplyHierarchyService;
 import com.etotem.cfc.service.SupplySystemService;
 import com.etotem.cfc.service.SupplySystemService;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
@@ -181,18 +183,39 @@ public class SupplyHierarchyController {
     }
     }
 
 
     @PostMapping("/my")
     @PostMapping("/my")
-    public Result<Map<String, Object>> getMyRelation(@RequestBody Map<String, Object> params) {
+    public Result<Map<String, Object>> getMyRelation(@RequestBody Map<String, Object> params,
+                                                     @RequestAttribute("userId") Long userId) {
+        if (userId == null || userId < 0) {
+            return Result.error("未登录");
+        }
         Long systemId = ParamUtils.getLong(params.get("systemId"));
         Long systemId = ParamUtils.getLong(params.get("systemId"));
-        Long userId = ParamUtils.getLong(params.get("userId"));
-        if (systemId == null || userId == null) {
-            return Result.error("参数不完整");
+        // 缺省取默认团队:优先管理员体系,否则回退到用户所属第一个团队(T31)
+        if (systemId == null) {
+            SupplySystem defaultSystem = supplySystemService.getByAdminId(userId);
+            if (defaultSystem == null) {
+                List<SupplySystem> teams = supplySystemService.getMyTeams(userId);
+                defaultSystem = teams.isEmpty() ? null : teams.get(0);
+            }
+            if (defaultSystem == null) {
+                return Result.error("您没有关联的供应商体系");
+            }
+            systemId = defaultSystem.getId();
+        }
+        // 越权防护:当前用户必须为体系的 admin/成员(T31)
+        if (!supplySystemService.isMemberOrAdmin(systemId, userId)) {
+            return Result.error("无权访问该团队");
         }
         }
 
 
         Map<String, Object> result = new HashMap<>();
         Map<String, Object> result = new HashMap<>();
+        result.put("systemId", systemId);
         result.put("parent", supplyHierarchyService.getParent(systemId, userId));
         result.put("parent", supplyHierarchyService.getParent(systemId, userId));
-        result.put("directChildren", supplyHierarchyService.getDirectChildren(systemId, userId));
-        result.put("allChildren", supplyHierarchyService.getAllChildren(systemId, userId));
+        List<User> directChildren = supplyHierarchyService.getDirectChildren(systemId, userId);
+        List<User> allChildren = supplyHierarchyService.getAllChildren(systemId, userId);
+        result.put("directChildren", directChildren);
+        result.put("allChildren", allChildren);
         result.put("parentChain", supplyHierarchyService.getParentChain(systemId, userId));
         result.put("parentChain", supplyHierarchyService.getParentChain(systemId, userId));
+        // 团队规模:当前用户在体系内的全部下级(T31 页面「团队规模」统计)
+        result.put("totalChildren", allChildren == null ? 0 : allChildren.size());
         return Result.success(result);
         return Result.success(result);
     }
     }
 
 

+ 33 - 2
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/SupplySystemController.java

@@ -58,14 +58,45 @@ public class SupplySystemController {
     }
     }
 
 
     @PostMapping("/my-system")
     @PostMapping("/my-system")
-    public Result<SupplySystem> getMySystem(@RequestAttribute("userId") Long userId) {
-        SupplySystem system = supplySystemService.getByAdminId(userId);
+    public Result<SupplySystem> getMySystem(@RequestAttribute("userId") Long userId,
+                                            @RequestBody(required = false) Map<String, Object> params) {
+        if (userId == null || userId < 0) {
+            return Result.error("未登录");
+        }
+        Long systemId = params != null ? ParamUtils.getLong(params.get("systemId")) : null;
+        SupplySystem system;
+        if (systemId != null) {
+            // 显式指定团队:校验当前用户是 admin/成员,防越权读取他人团队(T31)
+            system = supplySystemService.getBySystemIdForUser(systemId, userId);
+            if (system == null) {
+                return Result.error("无权访问该团队或团队不存在");
+            }
+        } else {
+            // 缺省取默认团队:优先管理员体系,否则回退到用户所属第一个团队
+            system = supplySystemService.getByAdminId(userId);
+            if (system == null) {
+                List<SupplySystem> teams = supplySystemService.getMyTeams(userId);
+                system = teams.isEmpty() ? null : teams.get(0);
+            }
+        }
         if (system == null) {
         if (system == null) {
             return Result.error("您没有关联的供应商体系");
             return Result.error("您没有关联的供应商体系");
         }
         }
         return Result.success(system);
         return Result.success(system);
     }
     }
 
 
+    /**
+     * 我的团队列表(小程序端「我的团队」顶部切换器数据源,T31)
+     * 按当前登录用户鉴权,返回其作为 admin/成员的全部供应体系,不泄露他人团队。
+     */
+    @PostMapping("/my-teams")
+    public Result<List<SupplySystem>> getMyTeams(@RequestAttribute("userId") Long userId) {
+        if (userId == null || userId < 0) {
+            return Result.error("未登录");
+        }
+        return Result.success(supplySystemService.getMyTeams(userId));
+    }
+
     // ========== Member Management ==========
     // ========== Member Management ==========
 
 
     @PostMapping("/member/list")
     @PostMapping("/member/list")

+ 18 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/SupplyTeamController.java

@@ -2,6 +2,7 @@ package com.etotem.cfc.controller.admin;
 
 
 import com.etotem.cfc.common.Result;
 import com.etotem.cfc.common.Result;
 import com.etotem.cfc.service.SupplyCustomerRelationService;
 import com.etotem.cfc.service.SupplyCustomerRelationService;
+import com.etotem.cfc.service.SupplySystemService;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
@@ -16,6 +17,9 @@ public class SupplyTeamController {
     @Resource
     @Resource
     private SupplyCustomerRelationService supplyCustomerRelationService;
     private SupplyCustomerRelationService supplyCustomerRelationService;
 
 
+    @Resource
+    private SupplySystemService supplySystemService;
+
     /**
     /**
      * 查询上级供应商下的客户列表
      * 查询上级供应商下的客户列表
      */
      */
@@ -24,6 +28,13 @@ public class SupplyTeamController {
             @RequestBody Map<String, Object> params,
             @RequestBody Map<String, Object> params,
             @RequestAttribute("userId") Long userId) {
             @RequestAttribute("userId") Long userId) {
         Long systemId = ParamUtils.getLong(params.get("systemId"));
         Long systemId = ParamUtils.getLong(params.get("systemId"));
+        if (systemId == null) {
+            return Result.error("systemId不能为空");
+        }
+        // 越权防护:当前用户必须为体系的 admin/成员(T31)
+        if (!supplySystemService.isMemberOrAdmin(systemId, userId)) {
+            return Result.error("无权访问该团队");
+        }
         Long parentId = ParamUtils.getLong(params.get("parentId"));
         Long parentId = ParamUtils.getLong(params.get("parentId"));
         int page = params.get("page") != null ? ((Number) params.get("page")).intValue() : 1;
         int page = params.get("page") != null ? ((Number) params.get("page")).intValue() : 1;
         int size = params.get("size") != null ? ((Number) params.get("size")).intValue() : 20;
         int size = params.get("size") != null ? ((Number) params.get("size")).intValue() : 20;
@@ -57,6 +68,13 @@ public class SupplyTeamController {
             @RequestBody Map<String, Object> params,
             @RequestBody Map<String, Object> params,
             @RequestAttribute("userId") Long userId) {
             @RequestAttribute("userId") Long userId) {
         Long systemId = ParamUtils.getLong(params.get("systemId"));
         Long systemId = ParamUtils.getLong(params.get("systemId"));
+        if (systemId == null) {
+            return Result.error("systemId不能为空");
+        }
+        // 越权防护:当前用户必须为体系的 admin/成员(T31)
+        if (!supplySystemService.isMemberOrAdmin(systemId, userId)) {
+            return Result.error("无权访问该团队");
+        }
         List<Map<String, Object>> members = supplyCustomerRelationService.listTeamMembers(systemId);
         List<Map<String, Object>> members = supplyCustomerRelationService.listTeamMembers(systemId);
         return Result.success(members);
         return Result.success(members);
     }
     }

+ 4 - 1
cfc-backend/src/main/java/com/etotem/cfc/service/SupplyCustomerRelationService.java

@@ -36,7 +36,10 @@ public class SupplyCustomerRelationService {
      * 返回:家庭ID、家庭名称、成员昵称、加入时间、归属来源
      * 返回:家庭ID、家庭名称、成员昵称、加入时间、归属来源
      */
      */
     public List<Map<String, Object>> listCustomers(Long systemId, Long parentId, Integer page, Integer size) {
     public List<Map<String, Object>> listCustomers(Long systemId, Long parentId, Integer page, Integer size) {
-        List<SupplyCustomerRelation> relations = supplyCustomerRelationMapper.listByParent(systemId, parentId);
+        // parentId 为空时返回整个体系的客户列表(团队维度「团队客户」,T31);否则按指定上级过滤
+        List<SupplyCustomerRelation> relations = parentId == null
+                ? supplyCustomerRelationMapper.listBySystem(systemId)
+                : supplyCustomerRelationMapper.listByParent(systemId, parentId);
         
         
         // 分页处理
         // 分页处理
         int fromIndex = (page - 1) * size;
         int fromIndex = (page - 1) * size;

+ 61 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/SupplySystemService.java

@@ -95,6 +95,67 @@ public class SupplySystemService extends ServiceImpl<SupplySystemMapper, SupplyS
         return this.getOne(wrapper);
         return this.getOne(wrapper);
     }
     }
 
 
+    /**
+     * 当前用户所属的供应体系列表(作为管理员或 active 成员,支持一人多团队)
+     * T31:小程序「我的团队」多团队管理 —— 团队切换器数据源
+     */
+    public List<SupplySystem> getMyTeams(Long userId) {
+        if (userId == null) return new java.util.ArrayList<>();
+
+        // 1. 用户作为 active 成员/管理员的体系 ID(创建体系时会自动插入 admin 成员记录)
+        java.util.List<Long> systemIds = new java.util.ArrayList<>();
+        java.util.List<SupplySystemMember> members = supplySystemMemberMapper.selectList(
+            new LambdaQueryWrapper<SupplySystemMember>()
+                .eq(SupplySystemMember::getUserId, userId)
+                .eq(SupplySystemMember::getStatus, "active"));
+        for (SupplySystemMember m : members) {
+            if (m.getSystemId() != null && !systemIds.contains(m.getSystemId())) {
+                systemIds.add(m.getSystemId());
+            }
+        }
+
+        // 2. 用户作为体系 admin(防御:部分旧数据可能无 member 记录)
+        java.util.List<SupplySystem> adminSystems = this.list(
+            new LambdaQueryWrapper<SupplySystem>()
+                .eq(SupplySystem::getAdminId, userId)
+                .eq(SupplySystem::getStatus, "active"));
+        for (SupplySystem s : adminSystems) {
+            if (!systemIds.contains(s.getId())) systemIds.add(s.getId());
+        }
+
+        if (systemIds.isEmpty()) return new java.util.ArrayList<>();
+
+        return this.list(new LambdaQueryWrapper<SupplySystem>()
+            .in(SupplySystem::getId, systemIds)
+            .eq(SupplySystem::getStatus, "active")
+            .orderByDesc(SupplySystem::getId));
+    }
+
+    /**
+     * 校验当前用户是否为体系的 admin 或 active 成员(越权防护,T31)
+     */
+    public boolean isMemberOrAdmin(Long systemId, Long userId) {
+        if (systemId == null || userId == null) return false;
+        SupplySystem system = this.getById(systemId);
+        if (system == null) return false;
+        if (system.getAdminId() != null && system.getAdminId().equals(userId)) return true;
+        Long count = supplySystemMemberMapper.selectCount(
+            new LambdaQueryWrapper<SupplySystemMember>()
+                .eq(SupplySystemMember::getSystemId, systemId)
+                .eq(SupplySystemMember::getUserId, userId)
+                .eq(SupplySystemMember::getStatus, "active"));
+        return count != null && count > 0;
+    }
+
+    /**
+     * 按 systemId 取体系并校验当前用户访问权限;无权限或不存在返回 null(T31)
+     */
+    public SupplySystem getBySystemIdForUser(Long systemId, Long userId) {
+        if (systemId == null || userId == null) return null;
+        if (!isMemberOrAdmin(systemId, userId)) return null;
+        return this.getById(systemId);
+    }
+
     // ========== Member Management ==========
     // ========== Member Management ==========
 
 
     public List<SupplySystemMember> memberList(Long systemId) {
     public List<SupplySystemMember> memberList(Long systemId) {

+ 147 - 8
cfc-frontend/pages/vendor/team-system/team-system.vue

@@ -1,5 +1,20 @@
 <template>
 <template>
   <view class="page-team-system" :style="{ '--font-scale': fontScale }">
   <view class="page-team-system" :style="{ '--font-scale': fontScale }">
+    <!-- 团队切换器(T31 多团队管理) -->
+    <view class="team-switcher-wrap" v-if="teamList.length > 0">
+      <scroll-view class="team-switcher" scroll-x="true" :show-scrollbar="false">
+        <view
+          class="team-tab"
+          v-for="team in teamList"
+          :key="team.id"
+          :class="{ 'team-tab-active': currentSystemId === team.id }"
+          @click="switchTeam(team.id)"
+        >
+          <text class="team-tab-text">{{ team.name || '未命名团队' }}</text>
+        </view>
+      </scroll-view>
+    </view>
+
     <!-- 头部:体系信息 -->
     <!-- 头部:体系信息 -->
     <view class="system-header" v-if="systemInfo">
     <view class="system-header" v-if="systemInfo">
       <view class="system-info">
       <view class="system-info">
@@ -134,13 +149,15 @@
 </template>
 </template>
 
 
 <script>
 <script>
-import { getVendorSystemInfo, getVendorHierarchyInfo, getVendorTeamMembers, getVendorTeamCustomers } from '@/utils/api.js'
+import { getVendorSystemInfo, getVendorHierarchyInfo, getVendorTeamMembers, getVendorTeamCustomers, getVendorTeamList } from '@/utils/api.js'
 import fontScaleMixin from '@/mixins/font-scale.js'
 import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
   mixins: [fontScaleMixin],
   mixins: [fontScaleMixin],
   data() {
   data() {
     return {
     return {
+      teamList: [],           // 我的团队列表(切换器数据源,T31)
+      currentSystemId: null,  // 当前选中的团队
       systemInfo: null,
       systemInfo: null,
       hierarchyInfo: null,
       hierarchyInfo: null,
       teamStats: {
       teamStats: {
@@ -171,13 +188,48 @@ export default {
   methods: {
   methods: {
     async loadData() {
     async loadData() {
       try {
       try {
-        // 并发获取所有数据
+        // 1. 拉取我的团队列表,解析当前选中团队
+        var teams = []
+        try {
+          const teamsRes = await getVendorTeamList()
+          teams = teamsRes.data || []
+        } catch (e) {
+          teams = []
+        }
+        this.teamList = teams
+
+        // 保持当前选中;失效(被移除/首次进入)则回退第一个团队
+        var stillValid = false
+        for (var i = 0; i < teams.length; i++) {
+          if (teams[i].id === this.currentSystemId) {
+            stillValid = true
+            break
+          }
+        }
+        if (!this.currentSystemId || !stillValid) {
+          this.currentSystemId = teams.length > 0 ? teams[0].id : null
+        }
+
+        if (!this.currentSystemId) {
+          // 无任何团队:清空数据
+          this.systemInfo = null
+          this.hierarchyInfo = null
+          this.teamMembers = []
+          this.teamCustomers = []
+          this.updateStats()
+          return
+        }
+
+        // 2. 并发加载当前团队数据(竞态防护:切换后旧响应不覆盖新团队)
+        var seq = (this._teamLoadSeq || 0) + 1
+        this._teamLoadSeq = seq
         const [systemRes, hierarchyRes, membersRes, customersRes] = await Promise.all([
         const [systemRes, hierarchyRes, membersRes, customersRes] = await Promise.all([
           this.fetchSystemInfo(),
           this.fetchSystemInfo(),
           this.fetchHierarchyInfo(),
           this.fetchHierarchyInfo(),
           this.fetchTeamMembers(),
           this.fetchTeamMembers(),
           this.fetchTeamCustomers()
           this.fetchTeamCustomers()
         ])
         ])
+        if (seq !== this._teamLoadSeq) return
 
 
         if (systemRes) {
         if (systemRes) {
           this.systemInfo = systemRes
           this.systemInfo = systemRes
@@ -199,10 +251,52 @@ export default {
       }
       }
     },
     },
 
 
+    // 切换团队:联动刷新成员/客户/统计(T31)
+    switchTeam(systemId) {
+      if (!systemId || systemId === this.currentSystemId) return
+      this.currentSystemId = systemId
+      this.systemInfo = null
+      this.hierarchyInfo = null
+      this.teamMembers = []
+      this.teamCustomers = []
+      this.loadTeamData()
+    },
+
+    // 按当前选中团队加载各数据源
+    async loadTeamData() {
+      // 竞态防护:仅应用最新一次切换的响应,避免快速切换时旧数据覆盖新团队
+      var seq = (this._teamLoadSeq || 0) + 1
+      this._teamLoadSeq = seq
+      try {
+        const [systemRes, hierarchyRes, membersRes, customersRes] = await Promise.all([
+          this.fetchSystemInfo(),
+          this.fetchHierarchyInfo(),
+          this.fetchTeamMembers(),
+          this.fetchTeamCustomers()
+        ])
+        if (seq !== this._teamLoadSeq) return
+        if (systemRes) {
+          this.systemInfo = systemRes
+        }
+        if (hierarchyRes) {
+          this.hierarchyInfo = hierarchyRes
+        }
+        if (membersRes) {
+          this.teamMembers = membersRes
+        }
+        if (customersRes) {
+          this.teamCustomers = customersRes
+        }
+        this.updateStats()
+      } catch (error) {
+        console.error('加载团队数据失败:', error)
+      }
+    },
+
     // 获取体系信息
     // 获取体系信息
     async fetchSystemInfo() {
     async fetchSystemInfo() {
       try {
       try {
-        const res = await getVendorSystemInfo()
+        const res = await getVendorSystemInfo(this.currentSystemId)
         return res.data || null
         return res.data || null
       } catch (e) {
       } catch (e) {
         return null
         return null
@@ -212,7 +306,7 @@ export default {
     // 获取层级关系
     // 获取层级关系
     async fetchHierarchyInfo() {
     async fetchHierarchyInfo() {
       try {
       try {
-        const res = await getVendorHierarchyInfo()
+        const res = await getVendorHierarchyInfo(this.currentSystemId)
         return res.data || null
         return res.data || null
       } catch (e) {
       } catch (e) {
         return null
         return null
@@ -222,7 +316,7 @@ export default {
     // 获取团队成员
     // 获取团队成员
     async fetchTeamMembers() {
     async fetchTeamMembers() {
       try {
       try {
-        const res = await getVendorTeamMembers(this.systemInfo && this.systemInfo.id)
+        const res = await getVendorTeamMembers(this.currentSystemId)
         return res.data || []
         return res.data || []
       } catch (e) {
       } catch (e) {
         return []
         return []
@@ -233,7 +327,7 @@ export default {
     async fetchTeamCustomers() {
     async fetchTeamCustomers() {
       try {
       try {
         const res = await getVendorTeamCustomers({
         const res = await getVendorTeamCustomers({
-          systemId: this.systemInfo && this.systemInfo.id,
+          systemId: this.currentSystemId,
           parentId: null,
           parentId: null,
           page: 1,
           page: 1,
           size: 50
           size: 50
@@ -257,10 +351,14 @@ export default {
       })
       })
     },
     },
 
 
-    // 跳转客户列表
+    // 跳转客户列表(携带当前团队)
     goToCustomers() {
     goToCustomers() {
+      var url = '/pages/vendor/team-customers/team-customers'
+      if (this.currentSystemId) {
+        url = url + '?systemId=' + this.currentSystemId
+      }
       uni.navigateTo({
       uni.navigateTo({
-        url: '/pages/vendor/team-customers/team-customers'
+        url: url
       })
       })
     }
     }
   }
   }
@@ -285,6 +383,47 @@ export default {
   box-shadow: 0 2rpx 12rpx rgba(249,115,22,0.08);
   box-shadow: 0 2rpx 12rpx rgba(249,115,22,0.08);
 }
 }
 
 
+/* 团队切换器(T31 多团队管理) */
+.team-switcher-wrap {
+  background-color: $app-surface;
+  padding: 20rpx 0;
+  margin-bottom: 24rpx;
+}
+
+.team-switcher {
+  width: 100%;
+  white-space: nowrap;
+}
+
+.team-tab {
+  display: inline-flex;
+  align-items: center;
+  padding: 12rpx 28rpx;
+  margin-left: $uni-space-lg;
+  border-radius: 999rpx;
+  background-color: $uni-primary-pale;
+  flex-shrink: 0;
+}
+
+.team-tab:last-child {
+  margin-right: $uni-space-lg;
+}
+
+.team-tab-active {
+  background-color: $brand-primary;
+}
+
+.team-tab-text {
+  font-size: calc(26rpx * var(--font-scale, 1));
+  color: $facade-text-body;
+  white-space: nowrap;
+}
+
+.team-tab-active .team-tab-text {
+  color: $app-surface;
+  font-weight: bold;
+}
+
 .system-info {
 .system-info {
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;

+ 15 - 4
cfc-frontend/utils/api.js

@@ -3429,11 +3429,22 @@ export const reviewGuideTask = (familyId, taskId, approved, comment) =>
   })
   })
 
 
 // 服务商团队体系相关API
 // 服务商团队体系相关API
-export const getVendorSystemInfo = () =>
-  request('/api/admin/supply-system/my-system', 'POST', {})
+// T31 多团队管理:my-system / supply-hierarchy/my 显式支持 systemId(缺省取默认团队);
+// my-teams 返回当前用户所属/创建的全部团队(顶部团队切换器数据源)
+export const getVendorSystemInfo = (systemId) => {
+  const data = {}
+  if (systemId) data.systemId = systemId
+  return request('/api/admin/supply-system/my-system', 'POST', data)
+}
+
+export const getVendorHierarchyInfo = (systemId) => {
+  const data = {}
+  if (systemId) data.systemId = systemId
+  return request('/api/admin/supply-hierarchy/my', 'POST', data)
+}
 
 
-export const getVendorHierarchyInfo = () =>
-  request('/api/admin/supply-hierarchy/my', 'POST', {})
+export const getVendorTeamList = () =>
+  request('/api/admin/supply-system/my-teams', 'POST', {})
 
 
 export const getVendorTeamMembers = (systemId) =>
 export const getVendorTeamMembers = (systemId) =>
   request('/api/admin/supply-team/members', 'POST', { systemId })
   request('/api/admin/supply-team/members', 'POST', { systemId })