|  | @@ -219,11 +219,6 @@ function themifyScript(
 | 
	
		
			
				|  |  |  上述的生成组件的脚本如下:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  ```javascript
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * 使用方式:node index.js --keys=key1,key2
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | - * 输出位置:当前目录下的 workspace/animated-component.vue 文件
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  |  const fs = require('fs');
 | 
	
		
			
				|  |  |  const path = require('path');
 | 
	
		
			
				|  |  |  const { parseString } = require('xml2js');
 | 
	
	
		
			
				|  | @@ -273,88 +268,74 @@ async function parseSVG(filePath) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  | - * 递归查找包含指定id的group元素
 | 
	
		
			
				|  |  | + * 递归查找所有包含指定id引用的group元素
 | 
	
		
			
				|  |  |   * @param {Object} node - XML节点对象
 | 
	
		
			
				|  |  |   * @param {string} id - 要查找的id
 | 
	
		
			
				|  |  | - * @returns {Object|null} 找到的group元素或null
 | 
	
		
			
				|  |  | + * @returns {Array} 找到的group元素数组
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  | -function findGroupWithId(node, id) {
 | 
	
		
			
				|  |  | -  // 检查当前节点是否有g元素
 | 
	
		
			
				|  |  | -  if (node.g && Array.isArray(node.g)) {
 | 
	
		
			
				|  |  | -    for (const group of node.g) {
 | 
	
		
			
				|  |  | -      // 检查group的id属性是否匹配
 | 
	
		
			
				|  |  | -      if (group.$ && group.$.id === id) {
 | 
	
		
			
				|  |  | -        return group;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // 递归检查子group
 | 
	
		
			
				|  |  | -      if (group.g) {
 | 
	
		
			
				|  |  | -        const result = findGroupWithId(group, id);
 | 
	
		
			
				|  |  | -        if (result) return group; // 返回找到的父group
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // 检查use元素是否引用了目标id
 | 
	
		
			
				|  |  | -      if (group.use && Array.isArray(group.use)) {
 | 
	
		
			
				|  |  | -        for (const use of group.use) {
 | 
	
		
			
				|  |  | -          if (use.$ && use.$['xlink:href'] === `#${id}`) {
 | 
	
		
			
				|  |  | -            return group;
 | 
	
		
			
				|  |  | +function findGroupsWithIdRef(node, id) {
 | 
	
		
			
				|  |  | +  const groups = [];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  function traverse(currentNode) {
 | 
	
		
			
				|  |  | +    if (!currentNode) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 检查当前节点是否为group且有use元素引用目标id
 | 
	
		
			
				|  |  | +    if (currentNode.g && Array.isArray(currentNode.g)) {
 | 
	
		
			
				|  |  | +      for (const group of currentNode.g) {
 | 
	
		
			
				|  |  | +        // 检查group是否有use元素引用目标id
 | 
	
		
			
				|  |  | +        if (group.use && Array.isArray(group.use)) {
 | 
	
		
			
				|  |  | +          for (const use of group.use) {
 | 
	
		
			
				|  |  | +            if (use.$ && use.$['xlink:href'] === `#${id}`) {
 | 
	
		
			
				|  |  | +              groups.push(currentNode);
 | 
	
		
			
				|  |  | +              break;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 递归检查子元素
 | 
	
		
			
				|  |  | +        traverse(group);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  return null;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * 从group元素中提取transform值
 | 
	
		
			
				|  |  | - * @param {Object} group - group元素对象
 | 
	
		
			
				|  |  | - * @returns {string|null} transform值或null
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -function extractTransform(group) {
 | 
	
		
			
				|  |  | -  if (!group || !group.$ || !group.$.transform) return null;
 | 
	
		
			
				|  |  | -  return group.$.transform;
 | 
	
		
			
				|  |  | +  traverse(node);
 | 
	
		
			
				|  |  | +  return groups;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  | - * 为SVG元素添加动态类绑定
 | 
	
		
			
				|  |  | + * 为SVG元素添加唯一标识和初始transform
 | 
	
		
			
				|  |  |   * @param {Object} svgData - 解析后的SVG对象
 | 
	
		
			
				|  |  | - * @param {Array<string>} keys - 需要添加绑定的key数组
 | 
	
		
			
				|  |  | - * @returns {Object} 修改后的SVG对象
 | 
	
		
			
				|  |  | + * @param {Array<string>} keys - 需要处理的key数组
 | 
	
		
			
				|  |  | + * @returns {Object} 修改后的SVG对象和元素映射
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  | -function addDynamicClassBinding(svgData, keys) {
 | 
	
		
			
				|  |  | +function addElementIdentifiers(svgData, keys) {
 | 
	
		
			
				|  |  | +  const elementInfoMap = new Map();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    keys.forEach((key) => {
 | 
	
		
			
				|  |  | -    const group = findGroupWithId(svgData, key);
 | 
	
		
			
				|  |  | -    if (group && group.$) {
 | 
	
		
			
				|  |  | -      // 添加动态类绑定
 | 
	
		
			
				|  |  | -      group.$[':class'] = `{${key}_animate:!manager.${key},${key}_animate_reverse:manager.${key}}`;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  return svgData;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | +    const groups = findGroupsWithIdRef(svgData, key);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * 生成CSS keyframes动画
 | 
	
		
			
				|  |  | - * @param {string} animationName - 动画名称
 | 
	
		
			
				|  |  | - * @param {Array<string>} transforms - 变换矩阵数组
 | 
	
		
			
				|  |  | - * @returns {string} 生成的CSS代码
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -function generateKeyframes(animationName, transforms) {
 | 
	
		
			
				|  |  | -  const steps = transforms.length;
 | 
	
		
			
				|  |  | -  let css = `@keyframes ${animationName} {\n`;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  transforms.forEach((transform, index) => {
 | 
	
		
			
				|  |  | -    if (transform) {
 | 
	
		
			
				|  |  | -      // 计算当前关键帧的百分比
 | 
	
		
			
				|  |  | -      const percentage = (index / (steps - 1)) * 100;
 | 
	
		
			
				|  |  | -      css += `  ${percentage.toFixed(0)}% {\n`;
 | 
	
		
			
				|  |  | -      css += `    transform: ${transform};\n`;
 | 
	
		
			
				|  |  | -      css += `  }\n`;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    groups.forEach((group, counter) => {
 | 
	
		
			
				|  |  | +      const elementId = `anim_${key}_${counter++}`;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // 确保group有属性对象
 | 
	
		
			
				|  |  | +      if (!group.$) group.$ = {};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // 添加唯一标识
 | 
	
		
			
				|  |  | +      group.$['data-anim-id'] = elementId;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // 保存初始transform
 | 
	
		
			
				|  |  | +      const transform = group.$.transform || '';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // 存储元素信息
 | 
	
		
			
				|  |  | +      elementInfoMap.set(elementId, {
 | 
	
		
			
				|  |  | +        key,
 | 
	
		
			
				|  |  | +        initialTransform: transform,
 | 
	
		
			
				|  |  | +        transforms: [], // 将在后续步骤填充
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  |    });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  css += '}\n';
 | 
	
		
			
				|  |  | -  return css;
 | 
	
		
			
				|  |  | +  return { modifiedSvg: svgData, elementInfoMap };
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
	
		
			
				|  | @@ -379,50 +360,127 @@ function extractSVGContent(svgObj) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  | - * 生成Vue组件文件内容
 | 
	
		
			
				|  |  | - * @param {string} svgContent - SVG内容字符串
 | 
	
		
			
				|  |  | - * @param {Object} transformsByKey - 每个key的transform数组
 | 
	
		
			
				|  |  | - * @param {Object} firstTransforms - 第一个SVG文件中每个key的transform
 | 
	
		
			
				|  |  | - * @param {Object} lastTransforms - 最后一个SVG文件中每个key的transform
 | 
	
		
			
				|  |  | - * @param {Array<string>} keys - key数组
 | 
	
		
			
				|  |  | - * @returns {string} 生成的Vue组件内容
 | 
	
		
			
				|  |  | + * 收集所有SVG文件中每个元素的transform变化
 | 
	
		
			
				|  |  | + * @param {string} workspaceDir - 工作目录路径
 | 
	
		
			
				|  |  | + * @param {Array} files - SVG文件列表
 | 
	
		
			
				|  |  | + * @param {Map} elementInfoMap - 元素信息Map
 | 
	
		
			
				|  |  | + * @returns {Promise<Map>} 更新后的元素信息Map
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  | -function generateVueComponent(svgContent, transformsByKey, firstTransforms, lastTransforms, keys) {
 | 
	
		
			
				|  |  | -  let template = `<template>\n${svgContent}\n</template>\n\n`;
 | 
	
		
			
				|  |  | +async function collectTransforms(workspaceDir, files, elementInfoMap) {
 | 
	
		
			
				|  |  | +  // 为每个元素初始化transform序列
 | 
	
		
			
				|  |  | +  for (const [elementId, info] of elementInfoMap) {
 | 
	
		
			
				|  |  | +    info.transforms = [];
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  let script = `<script setup lang="ts">\ndefineProps<{\nmanager:Record<string, boolean>;\n}>();\n</script>\n\n`;
 | 
	
		
			
				|  |  | +  // 按顺序处理所有SVG文件
 | 
	
		
			
				|  |  | +  for (const file of files) {
 | 
	
		
			
				|  |  | +    const filePath = path.join(workspaceDir, file);
 | 
	
		
			
				|  |  | +    const svgData = await parseSVG(filePath);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  let style = `<style scoped>\n`;
 | 
	
		
			
				|  |  | +    // 为每个元素查找对应的transform
 | 
	
		
			
				|  |  | +    for (const [elementId, info] of elementInfoMap) {
 | 
	
		
			
				|  |  | +      const key = info.key;
 | 
	
		
			
				|  |  | +      const groups = findGroupsWithIdRef(svgData.svg, key);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // 为每个key生成样式
 | 
	
		
			
				|  |  | -  keys.forEach((key) => {
 | 
	
		
			
				|  |  | -    const animationName = key.replace(/^___/, '').replace(/_/g, '');
 | 
	
		
			
				|  |  | +      // 查找具有相同相对位置的group(假设顺序一致)
 | 
	
		
			
				|  |  | +      const elementIndex = parseInt(elementId.split('_').pop());
 | 
	
		
			
				|  |  | +      if (groups[elementIndex] && groups[elementIndex].$ && groups[elementIndex].$.transform) {
 | 
	
		
			
				|  |  | +        info.transforms.push(groups[elementIndex].$.transform);
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        // 如果找不到transform,使用前一个值或初始值
 | 
	
		
			
				|  |  | +        const lastTransform = info.transforms.length > 0 ? info.transforms[info.transforms.length - 1] : info.initialTransform;
 | 
	
		
			
				|  |  | +        info.transforms.push(lastTransform);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // 添加keyframes
 | 
	
		
			
				|  |  | -    style += generateKeyframes(animationName, transformsByKey[key]);
 | 
	
		
			
				|  |  | +  return elementInfoMap;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // 添加正向动画类
 | 
	
		
			
				|  |  | -    style += `.${key}_animate {\n`;
 | 
	
		
			
				|  |  | -    style += `transition: transform 3s;\n`;
 | 
	
		
			
				|  |  | -    if (lastTransforms[key]) {
 | 
	
		
			
				|  |  | -      style += `transform: ${lastTransforms[key]};\n`;
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 生成Vue组件文件内容
 | 
	
		
			
				|  |  | + * @param {string} svgContent - SVG内容字符串
 | 
	
		
			
				|  |  | + * @param {Map} elementInfoMap - 元素信息Map
 | 
	
		
			
				|  |  | + * @param {Array<string>} keys - key数组
 | 
	
		
			
				|  |  | + * @returns {string} 生成的Vue组件内容
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function generateVueComponent(svgContent, elementInfoMap, keys) {
 | 
	
		
			
				|  |  | +  return `
 | 
	
		
			
				|  |  | +<template>\n${svgContent}\n</template>\n\n
 | 
	
		
			
				|  |  | +<script setup lang="ts">
 | 
	
		
			
				|  |  | +import { watch, onMounted, defineExpose, defineProps } from "vue";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const props = defineProps<{
 | 
	
		
			
				|  |  | +  manager: Record<string, boolean>;
 | 
	
		
			
				|  |  | +}>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 存储所有动画元素(不在模板中使用,不需要ref)
 | 
	
		
			
				|  |  | +const animElements = new Map<string, HTMLElement>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 元素信息(常量数据,使用Map)
 | 
	
		
			
				|  |  | +const elementInfo = new Map([
 | 
	
		
			
				|  |  | +${Array.from(elementInfoMap.entries())
 | 
	
		
			
				|  |  | +  .map(([key, value]) => `  ["${key}", ${JSON.stringify(value)}]`)
 | 
	
		
			
				|  |  | +  .join(',\n')}
 | 
	
		
			
				|  |  | +]);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 初始化元素引用
 | 
	
		
			
				|  |  | +onMounted(() => {
 | 
	
		
			
				|  |  | +  elementInfo.forEach((info, elementId) => {
 | 
	
		
			
				|  |  | +    const el = document.querySelector(\`[data-anim-id="\${elementId}"]\`);
 | 
	
		
			
				|  |  | +    if (el) {
 | 
	
		
			
				|  |  | +      animElements.set(elementId, el as HTMLElement);
 | 
	
		
			
				|  |  | +      // 设置初始transform
 | 
	
		
			
				|  |  | +      const initialTransform = info.transforms[0] || '';
 | 
	
		
			
				|  |  | +      el.setAttribute('transform', initialTransform);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    style += `/*animation: ${animationName} 3s forwards;*/\n`;
 | 
	
		
			
				|  |  | -    style += `}\n\n`;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 添加反向动画类
 | 
	
		
			
				|  |  | -    style += `.${key}_animate_reverse {\n`;
 | 
	
		
			
				|  |  | -    style += `transition: transform 3s;\n`;
 | 
	
		
			
				|  |  | -    if (firstTransforms[key]) {
 | 
	
		
			
				|  |  | -      style += `transform: ${firstTransforms[key]};\n`;
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 监听manager变化并执行动画
 | 
	
		
			
				|  |  | +watch(() => props.manager, (newManager) => {
 | 
	
		
			
				|  |  | +  Object.keys(newManager).forEach(key => {
 | 
	
		
			
				|  |  | +    const isActive = newManager[key];
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // 找到所有属于这个key的元素
 | 
	
		
			
				|  |  | +    animateByKey(key, isActive);
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +}, { deep: true });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 直接控制动画的方法
 | 
	
		
			
				|  |  | +const animateElement = (elementId: string, toEnd: boolean, duration: number = 3000) => {
 | 
	
		
			
				|  |  | +  const el = animElements.get(elementId);
 | 
	
		
			
				|  |  | +  const info = elementInfo.get(elementId);
 | 
	
		
			
				|  |  | +  
 | 
	
		
			
				|  |  | +  if (el && info && info.transforms.length > 1) {
 | 
	
		
			
				|  |  | +    el.style.transition = \`transform \${duration}ms\`;
 | 
	
		
			
				|  |  | +    el.setAttribute('transform', toEnd ? info.transforms[info.transforms.length - 1] : info.transforms[0]);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 批量控制同一key的所有元素
 | 
	
		
			
				|  |  | +const animateByKey = (key: string, toEnd: boolean, duration: number = 3000) => {
 | 
	
		
			
				|  |  | +  animElements.forEach((el, elementId) => {
 | 
	
		
			
				|  |  | +    const info = elementInfo.get(elementId);
 | 
	
		
			
				|  |  | +    if (info && info.key === key) {
 | 
	
		
			
				|  |  | +      animateElement(elementId, toEnd, duration);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    style += `/*animation: ${animationName} 3s forwards reverse;*/\n`;
 | 
	
		
			
				|  |  | -    style += `}\n\n`;
 | 
	
		
			
				|  |  |    });
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  style += `</style>`;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  return template + script + style;
 | 
	
		
			
				|  |  | +// 导出方法以便外部调用
 | 
	
		
			
				|  |  | +defineExpose({
 | 
	
		
			
				|  |  | +  animateElement,
 | 
	
		
			
				|  |  | +  animateByKey
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +</script>
 | 
	
		
			
				|  |  | +<style scoped>
 | 
	
		
			
				|  |  | +/* 可以添加一些基础样式 */
 | 
	
		
			
				|  |  | +[data-anim-id] {
 | 
	
		
			
				|  |  | +  transition: transform 3s;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +</style>`;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
	
		
			
				|  | @@ -457,54 +515,26 @@ async function main() {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      console.log(`找到 ${files.length} 个SVG文件`);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // 为每个key创建transform数组
 | 
	
		
			
				|  |  | -    const transformsByKey = {};
 | 
	
		
			
				|  |  | -    const firstTransforms = {};
 | 
	
		
			
				|  |  | -    const lastTransforms = {};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    keys.forEach((key) => {
 | 
	
		
			
				|  |  | -      transformsByKey[key] = [];
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 按顺序处理所有SVG文件
 | 
	
		
			
				|  |  | -    for (const file of files) {
 | 
	
		
			
				|  |  | -      const filePath = path.join(workspaceDir, file);
 | 
	
		
			
				|  |  | -      const svgData = await parseSVG(filePath);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // 为每个key查找对应的group并提取transform
 | 
	
		
			
				|  |  | -      for (const key of keys) {
 | 
	
		
			
				|  |  | -        const group = findGroupWithId(svgData.svg, key);
 | 
	
		
			
				|  |  | -        const transform = extractTransform(group);
 | 
	
		
			
				|  |  | -        transformsByKey[key].push(transform);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        // 如果是第一个文件,保存transform
 | 
	
		
			
				|  |  | -        if (file === files[0]) {
 | 
	
		
			
				|  |  | -          firstTransforms[key] = transform;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        // 如果是最后一个文件,保存transform
 | 
	
		
			
				|  |  | -        if (file === files[files.length - 1]) {
 | 
	
		
			
				|  |  | -          lastTransforms[key] = transform;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 读取第一个SVG文件并添加动态类绑定
 | 
	
		
			
				|  |  | +    // 读取第一个SVG文件
 | 
	
		
			
				|  |  |      const firstSvgPath = path.join(workspaceDir, files[0]);
 | 
	
		
			
				|  |  |      const firstSvgData = await parseSVG(firstSvgPath);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // 添加动态类绑定
 | 
	
		
			
				|  |  | -    const modifiedSvgData = addDynamicClassBinding(firstSvgData.svg, keys);
 | 
	
		
			
				|  |  | +    // 为SVG元素添加唯一标识
 | 
	
		
			
				|  |  | +    const { modifiedSvg, elementInfoMap } = addElementIdentifiers(firstSvgData.svg, keys);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 收集所有SVG文件中每个元素的transform变化
 | 
	
		
			
				|  |  | +    const updatedElementInfoMap = await collectTransforms(workspaceDir, files, elementInfoMap);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // 提取SVG内容(不包含XML声明和根标签)
 | 
	
		
			
				|  |  | -    const svgContent = extractSVGContent(modifiedSvgData);
 | 
	
		
			
				|  |  | +    const svgContent = extractSVGContent(modifiedSvg);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // 生成Vue组件
 | 
	
		
			
				|  |  | -    const vueComponent = generateVueComponent(svgContent, transformsByKey, firstTransforms, lastTransforms, keys);
 | 
	
		
			
				|  |  | +    const vueComponent = generateVueComponent(svgContent, updatedElementInfoMap, keys);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // 写入Vue组件文件
 | 
	
		
			
				|  |  |      fs.writeFileSync(outputFile, vueComponent);
 | 
	
		
			
				|  |  |      console.log(`Vue组件已生成: ${outputFile}`);
 | 
	
		
			
				|  |  | +    console.log(`共找到 ${updatedElementInfoMap.size} 个动画元素`);
 | 
	
		
			
				|  |  |    } catch (error) {
 | 
	
		
			
				|  |  |      console.error('错误:', error.message);
 | 
	
		
			
				|  |  |      process.exit(1);
 |