<template> <!-- 舆情分析 --> <div class="PublicOpinionAnalysis"> <!-- 左侧 --> <div class="moduleBox moduleBoxLeft"> <!-- 今日新增舆情 --> <div class="YqToday"> <div class="rqTitle">今日新增舆情</div> <div class="rqNumContent"> <div class="yqNumber"> <div class="Onnumber flex flex-align-center flex-justcontent-center"> <div class="OnnumberText" v-for="item in AllData.oneData.newsNumbers"> <div class="OnnumberTextA">{{ item }}</div> </div> </div> <div class="Upnumber flex flex-align-center flex-justcontent-center"> 同比昨日: <span class="red" v-if="AllData.oneData.newsPercentage >= 0"> <img :src="numOp" /> {{ Math.abs(AllData.oneData.newsPercentage) }}% </span> <span class="green" v-else> <img :src="numUp" /> {{ Math.abs(AllData.oneData.newsPercentage) }}% </span> </div> </div> </div> </div> <!-- 七日舆情统计 --> <div class="YqSeven"> <div class="rqTitle flex"> 七日舆情统计 <span>(总数:{{ AllData.sevenData.allNewsNumber }})</span> </div> <div class="rqContent" style="overflow: auto"> <div class="listBox" v-for="item in AllData.sevenData.datalist" @click="selectSeven(item)" style="cursor: pointer"> <div class="Yqtjabove flex"> <div class="icon"></div> <div class="typepattern"> {{ item.showName }} </div> <div class="leve4 flex flex-align-center flex-justcontent-center">{{ item.number || '0' }}条</div> <div :class="item.weekchain >= 0 ? 'red1' : 'green1'"> <el-icon v-if="item.weekchain >= 0"><Top /></el-icon> <el-icon v-else><Bottom /></el-icon> {{ Math.abs(item.weekchain) || '0' }}% </div> </div> <div class="Yqtjbelow flex" v-if="item.proportion != '100'"> <div class="zb" :style="{ width: `${item.proportion || '0'}%` }"></div> <div class="Arrows"></div> <div class="Wz">{{ item.proportion || '0' }}%</div> </div> <div class="Yqtjbelow flex" v-if="item.proportion == '100'"> <div class="zb" :style="{ width: `${item.proportion || '0'}%` }"> <div class="WzA" v-if="item.proportion == '100'">{{ item.proportion }}%</div> </div> </div> </div> </div> </div> <!-- 近30天舆情 --> <div class="YqThirty"> <div class="rqTitle"> 近30天舆情增量 <span>(总数:{{ AllData.thirtyData.alldataNumber }})</span> </div> <div class="rqContent"> <twoLine :echartData="lineData" :key="YqThirtyKey" /> </div> </div> </div> <!-- 右侧 --> <div class="moduleBox moduleBoxRight"> <!-- 本年舆情 --> <div class="YqToday"> <div class="rqTitle">本年舆情</div> <div class="rqNumContent"> <div class="yqNumber"> <div class="Onnumber flex flex-align-center flex-justcontent-center"> <div class="OnnumberText" v-for="item in AllData.yearData.yearNumbers"> <div class="OnnumberTextA">{{ item }}</div> </div> </div> <div class="Upnumber flex flex-align-center flex-justcontent-center"> 同比上年: <span class="red" v-if="AllData.yearData.newsPercentage >= 0"> <img :src="numOp" /> {{ Math.abs(AllData.yearData.newsPercentage) }}% </span> <span class="green" v-else> <img :src="numUp" /> {{ Math.abs(AllData.yearData.newsPercentage) }}% </span> </div> </div> </div> </div> <!-- 待处理舆情 --> <div class="DclYq"> <div class="rqTitle"> 待处理舆情跟踪<span>(总数:{{ AllData.pendingData.length }})</span> </div> <div class="rqContent"> <div class="sevenPublic"> <div class="hader"> <div class="tableHeaderList tableList1">舆情名称</div> <div class="tableHeaderList tableList2">舆情类型</div> <div class="tableHeaderList tableList3">跟踪情况</div> </div> <div class="ListBox"> <div class="tableBodyList flex" v-for="(item, index) in AllData.pendingData" :key="index"> <div class="tableBodyList_span1" :title="item.title"> {{ item.title }} </div> <div class="tableBodyList_span2"> {{ getChineseFun(AllData.typeList, 'wordCode', item.keywordsSecondary, 'showName') }} </div> <div class="tableBodyList_span3">待反馈</div> </div> <div v-if="AllData.pendingData.length == ''" class="flex flex-align-center flex-justcontent-center">暂无数据</div> </div> </div> </div> </div> <!-- 舆情来源 --> <div class="YqLy"> <div class="rqTitle"> 舆情来源分布<span>(总数:{{ AllData.YqlyData.allnewsnumber }})</span> </div> <div class="rqContent"> <ChartRy2 :echartData="ryData" :key="ryRefresh" @newsType="newsType" /> </div> </div> </div> <!-- 中间 --> <div class="BoxContent"> <!-- 近一年舆情统计 --> <div class="YqOneYear"> <div class="rqTitleA flex"> 近一年舆情统计<span>(总数:{{ AllData.yearChart.allnumber }})</span> </div> <div class="YqOneYearContent"> <ChartBar :key="refreshOneY" :echartData="echartData" /> </div> </div> <!-- 舆情跟踪管理 --> <div class="YqTrack"> <div class="rqTitleA"> 舆情跟踪管理<span>(总数:{{ total }})</span> <div class="TabList flex flex-align-center flex-justcontent-center"> <div style="width: 35%"> <div class="tabData flex"> <div class="eachClick" :class="tabActive == item.value ? 'active' : ''" v-for="item in rightTabArr" :key="item.value" @click="rightTabClick('day', item)" > {{ item.label }} </div> </div> </div> <div style="width: 31%"> <div class="tabData flex"> <div class="eachClick" :class="tabActive2 == item.value ? 'active' : ''" v-for="item in rightTabArr2" :key="item.value" @click="rightTabClick('active', item)" > {{ item.label }} </div> </div> </div> <div style="width: 31%"> <el-form class="drainageResponseBox"> <el-select v-model="AllData.queryParams.mainwords" size="small" @change="Kschange" style="width: 95%" placeholder="请选择类型" > <el-option v-for="(item, index) in AllData.typeList" :key="index" :label="item.showName" :value="item.wordCode" ></el-option> </el-select> </el-form> </div> <div @click="resetTable" style="cursor: pointer" title="重置"> <el-icon class="aaa"><RefreshLeft /></el-icon> </div> </div> </div> <div class="YqTracContent"> <el-table :data="tableData" height="100%" class="dispatchTable" stripe> <el-table-column prop="title" label="标题"> <template #default="scope"> <div class="tableLiName" :title="scope.row.title" @click="newsOpen(scope.row)">{{ scope.row.title }}</div> </template> </el-table-column> <el-table-column prop="publishTime" label="日期" /> <el-table-column prop="keywordsSecondary" label="类型"> <template #default="scope"> {{ getChineseFun(AllData.typeList, 'wordCode', scope.row.keywordsSecondary, 'showName') }} </template> </el-table-column> <el-table-column prop="fromWhere" label="来源" /> <el-table-column prop="publisher" label="发布单位" show-overflow-tooltip /> <el-table-column label="操作" width="170" align="center"> <template #default="scope"> <el-button type="primary" link @click="rowIgnore(scope.row)" v-if="scope.row.isIgnore == 0">忽略</el-button> <el-button type="primary" link @click="rowFollow(scope.row)" v-if="scope.row.isCare == 0">加关注</el-button> <el-button class="greening" link disabled v-if="scope.row.isCare == 1">已关注</el-button> <el-button type="primary" link @click="rowUpdate(scope.row)" v-if="scope.row.isFeedback == 0">分派</el-button> <el-button type="primary" link disabled v-if="scope.row.isFeedback == 1">待反馈</el-button> <el-button class="greening" link disabled v-if="scope.row.isFeedback == 2">已反馈</el-button> </template> </el-table-column> </el-table> <!-- 分页 --> <pagination v-show="total > 0" :total="total" v-model:page="AllData.queryParams.pageNum" v-model:limit="AllData.queryParams.pageSize" @pagination="getYqGzData" /> </div> </div> </div> <!-- 分派对话框 --> <el-dialog title="舆情分派" v-model="openFp" width="800px" class="publicDialog" :show-close="false" :close-on-click-modal="false" > <div class="publicDBox"> <div class="info"> <div class="boxName">舆情基本情况</div> <div class="list"> <div class="box"> <div class="title">新闻所属分类</div> <div class="flex10">{{ AllData.popData.keywordsMain }}</div> </div> <div class="box"> <div class="title">网站地址</div> <div class="flex10"> <a :href="AllData.popData.url" target="_blank">{{ AllData.popData.url }}</a> </div> </div> </div> <div class="list"> <div class="box"> <div class="title">网站来源</div> <div class="flex10">{{ AllData.popData.fromWhere }}</div> </div> <div class="box"> <div class="title">网站名称</div> <div class="flex10">{{ AllData.popData.publisher }}</div> </div> </div> <div class="list"> <div class="box"> <div class="title">采集时间</div> <div class="flex10">{{ AllData.popData.publishTime }}</div> </div> <div class="box"> <div class="title">所属分类</div> <div class="flex10">{{ AllData.popData.keywordsSecondary }}</div> </div> </div> </div> <div class="info"> <div class="boxName">问题督促处理</div> <el-form ref="ruleForm" :model="AllData.queryParams2" :rules="AllData.rules" label-width="150px"> <el-form-item label="责任单位:" prop="xesponsibilityunit" style="width: 100%"> <el-tree-select style="width: 100%" v-model="AllData.queryParams2.xesponsibilityunit" :data="deptList" placeholder="请选择责任单位" node-key="deptId" filterable :render-after-expand="false" clearable collapse-tags-tooltip :multiple="false" :props="{ value: 'deptId', label: 'deptName', children: 'children', }" @node-click="handleNodeClick" /> </el-form-item> <el-form-item label="处理人:" prop="feedbackuser" style="width: 100%"> <el-select placeholder="请选择处理人" v-model="AllData.queryParams2.feedbackuser" style="width: 100%"> <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId"></el-option> </el-select> </el-form-item> <!-- <el-form-item label="处理方式:" prop="infoxmationHandType" style="width: 100%"> <el-select placeholder="请选择处理方式" v-model="AllData.queryParams2.infoxmationHandType"> <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId"></el-option> </el-select> </el-form-item> --> <el-form-item label="最迟反馈时间:" prop="lastFeedbackTime" style="width: 100%"> <el-date-picker style="width: 100%" v-model="AllData.queryParams2.lastFeedbackTime" :default-time="defaultTime" type="datetime" placeholder="请选择最迟反馈时间" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" /> </el-form-item> </el-form> </div> </div> <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="submitForm">下发</el-button> <el-button @click="cancel">取 消</el-button> </div> </template> </el-dialog> </div> </template> <script setup name="PublicOpinionAnalysis"> import bus from '@/bus'; import { querySevenDayNews, queryThirtyDayNews, queryTodayAddNews, queryYearsNews, queryYearsNewsCharts, informationWuhanPaishuiPage, queryAllnewsClass, queryAllnewsUpdate, informationWuhanPaishuiList, queryAllnewsNewsFreeback, queryClassType, listDept, listUser, } from '@/api/DP_api/sentiment'; import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'; import twoLine from './components/twoLine.vue'; import ChartRy2 from './components/ChartRy.vue'; import ChartBar from './components/ChartBar.vue'; import numUp from '@/assets/images/pictureOnMap/numUp_icon.png'; //上升 import numOp from '@/assets/images/pictureOnMap/numDn_icon.png'; //下降 import { getChineseFun } from '@/utils/util.js'; const { proxy } = getCurrentInstance(); const total = ref(0); const openFp = ref(false); const tableData = ref([]); const YqThirtyKey = ref('1'); const refreshOneY = ref('1'); const ryRefresh = ref('1'); const AllData = reactive({ oneData: {}, sevenData: {}, thirtyData: {}, yearChart: {}, yearData: {}, YqlyData: {}, pendingData: {}, popData: {}, typeList: [], queryParams: { pageNum: 1, pageSize: 10, isIgnore: '0', fromWhere: '', mainwords: '', startTime: '', endTime: '', isCare: '', isFeedback: '', }, queryParams2: { xesponsibilityunit: '', feedbackuser: '', infoxmationHandType: '', lastFeedbackTime: '', }, rules: { xesponsibilityunit: [{ required: true, message: '请选择预警开始时间', trigger: 'blur' }], feedbackuser: [{ required: true, message: '请选择预警结束时间', trigger: 'blur' }], lastFeedbackTime: [{ required: true, message: '请选择最迟反馈时间', trigger: 'blur' }], }, }); const ryData = ref({}); const echartData = ref({}); const lineData = ref({ tabX: [], series: [ { name: '网页', tabY: [], }, { name: '质讯', tabY: [], }, { name: '微信', tabY: [], }, ], }); // 今日新增舆情 const getJrYq = item => { queryTodayAddNews().then(res => { AllData.oneData = res.data; }); }; // 七日舆情统计 const getSevenYq = item => { querySevenDayNews().then(res => { AllData.sevenData = res.data; }); }; // 本年舆情 const getThisYearYq = item => { queryYearsNews().then(res => { AllData.yearData = res.data; }); }; // 近30天舆情增量 const getthirtyYq = item => { queryThirtyDayNews().then(res => { YqThirtyKey.value++; AllData.thirtyData = res.data; lineData.value.tabX = AllData.thirtyData.timelist; lineData.value.series[0].tabY = AllData.thirtyData.wangyelist; lineData.value.series[1].tabY = AllData.thirtyData.zixunlist; lineData.value.series[2].tabY = AllData.thirtyData.weixinlist; }); }; // 舆情来源点击事件 async function newsType(data) { AllData.queryParams.fromWhere = data; getYqGzData(); } // 七日舆情统计点击事件 function selectSeven(data) { AllData.queryParams.mainwords = data.wordCode; getYqGzData(); } // 舆情来源分布 function getData() { let YQnumber = []; let YQfromwhere = []; queryAllnewsClass().then(res => { AllData.YqlyData = res.data; AllData.YqlyData.datalist.forEach(item => { YQnumber.push(item.number); YQfromwhere.push(item.fromwhere); }); }); setTimeout(() => { ryRefresh.value++; let obj = { xData: YQfromwhere, data: YQnumber, num: [], Maximum: '', }; let max = JSON.parse(JSON.stringify(obj.data)); let one = max.sort((a, b) => b - a)[0]; obj.Maximum = one; max.forEach(i => { obj.num.push(one); }); ryData.value = obj; }, 1000); } // 近一年舆情统计 function getOneYearData() { queryYearsNewsCharts().then(res => { AllData.yearChart = res.data; console.log(AllData.yearChart, ' AllData.yearChart AllData.yearChart AllData.yearChart'); }); setTimeout(() => { refreshOneY.value++; let obj = { xAxis: AllData.yearChart.timelist, seriesData: AllData.yearChart.datalist, num: [], Maximum: '', }; let max = JSON.parse(JSON.stringify(obj.seriesData)); let one = max.sort((a, b) => b - a)[0]; obj.Maximum = one; max.forEach(i => { obj.num.push(one); }); echartData.value = obj; }, 1000); } // 待处理舆情 function getDclYqData() { informationWuhanPaishuiList({ isFeedback: 1 }).then(res => { AllData.pendingData = res.data; }); } // 下拉框 function getdropdown() { queryClassType().then(res => { AllData.typeList = res.data; }); } //下拉框事件 function Kschange(val) { getYqGzData(); } // 重置 function resetTable() { AllData.queryParams.pageNum = 1; AllData.queryParams.pageSize = 10; AllData.queryParams.isIgnore = '0'; AllData.queryParams.fromWhere = ''; AllData.queryParams.mainwords = ''; AllData.queryParams.startTime = ''; AllData.queryParams.endTime = ''; AllData.queryParams.isCare = ''; AllData.queryParams.isFeedback = ''; // AllData.queryParams = {}; tabActive.value = ''; tabActive2.value = ''; getYqGzData(); } //舆情跟踪管理 async function getYqGzData() { informationWuhanPaishuiPage(AllData.queryParams).then(res => { tableData.value = res.data; total.value = res.total; }); } function newsOpen(data) { window.open(data.url); } const tabActive = ref(''); const tabActive2 = ref(''); const rightTabArr = ref([ { label: '最近7日', value: '1', }, { label: '最近30天', value: '2', }, ]); const rightTabArr2 = ref([ { label: '已关注', value: '1', }, { label: '已反馈', value: '2', }, ]); const rightTabClick = (type, tab) => { if (type == 'day') { tabActive.value = tab.value; if (tabActive.value == 1) { AllData.queryParams.endTime = proxy.moment(new Date().getTime()).format('YYYY-MM-DD HH:mm:ss'); AllData.queryParams.startTime = proxy.moment().add(-7, 'd').format('YYYY-MM-DD HH:mm:ss'); } if (tabActive.value == 2) { AllData.queryParams.endTime = proxy.moment(new Date().getTime()).format('YYYY-MM-DD HH:mm:ss'); AllData.queryParams.startTime = proxy.moment().add(-30, 'd').format('YYYY-MM-DD HH:mm:ss'); } } else if (type == 'active') { tabActive2.value = tab.value; if (tabActive2.value == 1) { AllData.queryParams.isCare = 1; AllData.queryParams.isFeedback = null; } if (tabActive2.value == 2) { AllData.queryParams.isCare = null; AllData.queryParams.isFeedback = 2; } } getYqGzData(); }; // 忽略点击事件 function rowIgnore(val) { let params = { id: val.id, isIgnore: 1, }; proxy.$modal .confirm('确认要忽略本舆情新闻吗?忽略后的舆情新闻将不在系统进行展示,但仍然可以通过后台管理进行导出和查看。') .then(function () { return queryAllnewsUpdate(params); }) .then(() => { proxy.$modal.msgSuccess('已忽略~'); getYqGzData(); }) .catch(() => {}); } // 加关注点击事件 function rowFollow(val) { let params = { id: val.id, isCare: 1, }; queryAllnewsUpdate(params).then(res => { if (res.code == 200) { proxy.$modal.msgSuccess('已关注!'); getYqGzData(); } }); } // 分派点击事件 function rowUpdate(data) { openFp.value = true; AllData.popData = data; getSelect(); } const deptList = ref([]); const getSelect = () => { listDept().then(res => { if (res.code === 200) { if (res.data?.length > 0) { deptList.value = proxy.handleTree(res.data, 'deptId'); console.log('新的接收人11', deptList.value); } } }); }; /** 节点单击事件 */ function handleNodeClick(data) { console.log(data.deptId, ' data.id'); getListUser(data.deptId); AllData.queryParams2.feedbackuser = ''; } //获取所有人员 const userList = ref([]); function getListUser(val) { listUser({ deptId: val }).then(res => { userList.value = res.data; }); } // 下发 点击 function submitForm() { proxy.$refs['ruleForm'].validate(valid => { AllData.queryParams2.isCare = 1; AllData.queryParams2.id = AllData.popData.id; console.log(AllData.queryParams2, '11111'); if (valid) { proxy.$modal .confirm( '确认要派发处理本舆情新闻吗?并且本条新闻将自动进行关注,确认操作吗?' ) .then(function () {}) .then(() => { proxy.$modal.msgSuccess('下发成功'); openFp.value = false; AllData.queryParams2 = {}; userList.value = []; getYqGzData(); }) .catch(() => {}); } }); } // 取消 function cancel() { proxy.resetForm('ruleForm'); userList.value = []; openFp.value = false; } onMounted(() => { setTimeout(() => bus.emit('YQ_head', false), 100); getYqGzData(); getdropdown(); getJrYq(); getSevenYq(); getthirtyYq(); getData(); getThisYearYq(); getOneYearData(); getDclYqData(); }); </script> <style lang="scss" scoped> @import '@/assets/styles/PublicOpinionAnalysis.scss'; </style>