You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用API更新Azure DevOps CFD组件后Web界面报错

问题

我编写了Python代码,通过Azure DevOps的Dashboard Widget更新API自动修改Cumulative Flow Diagram(CFD)组件的设置,使其显示过去14、15、16天的数据。API请求返回成功,但Web界面打开时抛出错误:

TypeError: e.split is not a function

尝试改用多行格式设置时,又出现了SyntaxError。以下是相关代码,请问如何修复该问题?

主代码

import fazer_requisicoes
import json
import base64
import os
from dotenv import load_dotenv
from pprint import pp

load_dotenv()

token_do_azure = os.environ['AZURE_DEVOPS_PAT']

pat_encoded = base64.b64encode((":" + token_do_azure).encode()).decode()
headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Basic {pat_encoded}'
}

settings_dict = {
    "chartDataSettings": {
        "timePeriod": {
            "settings": 16
        }
    }
}

def atualizar_cfd():
    organization = 'dummy'
    project = 'dummy'
    team = 'dummy'
    dashboard_id = 'dummy'
    widget_id = 'dummy'
    url = f'https://dev.azure.com/{organization}/{project}/{team}/_apis/dashboard/dashboards/{dashboard_id}/widgets/{widget_id}?api-version=7.2-preview.2'
    get_req = fazer_requisicoes.fazer_requisicoes("GET", url, headers)
    get_req_text = json.loads(get_req.text)
    # 假设ETag在响应体中,否则从headers获取
    current_etag_widget = get_req_text['eTag']
    current_etag_dashboard = get_req_text['dashboard']['eTag']
    pp(current_etag_widget)
    pp(current_etag_dashboard)
    url = f'https://dev.azure.com/{organization}/{project}/{team}/_apis/dashboard/dashboards/{dashboard_id}/widgets/{widget_id}?api-version=7.2-preview.2'
    req_body = {
        "id": widget_id,
        "name": "Cumulative Flow Diagram (CFD)",
        "eTag": f'{current_etag_widget}',
        'position': {'row': 4, 'column': 5},
        "size": {
            "rowSpan": 2, "columnSpan": 3
        },
        'settings': settings_dict,
        "settingsVersion":
        {
            "major": 1,
            "minor": 0,
            "patch": 0
        },
        "contributionId": "ms.vss-dashboards-web.Microsoft.VisualStudioOnline.Dashboards.CumulativeFlowDiagramWidget",
        'dashboard': {'position': -1,
                      'eTag': f'{current_etag_dashboard}',
                      'modifiedDate': '0001-01-01T00:00:00',
                      'lastAccessedDate': '0001-01-01T00:00:00'},
    }
    req = fazer_requisicoes.fazer_requisicoes("PATCH", url, headers, req_body)
    req_text = json.loads(req.text)
    req_response = json.dumps(req_text)
    pp(req_response)


def main():
    atualizar_cfd()


main()

请求函数代码

import requests
import time
import urllib3
from requests.exceptions import JSONDecodeError
from pprint import pprint

urllib3.disable_warnings()

session = requests.Session()

contador_timeout = 0
contador_SSL = 0

def fazer_requisicoes(metodo, url, headers, request_body=None):
    global contador_timeout
    global contador_SSL

    while True:
        try:
            if metodo in ['GET', 'DELETE']:
                req = session.request(metodo, url, headers=headers, verify=False)
            else:
                req = session.request(metodo, url, headers=headers, json=request_body, verify=False)
                try:
                    req.json()
                except JSONDecodeError:
                    print(f'{req.status_code}\n')
                    pprint(req.text)
                    print(f"收到无效响应,重试中...")
                    time.sleep(10)
                    continue 
            return req
        except requests.exceptions.ConnectTimeout as e:
            contador_timeout += 1
            print(f"第{contador_timeout}次超时错误,重试中...")
            time.sleep(10)
        except requests.exceptions.SSLError as e:
            contador_SSL += 1
            print(f"第{contador_SSL}次SSL错误,重试中...")
            time.sleep(10)

解决方案

1. 修正CFD组件的设置结构

Web界面的TypeError: e.split is not a function错误,是因为前端期望处理字符串类型的配置值,但你传入了数字类型。同时CFD组件的timePeriod配置必须明确指定类型,否则前端无法识别格式。

修改settings_dict为以下结构:

settings_dict = {
    "chartDataSettings": {
        "timePeriod": {
            "type": "daysBack",  # 指定时间范围类型为回溯天数
            "settings": "16"     # 改为字符串类型,匹配前端处理逻辑
        }
    }
}

2. 复用正确的settingsVersion

CFD组件的配置版本可能存在兼容性要求,手动指定的major:1可能不匹配。建议从GET请求返回的widget数据中直接复用现有版本:

# 在GET请求后添加
current_settings_version = get_req_text['settingsVersion']

然后在请求体中替换手动指定的版本:

"settingsVersion": current_settings_version,

3. 简化请求体中的dashboard字段

请求体中的dashboard字段仅需传入eTag即可,多余的字段可能引发前端解析异常:

'dashboard': {'eTag': current_etag_dashboard},

完整修改后的主代码片段

# ... 其他代码保持不变 ...

def atualizar_cfd():
    organization = 'dummy'
    project = 'dummy'
    team = 'dummy'
    dashboard_id = 'dummy'
    widget_id = 'dummy'
    url = f'https://dev.azure.com/{organization}/{project}/{team}/_apis/dashboard/dashboards/{dashboard_id}/widgets/{widget_id}?api-version=7.2-preview.2'
    get_req = fazer_requisicoes.fazer_requisicoes("GET", url, headers)
    get_req_text = json.loads(get_req.text)
    current_etag_widget = get_req_text['eTag']
    current_etag_dashboard = get_req_text['dashboard']['eTag']
    current_settings_version = get_req_text['settingsVersion']  # 复用现有版本号
    pp(current_etag_widget)
    pp(current_etag_dashboard)
    
    # 修正后的设置
    settings_dict = {
        "chartDataSettings": {
            "timePeriod": {
                "type": "daysBack",
                "settings": "16"
            }
        }
    }
    
    req_body = {
        "id": widget_id,
        "name": "Cumulative Flow Diagram (CFD)",
        "eTag": current_etag_widget,
        'position': {'row': 4, 'column': 5},
        "size": {"rowSpan": 2, "columnSpan": 3},
        'settings': settings_dict,
        "settingsVersion": current_settings_version,
        "contributionId": "ms.vss-dashboards-web.Microsoft.VisualStudioOnline.Dashboards.CumulativeFlowDiagramWidget",
        'dashboard': {'eTag': current_etag_dashboard},  # 简化dashboard字段
    }
    req = fazer_requisicoes.fazer_requisicoes("PATCH", url, headers, req_body)
    req_text = json.loads(req.text)
    req_response = json.dumps(req_text)
    pp(req_response)

修复原理

  • 添加timePeriod.type字段:明确告知CFD组件使用"回溯天数"的时间范围类型,符合前端解析逻辑。
  • 将settings值改为字符串:前端代码依赖字符串的split方法处理配置,数字类型会触发类型错误。
  • 复用现有settingsVersion:避免因版本不匹配导致的配置兼容性问题。
  • 简化dashboard字段:只保留必要的eTag,减少无关字段引发的解析异常。

内容的提问来源于stack exchange,提问作者fcoalcantarajr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 23:43:14