ソースを参照

1、blockly-台灯组件

liyanbo 7 ヶ月 前
コミット
e3c8f8ed0f
2 ファイル変更384 行追加45 行削除
  1. 373 44
      src/views/Blockly.vue
  2. 11 1
      vite.config.js

+ 373 - 44
src/views/Blockly.vue

@@ -13,6 +13,10 @@
             <block type="ai_text_to_image"></block>
             <block type="ai_text_to_video"></block>
             <block type="ai_text_to_text"></block>
+            <block type="ai_semantic_analysis"></block>
+            <block type="ai_smart_lamp"></block>
+            <block type="ai_lamp_set_brightness"></block>
+            <block type="ai_lamp_set_color"></block>
           </category>
 
           <!-- 其他原有分类保持不变 -->
@@ -347,11 +351,24 @@
       <div class="result-section">
         <h4>运行结果</h4>
         <div id="run-result" class="run-result-content"></div>
+
         <!-- 添加额外的图片预览区域 -->
         <div v-if="state.generatedContent.imageUrl" class="extra-image-preview">
           <h5>生成的图片:</h5>
           <img :src="state.generatedContent.imageUrl" class="extra-preview-image" alt="AI生成图片">
         </div>
+
+        <!-- 添加台灯显示区域 -->
+        <div class="lamp-preview-container">
+          <h5>AI智能台灯</h5>
+          <div class="lamp-display" :style="{ filter: `brightness(${state.lamp.brightness / 50})` }">
+            <div class="lamp-image" :style="{ boxShadow: `0 0 40px 20px ${state.lamp.color}80` }"></div>
+          </div>
+          <div class="lamp-info">
+            <p>亮度: {{ state.lamp.brightness }}%</p>
+            <p>颜色: {{ state.lamp.color }}</p>
+          </div>
+        </div>
       </div>
     </div>
 
@@ -407,10 +424,16 @@ const state = reactive({
   previewContent: '',
   isProcessing: false,
 
-//【文生图】文生图
-  modelId: 0,
+  //【文生图】文生图
   gradeId: '',
-  inProgressImageMap: {}
+  inProgressImageMap: {},
+
+
+  // 台灯状态
+  lamp: {
+    brightness: 50,  // 默认亮度50%
+    color: '#ffffff' // 默认颜色白色
+  },
 });
 
 // 【文生图】自动刷新image列表的定时器
@@ -420,13 +443,6 @@ const inProgressTimer = ref();
 onMounted(async () => {
   // 从全局状态初始化年级ID
   state.gradeId = globalState.initGradeId()
-  try{
-    // 获取modelId
-    const modelRes = await getModelIdByType({ type: ModelTypeEnum.TEXT_TO_IMAGE, platform: "DouBao" })
-    state.modelId = modelRes.data
-  }catch(error){
-    console.error('获取modelId失败:', error);
-  }
 
   // 注册AI语音输入积木
   Blockly.Blocks['ai_voice_input'] = {
@@ -511,6 +527,85 @@ onMounted(async () => {
     }
   };
 
+  // 注册AI语义识别积木
+  Blockly.Blocks['ai_semantic_analysis'] = {
+    init: function() {
+      this.appendDummyInput()
+          .appendField('语义识别');
+      this.appendValueInput('TEXT')
+          .setCheck('String')
+          .appendField('分析文本:');
+      this.appendDummyInput()
+          .appendField('分析类型:')
+          .appendField(new Blockly.FieldDropdown([
+            ['通用', 'general'],
+            ['情感', 'sentiment'],
+            ['关键词', 'keywords'],
+            ['意图', 'intent']
+          ]), 'TYPE');
+      this.setOutput(true, 'String');
+      this.setColour(290);
+      this.setTooltip('使用AI分析文本的语义内容并返回结果');
+      this.setHelpUrl('');
+    }
+  };
+
+  // 注册AI智能台灯积木
+  Blockly.Blocks['ai_smart_lamp'] = {
+    init: function() {
+      this.appendDummyInput()
+          .appendField('智能台灯控制');
+      this.appendValueInput('BRIGHTNESS')
+          .setCheck('Number')
+          .appendField('亮度 (0-100):');
+      this.appendValueInput('COLOR')
+          .setCheck('String')
+          .appendField('颜色:');
+      this.setInputsInline(false);
+      this.setPreviousStatement(true, null);
+      this.setNextStatement(true, null);
+      this.setColour(280);
+      this.setTooltip('控制智能台灯的亮度和颜色');
+      this.setHelpUrl('');
+    }
+  };
+
+  // 注册AI台灯设置亮度积木
+  Blockly.Blocks['ai_lamp_set_brightness'] = {
+    init: function() {
+      this.appendDummyInput()
+          .appendField('设置台灯亮度');
+      this.appendValueInput('BRIGHTNESS')
+          .setCheck('Number')
+          .appendField('亮度 (0-100):');
+      this.setInputsInline(false);
+      this.setPreviousStatement(true, null);
+      this.setNextStatement(true, null);
+      this.setColour(270);
+      this.setTooltip('设置智能台灯的亮度');
+      this.setHelpUrl('');
+    }
+  };
+
+  // 注册AI台灯设置颜色积木
+  Blockly.Blocks['ai_lamp_set_color'] = {
+    init: function() {
+      this.appendDummyInput()
+          .appendField('设置台灯颜色');
+      this.appendValueInput('COLOR')
+          .setCheck('String')
+          .appendField('颜色:');
+      this.appendDummyInput()
+          .appendField('可选颜色: 红,蓝,绿,黄,青,靛,紫');
+      this.setInputsInline(false);
+      this.setPreviousStatement(true, null);
+      this.setNextStatement(true, null);
+      this.setColour(275);
+      this.setTooltip('设置智能台灯的颜色');
+      this.setHelpUrl('');
+    }
+  };
+
   // 注册JavaScript代码生成器
   registerJavaScriptGenerators();
 
@@ -534,7 +629,6 @@ onUnmounted(() => {
   }
 });
 
-
 // AI服务配置
 const aiServiceConfig = {
   baseUrl: import.meta.env.VITE_BASE_URL + '/bjdxWeb/ai',
@@ -542,7 +636,8 @@ const aiServiceConfig = {
     voiceRecognition: '/voice-recognition',
     textToImage: '/create-painting',
     textToVideo: '/text-to-video',
-    textToText: '/text-to-text'
+    textToText: '/text-to-text',
+    semanticAnalysis: '/semantic-analysis'
   }
 };
 
@@ -556,23 +651,23 @@ const aiService = {
     if (!recognitionResult) return '';
 
     // 可选:将语音识别结果发送到后端进行优化处理
-    try {
-      const response = await fetch(`${aiServiceConfig.baseUrl}${aiServiceConfig.endpoints.voiceRecognition}`, {
-        method: 'POST',
-        headers: { 'Content-Type': 'application/json' },
-        body: JSON.stringify({
-          text: recognitionResult,
-          language
-        })
-      });
-
-      if (response.ok) {
-        const data = await response.json();
-        return data.optimizedText || recognitionResult;
-      }
-    } catch (error) {
-      console.warn('语音识别优化失败,使用原始结果', error);
-    }
+    // try {
+    //   const response = await fetch(`${aiServiceConfig.baseUrl}${aiServiceConfig.endpoints.voiceRecognition}`, {
+    //     method: 'POST',
+    //     headers: { 'Content-Type': 'application/json' },
+    //     body: JSON.stringify({
+    //       text: recognitionResult,
+    //       language
+    //     })
+    //   });
+    //
+    //   if (response.ok) {
+    //     const data = await response.json();
+    //     return data.optimizedText || recognitionResult;
+    //   }
+    // } catch (error) {
+    //   console.warn('语音识别优化失败,使用原始结果', error);
+    // }
 
     return recognitionResult;
   },
@@ -626,9 +721,17 @@ const aiService = {
 
     state.isProcessing = true;
     try {
+
+      //获取文生图-模型id
+      const modelRes = await getModelIdByType({ type: ModelTypeEnum.TEXT_TO_IMAGE, platform: "DouBao" })
+      if (!modelRes.data) {
+        ElMessage.error('获取模型ID失败');
+        return null;
+      }
+
       // 使用CreatePainting API创建图片任务
       const createRes = await CreatePainting({
-        "modelId": state.modelId,
+        "modelId": modelRes.data,
         "prompt": prompt,
         "width": 1024,
         "height": 1024
@@ -823,6 +926,105 @@ const aiService = {
     } finally {
       state.isProcessing = false;
     }
+  },
+
+  // 语义识别分析
+  async semanticAnalysis(text, type = 'general') {
+    console.log('semanticAnalysis', text, type);
+    state.isProcessing = true;
+    try {
+      const response = await fetch(`${aiServiceConfig.baseUrl}${aiServiceConfig.endpoints.semanticAnalysis}`, {
+        method: 'POST',
+        headers: { 'Content-Type': 'application/json' },
+        body: JSON.stringify({
+          text,
+          type
+        })
+      });
+
+      if (!response.ok) throw new Error('语义分析失败');
+
+      const data = await response.json();
+      state.generatedContent.text = data.result;
+
+      // 显示预览
+      state.previewType = 'text';
+      state.previewContent = data.result;
+      state.previewVisible = true;
+
+      return data.result;
+    } catch (error) {
+      console.error('语义分析失败:', error);
+      ElMessage.error('语义分析失败: ' + error.message);
+      return null;
+    } finally {
+      state.isProcessing = false;
+    }
+  },
+
+
+
+  // 设置台灯亮度
+  async setLampBrightness(brightness) {
+    // console.log('setLampBrightness', brightness);
+
+    // 验证亮度值在0-100之间
+    const validBrightness = Math.max(0, Math.min(100, parseInt(brightness) || 0));
+
+    // 更新状态
+    state.lamp.brightness = validBrightness;
+
+    // 模拟API调用(实际项目中可替换为真实API)
+    console.log(`台灯亮度已设置为: ${validBrightness}%`);
+
+    return validBrightness;
+  },
+
+  // 设置台灯颜色
+  async setLampColor(color) {
+    console.log('setLampColor', color);
+
+    // 预定义的颜色映射
+    const colorMap = {
+      '红': '#ff0000',
+      '蓝': '#0000ff',
+      '绿': '#00ff00',
+      '黄': '#ffff00',
+      '青': '#00ffff',
+      '靛': '#4b0082',
+      '紫': '#800080',
+      '白': '#ffffff',
+      '黑': '#000000'
+    };
+
+    // 获取有效的颜色值
+    let validColor = colorMap[color] || color;
+
+    // 检查是否是有效的颜色格式
+    if (!/^#[0-9A-F]{6}$/i.test(validColor)) {
+      validColor = '#ffffff'; // 默认白色
+    }
+
+    // 更新状态
+    state.lamp.color = validColor;
+
+    // 模拟API调用(实际项目中可替换为真实API)
+    console.log(`台灯颜色已设置为: ${validColor}`);
+
+    return validColor;
+  },
+
+  // 综合控制台灯
+  async controlLamp(brightness, color) {
+    console.log('controlLamp', brightness, color);
+
+    // 先设置亮度
+    await this.setLampBrightness(brightness);
+
+    // 再设置颜色
+    await this.setLampColor(color);
+
+    return { brightness: state.lamp.brightness, color: state.lamp.color };
   }
 };
 
@@ -834,7 +1036,7 @@ function registerJavaScriptGenerators() {
     const language = block.getFieldValue('LANGUAGE');
     const code = `await aiService.recognizeVoice(${prompt || "''"}, '${language}')`;
     console.log('ai_voice_input', prompt, language);
-    return code;
+    return [code, javascriptGenerator.ORDER_ATOMIC];
   };
 
   // 文本生成图片
@@ -861,6 +1063,37 @@ function registerJavaScriptGenerators() {
     const model = block.getFieldValue('MODEL');
     const code = `await aiService.textToText(${prompt}, '${model}')`;
     console.log('ai_text_to_text', prompt, model);
+    return [code, javascriptGenerator.ORDER_ATOMIC];
+  };
+
+  // 语义识别
+  javascriptGenerator.forBlock['ai_semantic_analysis'] = function(block, generator) {
+    const text = generator.valueToCode(block, 'TEXT', javascriptGenerator.ORDER_ATOMIC);
+    const type = block.getFieldValue('TYPE');
+    const code = `await aiService.semanticAnalysis(${text || "''"}, '${type}')`;
+    console.log('ai_semantic_analysis', text, type);
+    return [code, javascriptGenerator.ORDER_ATOMIC];
+  };
+
+  // 智能台灯控制
+  javascriptGenerator.forBlock['ai_smart_lamp'] = function(block, generator) {
+    const brightness = generator.valueToCode(block, 'BRIGHTNESS', javascriptGenerator.ORDER_ATOMIC);
+    const color = generator.valueToCode(block, 'COLOR', javascriptGenerator.ORDER_ATOMIC);
+    const code = `await aiService.controlLamp(${brightness || '50'}, ${color || "'白'"});`;
+    return code;
+  };
+
+  // 设置台灯亮度
+  javascriptGenerator.forBlock['ai_lamp_set_brightness'] = function(block, generator) {
+    const brightness = generator.valueToCode(block, 'BRIGHTNESS', javascriptGenerator.ORDER_ATOMIC);
+    const code = `await aiService.setLampBrightness(${brightness || '50'});`;
+    return code;
+  };
+
+  // 设置台灯颜色
+  javascriptGenerator.forBlock['ai_lamp_set_color'] = function(block, generator) {
+    const color = generator.valueToCode(block, 'COLOR', javascriptGenerator.ORDER_ATOMIC);
+    const code = `await aiService.setLampColor(${color || "'白'"});`;
     return code;
   };
 }
@@ -872,7 +1105,7 @@ function registerPythonGenerators() {
     const prompt = generator.valueToCode(block, 'PROMPT', pythonGenerator.ORDER_ATOMIC);
     const language = block.getFieldValue('LANGUAGE');
     const code = `ai_service.recognize_voice(${prompt || "''"}, '${language}')`;
-    return code;
+    return [code, pythonGenerator.ORDER_ATOMIC];
   };
 
   // 文本生成图片
@@ -896,6 +1129,36 @@ function registerPythonGenerators() {
     const prompt = generator.valueToCode(block, 'PROMPT', pythonGenerator.ORDER_ATOMIC);
     const model = block.getFieldValue('MODEL');
     const code = `ai_service.text_to_text(${prompt}, '${model}')`;
+    return [code, pythonGenerator.ORDER_ATOMIC];
+  };
+
+  // 语义识别
+  pythonGenerator.forBlock['ai_semantic_analysis'] = function(block, generator) {
+    const text = generator.valueToCode(block, 'TEXT', pythonGenerator.ORDER_ATOMIC);
+    const type = block.getFieldValue('TYPE');
+    const code = `ai_service.semantic_analysis(${text || "''"}, '${type}')`;
+    return [code, pythonGenerator.ORDER_ATOMIC];
+  };
+
+  // 智能台灯控制
+  pythonGenerator.forBlock['ai_smart_lamp'] = function(block, generator) {
+    const brightness = generator.valueToCode(block, 'BRIGHTNESS', pythonGenerator.ORDER_ATOMIC);
+    const color = generator.valueToCode(block, 'COLOR', pythonGenerator.ORDER_ATOMIC);
+    const code = `ai_service.control_lamp(${brightness || '50'}, ${color || "'白'"})`;
+    return code;
+  };
+
+  // 设置台灯亮度
+  pythonGenerator.forBlock['ai_lamp_set_brightness'] = function(block, generator) {
+    const brightness = generator.valueToCode(block, 'BRIGHTNESS', pythonGenerator.ORDER_ATOMIC);
+    const code = `ai_service.set_lamp_brightness(${brightness || '50'})`;
+    return code;
+  };
+
+  // 设置台灯颜色
+  pythonGenerator.forBlock['ai_lamp_set_color'] = function(block, generator) {
+    const color = generator.valueToCode(block, 'COLOR', pythonGenerator.ORDER_ATOMIC);
+    const code = `ai_service.set_lamp_color(${color || "'白'"})`;
     return code;
   };
 }
@@ -941,26 +1204,38 @@ async function runCode() {
 
     // 重定义console方法
     console.log = (...args) => {
-      outputBuffer += '<div class="log-message">' + args.map(arg =>
-          typeof arg === 'object' ? JSON.stringify(arg) : arg
-      ).join(' ') + '</div>';
-      resultElement.innerHTML = outputBuffer;
+      // 过滤掉包含Vue警告的日志
+      const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : arg).join(' ');
+
+      // 只显示不包含Vue warn的日志
+      if (!message.includes('[Vue warn]')) {
+        outputBuffer += '<div class="log-message">' + message + '</div>';
+        resultElement.innerHTML = outputBuffer;
+      }
       originalConsoleLog.apply(console, args);
     };
 
     console.error = (...args) => {
-      outputBuffer += '<div class="error-message">' + args.map(arg =>
-          typeof arg === 'object' ? JSON.stringify(arg) : arg
-      ).join(' ') + '</div>';
-      resultElement.innerHTML = outputBuffer;
+      // 过滤掉包含Vue警告的日志
+      const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : arg).join(' ');
+
+      // 只显示不包含Vue warn的日志
+      if (!message.includes('[Vue warn]')) {
+        outputBuffer += '<div class="error-message">' + message + '</div>';
+        resultElement.innerHTML = outputBuffer;
+      }
       originalConsoleError.apply(console, args);
     };
 
     console.warn = (...args) => {
-      outputBuffer += '<div class="warn-message">' + args.map(arg =>
-          typeof arg === 'object' ? JSON.stringify(arg) : arg
-      ).join(' ') + '</div>';
-      resultElement.innerHTML = outputBuffer;
+      // 过滤掉包含Vue警告的日志
+      const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : arg).join(' ');
+
+      // 只显示不包含Vue warn的日志
+      if (!message.includes('[Vue warn]')) {
+        outputBuffer += '<div class="warn-message">' + message + '</div>';
+        resultElement.innerHTML = outputBuffer;
+      }
       originalConsoleWarn.apply(console, args);
     };
 
@@ -1144,6 +1419,7 @@ window.aiService = aiService;
     flex-direction: column;
 
     .run-result-content {
+      color: black;
       flex: 1;
       background-color: #f8f9fa;
       border: 1px solid #ddd;
@@ -1202,4 +1478,57 @@ window.aiService = aiService;
   max-height: 400px;
   border-radius: 4px;
 }
+
+//台灯
+.lamp-preview-container {
+  margin-top: 20px;
+  padding: 10px;
+  background-color: rgba(255, 255, 255, 0.1);
+  border-radius: 8px;
+  text-align: center;
+}
+
+.lamp-display {
+  margin: 15px auto;
+  position: relative;
+  transition: all 0.3s ease;
+}
+
+.lamp-image {
+  width: 100px;
+  height: 150px;
+  margin: 0 auto;
+  background-color: #e0e0e0;
+  border-radius: 10px 10px 0 0;
+  position: relative;
+  box-shadow: 0 0 40px 20px #ffffff80;
+  transition: box-shadow 0.5s ease;
+
+  &::before {
+    content: '';
+    position: absolute;
+    top: 10px;
+    left: 10px;
+    right: 10px;
+    bottom: 40px;
+    background-color: #f5f5f5;
+    border-radius: 5px;
+  }
+
+  &::after {
+    content: '';
+    position: absolute;
+    bottom: 10px;
+    left: 40px;
+    width: 20px;
+    height: 30px;
+    background-color: #888888;
+  }
+}
+
+.lamp-info {
+  margin-top: 10px;
+  font-size: 14px;
+  color: #ffffff;
+}
 </style>

+ 11 - 1
vite.config.js

@@ -14,7 +14,17 @@ export default defineConfig(({ mode }) => {
       legacy({
         targets: ['defaults', 'not IE 11']
       }),
-      vue(),
+      vue({
+        template: {
+          compilerOptions: {
+            // 告诉Vue这些是原生自定义元素,不需要解析为Vue组件
+            isCustomElement: (tag) => {
+              // Blockly工具箱中使用的标签
+              return ['block', 'category', 'field', 'shadow', 'value', 'sep', 'label'].includes(tag)
+            }
+          }
+        }
+      }),
     ],
     base: './',
     resolve: {