getChartData.ts 2.5 KB
export interface ValueItem {
  value: number;
  itemStyle?: {
    color: string;
  };
}

export interface ChartData {
  categories: string[];
  values: ValueItem[];
}
export interface ChartComponentProps {
  data: {
    categories: string[];
    values: ValueItem[];
  };
}

export function extractDataFromText(text: string): ChartComponentProps | null {
  const startMarkers = ["```javascript", "```json"];
  let dataStartIndex = -1;
  let markerLength = 0;

  // 查找有效的数据块起始标记
  for (const marker of startMarkers) {
    const index = text.indexOf(marker);
    if (index !== -1) {
      dataStartIndex = index;
      markerLength = marker.length;
      break;
    }
  }

  let parsedData: any = null;

  // 如果找到有效数据块
  if (dataStartIndex !== -1) {
    // 查找数据块结束标记
    const dataEndIndex = text.indexOf("```", dataStartIndex + markerLength);
    if (dataEndIndex !== -1) {
      // 提取并清理数据块内容
      const dataBlock = text
        .slice(dataStartIndex + markerLength, dataEndIndex)
        .trim()
        .replace(/'/g, '"') // 转换单引号为双引号
        .replace(/(\w+)(?=\s*:)/g, '"$1"'); // 为键添加双引号

      try {
        // 尝试安全解析数据块内容
        parsedData = JSON.parse(dataBlock);
      } catch (error) {
        return null;
      }
    }
  }

  // 如果没有找到数据块,尝试将整个文本解析为 ChartData
  if (!parsedData) {
    try {
      const potentialData: any = JSON.parse(text);
      // 验证解析后的数据是否符合 ChartData 结构
      if (
        potentialData &&
        Array.isArray(potentialData.categories) &&
        potentialData.categories.every((c: any) => typeof c === "string") &&
        Array.isArray(potentialData.values) &&
        potentialData.values.every(
          (v: any) =>
            typeof v?.value === "number" &&
            v?.itemStyle &&
            typeof v.itemStyle?.color === "string",
        )
      ) {
        parsedData = potentialData;
      }
    } catch (error) {
      return null; // 如果解析失败,返回 null
    }
  }

  // 如果成功解析了数据并且符合 ChartData 类型,返回
  if (
    parsedData &&
    Array.isArray(parsedData.categories) &&
    Array.isArray(parsedData.values) &&
    parsedData.values.every(
      (v: any) =>
        typeof v?.value === "number" &&
        v?.itemStyle &&
        typeof v.itemStyle?.color === "string",
    )
  ) {
    return { data: parsedData as ChartData };
  }

  return null; // 如果未满足条件,则返回 null
}