|
|
@@ -8,21 +8,21 @@
|
|
|
智能台灯
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<img src="@/assets/images/desklamp.png" alt="智能台灯" class="full-screen-image" />
|
|
|
<!-- 使用动态样式设置灯光遮罩 -->
|
|
|
- <div v-if="isLightOn" :style="{ '--lamp-color': lampColor,'--lamp-opacity': lampBrightness / 100 }" class="lamp-light-mask"></div>
|
|
|
+ <div v-if="isLightOn" :style="{ '--lamp-color': state.lamp.color,'--lamp-opacity': state.lamp.brightness / 100 }" class="lamp-light-mask"></div>
|
|
|
|
|
|
<!-- 右下角按钮组 -->
|
|
|
<div class="button-group">
|
|
|
<el-button class="control-button run-button" @click="toggleLight">运行</el-button>
|
|
|
<el-button class="control-button code-button" @click="handleViewCode">查看代码</el-button>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<!-- 显示当前灯光信息 -->
|
|
|
<div v-if="isLightOn" class="lamp-info">
|
|
|
- <p>颜色: {{ lampColor }}</p>
|
|
|
- <p>亮度: {{ lampBrightness }}%</p>
|
|
|
+ <p>颜色: {{ state.lamp.color }}</p>
|
|
|
+ <p>亮度: {{ state.lamp.brightness }}%</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
@@ -43,20 +43,20 @@
|
|
|
style="height: 100%; width: 100%; background-color: #cccccc"
|
|
|
></div>
|
|
|
|
|
|
- <!-- blockly工具栏 -->
|
|
|
- <template>
|
|
|
- <xml id="toolbox" style="display: none">
|
|
|
- <!-- AI模块分类 - 扩展更多功能 -->
|
|
|
- <category name="AI模块" categorystyle="ai_category">
|
|
|
- <block type="ai_voice_input"></block>
|
|
|
- <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>
|
|
|
+ <!-- blockly工具栏 -->
|
|
|
+ <template>
|
|
|
+ <xml id="toolbox" style="display: none">
|
|
|
+ <!-- AI模块分类 - 扩展更多功能 -->
|
|
|
+ <category name="AI模块" categorystyle="ai_category">
|
|
|
+ <block type="ai_voice_input"></block>
|
|
|
+ <block type="ai_text_to_image"></block>
|
|
|
+ <block type="ai_text_to_video"></block>
|
|
|
+ <block type="ai_text_to_text"></block>
|
|
|
+ <block type="ai_smart_lamp_single_param"></block>
|
|
|
+ <block type="ai_smart_lamp"></block>
|
|
|
+ <block type="ai_lamp_set_brightness"></block>
|
|
|
+ <block type="ai_lamp_set_color"></block>
|
|
|
+ </category>
|
|
|
|
|
|
<!-- 其他原有分类保持不变 -->
|
|
|
<category name="逻辑" categorystyle="logic_category">
|
|
|
@@ -526,6 +526,9 @@ const goBack = () => {
|
|
|
// 切换灯光状态
|
|
|
const toggleLight = () => {
|
|
|
isLightOn.value = true;
|
|
|
+
|
|
|
+ generateCode('javascript');
|
|
|
+ runCode()
|
|
|
}
|
|
|
// 查看代码编程界面显示状态
|
|
|
const handleViewCode = () =>{
|
|
|
@@ -674,27 +677,23 @@ onMounted(async () => {
|
|
|
},
|
|
|
};
|
|
|
|
|
|
- // 注册AI语义识别积木
|
|
|
- Blockly.Blocks["ai_semantic_analysis"] = {
|
|
|
- init: function () {
|
|
|
- this.appendDummyInput().appendField("语义识别");
|
|
|
- this.appendValueInput("TEXT").setCheck("String").appendField("分析文本:");
|
|
|
+ //AI智能台灯单参数积木
|
|
|
+ Blockly.Blocks['ai_smart_lamp_single_param'] = {
|
|
|
+ init: function() {
|
|
|
this.appendDummyInput()
|
|
|
- .appendField("分析类型:")
|
|
|
- .appendField(
|
|
|
- new Blockly.FieldDropdown([
|
|
|
- ["通用", "general"],
|
|
|
- ["情感", "sentiment"],
|
|
|
- ["关键词", "keywords"],
|
|
|
- ["意图", "intent"],
|
|
|
- ]),
|
|
|
- "TYPE"
|
|
|
- );
|
|
|
- this.setOutput(true, "String");
|
|
|
- this.setColour(290);
|
|
|
- this.setTooltip("使用AI分析文本的语义内容并返回结果");
|
|
|
- this.setHelpUrl("");
|
|
|
- },
|
|
|
+ .appendField('智能台灯控制(单参数)');
|
|
|
+ this.appendValueInput('PARAMS')
|
|
|
+ .setCheck('String')
|
|
|
+ .appendField('参数(格式: 颜色,亮度,音乐):');
|
|
|
+ this.appendDummyInput()
|
|
|
+ .appendField('例如: 蓝,50,平静');
|
|
|
+ this.setInputsInline(false);
|
|
|
+ this.setPreviousStatement(true, null);
|
|
|
+ this.setNextStatement(true, null);
|
|
|
+ this.setColour(280);
|
|
|
+ this.setTooltip('通过一个参数字符串控制智能台灯的亮度、颜色和音乐\n格式: 颜色,亮度,音乐\n例如: 蓝,50,平静');
|
|
|
+ this.setHelpUrl('');
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
// 注册AI智能台灯积木
|
|
|
@@ -758,8 +757,74 @@ onMounted(async () => {
|
|
|
trashcan: true,
|
|
|
});
|
|
|
|
|
|
- // 工作区变化时自动生成JavaScript代码
|
|
|
- state.workspace.addChangeListener(() => generateCode("javascript"));
|
|
|
+// 加载初始XML内容
|
|
|
+ try {
|
|
|
+ // 使用字符串拼接代替模板字符串,避免特殊字符问题
|
|
|
+ const initialXml = '<xml xmlns="https://developers.google.com/blockly/xml">\n' +
|
|
|
+ ' <block type="ai_smart_lamp_single_param" id="]t3dfZuv34^1VI%c+Vww" x="50" y="90">\n' +
|
|
|
+ ' <value name="PARAMS">\n' +
|
|
|
+ ' <block type="ai_text_to_text" id="iIw6Y|#j@Kh_}]!6A;Ef">\n' +
|
|
|
+ ' <field name="MODEL">default</field>\n' +
|
|
|
+ ' <value name="PROMPT">\n' +
|
|
|
+ ' <block type="ai_voice_input" id="qo`+VHZpJ0^Y_;J2T!VT">\n' +
|
|
|
+ ' <field name="LANGUAGE">zh-CN</field>\n' +
|
|
|
+ ' <value name="PROMPT">\n' +
|
|
|
+ ' <block type="text" id="uoH(8P)Q{|IMHBw=Gv">\n' +
|
|
|
+ ' <field name="TEXT">请说话:</field>\n' +
|
|
|
+ ' </block>\n' +
|
|
|
+ ' </value>\n' +
|
|
|
+ ' </block>\n' +
|
|
|
+ ' </value>\n' +
|
|
|
+ ' </block>\n' +
|
|
|
+ ' </value>\n' +
|
|
|
+ ' </block>\n' +
|
|
|
+ '</xml>';
|
|
|
+
|
|
|
+ const xml = Blockly.utils.xml.textToDom(initialXml);
|
|
|
+ Blockly.Xml.domToWorkspace(xml, state.workspace);
|
|
|
+
|
|
|
+ // 强制重新渲染工作区
|
|
|
+ state.workspace.render();
|
|
|
+
|
|
|
+ // 添加更长的延迟确保DOM完全更新后再设置属性
|
|
|
+ setTimeout(() => {
|
|
|
+ // 确保所有块都可移动和可删除
|
|
|
+ const blocks = state.workspace.getAllBlocks();
|
|
|
+ blocks.forEach(block => {
|
|
|
+ // 直接设置块的可移动和可删除属性为true
|
|
|
+ block.setMovable(true);
|
|
|
+ block.setDeletable(true);
|
|
|
+ // 设置嵌套连接点也可编辑
|
|
|
+ if (block.inputList) {
|
|
|
+ block.inputList.forEach(input => {
|
|
|
+ if (input.connection) {
|
|
|
+ input.connection.setCheck(null); // 允许任何类型的连接
|
|
|
+ input.connection.setHangingPriority(10); // 设置较高的连接优先级
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 再次渲染以应用属性更改
|
|
|
+ state.workspace.render();
|
|
|
+
|
|
|
+ // 初始化完成后手动生成一次代码
|
|
|
+ generateCode("javascript");
|
|
|
+
|
|
|
+ // 初始化完成后添加工作区变化监听器
|
|
|
+ setTimeout(() => {
|
|
|
+ state.workspace.addChangeListener(() => generateCode("javascript"));
|
|
|
+ }, 500);
|
|
|
+ }, 1500);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载初始XML内容失败:', error);
|
|
|
+ }
|
|
|
+
|
|
|
+// 工作区变化时自动生成JavaScript代码
|
|
|
+// 注意:这里设置监听器的位置移到了初始化完成后
|
|
|
+ setTimeout(() => {
|
|
|
+ state.workspace.addChangeListener(() => generateCode("javascript"));
|
|
|
+ }, 1500);
|
|
|
});
|
|
|
// 组件卸载时清除定时器
|
|
|
onUnmounted(() => {
|
|
|
@@ -1148,7 +1213,7 @@ const aiService = {
|
|
|
// 如果没有活跃的对话ID,创建新对话
|
|
|
if (!state.activeConversationId) {
|
|
|
// 使用与TextToText.vue相同的方式创建对话
|
|
|
- const res = await CreateDialogue({ roleId: 10 });
|
|
|
+ const res = await CreateDialogue({ roleId: 75 });
|
|
|
state.activeConversationId = res.data;
|
|
|
console.log("创建会话:", res.data);
|
|
|
}
|
|
|
@@ -1244,52 +1309,12 @@ const aiService = {
|
|
|
state.conversationInProgress = 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)
|
|
|
- );
|
|
|
+ const validBrightness = Math.max(0, Math.min(100, parseInt(brightness) || 0));
|
|
|
|
|
|
// 更新状态
|
|
|
state.lamp.brightness = validBrightness;
|
|
|
@@ -1306,15 +1331,15 @@ const aiService = {
|
|
|
|
|
|
// 预定义的颜色映射
|
|
|
const colorMap = {
|
|
|
- 红: "#ff0000",
|
|
|
- 蓝: "#0000ff",
|
|
|
- 绿: "#00ff00",
|
|
|
- 黄: "#ffff00",
|
|
|
- 青: "#00ffff",
|
|
|
- 靛: "#4b0082",
|
|
|
- 紫: "#800080",
|
|
|
- 白: "#ffffff",
|
|
|
- 黑: "#000000",
|
|
|
+ '红': '#ff0000',
|
|
|
+ '蓝': '#0000ff',
|
|
|
+ '绿': '#00ff00',
|
|
|
+ '黄': '#ffff00',
|
|
|
+ '青': '#00ffff',
|
|
|
+ '靛': '#4b0082',
|
|
|
+ '紫': '#800080',
|
|
|
+ '白': '#ffffff',
|
|
|
+ '黑': '#000000'
|
|
|
};
|
|
|
|
|
|
// 获取有效的颜色值
|
|
|
@@ -1334,7 +1359,38 @@ const aiService = {
|
|
|
return validColor;
|
|
|
},
|
|
|
|
|
|
- // 综合控制台灯
|
|
|
+ // 综合控制台灯(参数格式:"颜色, 亮度, 音乐")
|
|
|
+ async controlLampWithSingleParam(params) {
|
|
|
+ // 解析参数字符串
|
|
|
+ let color = '白'; // 默认颜色
|
|
|
+ let brightness = 0; // 默认亮度
|
|
|
+ let music = ''; // 音乐信息(暂不处理)
|
|
|
+
|
|
|
+ if (params && typeof params === 'string') {
|
|
|
+ // 根据逗号分割参数
|
|
|
+ const paramArray = params.split(',').map(p => p.trim());
|
|
|
+
|
|
|
+ // 提取颜色(第一个参数)
|
|
|
+ if (paramArray.length > 0 && paramArray[0]) {
|
|
|
+ color = paramArray[0];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 提取亮度(第二个参数)
|
|
|
+ if (paramArray.length > 1 && paramArray[1]) {
|
|
|
+ brightness = paramArray[1];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 提取音乐(第三个参数,暂不处理)
|
|
|
+ if (paramArray.length > 2 && paramArray[2]) {
|
|
|
+ music = paramArray[2];
|
|
|
+ console.log('音乐信息(暂不处理):', music);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 调用控制台灯方法
|
|
|
+ return await this.controlLamp(brightness, color);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 综合控制台灯(参数格式:"颜色, 亮度, 音乐")
|
|
|
async controlLamp(brightness, color) {
|
|
|
console.log("controlLamp", brightness, color);
|
|
|
|
|
|
@@ -1351,128 +1407,66 @@ const aiService = {
|
|
|
// 注册JavaScript代码生成器
|
|
|
function registerJavaScriptGenerators() {
|
|
|
// 语音输入
|
|
|
- javascriptGenerator.forBlock["ai_voice_input"] = function (block, generator) {
|
|
|
- const prompt = generator.valueToCode(
|
|
|
- block,
|
|
|
- "PROMPT",
|
|
|
- javascriptGenerator.ORDER_ATOMIC
|
|
|
- );
|
|
|
- const language = block.getFieldValue("LANGUAGE");
|
|
|
- const code = `await aiService.recognizeVoice(${
|
|
|
- prompt || "''"
|
|
|
- }, '${language}')`;
|
|
|
- console.log("ai_voice_input", prompt, language);
|
|
|
+ javascriptGenerator.forBlock['ai_voice_input'] = function(block, generator) {
|
|
|
+ const prompt = generator.valueToCode(block, 'PROMPT', javascriptGenerator.ORDER_ATOMIC);
|
|
|
+ const language = block.getFieldValue('LANGUAGE');
|
|
|
+ const code = `await aiService.recognizeVoice(${prompt || "''"}, '${language}')`;
|
|
|
+ console.log('ai_voice_input', prompt, language);
|
|
|
return [code, javascriptGenerator.ORDER_ATOMIC];
|
|
|
};
|
|
|
|
|
|
// 文本生成图片
|
|
|
- javascriptGenerator.forBlock["ai_text_to_image"] = function (
|
|
|
- block,
|
|
|
- generator
|
|
|
- ) {
|
|
|
- const prompt = generator.valueToCode(
|
|
|
- block,
|
|
|
- "PROMPT",
|
|
|
- javascriptGenerator.ORDER_ATOMIC
|
|
|
- );
|
|
|
- const waitForCompletion =
|
|
|
- block.getFieldValue("WAIT_FOR_COMPLETION") === "TRUE";
|
|
|
+ javascriptGenerator.forBlock['ai_text_to_image'] = function(block, generator) {
|
|
|
+ const prompt = generator.valueToCode(block, 'PROMPT', javascriptGenerator.ORDER_ATOMIC);
|
|
|
+ const waitForCompletion = block.getFieldValue('WAIT_FOR_COMPLETION') === 'TRUE';
|
|
|
const code = `await aiService.textToImage(${prompt}, ${waitForCompletion});`;
|
|
|
- console.log("ai_text_to_image", prompt, waitForCompletion);
|
|
|
+ console.log('ai_text_to_image', prompt, waitForCompletion);
|
|
|
return code;
|
|
|
};
|
|
|
|
|
|
// 文本生成视频
|
|
|
- javascriptGenerator.forBlock["ai_text_to_video"] = function (
|
|
|
- block,
|
|
|
- generator
|
|
|
- ) {
|
|
|
- const prompt = generator.valueToCode(
|
|
|
- block,
|
|
|
- "PROMPT",
|
|
|
- javascriptGenerator.ORDER_ATOMIC
|
|
|
- );
|
|
|
- const waitForCompletion =
|
|
|
- block.getFieldValue("WAIT_FOR_COMPLETION") === "TRUE";
|
|
|
+ javascriptGenerator.forBlock['ai_text_to_video'] = function(block, generator) {
|
|
|
+ const prompt = generator.valueToCode(block, 'PROMPT', javascriptGenerator.ORDER_ATOMIC);
|
|
|
+ const waitForCompletion = block.getFieldValue('WAIT_FOR_COMPLETION') === 'TRUE';
|
|
|
const code = `await aiService.textToVideo(${prompt}, ${waitForCompletion});`;
|
|
|
- console.log("ai_text_to_video", prompt, waitForCompletion);
|
|
|
+ console.log('ai_text_to_video', prompt, waitForCompletion);
|
|
|
return code;
|
|
|
};
|
|
|
|
|
|
// 文本生成文本
|
|
|
- javascriptGenerator.forBlock["ai_text_to_text"] = function (
|
|
|
- block,
|
|
|
- generator
|
|
|
- ) {
|
|
|
- const prompt = generator.valueToCode(
|
|
|
- block,
|
|
|
- "PROMPT",
|
|
|
- javascriptGenerator.ORDER_ATOMIC
|
|
|
- );
|
|
|
- const model = block.getFieldValue("MODEL");
|
|
|
+ javascriptGenerator.forBlock['ai_text_to_text'] = function(block, generator) {
|
|
|
+ const prompt = generator.valueToCode(block, 'PROMPT', javascriptGenerator.ORDER_ATOMIC);
|
|
|
+ const model = block.getFieldValue('MODEL');
|
|
|
const code = `await aiService.textToText(${prompt}, '${model}')`;
|
|
|
- console.log("ai_text_to_text", 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_single_param'] = function(block, generator) {
|
|
|
+ const params = generator.valueToCode(block, 'PARAMS', javascriptGenerator.ORDER_ATOMIC);
|
|
|
+ const code = `await aiService.controlLampWithSingleParam(${params || "'白,0,平静'"});`;
|
|
|
+ return code;
|
|
|
};
|
|
|
|
|
|
- // 智能台灯控制
|
|
|
- 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 || "0"}, ${
|
|
|
- color || "'白'"
|
|
|
- });`;
|
|
|
+ // 智能台灯控制(多参数)
|
|
|
+ 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 || '0'}, ${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 || "0"});`;
|
|
|
+ javascriptGenerator.forBlock['ai_lamp_set_brightness'] = function(block, generator) {
|
|
|
+ const brightness = generator.valueToCode(block, 'BRIGHTNESS', javascriptGenerator.ORDER_ATOMIC);
|
|
|
+ const code = `await aiService.setLampBrightness(${brightness || '0'});`;
|
|
|
return code;
|
|
|
};
|
|
|
|
|
|
// 设置台灯颜色
|
|
|
- javascriptGenerator.forBlock["ai_lamp_set_color"] = function (
|
|
|
- block,
|
|
|
- generator
|
|
|
- ) {
|
|
|
- const color = generator.valueToCode(
|
|
|
- block,
|
|
|
- "COLOR",
|
|
|
- javascriptGenerator.ORDER_ATOMIC
|
|
|
- );
|
|
|
+ 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;
|
|
|
};
|
|
|
@@ -1481,109 +1475,55 @@ function registerJavaScriptGenerators() {
|
|
|
// 注册Python代码生成器
|
|
|
function registerPythonGenerators() {
|
|
|
// 语音输入
|
|
|
- pythonGenerator.forBlock["ai_voice_input"] = function (block, generator) {
|
|
|
- const prompt = generator.valueToCode(
|
|
|
- block,
|
|
|
- "PROMPT",
|
|
|
- pythonGenerator.ORDER_ATOMIC
|
|
|
- );
|
|
|
- const language = block.getFieldValue("LANGUAGE");
|
|
|
+ pythonGenerator.forBlock['ai_voice_input'] = function(block, generator) {
|
|
|
+ const prompt = generator.valueToCode(block, 'PROMPT', pythonGenerator.ORDER_ATOMIC);
|
|
|
+ const language = block.getFieldValue('LANGUAGE');
|
|
|
const code = `ai_service.recognize_voice(${prompt || "''"}, '${language}')`;
|
|
|
return [code, pythonGenerator.ORDER_ATOMIC];
|
|
|
};
|
|
|
|
|
|
// 文本生成图片
|
|
|
- pythonGenerator.forBlock["ai_text_to_image"] = function (block, generator) {
|
|
|
- const prompt = generator.valueToCode(
|
|
|
- block,
|
|
|
- "PROMPT",
|
|
|
- pythonGenerator.ORDER_ATOMIC
|
|
|
- );
|
|
|
- const waitForCompletion =
|
|
|
- block.getFieldValue("WAIT_FOR_COMPLETION") === "TRUE";
|
|
|
+ pythonGenerator.forBlock['ai_text_to_image'] = function(block, generator) {
|
|
|
+ const prompt = generator.valueToCode(block, 'PROMPT', pythonGenerator.ORDER_ATOMIC);
|
|
|
+ const waitForCompletion = block.getFieldValue('WAIT_FOR_COMPLETION') === 'TRUE';
|
|
|
const code = `ai_service.text_to_image(${prompt}, ${waitForCompletion})\n`;
|
|
|
return code;
|
|
|
};
|
|
|
|
|
|
// 文本生成视频
|
|
|
- pythonGenerator.forBlock["ai_text_to_video"] = function (block, generator) {
|
|
|
- const prompt = generator.valueToCode(
|
|
|
- block,
|
|
|
- "PROMPT",
|
|
|
- pythonGenerator.ORDER_ATOMIC
|
|
|
- );
|
|
|
- const waitForCompletion =
|
|
|
- block.getFieldValue("WAIT_FOR_COMPLETION") === "TRUE";
|
|
|
+ pythonGenerator.forBlock['ai_text_to_video'] = function(block, generator) {
|
|
|
+ const prompt = generator.valueToCode(block, 'PROMPT', pythonGenerator.ORDER_ATOMIC);
|
|
|
+ const waitForCompletion = block.getFieldValue('WAIT_FOR_COMPLETION') === 'TRUE';
|
|
|
const code = `ai_service.text_to_video(${prompt}, ${waitForCompletion})\n`;
|
|
|
return code;
|
|
|
};
|
|
|
|
|
|
// 文本生成文本
|
|
|
- pythonGenerator.forBlock["ai_text_to_text"] = function (block, generator) {
|
|
|
- const prompt = generator.valueToCode(
|
|
|
- block,
|
|
|
- "PROMPT",
|
|
|
- pythonGenerator.ORDER_ATOMIC
|
|
|
- );
|
|
|
- const model = block.getFieldValue("MODEL");
|
|
|
+ pythonGenerator.forBlock['ai_text_to_text'] = function(block, generator) {
|
|
|
+ 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 || "0"}, ${
|
|
|
- color || "'白'"
|
|
|
- })`;
|
|
|
+ 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 || '0'}, ${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 || "0"})`;
|
|
|
+ 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 || '0'})`;
|
|
|
return code;
|
|
|
};
|
|
|
|
|
|
// 设置台灯颜色
|
|
|
- pythonGenerator.forBlock["ai_lamp_set_color"] = function (block, generator) {
|
|
|
- const color = generator.valueToCode(
|
|
|
- block,
|
|
|
- "COLOR",
|
|
|
- pythonGenerator.ORDER_ATOMIC
|
|
|
- );
|
|
|
+ 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;
|
|
|
};
|
|
|
@@ -1618,8 +1558,7 @@ async function runCode() {
|
|
|
const resultElement = document.getElementById("run-result");
|
|
|
|
|
|
// 清空之前的结果
|
|
|
- resultElement.innerHTML =
|
|
|
- '<div class="running-indicator">代码运行中...</div>';
|
|
|
+ resultElement.innerHTML = '<div class="running-indicator">代码运行中...</div>';
|
|
|
|
|
|
// 保存原始console方法
|
|
|
const originalConsoleLog = console.log;
|
|
|
@@ -1632,13 +1571,11 @@ async function runCode() {
|
|
|
// 重定义console方法
|
|
|
console.log = (...args) => {
|
|
|
// 过滤掉包含Vue警告的日志
|
|
|
- const message = args
|
|
|
- .map((arg) => (typeof arg === "object" ? JSON.stringify(arg) : arg))
|
|
|
- .join(" ");
|
|
|
+ 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>";
|
|
|
+ if (!message.includes('[Vue warn]')) {
|
|
|
+ outputBuffer += '<div class="log-message">' + message + '</div>';
|
|
|
resultElement.innerHTML = outputBuffer;
|
|
|
}
|
|
|
originalConsoleLog.apply(console, args);
|
|
|
@@ -1646,13 +1583,11 @@ async function runCode() {
|
|
|
|
|
|
console.error = (...args) => {
|
|
|
// 过滤掉包含Vue警告的日志
|
|
|
- const message = args
|
|
|
- .map((arg) => (typeof arg === "object" ? JSON.stringify(arg) : arg))
|
|
|
- .join(" ");
|
|
|
+ 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>";
|
|
|
+ if (!message.includes('[Vue warn]')) {
|
|
|
+ outputBuffer += '<div class="error-message">' + message + '</div>';
|
|
|
resultElement.innerHTML = outputBuffer;
|
|
|
}
|
|
|
originalConsoleError.apply(console, args);
|
|
|
@@ -1660,13 +1595,11 @@ async function runCode() {
|
|
|
|
|
|
console.warn = (...args) => {
|
|
|
// 过滤掉包含Vue警告的日志
|
|
|
- const message = args
|
|
|
- .map((arg) => (typeof arg === "object" ? JSON.stringify(arg) : arg))
|
|
|
- .join(" ");
|
|
|
+ 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>";
|
|
|
+ if (!message.includes('[Vue warn]')) {
|
|
|
+ outputBuffer += '<div class="warn-message">' + message + '</div>';
|
|
|
resultElement.innerHTML = outputBuffer;
|
|
|
}
|
|
|
originalConsoleWarn.apply(console, args);
|
|
|
@@ -1674,20 +1607,16 @@ async function runCode() {
|
|
|
|
|
|
try {
|
|
|
// 添加安全检查
|
|
|
- if (
|
|
|
- code.includes("eval(") ||
|
|
|
- code.includes("Function(") ||
|
|
|
- code.includes("document.write") ||
|
|
|
- code.includes("window.location")
|
|
|
- ) {
|
|
|
- throw new Error("代码包含不安全的操作");
|
|
|
+ if (code.includes('eval(') || code.includes('Function(') ||
|
|
|
+ code.includes('document.write') || code.includes('window.location')) {
|
|
|
+ throw new Error('代码包含不安全的操作');
|
|
|
}
|
|
|
|
|
|
// 包装代码为异步函数执行,支持await
|
|
|
const wrappedCode = `(async () => { ${code} })()`;
|
|
|
await new Function(wrappedCode)();
|
|
|
|
|
|
- if (outputBuffer === "") {
|
|
|
+ if (outputBuffer === '') {
|
|
|
outputBuffer += '<div class="success-message">代码执行成功</div>';
|
|
|
resultElement.innerHTML = outputBuffer;
|
|
|
}
|
|
|
@@ -1701,26 +1630,31 @@ async function runCode() {
|
|
|
console.warn = originalConsoleWarn;
|
|
|
}
|
|
|
} catch (err) {
|
|
|
- console.error("运行代码时发生错误:", err);
|
|
|
- document.getElementById(
|
|
|
- "run-result"
|
|
|
- ).innerHTML = `<div class="error-message">运行代码时发生错误: ${err.message}</div>`;
|
|
|
+ console.error('运行代码时发生错误:', err);
|
|
|
+ document.getElementById('run-result').innerHTML =
|
|
|
+ `<div class="error-message">运行代码时发生错误: ${err.message}</div>`;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 保存JSON
|
|
|
function saveJson() {
|
|
|
- const output = document.getElementById("textarea");
|
|
|
- const json = Blockly.serialization.workspaces.save(state.workspace);
|
|
|
- output.value = JSON.stringify(json, null, 2);
|
|
|
- output.focus();
|
|
|
- output.select();
|
|
|
- taChange();
|
|
|
+ try {
|
|
|
+ const output = document.getElementById('textarea');
|
|
|
+ const json = Blockly.serialization.workspaces.save(state.workspace);
|
|
|
+ output.value = JSON.stringify(json, null, 2);
|
|
|
+ output.focus();
|
|
|
+ output.select();
|
|
|
+ taChange();
|
|
|
+ ElMessage.success('JSON保存成功');
|
|
|
+ } catch (error) {
|
|
|
+ console.error('保存JSON失败:', error);
|
|
|
+ ElMessage.error('保存JSON失败: ' + error.message);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 保存XML
|
|
|
function saveXml() {
|
|
|
- const output = document.getElementById("textarea");
|
|
|
+ const output = document.getElementById('textarea');
|
|
|
const xml = Blockly.Xml.workspaceToDom(state.workspace);
|
|
|
output.value = Blockly.Xml.domToPrettyText(xml);
|
|
|
output.focus();
|
|
|
@@ -1730,7 +1664,7 @@ function saveXml() {
|
|
|
|
|
|
// 重新加载
|
|
|
function load() {
|
|
|
- const input = document.getElementById("textarea");
|
|
|
+ const input = document.getElementById('textarea');
|
|
|
if (!input.value) return;
|
|
|
|
|
|
try {
|
|
|
@@ -1823,15 +1757,17 @@ window.aiService = aiService;
|
|
|
/* 台灯灯光样式 - 使用动态颜色 */
|
|
|
.lamp-light-mask {
|
|
|
position: absolute;
|
|
|
- width: rpx(100);
|
|
|
+ width: rpx(78);
|
|
|
height: rpx(350);
|
|
|
- margin-top: rpx(20);
|
|
|
- margin-left: rpx(250);
|
|
|
- background: radial-gradient(circle, var(--lamp-color) 0%, var(--lamp-color) 50%, rgba(255, 255, 255, 0) 70%);
|
|
|
- filter: blur(50px);
|
|
|
- transform: rotate(25deg);
|
|
|
+ margin-top: rpx(148.5);
|
|
|
+ margin-left: rpx(192);
|
|
|
+ background: linear-gradient(to bottom, var(--lamp-color) 0%, var(--lamp-color) 20%, rgba(255, 255, 255, 0) 80%);
|
|
|
+ filter: blur(40px);
|
|
|
+ transform: rotate(8.5deg);
|
|
|
transform-origin: top center;
|
|
|
opacity: var(--lamp-opacity, 0.6);
|
|
|
+ /* 创建扇形效果 */
|
|
|
+ clip-path: polygon(0% 0%, 100% 0%, 200% 100%, -100% 100%);
|
|
|
}
|
|
|
|
|
|
/* 灯光信息显示 */
|
|
|
@@ -1980,7 +1916,7 @@ window.aiService = aiService;
|
|
|
align-items: flex-start;
|
|
|
}
|
|
|
|
|
|
- .button-container >>> .el-button {
|
|
|
+ .button-container :deep(.el-button) {
|
|
|
flex-shrink: 0;
|
|
|
}
|
|
|
|