|
|
@ -47,8 +47,8 @@ |
|
|
|
<span class="title1">股票温度计</span> |
|
|
|
</div> |
|
|
|
<div class="div00"> |
|
|
|
<div class="div01">个股温度:{{ data1 ?? "NA" }}</div> |
|
|
|
<div class="div02">大盘温度:{{ data2 }}</div> |
|
|
|
<div class="div01">股票温度:{{ data2 ?? "NA" }}</div> |
|
|
|
<div class="div02">市场温度:{{ data1 }}</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<marketTemperature ref="marketTemperatureRef" /> |
|
|
@ -121,14 +121,40 @@ |
|
|
|
<div class="class09"> |
|
|
|
<img src="@/assets/img/AiEmotion/场景应用.png" alt="场景应用标题"> |
|
|
|
<div class="bk-image"> |
|
|
|
<div class="conclusion-container" v-if="parsedConclusion"> |
|
|
|
<div class="conclusion-item" v-if="parsedConclusion.one1 || parsedConclusion.one2"> |
|
|
|
<h4 class="conclusion-title">L1: 情绪监控</h4> |
|
|
|
<p class="conclusion-text" v-if="parsedConclusion.one1">{{ displayedTexts.one1 }}</p> |
|
|
|
<p class="conclusion-text" v-if="parsedConclusion.one2">{{ displayedTexts.one2 }}</p> |
|
|
|
</div> |
|
|
|
<div class="conclusion-item" v-if="parsedConclusion.two"> |
|
|
|
<h4 class="conclusion-title">L2: 情绪解码</h4> |
|
|
|
<p class="conclusion-text">{{ displayedTexts.two }}</p> |
|
|
|
</div> |
|
|
|
<div class="conclusion-item" v-if="parsedConclusion.three"> |
|
|
|
<h4 class="conclusion-title">L3: 情绪推演</h4> |
|
|
|
<p class="conclusion-text">{{ displayedTexts.three }}</p> |
|
|
|
</div> |
|
|
|
<div class="conclusion-item" v-if="parsedConclusion.four"> |
|
|
|
<h4 class="conclusion-title">L4: 情绪套利</h4> |
|
|
|
<p class="conclusion-text">{{ displayedTexts.four }}</p> |
|
|
|
</div> |
|
|
|
<!-- AI生成内容免责声明 --> |
|
|
|
<div class="disclaimer-item" v-if="parsedConclusion"> |
|
|
|
<p class="disclaimer-text">{{ displayedTexts.disclaimer }}</p> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="conclusion-placeholder" v-else> |
|
|
|
<p>等待股票分析结论...</p> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script setup> |
|
|
|
import { ref, reactive, computed, watch, nextTick, onMounted } from 'vue'; |
|
|
|
import { getReplyAPI } from '@/api/AiEmotionApi.js'; // 导入工作流接口方法 |
|
|
|
import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'; |
|
|
|
import { getReplyAPI, getConclusionAPI } from '@/api/AiEmotionApi.js'; // 导入工作流接口方法 |
|
|
|
import axios from 'axios'; |
|
|
|
import item from '@/assets/img/AiEmotion/bk01.png'; // 导入思维矩阵图片 |
|
|
|
import emotionDecod from '@/views/components/emotionDecod.vue'; // 导入情绪解码组件 |
|
|
@ -139,9 +165,12 @@ import StockTabs from '@/views/components/StockTabs.vue'; // 导入股票标签 |
|
|
|
import blueBorderImg from '@/assets/img/AiEmotion/blueBorder.png' //导入蓝色背景框图片 |
|
|
|
import { ElMessage } from 'element-plus'; |
|
|
|
import { useEmotionStore } from '@/store/emotion'; // 导入Pinia store |
|
|
|
import { useAudioStore } from '@/store/audio.js'; // 导入音频store |
|
|
|
import { Howl, Howler } from 'howler'; // 导入音频播放库 |
|
|
|
|
|
|
|
// 使用Pinia store |
|
|
|
const emotionStore = useEmotionStore(); |
|
|
|
const audioStore = useAudioStore(); |
|
|
|
|
|
|
|
// 组件引用 |
|
|
|
const marketTemperatureRef = ref(null); // 引用市场温度计组件 |
|
|
@ -155,6 +184,22 @@ const messages = ref([]); |
|
|
|
const isPageLoaded = ref(false); // 控制页面是否显示 |
|
|
|
const isRotating = ref(false);//控制旋转 |
|
|
|
const version1 = ref(2); // 版本号 |
|
|
|
const conclusionData = ref(''); // 存储第二个工作流接口返回的结论数据 |
|
|
|
|
|
|
|
// 打字机效果相关数据 |
|
|
|
const displayedTexts = ref({ |
|
|
|
one1: '', |
|
|
|
one2: '', |
|
|
|
two: '', |
|
|
|
three: '', |
|
|
|
four: '', |
|
|
|
disclaimer: '' |
|
|
|
}); |
|
|
|
const typewriterTimers = ref([]); |
|
|
|
|
|
|
|
// 音频播放相关数据 |
|
|
|
const audioUrl = ref(''); |
|
|
|
const isAudioPlaying = ref(false); |
|
|
|
|
|
|
|
// 计算属性 - 从store获取当前股票数据 |
|
|
|
const currentStock = computed(() => emotionStore.activeStock); |
|
|
@ -174,6 +219,18 @@ const data2 = computed(() => { |
|
|
|
const lastData = currentStock.value.apiData.GSWDJ?.at(-1); |
|
|
|
return lastData ? Math.round(lastData[2]) : null; |
|
|
|
}); |
|
|
|
const currentConclusion = computed(() => { |
|
|
|
return currentStock.value?.conclusionData || ''; |
|
|
|
}); |
|
|
|
const parsedConclusion = computed(() => { |
|
|
|
if (!currentConclusion.value) return null; |
|
|
|
try { |
|
|
|
return JSON.parse(currentConclusion.value); |
|
|
|
} catch (error) { |
|
|
|
console.error('解析结论数据失败:', error); |
|
|
|
return null; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 监听当前股票变化,重新渲染图表 |
|
|
|
watch(currentStock, (newStock) => { |
|
|
@ -186,6 +243,167 @@ watch(currentStock, (newStock) => { |
|
|
|
isPageLoaded.value = false; |
|
|
|
} |
|
|
|
}, { immediate: true }); |
|
|
|
|
|
|
|
// 监听parsedConclusion变化,触发打字机效果 |
|
|
|
watch(parsedConclusion, (newConclusion) => { |
|
|
|
if (newConclusion) { |
|
|
|
console.log('场景应用结论数据:', newConclusion); |
|
|
|
startTypewriterEffect(newConclusion); |
|
|
|
|
|
|
|
// 尝试多种可能的语音URL字段名 |
|
|
|
let voiceUrl = null; |
|
|
|
if (newConclusion.url) { |
|
|
|
// 清理URL字符串,去除空格、反引号等特殊字符 |
|
|
|
voiceUrl = newConclusion.url.toString().trim().replace(/[`\s]/g, ''); |
|
|
|
} else if (newConclusion.audioUrl) { |
|
|
|
voiceUrl = newConclusion.audioUrl.toString().trim().replace(/[`\s]/g, ''); |
|
|
|
} else if (newConclusion.voice_url) { |
|
|
|
voiceUrl = newConclusion.voice_url.toString().trim().replace(/[`\s]/g, ''); |
|
|
|
} else if (newConclusion.audio) { |
|
|
|
voiceUrl = newConclusion.audio.toString().trim().replace(/[`\s]/g, ''); |
|
|
|
} else if (newConclusion.tts_url) { |
|
|
|
voiceUrl = newConclusion.tts_url.toString().trim().replace(/[`\s]/g, ''); |
|
|
|
} |
|
|
|
|
|
|
|
if (voiceUrl && voiceUrl.startsWith('http')) { |
|
|
|
console.log('找到并清理后的语音URL:', voiceUrl); |
|
|
|
audioUrl.value = voiceUrl; |
|
|
|
playAudio(voiceUrl); |
|
|
|
} else { |
|
|
|
console.log('未找到有效的语音URL,原始URL:', newConclusion.url); |
|
|
|
console.log('结论数据中的所有字段:', Object.keys(newConclusion)); |
|
|
|
} |
|
|
|
} |
|
|
|
}, { immediate: true }); |
|
|
|
|
|
|
|
// 打字机效果函数 |
|
|
|
function startTypewriterEffect(conclusion) { |
|
|
|
// 清除之前的定时器 |
|
|
|
typewriterTimers.value.forEach(timer => clearTimeout(timer)); |
|
|
|
typewriterTimers.value = []; |
|
|
|
|
|
|
|
// 清空之前的显示文本 |
|
|
|
displayedTexts.value = { |
|
|
|
one1: '', |
|
|
|
one2: '', |
|
|
|
two: '', |
|
|
|
three: '', |
|
|
|
four: '', |
|
|
|
disclaimer: '' |
|
|
|
}; |
|
|
|
|
|
|
|
// 定义打字速度(毫秒) |
|
|
|
const typeSpeed = 50; |
|
|
|
let totalDelay = 0; |
|
|
|
|
|
|
|
// 为每个文本创建打字机效果 |
|
|
|
const textKeys = ['one1', 'one2', 'two', 'three', 'four']; |
|
|
|
|
|
|
|
textKeys.forEach((key) => { |
|
|
|
if (conclusion[key]) { |
|
|
|
const text = conclusion[key]; |
|
|
|
const startDelay = totalDelay; |
|
|
|
|
|
|
|
for (let i = 0; i <= text.length; i++) { |
|
|
|
const timer = setTimeout(() => { |
|
|
|
displayedTexts.value[key] = text.substring(0, i); |
|
|
|
}, startDelay + i * typeSpeed); |
|
|
|
|
|
|
|
typewriterTimers.value.push(timer); |
|
|
|
} |
|
|
|
|
|
|
|
// 更新总延迟,为下一个文本留出时间 |
|
|
|
totalDelay += text.length * typeSpeed + 300; // 额外300ms间隔 |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 添加免责声明的打字机效果(在所有内容显示完成后) |
|
|
|
const disclaimerText = '该内容由AI内容生成,请注意甄别'; |
|
|
|
const disclaimerStartDelay = totalDelay + 500; // 额外500ms间隔 |
|
|
|
|
|
|
|
for (let i = 0; i <= disclaimerText.length; i++) { |
|
|
|
const timer = setTimeout(() => { |
|
|
|
displayedTexts.value.disclaimer = disclaimerText.substring(0, i); |
|
|
|
}, disclaimerStartDelay + i * typeSpeed); |
|
|
|
|
|
|
|
typewriterTimers.value.push(timer); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 清理定时器的函数 |
|
|
|
function clearTypewriterTimers() { |
|
|
|
typewriterTimers.value.forEach(timer => clearTimeout(timer)); |
|
|
|
typewriterTimers.value = []; |
|
|
|
} |
|
|
|
|
|
|
|
// 音频播放函数 |
|
|
|
function playAudio(url) { |
|
|
|
console.log('尝试播放音频:', url); |
|
|
|
|
|
|
|
if (!url) { |
|
|
|
console.warn('音频URL为空,跳过播放'); |
|
|
|
isAudioPlaying.value = false; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 检查是否启用了语音功能 |
|
|
|
console.log('语音功能状态:', audioStore.isVoiceEnabled); |
|
|
|
if (!audioStore.isVoiceEnabled) { |
|
|
|
console.log('语音功能已关闭,跳过播放'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
console.log('开始创建音频实例...'); |
|
|
|
|
|
|
|
try { |
|
|
|
// 停止之前的音频 |
|
|
|
if (audioStore.nowSound) { |
|
|
|
audioStore.nowSound.stop(); |
|
|
|
} |
|
|
|
|
|
|
|
// 创建新的音频实例 |
|
|
|
const newSound = new Howl({ |
|
|
|
src: [url], |
|
|
|
html5: true, |
|
|
|
format: ['mp3', 'wav'], |
|
|
|
onplay: () => { |
|
|
|
isAudioPlaying.value = true; |
|
|
|
console.log('开始播放场景应用语音'); |
|
|
|
}, |
|
|
|
onend: () => { |
|
|
|
isAudioPlaying.value = false; |
|
|
|
console.log('场景应用语音播放结束'); |
|
|
|
}, |
|
|
|
onstop: () => { |
|
|
|
isAudioPlaying.value = false; |
|
|
|
console.log('场景应用语音播放停止'); |
|
|
|
}, |
|
|
|
onerror: (error) => { |
|
|
|
isAudioPlaying.value = false; |
|
|
|
console.error('音频播放错误:', error); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 保存音频实例到store |
|
|
|
audioStore.nowSound = newSound; |
|
|
|
audioStore.setAudioInstance(newSound); |
|
|
|
|
|
|
|
// 播放音频 |
|
|
|
newSound.play(); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('创建音频实例失败:', error); |
|
|
|
isAudioPlaying.value = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 停止音频播放 |
|
|
|
function stopAudio() { |
|
|
|
if (audioStore.nowSound) { |
|
|
|
audioStore.nowSound.stop(); |
|
|
|
} |
|
|
|
isAudioPlaying.value = false; |
|
|
|
} |
|
|
|
//导出方法供外部使用 |
|
|
|
defineExpose({ handleSendMessage }) |
|
|
|
// 触发图片旋转的方法 |
|
|
@ -238,12 +456,40 @@ async function handleSendMessage(input) { |
|
|
|
|
|
|
|
if (parsedData && parsedData.market && parsedData.code) { |
|
|
|
console.log("工作流接口返回股票信息:", parsedData); |
|
|
|
// 调用第二个工作流接口 |
|
|
|
const conclusionParams = { |
|
|
|
content: input.trim(), |
|
|
|
userData: { |
|
|
|
token: |
|
|
|
"9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnIlrmTwo5FbqJ9lWrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs", |
|
|
|
language: "cn", |
|
|
|
marketList: "hk,cn,usa,my,sg,vi,in,gb", |
|
|
|
}, |
|
|
|
code: parsedData.code, |
|
|
|
market: parsedData.market, |
|
|
|
}; |
|
|
|
console.log('======================================') |
|
|
|
|
|
|
|
// 同时调用第二个数据流接口和fetchData方法 |
|
|
|
const [conclusionResult, fetchDataResult] = await Promise.all([ |
|
|
|
getConclusionAPI(conclusionParams), |
|
|
|
fetchData(parsedData.code, parsedData.market, parsedData.name || "未知股票", input.trim()) |
|
|
|
]); |
|
|
|
|
|
|
|
// 处理结论接口返回的数据 |
|
|
|
const conclusionResponse = await conclusionResult.json(); |
|
|
|
console.log("第二个工作流接口返回数据:", conclusionResponse); |
|
|
|
|
|
|
|
// 将结论数据存储到响应式变量和store中 |
|
|
|
if (conclusionResponse && conclusionResponse.data) { |
|
|
|
conclusionData.value = conclusionResponse.data; |
|
|
|
// 将结论数据存储到store中的当前激活股票 |
|
|
|
emotionStore.updateActiveStockConclusion(conclusionResponse.data); |
|
|
|
console.log("结论数据已存储到响应式变量和store中:", conclusionData.value); |
|
|
|
} |
|
|
|
|
|
|
|
// 请求数据接口 |
|
|
|
fetchData(parsedData.code, parsedData.market, parsedData.name || "未知股票", input.trim()); |
|
|
|
console.log('------------------------------------') |
|
|
|
|
|
|
|
// 更新 span01 的内容 |
|
|
|
// updateSpan01(); |
|
|
|
} else { |
|
|
|
ElMessage.error('工作流接口未返回非股票信息'); |
|
|
|
} |
|
|
@ -271,8 +517,8 @@ async function fetchData(code, market, stockName, queryText) { |
|
|
|
}; |
|
|
|
|
|
|
|
const stockDataResult = await axios.post( |
|
|
|
"http://39.101.133.168:8828/link/api/aiEmotion/client/getAiEmotionData", |
|
|
|
// 'https://api.homilychart.com/link/api/aiEmotion/client/getAiEmotionData', |
|
|
|
// "http://39.101.133.168:8828/link/api/aiEmotion/client/getAiEmotionData", |
|
|
|
'https://api.homilychart.com/link/api/aiEmotion/client/getAiEmotionData', |
|
|
|
stockDataParams, |
|
|
|
{ |
|
|
|
headers: { |
|
|
@ -296,6 +542,7 @@ async function fetchData(code, market, stockName, queryText) { |
|
|
|
market: market |
|
|
|
}, |
|
|
|
apiData: stockDataResponse.data, |
|
|
|
conclusionData: conclusionData.value, // 包含结论数据 |
|
|
|
timestamp: new Date().toISOString() |
|
|
|
}; |
|
|
|
|
|
|
@ -372,14 +619,17 @@ const scrollToBottom = async () => { |
|
|
|
container.scrollTop = container.scrollHeight - container.offsetHeight; |
|
|
|
}; |
|
|
|
|
|
|
|
// setInterval(() =>{ |
|
|
|
// scrollToBottom(); |
|
|
|
// },1000); |
|
|
|
|
|
|
|
// 页面挂载完成后触发图片旋转 |
|
|
|
onMounted(() => { |
|
|
|
startImageRotation(); |
|
|
|
}); |
|
|
|
|
|
|
|
// 组件卸载时清理定时器和音频 |
|
|
|
onUnmounted(() => { |
|
|
|
clearTypewriterTimers(); |
|
|
|
stopAudio(); |
|
|
|
}); |
|
|
|
</script> |
|
|
|
|
|
|
|
<style scoped> |
|
|
@ -400,6 +650,9 @@ onMounted(() => { |
|
|
|
text-align: center; |
|
|
|
font-size: 24px; |
|
|
|
color: white; |
|
|
|
display: flex; |
|
|
|
justify-content: center; |
|
|
|
align-items: center; |
|
|
|
} |
|
|
|
|
|
|
|
.class003 .div01 { |
|
|
@ -413,6 +666,9 @@ onMounted(() => { |
|
|
|
text-align: center; |
|
|
|
font-size: 24px; |
|
|
|
color: white; |
|
|
|
display: flex; |
|
|
|
justify-content: center; |
|
|
|
align-items: center; |
|
|
|
} |
|
|
|
|
|
|
|
.golden-wheel { |
|
|
@ -454,6 +710,113 @@ onMounted(() => { |
|
|
|
height: auto; |
|
|
|
margin: 0 auto; |
|
|
|
margin-top: 20px; |
|
|
|
|
|
|
|
.conclusion-container { |
|
|
|
padding: 20px; |
|
|
|
border-radius: 15px; |
|
|
|
margin: 20px; |
|
|
|
background: linear-gradient(135deg, rgba(0, 212, 255, 0.15) 0%, rgba(0, 100, 200, 0.15) 100%); |
|
|
|
border: 2px solid rgba(0, 212, 255, 0.4); |
|
|
|
box-shadow: 0 8px 25px rgba(0, 212, 255, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1); |
|
|
|
backdrop-filter: blur(15px); |
|
|
|
|
|
|
|
.conclusion-item { |
|
|
|
margin-bottom: 20px; |
|
|
|
padding: 20px; |
|
|
|
border-radius: 12px; |
|
|
|
background: linear-gradient(135deg, rgba(0, 212, 255, 0.2) 0%, rgba(0, 150, 255, 0.1) 100%); |
|
|
|
border: 1px solid rgba(0, 212, 255, 0.5); |
|
|
|
border-left: 5px solid #00d4ff; |
|
|
|
box-shadow: 0 4px 15px rgba(0, 212, 255, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.1); |
|
|
|
transition: all 0.3s ease; |
|
|
|
position: relative; |
|
|
|
overflow: hidden; |
|
|
|
|
|
|
|
&::before { |
|
|
|
content: ''; |
|
|
|
position: absolute; |
|
|
|
top: 0; |
|
|
|
left: 0; |
|
|
|
right: 0; |
|
|
|
height: 2px; |
|
|
|
background: linear-gradient(90deg, #00d4ff, #0099ff, #00d4ff); |
|
|
|
opacity: 0.8; |
|
|
|
} |
|
|
|
|
|
|
|
&:hover { |
|
|
|
background: linear-gradient(135deg, rgba(0, 212, 255, 0.25) 0%, rgba(0, 150, 255, 0.15) 100%); |
|
|
|
transform: translateY(-2px) scale(1.02); |
|
|
|
box-shadow: 0 8px 25px rgba(0, 212, 255, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2); |
|
|
|
} |
|
|
|
|
|
|
|
&:last-child { |
|
|
|
margin-bottom: 0; |
|
|
|
} |
|
|
|
|
|
|
|
.conclusion-title { |
|
|
|
color: #00d4ff; |
|
|
|
font-size: 22px; |
|
|
|
font-weight: bold; |
|
|
|
margin: 0 0 15px 0; |
|
|
|
text-align: center; |
|
|
|
text-shadow: 0 2px 8px rgba(0, 212, 255, 0.5), 0 0 20px rgba(0, 212, 255, 0.3); |
|
|
|
letter-spacing: 2px; |
|
|
|
position: relative; |
|
|
|
|
|
|
|
&::after { |
|
|
|
content: ''; |
|
|
|
position: absolute; |
|
|
|
bottom: -5px; |
|
|
|
left: 50%; |
|
|
|
transform: translateX(-50%); |
|
|
|
width: 60px; |
|
|
|
height: 2px; |
|
|
|
background: linear-gradient(90deg, transparent, #00d4ff, transparent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.conclusion-text { |
|
|
|
color: #ffffff; |
|
|
|
font-size: 16px; |
|
|
|
line-height: 1.8; |
|
|
|
margin: 0 0 12px 0; |
|
|
|
text-align: left; |
|
|
|
word-wrap: break-word; |
|
|
|
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7); |
|
|
|
padding-left: 15px; |
|
|
|
position: relative; |
|
|
|
|
|
|
|
&::before { |
|
|
|
content: '▶'; |
|
|
|
position: absolute; |
|
|
|
left: 0; |
|
|
|
top: 0; |
|
|
|
color: #00d4ff; |
|
|
|
font-size: 12px; |
|
|
|
opacity: 0.7; |
|
|
|
} |
|
|
|
|
|
|
|
&:last-child { |
|
|
|
margin-bottom: 0; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.conclusion-placeholder { |
|
|
|
padding: 30px; |
|
|
|
text-align: center; |
|
|
|
border-radius: 12px; |
|
|
|
background: rgba(255, 255, 255, 0.05); |
|
|
|
border: 1px dashed rgba(153, 153, 153, 0.3); |
|
|
|
|
|
|
|
p { |
|
|
|
color: #999999; |
|
|
|
font-size: 16px; |
|
|
|
margin: 0; |
|
|
|
font-style: italic; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* 最后文字的颜色 */ |
|
|
@ -461,13 +824,47 @@ onMounted(() => { |
|
|
|
position: relative; |
|
|
|
color: white; |
|
|
|
text-align: left; |
|
|
|
padding: 3%; |
|
|
|
padding: 20px; |
|
|
|
border-radius: 15px; |
|
|
|
margin: 20px; |
|
|
|
background: linear-gradient(135deg, rgba(0, 212, 255, 0.15) 0%, rgba(0, 100, 200, 0.15) 100%); |
|
|
|
border: 2px solid rgba(0, 212, 255, 0.4); |
|
|
|
box-shadow: 0 8px 25px rgba(0, 212, 255, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1); |
|
|
|
backdrop-filter: blur(15px); |
|
|
|
} |
|
|
|
|
|
|
|
.text-container p { |
|
|
|
margin: 0 auto; |
|
|
|
font-size: 40px; |
|
|
|
margin-left: 10%; |
|
|
|
margin-left: 0%; |
|
|
|
padding: 20px; |
|
|
|
border-radius: 12px; |
|
|
|
background: linear-gradient(135deg, rgba(0, 212, 255, 0.2) 0%, rgba(0, 150, 255, 0.1) 100%); |
|
|
|
border: 1px solid rgba(0, 212, 255, 0.5); |
|
|
|
border-left: 5px solid #00d4ff; |
|
|
|
box-shadow: 0 4px 15px rgba(0, 212, 255, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.1); |
|
|
|
transition: all 0.3s ease; |
|
|
|
position: relative; |
|
|
|
overflow: hidden; |
|
|
|
text-shadow: 0 2px 8px rgba(0, 212, 255, 0.5), 0 0 20px rgba(0, 212, 255, 0.3); |
|
|
|
letter-spacing: 2px; |
|
|
|
} |
|
|
|
|
|
|
|
.text-container p::before { |
|
|
|
content: ''; |
|
|
|
position: absolute; |
|
|
|
top: 0; |
|
|
|
left: 0; |
|
|
|
right: 0; |
|
|
|
height: 2px; |
|
|
|
background: linear-gradient(90deg, #00d4ff, #0099ff, #00d4ff); |
|
|
|
opacity: 0.8; |
|
|
|
} |
|
|
|
|
|
|
|
.text-container p:hover { |
|
|
|
background: linear-gradient(135deg, rgba(0, 212, 255, 0.25) 0%, rgba(0, 150, 255, 0.15) 100%); |
|
|
|
transform: translateY(-2px) scale(1.02); |
|
|
|
box-shadow: 0 8px 25px rgba(0, 212, 255, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2); |
|
|
|
} |
|
|
|
|
|
|
|
.class07 { |
|
|
@ -489,6 +886,8 @@ onMounted(() => { |
|
|
|
.class0700 { |
|
|
|
margin: 0 auto; |
|
|
|
width: fit-content; |
|
|
|
margin-top: 2%; |
|
|
|
margin-bottom: 1%; |
|
|
|
} |
|
|
|
|
|
|
|
.class0702 { |
|
|
@ -614,6 +1013,8 @@ onMounted(() => { |
|
|
|
|
|
|
|
.class09 { |
|
|
|
text-align: center; |
|
|
|
margin-top: 2%; |
|
|
|
margin-bottom: 1%; |
|
|
|
} |
|
|
|
|
|
|
|
/* 为需要放大的图片添加样式 */ |
|
|
@ -879,6 +1280,12 @@ onMounted(() => { |
|
|
|
|
|
|
|
/* 手机端适配样式 */ |
|
|
|
@media only screen and (max-width: 768px) { |
|
|
|
|
|
|
|
.container { |
|
|
|
margin: 0 auto; |
|
|
|
max-width: 80vw; |
|
|
|
} |
|
|
|
|
|
|
|
.title4 { |
|
|
|
color: white; |
|
|
|
font-size: 20px; |
|
|
@ -962,14 +1369,14 @@ onMounted(() => { |
|
|
|
|
|
|
|
.img01 { |
|
|
|
height: auto; |
|
|
|
margin-left: 0rem; |
|
|
|
margin-left: 7%; |
|
|
|
width: 25%; |
|
|
|
margin-top: 10px; |
|
|
|
} |
|
|
|
|
|
|
|
.title1 { |
|
|
|
font-size: 10px; |
|
|
|
margin-left: 13px; |
|
|
|
font-size: 20px; |
|
|
|
margin-left: 5%; |
|
|
|
} |
|
|
|
|
|
|
|
.class02 .span02 { |
|
|
@ -1035,7 +1442,7 @@ onMounted(() => { |
|
|
|
} |
|
|
|
|
|
|
|
.text-container p { |
|
|
|
font-size: 20px; |
|
|
|
font-size: 16px; |
|
|
|
} |
|
|
|
|
|
|
|
.lz-img { |
|
|
@ -1060,6 +1467,54 @@ onMounted(() => { |
|
|
|
} |
|
|
|
|
|
|
|
.bk-image { |
|
|
|
.conclusion-container { |
|
|
|
padding: 15px; |
|
|
|
border-radius: 8px; |
|
|
|
margin: 8px; |
|
|
|
|
|
|
|
.conclusion-item { |
|
|
|
margin-bottom: 15px; |
|
|
|
|
|
|
|
&:last-child { |
|
|
|
margin-bottom: 0; |
|
|
|
} |
|
|
|
|
|
|
|
.conclusion-title { |
|
|
|
color: #00d4ff; |
|
|
|
font-size: 16px; |
|
|
|
font-weight: bold; |
|
|
|
margin: 0 0 8px 0; |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
|
|
|
|
.conclusion-text { |
|
|
|
color: #ffffff; |
|
|
|
font-size: 14px; |
|
|
|
line-height: 1.5; |
|
|
|
margin: 0 0 6px 0; |
|
|
|
text-align: left; |
|
|
|
word-wrap: break-word; |
|
|
|
|
|
|
|
&:last-child { |
|
|
|
margin-bottom: 0; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.conclusion-placeholder { |
|
|
|
padding: 15px; |
|
|
|
text-align: center; |
|
|
|
|
|
|
|
p { |
|
|
|
color: #999999; |
|
|
|
font-size: 12px; |
|
|
|
margin: 0; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.bk-image { |
|
|
|
background-size: 100% 100%; |
|
|
|
background-repeat: no-repeat; |
|
|
|
width: 100%; |
|
|
@ -1067,6 +1522,129 @@ onMounted(() => { |
|
|
|
margin: 0 auto; |
|
|
|
margin-top: 0px; |
|
|
|
margin-left: 0; |
|
|
|
|
|
|
|
.conclusion-container { |
|
|
|
padding: 20px; |
|
|
|
border-radius: 15px; |
|
|
|
margin: 20px; |
|
|
|
background: linear-gradient(135deg, rgba(0, 212, 255, 0.15) 0%, rgba(0, 100, 200, 0.15) 100%); |
|
|
|
border: 2px solid rgba(0, 212, 255, 0.4); |
|
|
|
box-shadow: 0 8px 25px rgba(0, 212, 255, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1); |
|
|
|
backdrop-filter: blur(15px); |
|
|
|
|
|
|
|
.conclusion-item { |
|
|
|
margin-bottom: 20px; |
|
|
|
padding: 20px; |
|
|
|
border-radius: 12px; |
|
|
|
background: linear-gradient(135deg, rgba(0, 212, 255, 0.2) 0%, rgba(0, 150, 255, 0.1) 100%); |
|
|
|
border: 1px solid rgba(0, 212, 255, 0.5); |
|
|
|
border-left: 5px solid #00d4ff; |
|
|
|
box-shadow: 0 4px 15px rgba(0, 212, 255, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.1); |
|
|
|
transition: all 0.3s ease; |
|
|
|
position: relative; |
|
|
|
overflow: hidden; |
|
|
|
|
|
|
|
&::before { |
|
|
|
content: ''; |
|
|
|
position: absolute; |
|
|
|
top: 0; |
|
|
|
left: 0; |
|
|
|
right: 0; |
|
|
|
height: 2px; |
|
|
|
background: linear-gradient(90deg, #00d4ff, #0099ff, #00d4ff); |
|
|
|
opacity: 0.8; |
|
|
|
} |
|
|
|
|
|
|
|
&:hover { |
|
|
|
background: linear-gradient(135deg, rgba(0, 212, 255, 0.25) 0%, rgba(0, 150, 255, 0.15) 100%); |
|
|
|
transform: translateY(-2px) scale(1.02); |
|
|
|
box-shadow: 0 8px 25px rgba(0, 212, 255, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2); |
|
|
|
} |
|
|
|
|
|
|
|
&:last-child { |
|
|
|
margin-bottom: 0; |
|
|
|
} |
|
|
|
|
|
|
|
.conclusion-title { |
|
|
|
color: #00d4ff; |
|
|
|
font-size: 22px; |
|
|
|
font-weight: bold; |
|
|
|
margin: 0 0 15px 0; |
|
|
|
text-align: center; |
|
|
|
text-shadow: 0 2px 8px rgba(0, 212, 255, 0.5), 0 0 20px rgba(0, 212, 255, 0.3); |
|
|
|
letter-spacing: 2px; |
|
|
|
position: relative; |
|
|
|
|
|
|
|
&::after { |
|
|
|
content: ''; |
|
|
|
position: absolute; |
|
|
|
bottom: -5px; |
|
|
|
left: 50%; |
|
|
|
transform: translateX(-50%); |
|
|
|
width: 60px; |
|
|
|
height: 2px; |
|
|
|
background: linear-gradient(90deg, transparent, #00d4ff, transparent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.conclusion-text { |
|
|
|
color: #ffffff; |
|
|
|
font-size: 16px; |
|
|
|
line-height: 1.8; |
|
|
|
margin: 0 0 12px 0; |
|
|
|
text-align: left; |
|
|
|
word-wrap: break-word; |
|
|
|
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7); |
|
|
|
padding-left: 15px; |
|
|
|
position: relative; |
|
|
|
|
|
|
|
&::before { |
|
|
|
content: '▶'; |
|
|
|
position: absolute; |
|
|
|
left: 0; |
|
|
|
top: 0; |
|
|
|
color: #00d4ff; |
|
|
|
font-size: 12px; |
|
|
|
opacity: 0.7; |
|
|
|
} |
|
|
|
|
|
|
|
&:last-child { |
|
|
|
margin-bottom: 0; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.conclusion-placeholder { |
|
|
|
padding: 30px; |
|
|
|
text-align: center; |
|
|
|
border-radius: 12px; |
|
|
|
background: rgba(255, 255, 255, 0.05); |
|
|
|
border: 1px dashed rgba(153, 153, 153, 0.3); |
|
|
|
|
|
|
|
p { |
|
|
|
color: #999999; |
|
|
|
font-size: 16px; |
|
|
|
margin: 0; |
|
|
|
font-style: italic; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.disclaimer-item { |
|
|
|
margin-top: 30px; |
|
|
|
padding: 20px; |
|
|
|
border-top: 1px solid rgba(153, 153, 153, 0.2); |
|
|
|
text-align: center; |
|
|
|
|
|
|
|
.disclaimer-text { |
|
|
|
color: #999999; |
|
|
|
font-size: 14px; |
|
|
|
margin: 0; |
|
|
|
font-style: italic; |
|
|
|
opacity: 0.8; |
|
|
|
letter-spacing: 1px; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.class05 { |
|
|
@ -1082,7 +1660,7 @@ onMounted(() => { |
|
|
|
background-repeat: no-repeat; |
|
|
|
width: 100%; |
|
|
|
height: auto; |
|
|
|
min-height: 32rem; |
|
|
|
min-height: 33rem; |
|
|
|
margin: 0 auto; |
|
|
|
} |
|
|
|
|
|
|
|