first commit
This commit is contained in:
184
src/views/components/dataEngine/hotCloud.vue
Normal file
184
src/views/components/dataEngine/hotCloud.vue
Normal file
@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<view>
|
||||
<topHeader ref="topHeaderRef"></topHeader>
|
||||
<a-space direction="vertical" style="background-color: #fff; width: 100%; padding: 24px; margin: 24px 0">
|
||||
<a-space align="center">
|
||||
<span>行业词云</span>
|
||||
<a-popover position="tl">
|
||||
<a-button type="primary" class="pop-btn">
|
||||
<template #icon>
|
||||
<icon-question-circle />
|
||||
</template>
|
||||
</a-button>
|
||||
<template #content>
|
||||
<p>基于xxx获取数据xxx,一段文字描述该数据的获取方式和来源等xxx</p>
|
||||
</template>
|
||||
</a-popover>
|
||||
</a-space>
|
||||
<div class="multi-row-tag-cloud">
|
||||
<!-- 动态生成多行标签 -->
|
||||
<div
|
||||
v-for="(row, rowIndex) in tagRows"
|
||||
:key="rowIndex"
|
||||
class="tag-row"
|
||||
:style="{ justifyContent: row.align || 'center' }"
|
||||
>
|
||||
<a-tag
|
||||
v-for="(tag, tagIndex) in row.tags"
|
||||
:key="tagIndex"
|
||||
:style="{
|
||||
fontSize: `${getFontSize(rowIndex, tagIndex)}px`,
|
||||
lineHeight: `${getLineHeight(rowIndex, tagIndex) + 10}px`,
|
||||
color: '#6d4cfe',
|
||||
backgroundColor: '#F0EDFF',
|
||||
margin: '12px',
|
||||
transition: 'all 0.3s',
|
||||
paddingLeft: `${getPaddingLeft(rowIndex, tagIndex)}px`,
|
||||
paddingRight: `${getPaddingLeft(rowIndex, tagIndex)}px`,
|
||||
paddingTop: `${getPadding(rowIndex, tagIndex)}px`,
|
||||
paddingBottom: `${getPadding(rowIndex, tagIndex)}px`,
|
||||
borderRadius: '100px',
|
||||
borderRadius: '100px',
|
||||
}"
|
||||
@mouseenter="hoverTag = tag"
|
||||
@mouseleave="hoverTag = null"
|
||||
>
|
||||
<a-space>
|
||||
<a-tooltip :content="`性价比:${Number(tag.rate * 100)}%`" position="tl">
|
||||
<a-space>{{ tag.term }}</a-space>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</a-tag>
|
||||
</div>
|
||||
</div>
|
||||
</a-space>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import topHeader from './topHeader.vue';
|
||||
import { ref, computed } from 'vue';
|
||||
import { fetchindustryTerms } from '@/api/all/index';
|
||||
|
||||
const topHeaderRef = ref();
|
||||
// 从topHeader获取统一的状态
|
||||
const selectedIndustry = computed(() => topHeaderRef.value?.selectedIndustry);
|
||||
const selectedSubCategory = computed(() => topHeaderRef.value?.selectedSubCategory);
|
||||
const selectedTimePeriod = computed(() => topHeaderRef.value?.selectedTimePeriod);
|
||||
|
||||
const getIndustryTerms = async () => {
|
||||
const params = {
|
||||
industry_id: selectedIndustry.value,
|
||||
time_dimension: selectedTimePeriod.value,
|
||||
};
|
||||
const res = await fetchindustryTerms(params);
|
||||
// 这里需要根据API返回的数据结构处理成tagRows需要的格式
|
||||
tagRows.value = processTagData(res);
|
||||
};
|
||||
|
||||
// 标签数据(按行分组)
|
||||
const tagRows = ref();
|
||||
const hoverTag = ref(null);
|
||||
|
||||
// 根据行列位置计算字体大小(中间最大)
|
||||
const getFontSize = (rowIndex, tagIndex) => {
|
||||
const centerRow = Math.floor(tagRows.value.length / 2);
|
||||
const distance = Math.abs(rowIndex - centerRow);
|
||||
return 38 - distance * 8 + (tagIndex % 2) * 5; // 基础24px,行距影响4px,微调差异2px
|
||||
};
|
||||
|
||||
const getLineHeight = (rowIndex, tagIndex) => {
|
||||
const centerRow = Math.floor(tagRows.value.length / 2);
|
||||
const distance = Math.abs(rowIndex - centerRow);
|
||||
return 48 - distance * 8 + (tagIndex % 2) * 5; // 基础24px,行距影响4px,微调差异2px
|
||||
};
|
||||
|
||||
const getPaddingLeft = (rowIndex, tagIndex) => {
|
||||
const centerRow = Math.floor(tagRows.value.length / 2);
|
||||
const distance = Math.abs(rowIndex - centerRow);
|
||||
return 30 - distance * 8 + (tagIndex % 2) * 5; // 基础24px,行距影响4px,微调差异2px
|
||||
};
|
||||
|
||||
const getPadding = (rowIndex, tagIndex) => {
|
||||
const centerRow = Math.floor(tagRows.value.length / 2);
|
||||
const distance = Math.abs(rowIndex - centerRow);
|
||||
return 28 - distance * 8 + (tagIndex % 2) * 5; // 基础24px,行距影响4px,微调差异2px
|
||||
};
|
||||
|
||||
// 处理API返回数据为tagRows格式
|
||||
const processTagData = (apiData) => {
|
||||
const totalGroups = 7; // 总组数
|
||||
const middleIndex = Math.floor(totalGroups / 2); // 中间位置(索引3)
|
||||
const chunkSize = Math.ceil(apiData.length / totalGroups); // 每组大小
|
||||
const arr = [];
|
||||
|
||||
// 1. 先按顺序分组
|
||||
const tempGroups = [];
|
||||
for (let i = 0; i < totalGroups; i++) {
|
||||
const start = i * chunkSize;
|
||||
const end = start + chunkSize;
|
||||
tempGroups.push(apiData.slice(start, end));
|
||||
}
|
||||
|
||||
// 2. 从中间开始,左右交替插入
|
||||
for (let i = 0; i < totalGroups; i++) {
|
||||
// 计算当前组应该插入的位置
|
||||
const insertPos = i % 2 === 0 ? middleIndex + i / 2 : middleIndex - Math.ceil(i / 2);
|
||||
|
||||
// 确保不越界
|
||||
if (insertPos >= 0 && insertPos < totalGroups) {
|
||||
arr[insertPos] = { tags: tempGroups[i], align: 'center' };
|
||||
}
|
||||
}
|
||||
|
||||
return arr.filter(Boolean); // 移除可能的空项
|
||||
};
|
||||
|
||||
// 监听筛选条件变化
|
||||
watch([selectedIndustry, selectedTimePeriod], () => {
|
||||
getIndustryTerms();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
getIndustryTerms();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 自定义样式 */
|
||||
:deep(.arco-table-th) {
|
||||
background-color: var(--color-fill-2);
|
||||
}
|
||||
|
||||
:deep(.arco-table-tr):hover {
|
||||
background-color: var(--color-fill-1);
|
||||
}
|
||||
:deep(.arco-btn-outline) {
|
||||
color: #6d4cfe !important;
|
||||
border-color: #6d4cfe !important;
|
||||
}
|
||||
:deep(.arco-modal-body) {
|
||||
padding: 0px;
|
||||
}
|
||||
.multi-row-tag-cloud {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.tag-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* 悬停放大效果 */
|
||||
a-tag:hover {
|
||||
transform: scale(1.1);
|
||||
z-index: 1;
|
||||
}
|
||||
.pop-btn {
|
||||
background: #fff !important;
|
||||
border-color: #fff !important;
|
||||
color: #737478 !important;
|
||||
margin-left: -5px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user