Files
fengjie-datascreen/src/views/sentiment/index.vue
duanliang de4f68066c 5.4
2025-06-04 14:56:19 +08:00

587 lines
14 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.
<template>
<div class="container">
<div class="flex">
<div class="box-1 mr-8">
<Title1 title="最新舆情" />
<div class="list">
<div class="item" @click="handleHot(item)" v-for="(item, index) in hotNewList" :key="index">
<p
:class="{
'status-error': item.type == '负面',
'status-warning': item.type == '正面',
'status-primary': item.type == '中性'
}"
>{{ item.type }}</p
>
<p class="content">
{{ item.title }}
</p>
<p class="date">{{ item.time }}</p>
</div>
</div>
</div>
<div class="box-2 mr-8" :class="homeStore.amplify?'':'coll-box'">
<div class="flex justify-center">
<div class="top flex justify-evenly">
<count-item label="今日舆情总数" :count="total" suffix="条" color="#ffffff" />
<count-item label="今日非敏感舆情" :count="unsensitive" suffix="条" color="#ffffff" />
<count-item label="今日负面舆情" :count="sensitive" suffix="条" color="#ffffff" />
</div>
</div>
<div class="flex mt-20 gap-8 ml-8 mr-8">
<div v-for="(item, index) in stateList" :key="index" class="border flex-1">
<Title3 :title="item.name" />
<pie-row :width="490" :height="330" :dataList="item.data" :total="item.total" />
</div>
</div>
</div>
<div class="box-5">
<Title1 title="数据来源分析" />
<data-source />
</div>
</div>
<div class="flex mt-8">
<div class="box-2 mr-8 rela" :class="homeStore.amplify?'':'coll-box'">
<Title1 title="舆情指数" />
<div class="select-box">
<Select
v-model="params.id"
label="选择景区"
:options="options"
@on-change="getLineChart"
/>
</div>
<div class="coll-box-3">
<Line
:width="1500"
:height="400"
:data="seriesData"
:xAxisData="xAxisData"
:seriesConfig="{ smooth: false, symbol: 'circle' }"
/>
</div>
</div>
<div class="box-4 mr-8 rela">
<Title1 title="地域分析" />
<Area />
</div>
<div class="box-3">
<Title1 title="词频分析" />
<word-cloud />
</div>
</div>
<el-dialog :title="'舆情详情'" center v-model="dialogTableVisible">
<div class="bom-box">
<div class="table">
<div class="modal-body">
<div class="m-modal">
<!-- <div class="detail-item">
<span class="label">标识</span>
<span class="value">{{ detailsHot.id }}</span>
</div> -->
<div class="detail-item">
<span class="label">文章作者</span>
<span class="value">{{ detailsHot.newsAuthor }}</span>
</div>
<div class="detail-item">
<span class="label">情感属性</span>
<span class="value">{{ detailsHot.newsEmotion }}</span>
</div>
</div>
<div class="m-modal">
<div class="detail-item">
<span class="label">发布平台</span>
<span class="value">{{ detailsHot.platformName }}</span>
</div>
<div class="detail-item">
<span class="label">发布时间</span>
<span class="value">{{ detailsHot.newsPosttime }}</span>
</div>
</div>
<div class="m-modal">
<div class="detail-item">
<span class="label">原文链接</span>
<a :href="detailsHot.newsUrl" target="_blank" class="link">{{ detailsHot.newsUrl }}</a>
</div>
</div>
<div class="detail-item">
<span class="label">文章标题</span>
<div class="content" v-html="detailsHot.newsTitle"></div>
</div>
<div class="detail-item">
<span class="label">新闻内容</span>
<div class="content" v-html="detailsHot.newsContent"></div>
</div>
</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script setup>
import Area from './components/area.vue'
import wordCloud from './components/wordCloud.vue'
import dataSource from './components/dataSource.vue'
import {
getHotNewApi,
getLineChartApi,
getStateApi,
getTotalApi,
getSpotApi,
getGsdataDetailApi
} from '@/api/sentiment.js'
import { useHomeStore } from '@/stores/home'
const homeStore = useHomeStore()
let seriesData = ref([])
let xAxisData = ref([])
let hotNewList = ref([])
let total = ref(0)
let sensitive = ref(0)
let unsensitive = ref(0)
let stateList = ref([])
let options = ref([])
let params = reactive({ id: '' })
let dialogTableVisible = ref(false)
let detailsHot = ref({})
// 详情
const handleHot = async(item)=>{
let res = await getGsdataDetailApi(item.id)
console.log(res)
detailsHot.value = res.data
dialogTableVisible.value = true
}
const getStop = async () => {
let res = await getSpotApi()
options.value = res.data
}
const getTotal = async () => {
let res = await getTotalApi()
total.value = res.data.total
sensitive.value = res.data.sensitive
unsensitive.value = res.data.unsensitive
}
const getState = async () => {
let res = await getStateApi()
stateList.value = res.data
}
const getLineChart = async () => {
let res = await getLineChartApi(params)
xAxisData.value = res.data.data
seriesData.value = res.data.series
}
const getHotNew = async () => {
let res = await getHotNewApi()
hotNewList.value = res.data
}
let timer = null
onMounted(() => {
getStop()
getHotNew()
getTotal()
timer = setInterval(()=>{
getState()
},2000)
getLineChart()
})
onUnmounted(() => {
if (timer) clearInterval(timer)
})
</script>
<style lang="scss" scoped>
.modal-header h3 {
margin: 0;
}
.close-btn {
background: none;
border: none;
font-size: 20px;
cursor: pointer;
}
.modal-body {
padding: 16px;
color:#fff;
height:vh(780);
overflow:auto;
/* 滚动条整体样式 */
&::-webkit-scrollbar {
width: vw(4); /* 滚动条的宽度 */
}
/* 滚动条轨道 */
&::-webkit-scrollbar-track {
background: 'transparent'; /* 轨道的背景色 */
}
/* 滚动条滑块 */
&::-webkit-scrollbar-thumb {
background: rgba(0, 150, 255, 0.63); /* 滑块的背景色 */
border-radius: 5px; /* 滑块的圆角 */
}
}
.m-modal{
display: flex;
}
.detail-item {
flex:1;
margin-bottom: 12px;
line-height: 1.5;
}
/* .label {
font-weight: bold;
color: #666;
}
.value {
color: #333;
} */
.link {
color: #1890ff;
text-decoration: none;
// font-size:vw(14);
}
.title {
margin: 8px 0;
}
.content {
white-space: pre-wrap;
line-height: 2;
color: #fff;
margin-top:vh(10);
width:100%;
img{
width:100%;
}
}
.content *{
width:100%;
}
.modal-footer {
padding: 16px;
border-top: 1px solid #eee;
text-align: right;
}
.confirm-btn {
padding: 8px 16px;
background: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
<style lang="scss" scoped>
:deep(.el-dialog__headerbtn .el-dialog__close){
color:#fff;
font-size:40px;
position:relative;
top:15px;
right:15px;
}
:deep(.el-dialog__header.show-close){
padding-right:0;
}
:deep(.el-dialog) {
background: url('/src/assets/images/map-bg-2.png') no-repeat center;
background-size: 100% 100%;
// width:vw(1500);
height:vh(880);
// overflow:auto;
}
:deep(.el-dialog__title) {
color: #fff;
font-weight: bold;
}
.sp-ico {
width: vw(40);
}
.item-name {
width: 90%;
text-align: center;
}
.sp-img {
width: vw(100);
}
.correspondence {
margin: vw(8);
width: vw(300);
height: vh(1070);
background-image: url('@/assets/images/bg-1.png');
background-size: 100% 100%;
}
.bom-box2{
// margin-top:vh(10);
min-width:vw(900);
height:vh(800);
}
.header-title{
font-size:vw(32);
color:#fff;
text-align:center;
font-weight:bold;
margin-bottom:vh(20);
}
.bom-box {
.table2{
width:100%;
height:vh(740);
}
.table {
width: 100%;
margin-top: vh(5);
.header {
height: vh(28);
font-weight: 400;
font-size: vw(24);
color: #fff;
display: flex;
background: linear-gradient(180deg, rgba(0, 99, 255, 0) 0%, #0063ff 100%);
& > div {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
}
.list {
overflow-y: auto;
height: vh(490);
/* 滚动条整体样式 */
&::-webkit-scrollbar {
width: vw(4); /* 滚动条的宽度 */
}
/* 滚动条轨道 */
&::-webkit-scrollbar-track {
background: 'transparent'; /* 轨道的背景色 */
}
/* 滚动条滑块 */
&::-webkit-scrollbar-thumb {
background: rgba(0, 150, 255, 0.63); /* 滑块的背景色 */
border-radius: 5px; /* 滑块的圆角 */
}
.item {
height: vh(50);
font-weight: 400;
font-size: vw(24);
color: #f1f7ff;
display: flex;
&:nth-child(2n + 1) {
background: linear-gradient(
90deg,
rgba(0, 150, 255, 0) 0%,
rgba(0, 150, 255, 0.22) 100%
);
}
& > div {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
white-space: nowrap; /* 保证文本在一行内显示 */
overflow: hidden; /* 隐藏溢出的内容 */
text-overflow: ellipsis; /* 使用省略号表示文本溢出 */
}
}
}
}
.title {
span {
margin-left: vw(30);
font-weight: 800;
font-size: vw(15);
line-height: vh(26);
text-align: center;
font-style: normal;
text-transform: none;
background: linear-gradient(90deg, #ffffff 0%, #5cb5ff 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
}
}
}
.top-box {
width: 100%;
height: vh(500);
.icon-box {
font-weight: 400;
font-size: vw(14);
color: #ffffff;
line-height: vh(16);
flex-wrap: wrap;
.item {
cursor: pointer;
width: 50%;
margin-top: vh(40);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
&:nth-child(3n) {
margin-right: 0;
}
& > img {
width: vw(54);
height: auto;
}
}
}
.title {
width: vw(260);
height: vh(26);
text-align: center;
line-height: vh(26);
margin-left: vw(32.5);
font-size: vw(16);
font-weight: 800;
color: #fff;
background-image: url('@/assets/images/title-1.png');
background-size: 100% 100%;
}
}
</style>
<style scoped lang="scss">
.select-box {
position: absolute;
z-index: 99;
top: vh(10);
right: vw(10);
}
.container {
flex: 1;
margin-top: vh(120);
box-sizing: border-box;
justify-content: center;
.bg {
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
}
.top {
width: vw(600);
height: vh(50);
margin-top: vh(35);
}
.box-1 {
width: vw(790);
height: vh(470);
@extend .bg;
}
.box-2 {
width: vw(1514);
height: vh(470);
@extend .bg;
}
.box-3 {
width: vw(810);
height: vh(470);
@extend .bg;
}
.box-4{
width: vw(850);
height: vh(470);
@extend .bg;
}
.box-5{
width: vw(870);
height: vh(470);
@extend .bg;
}
.border {
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
}
.list {
margin: 0 vw(20);
overflow-y: auto;
height: vh(400);
/* 滚动条整体样式 */
&::-webkit-scrollbar {
width: vw(4); /* 滚动条的宽度 */
}
/* 滚动条轨道 */
&::-webkit-scrollbar-track {
background: 'transparent'; /* 轨道的背景色 */
}
/* 滚动条滑块 */
&::-webkit-scrollbar-thumb {
background: rgba(0, 150, 255, 0.63); /* 滑块的背景色 */
border-radius: 5px; /* 滑块的圆角 */
}
.item {
display: flex;
align-items: center;
height: vh(40);
&:nth-child(2n + 1) {
background: rgba(3, 78, 153, 0.3);
}
.status {
width: vw(40);
height: vh(20);
line-height: vh(20);
text-align: center;
margin: 0 vw(20);
font-weight: 400;
font-size: vw(12);
color: #ffffff;
border-radius: vw(2);
&-error {
@extend .status;
background: #d9011b;
}
&-warning {
@extend .status;
background: #50F0A6;
}
&-primary {
@extend .status;
background: #2380fb;
}
}
.content {
flex: 1;
font-weight: 400;
font-size: vw(15);
color: #ffffff;
white-space: nowrap; /* 保证文本在一行内显示 */
overflow: hidden; /* 隐藏溢出的内容 */
text-overflow: ellipsis; /* 使用省略号表示文本溢出 */
}
.date {
margin: 0 vw(20);
font-weight: 400;
font-size: vw(12);
color: rgba(255, 255, 255, 0.7);
}
}
}
}
.container .coll-box{
width:100%;
.coll-box-3{
display:flex;
justify-content: center;
}
}
</style>