feat:完善舆情监测功能

This commit is contained in:
zjc
2024-12-26 13:46:27 +08:00
parent 50a6b06381
commit 809c950301
11 changed files with 192 additions and 139 deletions

View File

@@ -106,6 +106,7 @@ const instance = axios.create({
*/
instance.interceptors.request.use(
(config) => {
console.log(config, 'config')
// 规范写法 不可随意自定义
let urlParams = {}
if (config.params) {

View File

@@ -41,10 +41,11 @@ export function getHotWordApi() {
}
// 舆情指数
export function getLineChartApi() {
export function getLineChartApi(data) {
return request({
url: '/api/largeScreen/gsdata/lineChart',
method: 'post'
method: 'get',
params: data
})
}
@@ -55,3 +56,11 @@ export function getAreaApi() {
method: 'post'
})
}
// 景区选择
export function getSpotApi() {
return request({
url: '/api/largeScreen/gsdata/spot',
method: 'post'
})
}

View File

@@ -8,7 +8,7 @@
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="(item, index) in options" :key="index" :command="item">
<span class="label"> {{ item.label }}</span>
<span class="label"> {{ item.ssname }}</span>
</el-dropdown-item>
</el-dropdown-menu>
</template>
@@ -27,8 +27,10 @@
default: () => []
}
})
let emit = defineEmits(['on-change'])
const handleCommand = (command) => {
console.log(command)
emit('on-change', command)
}
</script>

View File

@@ -8,10 +8,10 @@
/>
</template>
<script setup>
import * as echarts from 'echarts'
import styleUtil from '@/utils/styleUtil'
import { fitChartSize } from '@/utils/dataUtil'
import { guid } from '@/utils/util'
import { useEchart } from '@/hooks/echart'
const props = defineProps({
width: {
type: Number,
@@ -38,9 +38,8 @@
default: () => {}
}
})
const { id, setOption, initChart } = useEchart()
let id = ref(guid())
let lineChart = null
let timer = null
let currentIndex = -1
@@ -64,14 +63,14 @@
valueStr += `<div>${item.seriesName}${item.value}</div>`
})
let str = `<div style="
background: #07356B;
border: 1px solid #0096FF;
color: #fff;
font-weight: 600;
font-size: ${fitChartSize(16)}px;
border-radius: ${fitChartSize(4)}px;
padding: ${fitChartSize(4)}px ${fitChartSize(12)}px;">
${valueStr}</div>`
background: #07356B;
border: 1px solid #0096FF;
color: #fff;
font-weight: 600;
font-size: ${fitChartSize(16)}px;
border-radius: ${fitChartSize(4)}px;
padding: ${fitChartSize(4)}px ${fitChartSize(12)}px;">
${valueStr}</div>`
return str
}
},
@@ -131,20 +130,8 @@
},
series: []
}
watch(
() => props.data,
(val) => {
if (val.length > 0) {
setTimeout(() => {
initChart()
}, 500)
}
},
{ immediate: true }
)
const initChart = () => {
const dom = document.getElementById(id.value)
lineChart = echarts.init(dom)
const init = () => {
initChart()
defaultConfig.xAxis.data = props.xAxisData
props.data.map((item, index) => {
defaultConfig.series.push({
@@ -163,53 +150,28 @@
})
defaultConfig.legend.data.push(item.name)
})
lineChart.setOption({
setOption({
...defaultConfig,
...props.config
})
// // 开启轮播
// startTooltipLoop()
// // 鼠标悬浮,停止轮播
// dom.addEventListener('mousemove', () => {
// console.log('mouse move')
// closeSwitchTooltip()
// })
// // 鼠标离开,继续轮播
// dom.addEventListener('mousedown', () => {
// console.log('mouse down')
// startTooltipLoop()
// })
// 监听窗口大小变化
window.addEventListener('resize', resize)
}
const resize = () => {
if (lineChart) {
lineChart.dispose()
lineChart = null
initChart()
}
}
// // 切换tooltip
// const switchTooltip = () => {
// // 取消之前高亮的图形
// lineChart.dispatchAction({
// chart.value.dispatchAction({
// type: 'downplay',
// seriesIndex: 0,
// dataIndex: currentIndex
// })
// currentIndex = (currentIndex + 1) % 8
// // 高亮当前图形
// lineChart.dispatchAction({
// chart.value.dispatchAction({
// type: 'highlight',
// seriesIndex: 0,
// dataIndex: currentIndex
// })
// // 显示tooltip
// lineChart.dispatchAction({
// chart.value.dispatchAction({
// type: 'showTip',
// seriesIndex: 0,
// dataIndex: currentIndex

View File

@@ -9,10 +9,9 @@
</template>
<script setup>
import * as echarts from 'echarts'
import styleUtil from '@/utils/styleUtil'
import { fitChartSize } from '@/utils/dataUtil'
import { guid } from '@/utils/util'
import { useEchart } from '@/hooks/echart'
const props = defineProps({
width: {
@@ -32,12 +31,16 @@
dataList: {
type: Array,
default: () => []
},
total: {
type: Number,
default: () => 0
}
})
let id = ref(guid())
let pieChart = null
var colorList = ['#FDC40A', '#FF5232', '#50F0A6', '#5FDFFA', '']
const { id, chart, setOption, initChart } = useEchart()
var colorList = ['#FDC40A', '#FF5232', '#50F0A6', '#5FDFFA']
var defaultCofig = {
color: colorList,
@@ -45,16 +48,12 @@
orient: 'vertical',
bottom: 'center',
left: '70%',
data: [],
itemWidth: fitChartSize(16),
itemHeight: fitChartSize(16),
itemGap: fitChartSize(10),
formatter: (name) => {
return name + '\u3000' + '19%'
},
itemWidth: fitChartSize(20),
itemHeight: fitChartSize(20),
itemGap: fitChartSize(20),
textStyle: {
color: '#ffffff',
fontSize: fitChartSize(12)
fontSize: fitChartSize(20)
}
},
series: [
@@ -71,7 +70,7 @@
position: 'center',
fontWeight: 'bold',
formatter: function (o) {
return `{value|123456}` + '\n' + `{name|整改率}`
return `{value|123456}` + '\n' + `{name|舆情总数 }`
},
rich: {
value: {
@@ -94,30 +93,24 @@
]
}
const initChart = () => {
const dom = document.getElementById(id.value)
pieChart = echarts.init(dom)
defaultCofig.series[0].data = props.dataList
pieChart.setOption({
...defaultCofig,
...props.config
})
// 监听窗口大小变化
window.addEventListener('resize', resize)
}
const resize = () => {
if (pieChart) {
pieChart.dispose()
pieChart = null
initChart()
}
}
watch(
() => props.dataList,
(newVal) => {
if (newVal.length > 0) {
nextTick(() => {
initChart()
defaultCofig.legend.formatter = (name) => {
let percent = props.dataList.find((item) => item.name == name).value
return name + '\u3000' + `${percent}%`
}
defaultCofig.series[0].data = props.dataList
defaultCofig.series[0].label.formatter = () => {
return `{value|${props.total}}` + '\n' + `{name|舆情总数 }`
}
setOption({
...defaultCofig,
...props.config
})
})
}
},

28
src/hooks/echart.js Normal file
View File

@@ -0,0 +1,28 @@
import { ref } from 'vue'
import * as echarts from 'echarts'
import { guid } from '@/utils/util'
export function useEchart() {
let chart = ref(null)
let id = ref(guid())
const initChart = () => {
const dom = document.getElementById(id.value)
chart.value = echarts.init(dom)
}
const setOption = (params) => {
chart.value.setOption(params)
}
const resize = () => {
if (chart) {
chart.dispose()
chart = null
initChart()
}
}
onMounted(() => {
// 监听窗口大小变化
window.addEventListener('resize', resize)
})
return { id, chart, setOption, initChart }
}

View File

@@ -1,4 +1,5 @@
import { ref } from 'vue'
export function useMap() {
let map = ref(null)
// 初始化地图

57
src/hooks/socket.js Normal file
View File

@@ -0,0 +1,57 @@
import { ref } from 'vue'
export function useWebSocket(url) {
let socket = ref(null)
let data = ref(null)
let isConnected = ref(false)
const connectWebSocket = () => {
socket.value = new WebSocket(url, 'echo-protocol', {
headers: {
Authorization:
'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImE1OWFmNWYwLTU3OWItNDJkNy1hZDJhLTY0Y2JlODA5ZWI1NiJ9.BTxvu6jUWbN0qONWf5K6VzXopE8T8qXzKuX-mij21VJT4U0LdgnqToyqeNDQ2OyJ6cvpdJBzQ9mEEb-dnwrTpQ'
}
})
socket.value.onopen = () => {
isConnected.value = true
console.log('WebSocket connected')
sendMessage(
JSON.stringify({
action: 'start',
type: 'index'
})
)
}
socket.value.onerror = (error) => {
console.error('WebSocket error:', error)
}
socket.value.onmessage = (message) => {
// 处理接收到的消息
console.log('Received message:', JSON.parse(message.data))
if (JSON.parse(message.data)) {
data.value = JSON.parse(message.data)
}
}
socket.value.onclose = () => {
console.log('WebSocket disconnected')
}
}
const sendMessage = (message) => {
if (socket.value) {
socket.value.send(message)
}
}
onMounted(() => {
connectWebSocket()
})
onUnmounted(() => {
if (socket.value) {
socket.value.close()
}
})
return { socket, data, isConnected, connectWebSocket, sendMessage }
}

View File

@@ -150,12 +150,12 @@
<span class="text">男性</span>
<div class="progress">
<el-progress
:percentage="50"
:percentage="genderRate['男']"
:show-text="false"
color="linear-gradient( to right, #074D90 0%, #55E0FF 100%)"
/>
</div>
<span class="man">50%</span>
<span class="man">{{ genderRate['男'] }}%</span>
</div>
</div>
<div class="cell pt-20">
@@ -164,13 +164,13 @@
<span class="text">女性</span>
<div class="progress">
<el-progress
:percentage="50"
:percentage="genderRate['女']"
:show-text="false"
color="linear-gradient( to right,
#0A4482 0%, #FF7021 100%)"
/>
</div>
<span class="woman">50%</span>
<span class="woman">{{ genderRate['女'] }}%</span>
</div>
</div>
</div>
@@ -189,10 +189,23 @@
<script setup>
import countup from 'vue-countup-v3'
import AgeRatio from './age-ratio.vue'
import top from './top.vue'
import gauge from './gauge.vue'
import ticket from './ticket.vue'
import ageRatio from './age-ratio.vue'
let props = defineProps({
data: {
type: Object,
default: () => ({})
}
})
let genderRate = computed(() => {
if (props.data?.userPortrait) return props.data?.userPortrait.genderRate
return {
: 0,
: 0
}
})
let xAxisData = ref([
'12-16 10:00',
'12-16 14:00',

View File

@@ -1,16 +1,21 @@
<template>
<Header title="奉节县旅游指挥调度中心" is-skip :nav-left="navLeft" :nav-right="navRight" />
<CoreVideo />
<box2 />
<box1 :data="data" />
<box3 />
<box4 />
<Correspondence />
</template>
<script setup>
import box2 from './components/box-2.vue'
import box1 from './components/box-1.vue'
import box3 from './components/box-3.vue'
import box4 from './components/box-4.vue'
import { useWebSocket } from '@/hooks/socket'
const { data, sendMessage } = useWebSocket('ws://36.138.38.16:81/ws/third-party')
const navLeft = [
{ name: '安全', path: '/monitor' },
{ name: '景区', path: '/scenic' },
@@ -22,30 +27,4 @@
{ name: '舆情', path: '/sentiment' },
{ name: '酒店' }
]
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

@@ -24,18 +24,10 @@
</div>
</div>
<div class="flex mt-20 gap-8 ml-8 mr-8">
<div v-for="(item, index) in stateList" class="border flex-1">
<Title3 :title="index" />
<pie-row :width="500" :height="330" :dataList="item" />
<div v-for="(item, index) in stateList" :key="index" class="border flex-1">
<Title3 :title="item.name" />
<pie-row :width="500" :height="330" :dataList="item.data" :total="item.total" />
</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 class="box-1">
@@ -46,6 +38,7 @@
<div class="flex mt-10">
<div class="box-2 mr-10">
<Title1 title="舆情指数" />
<Dropdown :options="options" @on-change="onChange" />
<Line
:width="1560"
:height="400"
@@ -71,7 +64,13 @@
import Area from './components/area.vue'
import wordCloud from './components/wordCloud.vue'
import dataSource from './components/dataSource.vue'
import { getHotNewApi, getLineChartApi, getStateApi, getTotalApi } from '@/api/sentiment.js'
import {
getHotNewApi,
getLineChartApi,
getStateApi,
getTotalApi,
getSpotApi
} from '@/api/sentiment.js'
let seriesData = ref([])
let xAxisData = ref([])
@@ -80,7 +79,15 @@
let sensitive = ref(0)
let unsensitive = ref(0)
let stateList = ref([])
let options = ref([])
const onChange = (e) => {
console.log(e, '===')
getLineChart(e.id)
}
const getStop = async () => {
let res = await getSpotApi()
options.value = res.data
}
const getTotal = async () => {
let res = await getTotalApi()
total.value = res.data.total
@@ -92,8 +99,8 @@
stateList.value = res.data
console.log(stateList.value, '------')
}
const getLineChart = async () => {
let res = await getLineChartApi()
const getLineChart = async (id) => {
let res = await getLineChartApi({ id })
xAxisData.value = res.data.data
seriesData.value = res.data.series
}
@@ -102,6 +109,7 @@
hotNewList.value = res.data
}
onMounted(() => {
getStop()
getHotNew()
getTotal()
getState()