|
|
@@ -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>
|