Files
lingji-work-fe/src/views/components/dataEngine/keyBrandMovement.vue
2025-07-01 16:39:47 +08:00

298 lines
8.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- eslint-disable vue/no-duplicate-attributes -->
<template>
<view>
<topHeader ref="topHeaderRef" @click="search"></topHeader>
<!-- 重点品牌列表 -->
<a-space
direction="vertical"
class="bg-#fff rounded-8px border-1px border-#D7D7D9 border-solid w-100% py-0 px-20px mb-24px"
>
<div class="title-row">
<span class="title mr-4px">重点品牌列表</span>
<a-tooltip>
<template #content
>基于该行业中近期提及频次高用户互动活跃的品牌内容筛选出关注度较高的代表性品牌</template
>
<icon-question-circle size="16" class="!color-#737478" />
</a-tooltip>
</div>
<a-table
:columns="columns"
:data="dataList"
:filter-icon-align-left="alignLeft"
:scroll="true"
:pagination="false"
@change="handleChange"
>
<template #empty>
<NoData />
</template>
<template #hotTitle>
<a-space>
<span>热度指数</span>
<a-tooltip>
<template #content>综合话题出现频次互动数据如点赞收藏评论加权计算的热度得分</template>
<icon-question-circle size="14" class="!color-#737478" />
</a-tooltip>
</a-space>
</template>
<template #trendTitle>
<a-space>
<span>变化幅度</span>
<a-tooltip>
<template #content>仅基于品牌出现频次</template>
<icon-question-circle size="14" class="!color-#737478" />
</a-tooltip>
</a-space>
</template>
<template #volume_rateTitle>
<a-space>
<span>占总声量比例</span>
<a-tooltip>
<template #content>该品牌在当前周期内被提及的内容量占整个行业内容总量的比例</template>
<icon-question-circle size="14" class="!color-#737478" />
</a-tooltip>
</a-space>
</template>
<template #rank="{ record }">
<img v-if="record.rank == 1" :src="topImages[0]" style="width: 25px; height: 17px" />
<img v-else-if="record.rank == 2" :src="topImages[1]" style="width: 25px; height: 17px" />
<img v-else-if="record.rank == 3" :src="topImages[2]" style="width: 25px; height: 17px" />
<span v-else>{{ record.rank }}</span>
</template>
<template #hot="{ record }">
<img v-for="i in record.hot" :key="i" :src="starImages[i - 1]" style="width: 16px; height: 16px" />
</template>
<template #trend="{ record }">
<div class="flex items-center" :class="record.trend > 0 ? 'color-#F64B31' : 'color-#25C883'">
<icon-arrow-up v-if="record.trend > 0" size="16" />
<icon-arrow-down v-else size="16" />
{{ `${record.trend * 100}%` }}
</div>
</template>
<template #volumeRate="{ record }"> <a-statistic :value="record.volume_rate * 100" />% </template>
</a-table>
</a-space>
<!-- 舆情 & 敏感动态-->
<a-space
direction="vertical"
class="bg-#fff rounded-8px border-1px border-#D7D7D9 border-solid w-100% py-0 px-20px mb-24px"
>
<div class="title-row">
<span class="title mr-4px">舆情 & 敏感动态</span>
<a-tooltip>
<template #content
>基于情绪分析与敏感词识别对行业内容中的负面或争议性话题进行监测辅助判断舆情风险动态</template
>
<icon-question-circle size="16" class="!color-#737478" />
</a-tooltip>
</div>
<a-table :data="otherList" :columns="columns2" :pagination="false" :scroll="true" style="font-size: 12px">
<template #empty>
<NoData />
</template>
</a-table>
</a-space>
</view>
</template>
<script setup>
import topHeader from './topHeader.vue';
import { fetchFocusBrandsList, fetchEventDynamicsList } from '@/api/all/index';
import { ref, onMounted, computed } from 'vue';
import star1 from '@/assets/img/hottranslation/star-fill1.png';
import star2 from '@/assets/img/hottranslation/star-fill2.png';
import star3 from '@/assets/img/hottranslation/star-fill3.png';
import star4 from '@/assets/img/hottranslation/star-fill4.png';
import star5 from '@/assets/img/hottranslation/star-fill5.png';
import top1 from '@/assets/img/captcha/top1.svg';
import top2 from '@/assets/img/captcha/top2.svg';
import top3 from '@/assets/img/captcha/top3.svg';
const topImages = [top1, top2, top3];
const starImages = [star1, star2, star3, star4, star5];
const topHeaderRef = ref();
// 从topHeader获取统一的状态
const selectedIndustry = computed(() => topHeaderRef.value?.selectedIndustry);
const selectedSubCategory = computed(() => topHeaderRef.value?.selectedSubCategory);
const selectedTimePeriod = computed(() => topHeaderRef.value?.selectedTimePeriod);
const dataList = ref([]);
const otherList = ref([]);
const columns = [
{
title: '排名',
dataIndex: 'rank',
slotName: 'rank',
width: 60,
minWidth: 60,
},
{
title: '品牌名称',
dataIndex: 'name',
width: 120,
minWidth: 120,
},
{
titleSlotName: 'hotTitle',
width: 180,
minWidth: 180,
title: '热度指数',
dataIndex: 'hot',
sortable: {
sortDirections: ['ascend', 'descend'],
},
slotName: 'hot',
},
{
titleSlotName: 'trendTitle',
title: '变化幅度',
dataIndex: 'trend',
width: 180,
minWidth: 180,
sortable: {
sortDirections: ['ascend', 'descend'],
},
slotName: 'trend',
},
{
titleSlotName: 'volume_rateTitle',
title: '占总声量比例',
dataIndex: 'volumeRate',
width: 180,
minWidth: 180,
sortable: {
sortDirections: ['ascend', 'descend'],
},
slotName: 'volumeRate',
},
];
const columns2 = [
{
title: '品牌',
dataIndex: 'brand',
width: 100,
minWidth: 100,
},
{
title: '事件标题',
dataIndex: 'title',
width: 180,
minWidth: 180,
sortable: {},
},
{
title: '事件详情',
dataIndex: 'content',
width: 220,
minWidth: 220,
sortable: {},
},
];
const search = () => {
getFocusBrandsList();
getEventDynamicsList();
};
const getFocusBrandsList = async () => {
const params = {
industry_id: selectedIndustry.value,
time_dimension: selectedTimePeriod.value,
};
if (selectedIndustry.value == undefined) {
return;
}
if (selectedSubCategory.value == undefined) {
return;
}
if (selectedSubCategory.value != 0) {
params['industry_id'] = selectedSubCategory.value;
}
const res = await fetchFocusBrandsList(params);
if (res.code == 200) {
// 这里需要根据API返回的数据结构处理成tagRows需要的格式
dataList.value = res.data;
}
};
const getEventDynamicsList = async () => {
const params = {
industry_id: selectedIndustry.value,
time_dimension: selectedTimePeriod.value,
};
if (selectedIndustry.value == undefined) {
return;
}
if (selectedSubCategory.value == undefined) {
return;
}
if (selectedSubCategory.value != 0) {
params['industry_id'] = selectedSubCategory.value;
}
const res = await fetchEventDynamicsList(params);
if (res.code == 200) {
// 这里需要根据API返回的数据结构处理成tagRows需要的格式
otherList.value = res.data;
}
};
onMounted(() => {
getFocusBrandsList();
getEventDynamicsList();
});
// 监听筛选条件变化
watch([selectedTimePeriod, selectedSubCategory], () => {
getFocusBrandsList();
getEventDynamicsList();
});
watch(selectedIndustry, () => {
selectedSubCategory.value = 0;
getFocusBrandsList();
getEventDynamicsList;
});
</script>
<style scoped lang="scss">
/* 自定义样式 */
:deep(.arco-table-th) {
background-color: var(--color-fill-2);
}
:deep(.arco-table-tr):hover {
background-color: var(--color-fill-1);
}
:deep(.arco-statistic-content .arco-statistic-value-integer) {
font-size: 14px;
}
.pop-btn {
background: #fff !important;
border-color: #fff !important;
color: #737478 !important;
margin-left: -5px;
}
:deep(.arco-btn-outline) {
color: #6d4cfe !important;
border-color: #6d4cfe !important;
}
.pop-btn2 {
background: transparent !important;
border-color: transparent !important;
color: #737478 !important;
margin-left: -10px;
}
.title-row {
display: flex;
height: 64px;
padding: 10px 0 2px 0;
align-items: center;
.title {
color: var(--Text-1, #211f24);
font-family: 'PuHuiTi-Medium';
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px; /* 150% */
}
}
</style>