Browse Source

接入股票结论的接口并使用打字机效果;语音播放完成。

ds_hxl
宋杰 2 weeks ago
parent
commit
5e3a829a14
  1. 2
      src/api/AiEmotionApi.js
  2. 15
      src/store/emotion.ts
  3. 618
      src/views/AiEmotion.vue
  4. 33
      src/views/components/marketTemperature.vue

2
src/api/AiEmotionApi.js

@ -21,7 +21,7 @@ export const getReplyAPI = function (params) {
};
// 获取第二个工作流给出的结论
export const getConclusion = function (params) {
export const getConclusionAPI = function (params) {
return fetch("https://api.coze.cn/v1/workflow/run", {
method: "POST",
body: JSON.stringify({

15
src/store/emotion.ts

@ -62,6 +62,7 @@ export const useEmotionStore = defineStore('emotion', {
queryText: stockData.queryText,
stockInfo: stockData.stockInfo,
apiData: stockData.apiData,
conclusionData: stockData.conclusionData,
timestamp: stockData.timestamp
});
},
@ -101,10 +102,22 @@ export const useEmotionStore = defineStore('emotion', {
queryText: historyItem.queryText,
stockInfo: historyItem.stockInfo,
apiData: historyItem.apiData,
conclusionData: historyItem.conclusionData,
timestamp: historyItem.timestamp
};
this.addStock(stockData);
},
// 更新股票的结论数据
updateStockConclusion(index: number, conclusionData: string) {
if (index >= 0 && index < this.stockList.length) {
this.stockList[index].conclusionData = conclusionData;
this.stockList[index].timestamp = new Date().toISOString();
}
},
// 更新当前激活股票的结论数据
updateActiveStockConclusion(conclusionData: string) {
this.updateStockConclusion(this.activeStockIndex, conclusionData);
},
},
});
@ -117,6 +130,7 @@ interface HistoryItem {
market: string; // 市场(如 usa/cn/hk)
};
apiData: any; // 接口返回的原始数据(包含图表数据)
conclusionData?: string; // 第二个工作流接口返回的结论数据
timestamp: string; // 记录时间
}
@ -129,5 +143,6 @@ interface StockData {
market: string; // 市场
};
apiData: any; // API返回的完整数据
conclusionData?: string; // 第二个工作流接口返回的结论数据
timestamp: string; // 数据获取时间
}

618
src/views/AiEmotion.vue

@ -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(parsedData.code, parsedData.market, parsedData.name || "未知股票", input.trim());
// 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);
}
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;
}

33
src/views/components/marketTemperature.vue

@ -353,6 +353,23 @@ defineExpose({ initChart })
padding: 20px;
width: 80%;
margin-left: 8%;
height: auto;
overflow: visible;
}
.border4 .el-table {
height: auto !important;
max-height: none !important;
}
.border4 .el-table__body-wrapper {
height: auto !important;
max-height: none !important;
overflow: visible !important;
}
.border4 .el-table__body {
height: auto !important;
}
/* 手机端适配样式 */
@ -369,6 +386,22 @@ defineExpose({ initChart })
width: 100%;
margin-left: 0%;
height: auto;
overflow: visible;
}
.border4 .el-table {
height: auto !important;
max-height: none !important;
}
.border4 .el-table__body-wrapper {
height: auto !important;
max-height: none !important;
overflow: visible !important;
}
.border4 .el-table__body {
height: auto !important;
}
.el-table .hidden-columns {

Loading…
Cancel
Save