feat:对接舆情监测相关接口

This commit is contained in:
zjc
2024-12-25 18:17:00 +08:00
parent 45c85763dd
commit 50a6b06381
23 changed files with 532 additions and 214 deletions

View File

@@ -40,7 +40,17 @@
</div>
</div>
</div>
<Map />
<div class="rela">
<div class="alarm-box">
<ul class="flex">
<li class="alarm-item" v-for="(item, index) in list" :key="index">
<img class="icon" :src="item.icon" />
<span>{{ item.label }}</span>
</li>
</ul>
</div>
<Map />
</div>
<div class="footer">
<div class="left">
<div>
@@ -112,7 +122,30 @@
<script setup>
import countup from 'vue-countup-v3'
import ScrollNumber from '@/components/ScrollNumber/index.vue'
import icon8 from '@/assets/images/icon-8.png'
import icon9 from '@/assets/images/icon-9.png'
import icon10 from '@/assets/images/icon-10.png'
import icon11 from '@/assets/images/icon-11.png'
let count = ref('6945959')
let list = ref([
{
label: '安全异常',
icon: icon8
},
{
label: '排队异常',
icon: icon9
},
{
label: '停车异常',
icon: icon10
},
{
label: '舆论异常',
icon: icon11
}
])
</script>
<style lang="scss" scoped>
@@ -141,7 +174,7 @@
.item {
flex: 1;
.label {
margin-bottom: vh(10);
margin-bottom: vh(20);
font-weight: 400;
font-size: vw(16);
color: rgba(255, 255, 255, 0.9);
@@ -168,6 +201,29 @@
background: linear-gradient(180deg, #00b7ff 0%, #0033ff 100%);
}
}
.alarm-box {
position: absolute;
top: vw(20);
left: vw(20);
z-index: 99999;
.alarm-item {
width: vw(110);
height: vh(40);
margin-right: vw(4);
font-weight: 400;
font-size: vw(14);
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(to bottom, rgba(238, 44, 44, 0) 0%, #ee2c2c 100%);
.icon {
width: vw(20);
height: vw(20);
margin-right: vw(4);
}
}
}
.footer {
display: flex;
width: 100%;

View File

@@ -22,5 +22,30 @@
{ name: '舆情', path: '/sentiment' },
{ name: '酒店' }
]
onMounted(() => {})
onMounted(() => {
let socket = new WebSocket('ws://36.138.38.16:81/ws/third-party', 'echo-protocol', {
headers: {
Authorization:
'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImE1OWFmNWYwLTU3OWItNDJkNy1hZDJhLTY0Y2JlODA5ZWI1NiJ9.BTxvu6jUWbN0qONWf5K6VzXopE8T8qXzKuX-mij21VJT4U0LdgnqToyqeNDQ2OyJ6cvpdJBzQ9mEEb-dnwrTpQ'
}
})
socket.onopen = () => {
console.log('WebSocket connected')
socket.send(
JSON.stringify({
action: 'start',
type: 'index'
})
)
}
socket.onerror = (error) => {
console.error('WebSocket error:', error)
}
socket.onmessage = (message) => {
console.log('Received message:', message.data)
let data = JSON.parse(message.data)
console.log('Received message:', data)
}
socket.onclose = () => {}
})
</script>

View File

@@ -1,15 +1,18 @@
<template>
<div class="emotion" id="emotion" />
<div class="area" id="area" />
</template>
<script setup>
import * as echarts from 'echarts'
import { fitChartSize } from '@/utils/dataUtil'
let emotionChart = null
const initChart = () => {
const dom = document.getElementById('emotion')
emotionChart = echarts.init(dom)
emotionChart.setOption({
import { getAreaApi } from '@/api/sentiment.js'
let areaChart = null
const initChart = async () => {
const dom = document.getElementById('area')
areaChart = echarts.init(dom)
let res = await getAreaApi()
areaChart.setOption({
legend: {
top: 'top',
itemWidth: fitChartSize(30),
@@ -23,30 +26,27 @@
{
name: 'Nightingale Chart',
type: 'pie',
radius: ['10%', '70%'],
radius: ['30%', '60%'],
center: ['50%', '56%'],
roseType: 'area',
labelLine: {
normal: {
show: true,
length: 1
}
},
itemStyle: {
borderRadius: fitChartSize(10)
},
data: [
{ value: 40, name: 'rose 1' },
{ value: 38, name: 'rose 2' },
{ value: 32, name: 'rose 3' },
{ value: 30, name: 'rose 4' },
{ value: 28, name: 'rose 5' },
{ value: 26, name: 'rose 6' },
{ value: 22, name: 'rose 7' },
{ value: 18, name: 'rose 8' }
]
data: res.data
}
]
})
}
const resize = () => {
if (emotionChart) {
emotionChart.dispose()
emotionChart = null
if (areaChart) {
areaChart.dispose()
areaChart = null
initChart()
}
}
@@ -57,7 +57,7 @@
</script>
<style scoped lang="scss">
.emotion {
.area {
width: vw(740);
height: vh(400);
}

View File

@@ -8,18 +8,44 @@
<p>敏感舆情</p>
</div>
<div class="list">
<div class="cell" v-for="(item, index) in 10" :key="index">
<p><span class="index">排名</span></p>
<p><span class="name">手机新浪网</span></p>
<p><span class="name">新闻</span></p>
<p><span class="number">580</span></p>
<p><span class="status">1000</span></p>
<div class="cell" v-for="(item, index) in list" :key="index">
<p>
<span
class="index"
:class="{ first: item.rank == 1, second: item.rank == 2, third: item.rank == 3 }"
>
{{ item.rank }}
</span>
</p>
<p>
<span class="name">{{ item.title }}</span>
</p>
<p>
<span class="name">{{ item.type }}</span>
</p>
<p>
<span class="number">{{ item.num }}</span>
</p>
<p>
<span class="status">{{ item.num_sensitive }}</span>
</p>
</div>
</div>
</div>
</template>
<script setup></script>
<script setup>
import { getMediaTypeApi } from '@/api/sentiment.js'
let list = ref([])
const getMediaType = async () => {
let res = await getMediaTypeApi()
list.value = res.data
}
onMounted(() => {
getMediaType()
})
</script>
<style scoped lang="scss">
.table {
@@ -84,6 +110,18 @@
border-radius: vw(2);
background-color: #495c77;
}
.first {
@extend .index;
background-color: #d9011b;
}
.second {
@extend .index;
background-color: #feae00;
}
.third {
@extend .index;
background-color: #2380fb;
}
.name {
font-weight: 400;
font-size: vw(15);

View File

@@ -6,11 +6,13 @@
import * as echarts from 'echarts'
import 'echarts-wordcloud'
import { fitChartSize } from '@/utils/dataUtil'
import { getHotWordApi } from '@/api/sentiment'
let wordChart = null
const initChart = () => {
const initChart = async () => {
const dom = document.getElementById('wordCloud')
wordChart = echarts.init(dom)
let res = await getHotWordApi()
wordChart.setOption({
//你的代码
series: [
@@ -45,56 +47,7 @@
padding: fitChartSize(10),
backgroundColor: 'rgba(0,255,255,.2)'
},
data: [
{
value: 2,
name: '体外循环'
},
{
value: 1,
name: '偏好现金'
},
{
value: 7.75434839431,
name: '新成立公司'
},
{
value: 11.3865516372,
name: '相同董监高'
},
{
value: 7.75434839431,
name: '司法风险'
},
{
value: 5.83541244308,
name: '小微企业'
},
{
value: 15.83541244308,
name: '同名称交易'
},
{
value: 2.83541244308,
name: '高频交易'
},
{
value: 5.83541244308,
name: '大额交易'
},
{
value: 10.83541244308,
name: '贸易公司'
},
{
value: 5.83541244308,
name: '票据偏好'
},
{
value: 5.83541244308,
name: '空转走单'
}
]
data: res.data
}
]
})
@@ -115,6 +68,6 @@
<style scoped lang="scss">
.wordCloud {
width: vw(760);
height: vh(420);
height: vh(410);
}
</style>

View File

@@ -6,36 +6,36 @@
<div class="box-1 mr-10">
<Title1 title="最新舆情" />
<div class="list">
<div class="item" v-for="item in 20">
<p class="status status-error">负面</p>
<div class="item" v-for="(item, index) in hotNewList" :key="index">
<p class="status status-error">{{ item.type }}</p>
<p class="content">
这是一条关于三侠之颠旅游舆情的负面新闻这是一条关于三侠之颠旅游舆情的负面这是一条关于三侠之颠旅游舆情的负面新闻这是一条关于三侠之颠旅游舆情的负面
{{ item.title }}
</p>
<p class="date">2024-12.16 23:58</p>
<p class="date">{{ item.time }}</p>
</div>
</div>
</div>
<div class="box-2 mr-10">
<div class="flex justify-center">
<div class="top flex justify-evenly">
<count-item label="今日舆情总数" :count="35600" suffix="条" color="#fff" />
<count-item label="今日正面舆情" :count="35600" suffix="条" color="#fff" />
<count-item label="今日负面舆情" :count="35600" suffix="条" color="#fff" />
<count-item label="今日舆情总数" :count="total" suffix="条" color="#ffffff" />
<count-item label="今日正面舆情" :count="sensitive" suffix="条" color="#ffffff" />
<count-item label="今日负面舆情" :count="unsensitive" suffix="条" color="#ffffff" />
</div>
</div>
<div class="flex mt-20 gap-8 ml-8 mr-8">
<div class="border flex-1">
<div v-for="(item, index) in stateList" class="border flex-1">
<Title3 :title="index" />
<pie-row :width="500" :height="330" :dataList="item" />
</div>
<!-- <div class="border flex-1">
<Title3 title="山峡之巅" />
<pie-row :width="500" :height="330" />
</div>
<div class="border flex-1">
<Title3 title="山峡之巅" />
<pie-row :width="500" :height="330" />
</div>
<div class="border flex-1">
<Title3 title="山峡之巅" />
<pie-row :width="500" :height="330" />
</div>
</div> -->
</div>
</div>
<div class="box-1">
@@ -49,23 +49,14 @@
<Line
:width="1560"
:height="400"
:data="[
{
name: '企业数',
data: [64, 159, 112, 86, 151, 131, 118, 232, 23, 64, 159, 112, 86, 151, 131, 118]
},
{
name: '交易量',
data: [124, 30, 77, 97, 67, 75, 70, 334, 123, 124, 30, 77, 97, 67, 75, 70]
}
]"
:data="seriesData"
:xAxisData="xAxisData"
:seriesConfig="{ smooth: false, symbol: 'circle' }"
/>
</div>
<div class="box-1 mr-10">
<Title1 title="情感分布" />
<emotion />
<Title1 title="地域分析" />
<Area />
</div>
<div class="box-1 mr-10">
<Title1 title="词频分析" />
@@ -77,27 +68,45 @@
</template>
<script setup>
import emotion from './components/emotion.vue'
import Area from './components/area.vue'
import wordCloud from './components/wordCloud.vue'
import dataSource from './components/dataSource.vue'
let xAxisData = ref([
'12-16 10:00',
'12-16 14:00',
'12-16 16:00',
'12-16 22:00',
'12-17 02:00',
'12-17 06:00',
'12-17 10:00',
'12-17 14:00',
'12-17 16:00',
'12-16 22:00',
'12-18 02:00',
'12-18 06:00',
'12-8 10:00',
'12-18 14:00',
'12-18 16:00',
'12-18 20:00'
])
import { getHotNewApi, getLineChartApi, getStateApi, getTotalApi } from '@/api/sentiment.js'
let seriesData = ref([])
let xAxisData = ref([])
let hotNewList = ref([])
let total = ref(0)
let sensitive = ref(0)
let unsensitive = ref(0)
let stateList = ref([])
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
console.log(stateList.value, '------')
}
const getLineChart = async () => {
let res = await getLineChartApi()
xAxisData.value = res.data.data
seriesData.value = res.data.series
}
const getHotNew = async () => {
let res = await getHotNewApi()
hotNewList.value = res.data
}
onMounted(() => {
getHotNew()
getTotal()
getState()
getLineChart()
})
</script>
<style scoped lang="scss">