好的 - 我写了一个例子,我认为它说明了到达你想去的地方需要什么。它通过在 queryConfig 数组中执行两个查询来做到这一点:一个用于用户,另一个用于 UserIterationCapacity,用于感兴趣的迭代。然后,在 processResults 函数中,代码构造了三个哈希:
teamMembersByTeamName:每个项目的团队成员字符串,hashkey:团队/项目名称 
myTeamList:包含来自用户(第一个)查询的用户数据,为感兴趣的团队选择,hashkey:用户名 
userIterationCapacityByUser: 包含来自第二个查询的 UserIterationCapacity 数据,hashkey: UserName 
最后,代码通过 UserName 进行交叉遍历,为所有 TeamMember 重新构建容量数据,即使他们没有为感兴趣的 Sprint 定义容量。如果是这种情况,容量将显示为“N/A”。
您需要自定义workspaceOID、projectOID和myTeamSlashProjectName变量以使其在您的环境中工作。您可能想要自定义和调整 - 这只是一个粗略的代码示例。但希望足以说明这个概念。
    <!-- Copyright (c) 2012 Rally Software Development Corp. All rights reserved -->
    <html>
    <head>
       <title>Team Capacity Summary Example</title>
       <meta name="Name" content="App Example: Team Capacity Summary" />
       <meta name="Version" content="1.31" />
       <meta name="Vendor" content="Rally Labs" />
       <script type="text/javascript" src="https://rally1.rallydev.com/apps/1.31/sdk.js"></script>
       <script type="text/javascript">
       var rallyDataSource = null;
       var iterationDropdown = null;
       var selectedIteration = "Iteration 1";
       var workspaceOID = "12345678910";
       var projectOID = "12345678911";
       var myTeamSlashProjectName = "My Project";
       var table;
        function iterationSelected(dropdown, eventArgs) {
              var selectedItem = eventArgs.item;
              selectedIteration = eventArgs.value;
              runMainQuery();
        }
        function runMainQuery() {
            var queryConfig = [];
            var capacityQueryString = '((Iteration.Name = ' + '"' + 
                    selectedIteration + 
                    '") AND (Project.ObjectID = "' + 
                    projectOID +
                     '"))';
            console.log(capacityQueryString);
            queryConfig[0] = {
                key: "usercapacities", 
                type: "UserIterationCapacity", 
                fetch: "Capacity,User,Role,EmailAddress,DisplayName,UserName",
                query: capacityQueryString
            };
            queryConfig[1] = {
                type: "users",
                key:  "userdata",
                fetch: "UserName,EmailAddress,DisplayName,UserName,UserPermissions,Project,Role,Name,TeamMemberships,Project,Name"
            };          
            rallyDataSource.findAll(queryConfig, processResults);
        }
        function processResults(results) {      
            // Populate a hash of team members by team name 
            var teamMembersByTeamName= new Array();
            for (i=0;i<results.userdata.length;i++){
                myUser = results.userdata[i];
                myUserName = myUser.UserName;
                myEmailAddress = myUser.EmailAddress;
                myDisplayName = myUser.DisplayName;
                myRole = "N/A";
                if (myUser.TeamMemberships) {
                    myTeamMemberships = myUser.TeamMemberships;
                    for (j=0;j<myTeamMemberships.length;j++) {
                        thisTeam = myTeamMemberships[j];
                        thisTeamName = thisTeam.Name;
                        if (!(thisTeamName in teamMembersByTeamName)) {
                            teamMembersByTeamName[thisTeamName] = [];
                        }
                        var dataToPush = new Array();
                        dataToPush["UserName"] = myUserName;
                        dataToPush["EmailAddress"] = myEmailAddress;
                        dataToPush["DisplayName"] = myDisplayName;
                        dataToPush["Role"] = myRole;
                        dataToPush["Capacity"] = "N/A";
                        teamMembersByTeamName[thisTeamName].push(dataToPush);
                    }
                }
            }
            // Now populate a hash of User Capacities
            var userIterationCapacityByUser = new Array();
            for (i=0;i<results.usercapacities.length;i++) {
                thisCapacityObject = results.usercapacities[i];
                thisUserName = thisCapacityObject.User.UserName;
                if (!(thisUserName in userIterationCapacityByUser)) {
                    thisUser = thisCapacityObject.User;
                    thisCapacity = thisCapacityObject.Capacity;
                    userIterationCapacityByUser[thisUserName] = [];
                    var dataToPush = new Array();
                    dataToPush["UserName"] = thisUser.UserName;
                    dataToPush["EmailAddress"] = thisUser.EmailAddress;
                    dataToPush["DisplayName"] = thisUser.DisplayName;
                    dataToPush["Role"] = thisUser.Role;
                    dataToPush["Capacity"] = thisCapacity;
                    userIterationCapacityByUser[thisUserName].push(dataToPush);             
                }
            }
            // Setup and configure the table
            var tableDiv = document.getElementById('tableDiv');
            var tableConfig = { columns: 
                 [{key: 'emailaddress', header: 'Team Member Email', width: 200}, 
                 {key: 'displayname', header: 'Display name'},
                 {key: 'username', header: 'User name'},
                 {key: 'role', header: 'Role'},
                 {key: 'cap', header: 'Capacity'}] };
            if(table != null){
                table.destroy();
            }
            table = new rally.sdk.ui.Table(tableConfig);        
            // Finally cross-walk team membership by correlating the data from the two hashes
            // Grab team list of interest
            myTeamList = teamMembersByTeamName[myTeamSlashProjectName];
            for(i=0;i<myTeamList.length;i++) {
                myTeamMemberData = myTeamList[i];
                myUserNameFromTeamList = myTeamMemberData["UserName"];
                // User has capacity information - populate data from that result set
                if (myUserNameFromTeamList in userIterationCapacityByUser) {                
                    myUserDataArray = userIterationCapacityByUser[myUserNameFromTeamList];
                    myUserData = myUserDataArray[0];            
                } // User doesn't have capacity information - populate data from user query
                else {
                    myUserData = myTeamMemberData;
                }
                var myUserName = myUserData["UserName"];
                var myEmailAddress = myUserData["EmailAddress"];
                var myDisplayName = myUserData["DisplayName"];
                var myRole = myUserData["Role"];
                var myCapacity = myUserData["Capacity"];
                if (myDisplayName) { 
                    thisDisplayName = myDisplayName;
                } else {
                    thisDisplayName = "N/A";
                }
                var rowInfo = {
                    'emailaddress': myEmailAddress, 
                    'displayname': thisDisplayName, 
                    'username': myUserName,
                    'role' : myRole, 
                    'cap' : myCapacity};
                table.addRow(rowInfo);
            }
            var tableDiv = document.getElementById("tableDiv");     
            table.display(tableDiv);
        }
        function onLoad() {
          rallyDataSource = new rally.sdk.data.RallyDataSource('__WORKSPACE_OID__',
                                                       '__PROJECT_OID__',
                                                       '__PROJECT_SCOPING_UP__',
                                                       '__PROJECT_SCOPING_DOWN__');
          var config = {
                label : "Select an iteration ",
                defaultDisplayValue: selectedIteration
          };
          var iterationDropdown = new rally.sdk.ui.IterationDropdown(config, rallyDataSource);
          iterationDropdown.display("aDiv", iterationSelected);
        }
           rally.addOnLoad(onLoad);
        </script>
    </head>
      <body>
        <div id="aDiv"></div>
        <div id="tableDiv"></div>
    </body>
    </html>