587 lines
14 KiB
Vue
587 lines
14 KiB
Vue
<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>
|