<template>
  <div class="app-container">
    <div class="containerBlock">
      <!-- 添加加载状态和错误提示 -->
      <div v-if="loadingError" class="error-message">
        {{ loadingError }}
      </div>
      <div v-if="!isWidgetReady" class="loading-message">
        加载中...
      </div>

      <div class="toolbar" v-if="isWidgetReady">
        <v-btn
          class="tool-button"
          @click="toggleDrawText"
          :class="{ 'active': isDrawingText }"
        >
          <v-icon>mdi-format-text</v-icon>
          Draw Text
        </v-btn>
        <!-- 添加画笔工具按钮 -->
        <v-btn
          class="tool-button"
          @click="toggleLineStylePanel"
          :class="{ 'active': showLineStylePanel }"
        >
          <v-icon>mdi-lead-pencil</v-icon>
          Draw Pencil
        </v-btn>
        <!-- 添加颜色映射选择器 -->
        <div class="color-maps">
          <span class="color-maps-label">颜色映射:</span>
          <el-select v-model="currentColorMap" @change="switchColorMap" size="small">
            <el-option 
              v-for="map in colorMaps" 
              :key="map" 
              :label="map" 
              :value="map">
            </el-option>
          </el-select>
        </div>
        
        <!-- 添加工具栏控制组件 -->
        <toolbar-controls 
          :plots="plots" 
          :data-loaded="isWidgetReady" 
          :show-line-style-panel="showLineStylePanel"
          @toggleLineStylePanel="toggleLineStylePanel"
          @exporting="exporting = $event"
          @closePrintDialog="showPrintDialog = false" />
      </div>
      <canvas ref="plot" id="canvas"/>

      <!-- 自定义右键菜单 -->
      <div v-if="contextMenu.visible" class="context-menu" :style="{
          left: `${contextMenu.x}px`,
          top: `${contextMenu.y}px`
      }" @mouseleave="hideContextMenu">
          <div v-for="(item, index) in contextMenuItems" :key="index">
              <div v-if="item.type === 'separator'" class="context-menu-separator">
              </div>
              <div v-else class="context-menu-item" :class="{ disabled: !isMenuItemEnabled(item.action) }"
                  @click="handleMenuAction(item.action)">
                  <span>
                      <v-icon small class="mr-2">{{ item.icon }}</v-icon>
                      {{ item.text }}
                  </span>
                  <span class="shortcut" v-if="item.shortcut">{{ item.shortcut }}</span>
              </div>
          </div>
      </div>

      <!-- 文本样式面板 -->
      <div class="style-panel text-style-panel" :class="{ 'style-panel-visible': showTextStylePanel }">
        <div class="style-panel-header">
          <h3>文本样式</h3>
          <el-button icon="el-icon-close" size="mini" circle @click="showTextStylePanel = false"></el-button>
        </div>
        <div class="style-content">
          <!-- 填充样式部分 -->
          <div class="style-section-title">填充样式</div>
          <div class="style-item">
            <span class="style-label">颜色：</span>
            <el-color-picker v-model="fillStyle.color" show-alpha @change="updateFillStyle">
            </el-color-picker>
          </div>
          <div class="style-item">
            <span class="style-label">样式：</span>
            <el-select v-model="fillStyle.pattern" placeholder="选择填充样式" @change="updateFillStyle">
              <el-option v-for="(pattern, key) in fillPatterns" :key="key" :label="key" :value="key">
                <div class="pattern-preview-fill" :style="getFillPatternStyle(key)"></div>
              </el-option>
            </el-select>
          </div>
          <div class="style-divider"></div>
          <!-- 线条样式部分 -->
          <div class="style-section-title">线条样式</div>
          <div class="style-item">
            <span class="style-label">颜色：</span>
            <el-color-picker v-model="lineStyle.color" show-alpha @change="updateLineStyle">
            </el-color-picker>
          </div>
          <div class="style-item">
            <span class="style-label">宽度：</span>
            <el-slider v-model="lineStyle.width" :min="1" :max="12" show-input
              @change="updateLineStyle">
            </el-slider>
          </div>
          <div class="style-item">
            <span class="style-label">样式：</span>
            <el-select v-model="lineStyle.pattern" placeholder="选择线条样式" @change="updateLineStyle">
              <el-option v-for="(pattern, key) in linePatterns" :key="key" :label="key" :value="key">
                <div class="pattern-preview-line" :style="getLinePatternStyle(key)"></div>
              </el-option>
            </el-select>
          </div>
          <!-- 分隔线 -->
          <div class="style-divider"></div>
          <div class="style-section-title">文本样式</div>
          <div class="style-item">
            <span class="style-label">颜色：</span>
            <el-color-picker v-model="textStyle.color" show-alpha @change="updateTextStyle">
            </el-color-picker>
          </div>
          <div class="style-item">
            <span class="style-label">大小：</span>
            <el-slider v-model="textStyle.size" :min="8" :max="60" show-input
              @change="handleFontSizeChange">
            </el-slider>
          </div>
          <div class="style-item">
            <span class="style-label">字体：</span>
            <el-select v-model="textStyle.font" placeholder="选择字体" @change="handleFontChange">
              <el-option v-for="(font, index) in Object.keys(TEXT_PATTERNS)" :key="index" :label="font"
                :value="font" :style="{ fontFamily: font }">
                {{ font }}
              </el-option>
            </el-select>
          </div>
          <div class="style-item">
            <span class="style-label">对齐：</span>
            <div class="text-style-buttons">
              <el-button-group style="width: 100%">
                <el-button style="min-width: 20%; max-width: 20%"
                  :type="textStyle.align === 'left' ? 'primary' : ''"
                  @click="textStyle.align = 'left'; updateTextStyle()" title="左对齐">
                  <i class="el-icon-s-fold"></i>
                </el-button>
                <el-button style="min-width: 20%; max-width: 20%"
                  :type="textStyle.align === 'center' ? 'primary' : ''"
                  @click="textStyle.align = 'center'; updateTextStyle()" title="居中对齐">
                  <i class="el-icon-menu"></i>
                </el-button>
                <el-button style="min-width: 20%; max-width: 20%"
                  :type="textStyle.align === 'right' ? 'primary' : ''"
                  @click="textStyle.align = 'right'; updateTextStyle()" title="右对齐">
                  <i class="el-icon-s-unfold"></i>
                </el-button>
                <!-- 粗体按钮 -->
                <el-button style="min-width: 20%; max-width: 20%" :type="textStyle.bold ? 'primary' : ''"
                  @click="textStyle.bold = !textStyle.bold; updateTextStyle()" title="粗体">
                  <span style="font-weight: bold">B</span>
                </el-button>
                <!-- 斜体按钮 -->
                <el-button style="min-width: 20%; max-width: 20%" :type="textStyle.italic ? 'primary' : ''"
                  @click="textStyle.italic = !textStyle.italic; updateTextStyle()" title="斜体">
                  <span style="font-style: italic">I</span>
                </el-button>
              </el-button-group>
            </div>
          </div>
          <!-- 添加属性部分 -->
          <div class="style-divider"></div>
          <div class="style-section-title">属性</div>
          <div class="style-item">
            <span class="style-label">边框圆角：</span>
            <el-input-number v-model="textStyle.borderRadius" :min="0" :max="30" size="small"
              @change="handleBorderRadiusChange">
            </el-input-number>
          </div>
          <div class="style-item">
            <el-checkbox v-model="textStyle.fixedFont" @change="handleFixedFontChange">
              固定字体
            </el-checkbox>
          </div>
        </div>
      </div>

      <!-- 线条样式面板 -->
      <div class="style-panel line-style-panel" :class="{ 'style-panel-visible': showLineStylePanel }">
        <div class="style-panel-header">
          <h3>线条样式</h3>
          <el-button icon="el-icon-close" size="mini" circle @click="showLineStylePanel = false"></el-button>
        </div>
        <div class="style-content">
          <div class="style-item">
            <span class="style-label">颜色：</span>
            <el-color-picker v-model="lineStyle.color" show-alpha @change="updateLineStyle">
            </el-color-picker>
          </div>
          <div class="style-item">
            <span class="style-label">样式：</span>
            <el-select v-model="lineStyle.pattern" placeholder="选择线条样式" @change="updateLineStyle">
              <el-option v-for="(pattern, key) in linePatterns" :key="key" :label="key" :value="key">
                <div class="pattern-preview-line" :style="getLinePatternStyle(key)"></div>
              </el-option>
            </el-select>
          </div>
          <div class="style-item">
            <span class="style-label">宽度：</span>
            <el-slider v-model="lineStyle.width" :min="1" :max="12" show-input
              @change="updateLineStyle">
            </el-slider>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import {SeismicViewWidget} from '@int/geotoolkit/seismic/widgets/SeismicViewWidget';
import {SeismicColors} from '@int/geotoolkit/seismic/util/SeismicColors';
import {SeismicPipeline} from '@int/geotoolkit/seismic/pipeline/SeismicPipeline';
import {SegyReader} from '@int/geotoolkit/seismic/data/SegyReader';
import {StandardSegyFormat} from '@int/geotoolkit/seismic/data/StandardSegyFormat';
import {LocalFile} from '@int/geotoolkit/seismic/data/LocalFile';
import {Plot} from '@int/geotoolkit/plot/Plot';
import { getToken } from '@/utils/auth';
import {Group} from '@int/geotoolkit/scene/Group';
import {Paint} from '@int/geotoolkit/controls/tools/Paint';
import {PaintMode} from '@int/geotoolkit/controls/tools/PaintMode';
import {EditEvents} from '@int/geotoolkit/controls/tools/EditEvents';
import {EditMode} from '@int/geotoolkit/controls/tools/EditMode';
import {Selection, Events as SelectionEvents} from '@int/geotoolkit/controls/tools/Selection';
import {TextStyle} from '@int/geotoolkit/attributes/TextStyle';
import {LineStyle} from '@int/geotoolkit/attributes/LineStyle';
import {FillStyle} from '@int/geotoolkit/attributes/FillStyle';
import {Path} from '@int/geotoolkit/scene/shapes/Path';
import { LINE_PATTERNS, FILL_PATTERNS, TEXT_PATTERNS, LINESTYLE_PATTERNS, IMAGE_PATTERNS, LS_KEYS, FS_KEYS, TS_KEYS } from '@/api/Patterns.js';
import {SizeMode} from '@int/geotoolkit/scene/shapes/Text';
import {RgbaColor} from '@int/geotoolkit/util/RgbaColor';
// 导入新的组件
import ToolbarControls from '@/components/ToolbarControls.vue';
import LineStylePanel from '@/components/LineStylePanel.vue';

// 线条样式模式常量
const TEXT_PATTERN_KEYS = Object.keys(TEXT_PATTERNS);
const FILL_PATTERN_KEYS = Object.keys(FILL_PATTERNS);
const LINE_PATTERN_KEYS = Object.keys(LINE_PATTERNS);

// 在export default前添加interpolate函数
const interpolate = function (target, startIndex, endIndex, startColor, endColor) {
  // 添加参数验证
  if (!target || !Array.isArray(target)) {
    console.error('interpolate: target必须是数组');
    return;
  }
  
  if (typeof startIndex !== 'number' || typeof endIndex !== 'number' || 
      startIndex < 0 || endIndex >= target.length || startIndex > endIndex) {
    console.error(`interpolate: 索引无效 - startIndex: ${startIndex}, endIndex: ${endIndex}, target.length: ${target.length}`);
    return;
  }
  
  if (!startColor || !endColor || 
      typeof startColor.R !== 'number' || typeof startColor.G !== 'number' || typeof startColor.B !== 'number' || 
      typeof endColor.R !== 'number' || typeof endColor.G !== 'number' || typeof endColor.B !== 'number') {
    console.error('interpolate: 颜色必须包含有效的RGB值');
    return;
  }
  
  const offset = startIndex;
  const stop = (endIndex - startIndex);
  let r, g, b;

  const stepR = (endColor.R - startColor.R) / (stop);
  const stepG = (endColor.G - startColor.G) / (stop);
  const stepB = (endColor.B - startColor.B) / (stop);
  
  try {
    for (let i = 0; i <= stop; ++i) {
      r = startColor.R + i * stepR;
      g = startColor.G + i * stepG;
      b = startColor.B + i * stepB;
      target[offset + i] = new RgbaColor(
        Math.round(r < 255 ? r : 255),
        Math.round(g < 255 ? g : 255),
        Math.round(b < 255 ? b : 255),
        255
      );
    }
  } catch (error) {
    console.error(`interpolate: 创建颜色时出错 - ${error.message}`);
  }
};

export default {
  name: "seismic",
  components: {
    ToolbarControls,
    LineStylePanel
  },
  data() {
    return {
      plots: null,
      fileTxt: '',
      widget: null,
      annotationTool: null,
      annotations: null,
      isDrawingText: false,
      showTextStylePanel: false,
      showLineStylePanel: false,
      showPrintDialog: false,
      exporting: false,
      // 添加画笔工具相关属性
      pencilTool: null,
      selectedShape: null,
      selectedShapes: [],
      annotationLayer: null,
      pencilState: {
        isDrawing: false,
        currentPath: null,
        lastPoint: null,
        paths: []
      },
      pencilConfig: {
        minDistance: 2,  // 减小最小距离使绘制更流畅
        lineWidth: 2,
        lineColor: '#0351ad',
        linePattern: 'Solid'
      },
      // 添加颜色映射选择器
      currentColorMap: 'CustomGrayScale', // 默认使用灰度渐变
      colorMaps: ['CustomGrayScale', 'CustomRedScale'], // 可用的颜色映射
      textStyle: {
        color: '#000000',
        size: 12,
        font: 'Sans-serif',
        bold: false,
        italic: false,
        align: 'left',
        wrap: true,
        ellipsis: true,
        borderRadius: 10,
        fixedFont: false,
      },
      lineStyle: {
        color: '#0351ad',
        width: 2,
        pattern: 'Solid'
      },
      fillStyle: {
        color: '#c7e1f6',
        pattern: 'Solid',
        opacity: 100
      },
      fillPatterns: IMAGE_PATTERNS,

      TEXT_PATTERNS: TEXT_PATTERNS,
      FILL_PATTERNS: FILL_PATTERNS,
      LINE_PATTERNS: LINE_PATTERNS,
      LINESTYLE_PATTERNS: LINESTYLE_PATTERNS,
      linePatterns: LINESTYLE_PATTERNS,

      initialLineStyle: null,
      initialTextStyle: null,
      initialFillStyle: null,

      textPatterns: {
        'None': [0, 10],
        'Solid': [],
        'Dash': [20, 4],
        'Dot': [2, 4],
        'DashDot': [20, 4, 2, 4],
        'DashDotDot': [20, 4, 2, 4, 2, 4]
      },

      isWidgetReady: false,
      loadingError: null,
      pipeline: null,
      colorProvider: null,

      // 右键菜单相关数据
      contextMenu: {
        visible: false,
        x: 0,
        y: 0
      },
      contextMenuItems: [
        {
          text: '撤销',
          icon: 'mdi-undo',
          shortcut: 'Ctrl+Z',
          action: 'undo'
        },
        {
          text: '重做',
          icon: 'mdi-redo',
          shortcut: 'Ctrl+Y',
          action: 'redo'
        },
        { type: 'separator' },
        {
          text: '复制',
          icon: 'mdi-content-copy',
          shortcut: 'Ctrl+C',
          action: 'copy'
        },
        {
          text: '粘贴',
          icon: 'mdi-content-paste',
          shortcut: 'Ctrl+V',
          action: 'paste'
        },
        {
          text: '删除',
          icon: 'mdi-delete',
          shortcut: 'Del',
          action: 'delete'
        }
      ],
      clipboard: null, // 用于存储复制的路径
      undoStack: [], // 撤销栈
      redoStack: [], // 重做栈
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.createScene(this.$refs.plot);
      
      if (this.widget) {
        this.widget.on('ready', () => {
          this.initAnnotationTools(this.widget);
        });
      }
    });
    
    if (this.$refs.plot) {
      this.$refs.plot.addEventListener('contextmenu', this.showContextMenu);
      document.addEventListener('click', this.hideContextMenu);
      // 添加键盘事件监听
      window.addEventListener('keydown', this.handleKeyDown);
    }
  },
  methods:{
    onFileOpen (evt, plot, fileInfo) {
      evt.stopPropagation();
      evt.preventDefault();
      const files = evt.target.files;
      return this.handleFileSelect(this.plots);
    },
    handleFileSelect (plot) {
      let url = process.env.VUE_APP_BASE_API + "/ndy/dz/getSegyDataFile?fileName=density.segy";
      let fileName = 'density.segy';
      
      fetch(url, { 
        headers: { 
          Authorization: "Bearer " + getToken() 
        } 
      })
        .then((response) => {
          if (!response.ok) {
            throw new Error(`网络请求失败: ${response.status} ${response.statusText}`);
          }
          return response.blob();
        })
        .then((blob) => {
          if (!blob || blob.size === 0) {
            throw new Error('获取到的文件数据为空');
          }
          
          let filesObj = new File([blob], fileName, {type: blob.type, lastModified: Date.now()});
          let files = [];
          files.push(filesObj);
          
          if (!this.widget) {
            this.loadingError = 'Widget未初始化，无法加载数据';
            console.error(this.loadingError);
            return;
          }

          if (files.length > 0) {
            const file = new LocalFile(files[0]);
            if (!file) {
              this.loadingError = '无法创建LocalFile对象';
              console.error(this.loadingError);
              return;
            }
            
            try {
              new SegyReader(file, new StandardSegyFormat(), -6)
                .loadMetaData((reader) => {
                  if (reader instanceof Error) {
                    this.loadingError = `加载元数据失败: ${reader.message}`;
                    console.error(this.loadingError);
                    return;
                  }
                  reader.readDataSetStatistics((reader, statistics) => {
                    try {
                      if (!statistics) {
                        throw new Error('无法获取数据集统计信息');
                      }
                      
                      const pipeline = new SeismicPipeline(file.name, reader, statistics);
                      if (!pipeline) {
                        throw new Error('无法创建SeismicPipeline');
                      }
                      
                      const colorProvider = SeismicColors.getDefault();
                      if (!colorProvider) {
                        throw new Error('无法获取默认颜色提供者');
                      }
                      
                      // 保存引用以便后续使用
                      this.pipeline = pipeline;
                      this.colorProvider = colorProvider;
                      
                      // 注册颜色映射
                      this.registerColorMaps(colorProvider);
                      
                      // 使用当前选择的颜色映射
                      const colorMap = colorProvider.createNamedColorMap(this.currentColorMap);
                      if (!colorMap) {
                        console.warn(`颜色映射'${this.currentColorMap}'创建失败，回退到默认映射`);
                        // 尝试使用第一个可用的颜色映射
                        if (this.colorMaps.length > 0) {
                          this.currentColorMap = this.colorMaps[0];
                          const fallbackColorMap = colorProvider.createNamedColorMap(this.currentColorMap);
                          if (!fallbackColorMap) {
                            throw new Error('无法创建任何颜色映射');
                          }
                          pipeline.setColorMap(fallbackColorMap);
                        } else {
                          throw new Error('无法创建任何颜色映射，且没有可用的备选映射');
                        }
                      } else {
                        pipeline.setColorMap(colorMap);
                      }
                      
                      pipeline.setPlotType({'Wiggle': false, 'InterpolatedDensity': true});
                      
                      if (this.widget) {
                        this.widget.setPipeline(pipeline);
                        this.widget.fitToBounds();
                        this.initAnnotationTools(this.widget);
                      } else {
                        throw new Error('Widget在设置pipeline时不可用');
                      }
                    } catch (error) {
                      this.loadingError = `设置pipeline失败: ${error.message}`;
                      console.error('Error setting up pipeline:', error);
                    }
                  });
                });
            } catch (error) {
              this.loadingError = `加载SEGY文件失败: ${error.message}`;
              console.error('Error loading SEGY file:', error);
            }
          }
        })
        .catch(error => {
          this.loadingError = `获取地震数据失败: ${error.message}`;
          console.error('Error fetching seismic data:', error);
        });
    },

    createScene (canvas) {
      // 创建SeismicViewWidget实例
      this.widget = new SeismicViewWidget(null, {
        'colorbar': {
          'axis': {
            'tickgenerator': {
              'edge': {
                'tickvisible': false,
                'labelvisible': false
              }
            }
          }
        },
        'layouttype': 'inside',
        'statusbar': {
          'visible': false
        }
      });
      
      // 创建Plot实例
      this.plots = new Plot({
        'root': this.widget,
        'canvasElement': canvas
      });

      // 确保widget和plot都创建完成后再加载数据
      this.$nextTick(() => {
        this.handleFileSelect(this.plots);
      });
    },

    initAnnotationTools(widget) {
      if (!this.checkWidgetStatus()) return;
      
      try {
        // 创建注释层
        this.annotations = new Group();
        widget.getOverlayLayer().addChild(this.annotations);
        
        // 创建注释工具
        this.annotationTool = new Paint({
          'layer': widget.getManipulatorLayer(),
          'node': {
            'radius': 10,
            'fillstyle': '#c7e1f6',
            'linestyle': {
              'color': '#0351ad',
              'width': 2
            },
            'textbox': {
              'border': true,
              'borderradius': 10,
              'fixedsize': false,
              'wordwrap': true,
              'padding': 5
            },
            'selectable': true,
            'movable': true,
            'editable': true
          },
          'handles': {
            'anchor': {
              'fillstyle': '#8be73d',
              'linestyle': '#0351ad'
            }
          }
        });

        // 添加选择工具，确保它能选择注释层中的对象
        const selectionTool = new Selection()
          .setNodeFilter((nodes) => nodes.filter((node) => 
            this.annotations.indexOfChild(node) >= 0))
          .addListener(SelectionEvents.onPick, (tool, eventArgs) => {
            // 如果注释工具不可用，则返回
            if (!this.annotationTool.isEnabled() && !this.pencilTool?.isEnabled()) return;
            
            const selection = eventArgs.getSelection();
            const length = selection.length;
            
            // 如果没有选中任何形状并且当前处于编辑模式，则清除当前编辑节点
            if (length === 0) {
              if (this.annotationTool.getMode() === PaintMode.Edit) {
                this.annotationTool.editNode(null);
              }
              if (this.pencilTool && this.pencilTool.getMode() === PaintMode.Edit) {
                this.pencilTool.editNode(null);
              }
            } 
            // 如果选中了形状，且不是当前正在编辑的形状，则开始编辑该形状
            else if (length > 0) {
              const selectedNode = selection[length - 1];
              const currentTool = this.annotationTool.isEnabled() ? this.annotationTool : 
                                 (this.pencilTool && this.pencilTool.isEnabled() ? this.pencilTool : null);
              
              if (currentTool && selectedNode !== currentTool.getShape()) {
                currentTool.setEditMode(EditMode.EditNode);
                currentTool.editNode(selectedNode);
                this.selectedShape = selectedNode;
                eventArgs.stopPropagation(true, true);
              }
            }
          });

        widget.getTool().insert(0, selectionTool);

        // 添加事件监听
        this.annotationTool
          .addListener(EditEvents.Start, (tool, command) => {
            this.annotations.addChild(command.getNode());
          })
          .addListener(EditEvents.End, (tool, node) => {
            tool.setEditMode(EditMode.EditNode);
            tool.editNode(node);
            this.selectedShape = node;
            
            this.requestRepaint();
          });

        this.annotationTool
          .editNode(null)
          .setEnabled(false);

        widget.getTool().insert(0, this.annotationTool);
        this.isWidgetReady = true;
      } catch (error) {
        console.error('初始化注释工具时出错:', error);
        this.loadingError = error.message;
      }
    },

    toggleDrawText() {
      if (!this.checkWidgetStatus() || !this.isWidgetReady) {
        console.warn('Widget or annotation tools not ready');
        return;
      }

      if (!this.annotationTool) {
        console.warn('注释工具未初始化');
        return;
      }

      this.isDrawingText = !this.isDrawingText;
      this.showTextStylePanel = this.isDrawingText;
      
      if (this.isDrawingText) {
        // 先设置属性
        this.annotationTool.setProperties({
          'editmode': EditMode.Create,
          'mode': PaintMode.Text,
          'node': {
            'textstyle': new TextStyle({
              color: this.textStyle.color,
              size: this.textStyle.size,
              font: this.textStyle.font,
              alignment: this.textStyle.align
            }),
            'selectable': true,
            'movable': true,
            'editable': true,
            'preserveontextfinish': true,
            'preserveonblur': true,
            'autofocus': true
          }
        });
        // 最后启用工具
        this.annotationTool.setEnabled(true);
      } else {
        this.annotationTool.setEnabled(false);
        this.annotationTool.editNode(null);
      }
    },

    removeAnnotation() {
      if (this.annotationTool && this.annotationTool.isEnabled() && 
          this.annotationTool.getMode() === PaintMode.Edit &&
          this.annotationTool.getShape()) {
        if (Array.isArray(this.annotationTool.getShape())) {
          this.annotationTool.getShape().forEach((shape) => shape.dispose());
        } else {
          this.annotationTool.getShape().dispose();
        }
        this.annotationTool.editNode(null);
      }
    },

    updateAllStyles() {
      if (this.annotationTool && this.annotationTool.getShape()) {
        const shape = this.annotationTool.getShape();
        
        // 创建完整的字体字符串
        const fontString = `${this.textStyle.bold ? 'bold ' : ''}${this.textStyle.italic ? 'italic ' : ''}${this.textStyle.size}px ${this.textStyle.font}`;
        
        // 创建基本文本样式
        const textStyle = new TextStyle({
          'font': fontString,
          'color': this.textStyle.color,
          'alignment': this.textStyle.align
        });

        // 创建线条样式
        const lineStyle = new LineStyle({
          'color': this.lineStyle.color,
          'width': this.lineStyle.width,
          'pattern': this.getProcessedLinePattern(this.lineStyle.pattern)
        });

        // 创建填充样式
        const fillStyle = new FillStyle(
          this.fillStyle.color,
          this.fillPatterns[this.fillStyle.pattern]
        );

        // 设置形状的所有属性
        const shapeProperties = {
          'textstyle': textStyle,
          'linestyle': lineStyle,
          'fillstyle': fillStyle,
          'sizemode': this.textStyle.fixedFont ? 
            (SizeMode.FixedWidth | SizeMode.FixedHeight) : 
            SizeMode.WrappedWidth,
          'textbox': {
            'border': this.textStyle.borderRadius > 0,
            'borderradius': this.textStyle.borderRadius,
            'padding': this.textStyle.borderRadius > 0 ? this.textStyle.borderRadius : 5
          }
        };

        // 在形状上设置所有属性
        shape.setProperties(shapeProperties);

        // 在工具上设置属性
        this.annotationTool.setProperties({
          'textbox': shapeProperties.textbox,
          'sizemode': shapeProperties.sizemode
        });

        // 强制重绘
        if (shape.invalidate) {
          shape.invalidate();
        }
      }
    },

    // 修改字体大小变化处理方法
    handleFontSizeChange(value) {
      this.textStyle.size = value;
      this.updateAllStyles();
    },

    // 修改字体变化处理方法
    handleFontChange(value) {
      this.textStyle.font = value;
      this.updateAllStyles();
    },

    // 修改字体样式处理方法
    handleFontStyleChange() {
      this.updateAllStyles();
    },

    updateTextStyle() {
      this.updateAllStyles();
    },

    updateLineStyle() {
      // 创建新的线条样式
      const lineStyle = new LineStyle({
        color: this.lineStyle.color,
        width: this.lineStyle.width,
        pattern: this.getProcessedLinePattern(this.lineStyle.pattern)
      });

      // 如果pencilTool正在使用，更新其属性
      if (this.pencilTool && this.pencilTool.isEnabled()) {
        this.pencilTool.setProperties({
          'node': {
            'linestyle': lineStyle
          }
        });
        
        // 如果有选中的形状，也更新它的样式
        if (this.selectedShape) {
          this.selectedShape.setProperties({
            'linestyle': lineStyle
          });
          this.requestRepaint();
        }
      }
    },

    updateFillStyle() {
      this.updateAllStyles();
    },

    getFillPatternStyle(key) {
      // 基本样式对象
      const baseStyle = {
        height: '24px',
        width: '100%',
        marginTop: '5px',
        marginBottom: '5px',
        border: '1px solid #ddd',
        background: 'white' // 设置白色背景以便更好显示样式
      };

      // 如果是Solid模式，直接使用设置的颜色
      if (key === 'Solid') {
        return {
          ...baseStyle,
          background: this.fillStyle.color
        };
      }

      // 如果是None，显示透明背景
      if (key === 'None') {
        return {
          ...baseStyle,
          background: 'transparent'
        };
      }

      // 使用FILL_PATTERNS中的URL作为背景
      if (this.FILL_PATTERNS && this.FILL_PATTERNS[key]) {
        return {
          ...baseStyle,
          backgroundImage: `url(${this.FILL_PATTERNS[key]})`,
          backgroundRepeat: 'repeat',
          backgroundSize: 'auto'
        };
      }

      // 默认返回基本样式
      return baseStyle;
    },

    getLinePatternStyle(key) {
      let dashStyle = '';

      // 使用处理后的线条模式
      const patternArray = this.getProcessedLinePattern(key);
      if (patternArray && patternArray.length > 0) {
        dashStyle = patternArray.join('px ') + 'px';
      }

      return {
        background: 'transparent',
        backgroundImage: `url(${this.LINE_PATTERNS[key]})`,
        backgroundRepeat: 'no-repeat',
        backgroundSize: 'contain',
        backgroundPosition: 'center',
        height: '20px',
        width: '100%',
        margin: '5px 0'
      };
    },

    getProcessedLinePattern(pattern) {
      // 如果pattern是数组，直接返回
      if (Array.isArray(pattern)) {
        return pattern;
      }

      // 如果pattern是LINESTYLE_PATTERNS的键，使用该值
      if (this.linePatterns && this.linePatterns[pattern]) {
        return this.linePatterns[pattern];
      }

      // 根据常见的模式名称提供默认数组
      if (typeof pattern === 'string') {
        switch (pattern) {
          case 'Dash':
            return [20, 4];
          case 'Dot':
            return [2, 4];
          case 'DashDot':
            return [20, 4, 2, 4];
          case 'DashDotDot':
            return [20, 4, 2, 4, 2, 4];
          case 'ShortDash':
            return [10, 4];
          case 'LongDash':
            return [40, 4];
          case 'DashLongDash':
            return [20, 4, 40, 4];
          case 'Solid':
          case 'None':
          default:
            return []; // 默认为实线
        }
      }

      // 默认返回空数组（实线）
      console.log('使用默认实线模式，无法识别模式:', pattern);
      return [];
    },

    debounce(fn, delay = 300) {
      let timer = null;
      return (...args) => {
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
          fn.apply(this, args);
        }, delay);
      };
    },

    checkWidgetStatus() {
      if (!this.widget) {
        console.warn('Widget未初始化');
        this.loadingError = 'Widget未初始化';
        return false;
      }
      
      // 检查widget的关键方法是否可用
      const requiredMethods = ['setPipeline', 'fitToBounds', 'getOverlayLayer', 'getManipulatorLayer', 'getTool', 'invalidate'];
      for (const method of requiredMethods) {
        if (typeof this.widget[method] !== 'function') {
          console.error(`Widget缺少关键方法: ${method}`);
          this.loadingError = `Widget初始化不完整，缺少方法: ${method}`;
          return false;
        }
      }
      
      return true;
    },

    // 修改边框圆角更新方法
    handleBorderRadiusChange(value) {
      // 确保值为数字
      const radius = parseInt(value) || 0;
      this.textStyle.borderRadius = radius;
      this.updateAllStyles();
    },

    // 修改固定字体更新方法
    handleFixedFontChange(value) {
      this.textStyle.fixedFont = value;
      this.updateAllStyles();
    },

    // 添加清除所有工具状态的方法
    clearAllTools() {
      this.showTextStylePanel = false;
      this.showLineStylePanel = false;
      this.isDrawingText = false;

      if (this.annotationTool) {
        this.annotationTool.setEnabled(false);
        this.annotationTool.editNode(null);
      }

      if (this.pencilTool) {
        this.pencilTool.setEnabled(false);
        const widget = this.plots.getRoot();
        if (widget && widget.getTool()) {
          widget.getTool().remove(this.pencilTool);
        }
      }

      this.requestRepaint();
    },
    
    // 添加请求重绘的方法
    requestRepaint() {
      if (this.widget) {
        this.widget.invalidate();
      }
      if (this.annotations) {
        this.annotations.invalidate();
      }
      if (this.plots && this.plots.getRoot()) {
        this.plots.getRoot().invalidate();
      }
      if (this.pencilTool && this.pencilTool.isEnabled()) {
        this.pencilTool.invalidate();
      }
      if (this.annotationTool && this.annotationTool.isEnabled()) {
        this.annotationTool.invalidate();
      }
    },

    // 添加更新选择视觉反馈的方法
    updateSelectionVisualFeedback() {
      // 更新所有形状的选中状态
      if (this.annotationLayer) {
        const children = this.annotationLayer.getChildren();
        if (children) {
          children.forEach(shape => {
            const isSelected = this.selectedShapes.indexOf(shape) >= 0;
            shape.setProperties({
              'selected': isSelected
            });
          });
        }
      }
      this.requestRepaint();
    },

    // 添加切换颜色映射的方法
    switchColorMap(colorMapName) {
      if (!this.pipeline || !this.colorProvider) {
        console.error('Pipeline or colorProvider not initialized');
        return;
      }
      
      this.currentColorMap = colorMapName;
      
      // 添加额外的检查，确保colorMap不为null
      const colorMap = this.colorProvider.createNamedColorMap(colorMapName);
      if (!colorMap) {
        console.error(`创建颜色映射失败: ${colorMapName}可能未正确注册`);
        return;
      }
      
      // 使用有效的colorMap
      this.pipeline.setColorMap(colorMap);
      
      // 使用正确的方法更新视图
      if (this.widget) {
        this.widget.invalidate(); // 使组件重新渲染
        this.widget.fitToBounds(); // 调整视图以适应数据
      } else {
        console.error('Widget不可用，无法更新视图');
      }
      
      // 如果plots对象存在redraw方法，使用它来触发重绘
      if (this.plots && typeof this.plots.redraw === 'function') {
        this.plots.redraw();
      }
    },

    // 添加注册颜色映射的方法
    registerColorMaps(colorProvider) {
      if (!colorProvider) {
        console.error('colorProvider为空，无法注册颜色映射');
        return;
      }
      
      try {
        // 注册灰度渐变色映射
        colorProvider.register('CustomGrayScale', (map) => {
          if (!map) {
            console.error('CustomGrayScale映射对象为空');
            return;
          }
          
          const colors = new Array(255); // 创建255个颜色点以实现平滑渐变
          
          try {
            // 白色到黑色的平滑渐变
            // 前60%保持较亮的白色区域
            interpolate(colors, 0, 152, {
              A: 255,
              R: 254,
              G: 254,
              B: 254
            }, {
              A: 255,
              R: 240,
              G: 240,
              B: 240
            });

            // 中间过渡区域（约20%）
            interpolate(colors, 153, 203, {
              A: 255,
              R: 240,
              G: 240,
              B: 240
            }, {
              A: 255,
              R: 150,
              G: 150,
              B: 150
            });

            // 最后的深色渐变区域（约20%）
            interpolate(colors, 204, 254, {
              A: 255,
              R: 150,
              G: 150,
              B: 150
            }, {
              A: 255,
              R: 0,
              G: 0,
              B: 0
            });
            
            map.set(colors);
          } catch (error) {
            console.error('设置CustomGrayScale颜色映射失败:', error);
          }
        });
        
        // 注册新的红色系列渐变映射
        colorProvider.register('CustomRedScale', (map) => {
          if (!map) {
            console.error('CustomRedScale映射对象为空');
            return;
          }
          
          const colors = new Array(255);
          
          try {
            // 分段使用提供的5个颜色点
            // 第1段：240,58,39(红色) 到 217,186,138(浅棕色)
            interpolate(colors, 0, 63, {
              A: 255,
              R: 240,
              G: 58,
              B: 39
            }, {
              A: 255,
              R: 217,
              G: 186,
              B: 138
            });
            
            // 第2段：217,186,138(浅棕色) 到 242,242,251(接近白色)
            interpolate(colors, 64, 127, {
              A: 255,
              R: 217,
              G: 186,
              B: 138
            }, {
              A: 255,
              R: 242,
              G: 242,
              B: 251
            });
            
            // 第3段：242,242,251(接近白色) 到 137,137,165(灰紫色)
            interpolate(colors, 128, 191, {
              A: 255,
              R: 242,
              G: 242,
              B: 251
            }, {
              A: 255,
              R: 137,
              G: 137,
              B: 165
            });
            
            // 第4段：137,137,165(灰紫色) 到 44,43,48(深灰色)
            interpolate(colors, 192, 254, {
              A: 255,
              R: 137,
              G: 137,
              B: 165
            }, {
              A: 255,
              R: 44,
              G: 43,
              B: 48
            });
            
            map.set(colors);
          } catch (error) {
            console.error('设置CustomRedScale颜色映射失败:', error);
          }
        });
        
        console.log('颜色映射注册成功');
      } catch (error) {
        console.error('注册颜色映射失败:', error);
      }
    },

    toggleLineStylePanel() {
      // 如果工具已经激活，则停用
      if (this.showLineStylePanel) {
        this.deactivatePencilTool();
        return;
      }

      this.clearAllTools();
      this.showLineStylePanel = true;

      if (!this.checkWidgetStatus() || !this.isWidgetReady) return;

      const widget = this.plots.getRoot();
      if (!widget) return;

      // 确保注释层存在
      if (!this.annotations) {
        this.annotations = new Group();
        widget.getOverlayLayer().addChild(this.annotations);
        this.annotations.setVisible(true);
      }

      // 创建或更新铅笔工具
      if (!this.pencilTool) {
        const lineStyle = new LineStyle({
          color: this.lineStyle.color,
          width: this.lineStyle.width,
          pattern: this.getProcessedLinePattern(this.lineStyle.pattern)
        });

        this.pencilTool = new Paint({
          'layer': widget.getManipulatorLayer(),
          'mode': PaintMode.Pencil,
          'editmode': EditMode.Create,
          'node': {
            'linestyle': lineStyle,
            'selectable': true,
            'movable': true,
            'editable': true
          }
        });

        // 添加事件监听
        this.pencilTool
          .addListener(EditEvents.Start, (tool, command) => {
            console.log('开始绘制', command.getNode());
            this.annotations.addChild(command.getNode());
          })
          .addListener(EditEvents.Change, (tool, event) => {
            console.log('绘制中');
          })
          .addListener(EditEvents.End, (tool, node) => {
            console.log('绘制结束', node);
            if (node && this.annotations.indexOfChild(node) === -1) {
              this.annotations.addChild(node);
            }
            
            // 绘制结束后切换到编辑模式而不是停用工具
            tool.setEditMode(EditMode.EditNode);
            tool.editNode(node);
            
            // 记录当前选中的形状
            this.selectedShape = node;
            
            this.requestRepaint();
          });
      }

      // 设置工具为活动状态
      this.pencilTool.setMode(PaintMode.Pencil);
      this.pencilTool.setEditMode(EditMode.Create);
      
      // 获取工具管理器并添加工具
      const toolManager = widget.getTool();
      
      try {
        toolManager.remove(this.pencilTool);
      } catch (e) {
        // 忽略错误，工具可能已经被移除
      }
      
      toolManager.insert(0, this.pencilTool);
      this.pencilTool.setEnabled(true);
    },

    deactivatePencilTool() {
      this.showLineStylePanel = false;
      if (this.pencilTool) {
        this.pencilTool.setEnabled(false);
        const widget = this.plots.getRoot();
        if (widget && widget.getTool()) {
          try {
            widget.getTool().remove(this.pencilTool);
          } catch (e) {
            // 忽略错误，工具可能已经被移除
          }
        }
        
        // 清除选中的形状
        this.selectedShape = null;
      }
    },

    zoomIn() {
      if (this.plots && this.dataLoaded && !this.zoomInProgress) {
        // ... 放大实现
      }
    },

    zoomOut() {
      if (this.plots && this.dataLoaded && !this.zoomInProgress) {
        // ... 缩小实现
      }
    },

    async exportToPDF(data) {
      if (!this.plots || !this.dataLoaded) {
        this.$message.warning('请等待数据加载完成');
        return;
      }
      // ... PDF导出实现
    },

    /**
     * 显示右键菜单
     */
    showContextMenu(event) {
      event.preventDefault();
      
      // 获取当前活动的工具和选中的形状
      const activeTool = this.pencilTool && this.pencilTool.isEnabled() ? this.pencilTool : 
                       (this.annotationTool && this.annotationTool.isEnabled() ? this.annotationTool : null);
                       
      // 如果没有活动工具或选中的形状，则不显示菜单
      if (!activeTool || !activeTool.getShape()) return;

      const rect = this.$refs.plot.getBoundingClientRect();
      this.contextMenu.x = event.clientX - rect.left;
      this.contextMenu.y = event.clientY - rect.top;
      this.contextMenu.visible = true;

      // 记录当前右键菜单使用的工具
      this._contextMenuTool = activeTool;

      event.stopPropagation();
    },

    /**
     * 隐藏右键菜单
     */
    hideContextMenu() {
      this.contextMenu.visible = false;
      this._contextMenuTool = null;
    },

    /**
     * 检查菜单项是否可用
     */
    isMenuItemEnabled(action) {
      // 获取当前活动的工具
      const tool = this._contextMenuTool;
      
      if (!tool) return false;
      
      switch (action) {
        case 'undo':
          // 使用工具的getHistory方法获取历史记录对象
          return tool.getHistory && tool.getHistory() && tool.getHistory().canUndo();
        case 'redo':
          // 使用工具的getHistory方法获取历史记录对象
          return tool.getHistory && tool.getHistory() && tool.getHistory().canRedo();
        case 'copy':
        case 'delete':
          return tool.getShape() != null;
        case 'paste':
          return this.clipboard !== null;
        default:
          return true;
      }
    },

    /**
     * 处理菜单动作
     */
    handleMenuAction(action) {
      if (!this.isMenuItemEnabled(action)) return;
      
      const tool = this._contextMenuTool;
      
      if (!tool) {
        this.hideContextMenu();
        return;
      }

      switch (action) {
        case 'undo':
          // 使用工具的undo方法或history对象的undo方法
          if (tool.undo) {
            tool.undo();
          } else if (tool.getHistory && tool.getHistory()) {
            tool.getHistory().undo();
          }
          break;
        case 'redo':
          // 使用工具的redo方法或history对象的redo方法
          if (tool.redo) {
            tool.redo();
          } else if (tool.getHistory && tool.getHistory()) {
            tool.getHistory().redo();
          }
          break;
        case 'copy':
          this.copyShape(tool);
          break;
        case 'paste':
          this.pasteShape();
          break;
        case 'delete':
          this.deleteShape(tool);
          break;
      }

      this.hideContextMenu();
      this.requestRepaint();
    },

    copyShape(tool) {
      const shape = tool.getShape();
      if (!shape) return;
      
      // 存储形状的克隆
      this.clipboard = Array.isArray(shape) ? 
        shape.map(node => node.clone()) : 
        [shape.clone()];
    },

    pasteShape() {
      if (!this.clipboard || this.clipboard.length === 0) return;
      
      // 创建偏移量，以便粘贴的形状不会完全覆盖原始形状
      const offset = 20;
      
      // 克隆并移动复制的形状
      this.clipboard.forEach(node => {
        const clone = node.clone();
        
        // 移动克隆的形状
        if (clone.translate) {
          clone.translate(offset, offset);
        }
        
        // 添加到注释层
        this.annotations.addChild(clone);
      });
      
      this.requestRepaint();
    },

    deleteShape(tool) {
      const shape = tool.getShape();
      if (!shape) return;
      
      // 如果是数组，删除所有选中的形状
      if (Array.isArray(shape)) {
        shape.forEach(node => {
          const index = this.annotations.indexOfChild(node);
          if (index >= 0) {
            this.annotations.removeChild(node);
          }
        });
      } else {
        // 删除单个形状
        const index = this.annotations.indexOfChild(shape);
        if (index >= 0) {
          this.annotations.removeChild(shape);
        }
      }
      
      // 清除工具当前编辑的节点
      tool.editNode(null);
      
      this.requestRepaint();
    },

    handleKeyDown(event) {
      // 检查是否有活动的工具
      const activeTool = this.pencilTool && this.pencilTool.isEnabled() ? this.pencilTool : 
                       (this.annotationTool && this.annotationTool.isEnabled() ? this.annotationTool : null);
      
      if (!activeTool) return;
      
      // 获取历史记录对象
      const history = activeTool.getHistory && activeTool.getHistory();
      
      // Ctrl+Z: 撤销
      if (event.ctrlKey && event.key === 'z') {
        if (activeTool.undo) {
          activeTool.undo();
          this.requestRepaint();
          event.preventDefault();
        } else if (history && history.canUndo && history.canUndo()) {
          history.undo();
          this.requestRepaint();
          event.preventDefault();
        }
      }
      
      // Ctrl+Y: 重做
      else if (event.ctrlKey && event.key === 'y') {
        if (activeTool.redo) {
          activeTool.redo();
          this.requestRepaint();
          event.preventDefault();
        } else if (history && history.canRedo && history.canRedo()) {
          history.redo();
          this.requestRepaint();
          event.preventDefault();
        }
      }
      
      // Delete: 删除
      else if (event.key === 'Delete') {
        if (activeTool.getShape()) {
          this.deleteShape(activeTool);
          event.preventDefault();
        }
      }
    },

    // 添加一个新方法，用于切换形状的编辑状态
    toggleShapeEditMode(shape) {
      if (!shape) return;
      
      // 获取活动工具
      const activeTool = this.pencilTool && this.pencilTool.isEnabled() ? this.pencilTool : 
                        (this.annotationTool && this.annotationTool.isEnabled() ? this.annotationTool : null);
      
      if (!activeTool) return;
      
      // 如果当前不是编辑模式，则切换到编辑模式
      if (activeTool.getMode() !== PaintMode.Edit) {
        activeTool.setMode(PaintMode.Edit);
      }
      
      // 如果当前编辑的不是这个形状，则开始编辑这个形状
      if (activeTool.getShape() !== shape) {
        activeTool.setEditMode(EditMode.EditNode);
        activeTool.editNode(shape);
        this.selectedShape = shape;
      }
      
      this.requestRepaint();
    },
  },

  beforeDestroy() {
    // 清理资源
    if (this.plots) {
      this.plots.dispose();
    }
    if (this.annotationTool) {
      this.annotationTool.dispose();
    }
    if (this.pencilTool) {
      this.pencilTool.dispose();
    }
    
    if (this.$refs.plot) {
      this.$refs.plot.removeEventListener('contextmenu', this.showContextMenu);
      document.removeEventListener('click', this.hideContextMenu);
      // 移除键盘事件监听
      window.removeEventListener('keydown', this.handleKeyDown);
    }
  }
}
</script>

<style>
#canvas{
  width: 100%!important;
  height: 500px;
  margin-top: 20px;
}

.toolbar {
  padding: 10px;
  background-color: #f5f5f5;
  border-bottom: 1px solid #ddd;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}

.tool-button {
  margin-right: 8px;
  padding: 6px 12px;
  background-color: #fff;
  border: 1px solid #ddd;
  border-radius: 4px;
  cursor: pointer;
}

.tool-button:hover {
  background-color: #e6e6e6;
}

.tool-button.active {
  background-color: #e6e6e6;
  border-color: #adadad;
}

/* 样式面板相关样式 */
.style-panel {
  position: fixed;
  right: -300px;
  top: 0;
  width: 300px;
  height: 100vh;
  background-color: #fff;
  box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1);
  transition: right 0.3s ease;
  z-index: 1000;
  overflow-y: auto;
}

.style-panel-visible {
  right: 0;
}

.style-panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 15px;
  border-bottom: 1px solid #ddd;
}

.style-panel-header h3 {
  margin: 0;
  font-size: 16px;
}

.style-content {
  padding: 15px;
}

.style-section-title {
  font-weight: bold;
  margin: 10px 0;
  color: #333;
}

.style-item {
  margin-bottom: 15px;
}

.style-label {
  display: block;
  margin-bottom: 5px;
  color: #666;
}

.style-divider {
  height: 1px;
  background-color: #eee;
  margin: 15px 0;
}

.text-style-buttons {
  display: flex;
  gap: 5px;
}

.pattern-preview-fill {
  width: 100%;
  height: 24px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

/* 调整滑块和输入框的样式 */
.el-slider {
  margin-top: 8px;
}

.el-input-number {
  width: 100%;
}

.el-select {
  width: 100%;
}

.el-color-picker {
  width: 100%;
}

/* 添加错误和加载状态样式 */
.error-message {
  color: red;
  padding: 10px;
  margin: 10px;
  background-color: #fff3f3;
  border: 1px solid #ffa7a7;
  border-radius: 4px;
}

.loading-message {
  text-align: center;
  padding: 20px;
  color: #666;
}

.color-maps {
  margin-right: 15px;
}

.color-maps-label {
  margin-right: 8px;
  font-size: 14px;
  color: #666;
}

.el-select {
  width: 120px;
}

.toolbar-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 5px;
}

.is-active {
  background-color: #e6e6e6;
  border-color: #adadad;
}

.context-menu {
  position: fixed;
  background-color: #fff;
  border: 1px solid #ddd;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  z-index: 1001;
  padding: 5px 0;
}

.context-menu-separator {
  height: 1px;
  background-color: #eee;
  margin: 5px 0;
}

.context-menu-item {
  padding: 8px 16px;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 14px;
  color: #333;
}

.context-menu-item:hover {
  background-color: #f5f5f5;
}

.context-menu-item.disabled {
  color: #999;
  cursor: not-allowed;
}

.context-menu-item.disabled:hover {
  background-color: transparent;
}

.shortcut {
  font-size: 12px;
  color: #999;
  margin-left: 16px;
}

.pattern-preview-line {
  width: 100%;
  height: 20px;
  border: 1px solid #ddd;
  border-radius: 4px;
}
</style>

