提交 4d6004fe authored 作者: coderBryanFu's avatar coderBryanFu

feat:更新数据资源库

上级 21a55ab7
......@@ -12,6 +12,7 @@ export function search(data) {
})
}
// 智库列表
export function getThinkTankList() {
return request({
method: 'GET',
......@@ -19,9 +20,50 @@ export function getThinkTankList() {
})
}
// 立法阶段
export function getStatusList() {
return request({
method: 'GET',
url: `/temporarySearch/search-info/dBillStage`,
})
}
// 省名字列表
export function getProvinceList() {
return request({
method: 'GET',
url: `/temporarySearch/search-info/all-provinceName`,
})
}
// 国家列表
export function getCountryList() {
return request({
method: 'GET',
url: `/temporarySearch/search-info/all-countryName`,
})
}
// 实体类型
export function getEntityTypes() {
return request({
method: 'GET',
url: `/temporarySearch/search-info/entityTypes`,
})
}
// 物项类别
export function getMaterialCategory() {
return request({
method: 'GET',
url: `/temporarySearch/search-info/all-materialCategory`,
})
}
// 商业管制清单-管控原因
export function getControlReason() {
return request({
method: 'GET',
url: `/temporarySearch/search-info/all-controlReason`,
})
}
\ No newline at end of file
......@@ -12,6 +12,7 @@ const useTagsViewStore = defineStore('tags-view', {
this.addCachedView(view)
},
addVisitedView(view) {
this.visitedViews = localStorage.getItem('visitedViews') && JSON.parse(localStorage.getItem('visitedViews')) || []
this.visitedViews.forEach(item => {
item.active = false
})
......@@ -23,8 +24,8 @@ const useTagsViewStore = defineStore('tags-view', {
...view,
title: view.meta?.title || '未命名'
})
localStorage.setItem('visitedViews', JSON.stringify(this.visitedViews))
} else {
this.visitedViews.forEach(v => {
if (v.path === view.path) {
v.active = true
......@@ -49,7 +50,7 @@ const useTagsViewStore = defineStore('tags-view', {
if (index !== -1) {
this.visitedViews.splice(index, 1)
}
localStorage.setItem('visitedViews', JSON.stringify(this.visitedViews))
resolve([...this.visitedViews])
})
},
......@@ -64,6 +65,13 @@ const useTagsViewStore = defineStore('tags-view', {
}
},
loadVisitedViewFromLocalStorage() {
const saved = localStorage.getItem('visitedViews')
if (saved) {
this.items = JSON.parse(saved)
}
},
// 关闭其他/右侧/全部
delOthersViews(view) {
......
......@@ -4,7 +4,7 @@
<div class="header-top">
<SelectBox :placeholder-name="areaPlaceHolder" select-title="科技领域" :select-list="areaList"
:select-name="selectedArea" @update:select-text="handleSelectArea" />
<SelectBox :placeholder-name="DatePlaceHolder" select-title="提时间" :select-list="dateList"
<SelectBox :placeholder-name="DatePlaceHolder" select-title="提时间" :select-list="dateList"
:select-name="selectedDate" :custom-time="customTime" @update:select-text="handleSelectDate"
@update:custom-time="handleCustomDate" />
<SelectBox v-if="isFolderAll" :placeholder-name="partyPlaceHolder" select-title="所属党派" :select-list="partyList"
......@@ -53,7 +53,7 @@
<ChartHeader :list="staticsDemensionList" @clickItem="handleClickDemensionItem">
<template #chart-header-right>
<el-select v-model="selectedTime" placeholder="选择时间" style="width: 150px"
v-show="curDemension === '提案时间'">
v-show="curDemension === '提案时间'" @change="handleChangeTime">
<el-option v-for="item in timeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
......@@ -123,7 +123,8 @@
<el-table-column type="selection" width="40" />
<el-table-column label="法案名称" width="455">
<template #default="scope">
<span class="title-item text-compact-bold" @click="handleClickToDetail(scope.row)">{{ scope.row.originalTitle
<span class="title-item text-compact-bold" @click="handleClickToDetail(scope.row)">{{
scope.row.originalTitle
}}</span>
</template>
</el-table-column>
......@@ -184,10 +185,20 @@ const handleSwitchChartData = () => {
const curDemensionItem = staticsDemensionList.value.filter(item => {
return item.name === curDemension.value
})[0]
timer1.value = setTimeout(() => {
// timer1.value = setTimeout(() => {
activeChart.value = curDemensionItem.chartTypeList[0]
if (curDemension.value === '提案时间') {
if (selectedTime.value === '按月度统计') {
curChartData.value = curDemensionItem.data
})
} else if (selectedTime.value === '按季度统计') {
curChartData.value = curDemensionItem.quatarData
} else {
curChartData.value = curDemensionItem.yearData
}
} else {
curChartData.value = curDemensionItem.data
}
// })
}
}
......@@ -206,10 +217,12 @@ const staticsDemensionList = ref([
dataY: []
},
quatarData: {
dataX: [],
dataY: []
},
yearData: {
dataX: [],
dataY: []
}
},
{
......@@ -273,11 +286,17 @@ const handleClickDemensionItem = (val) => {
curDemension.value = val.name
timer2.value = setTimeout(() => {
activeChart.value = val.chartTypeList[0]
if (curDemension.value === '发布时间' && selectedTime.value === '按年度统计') {
curChartData.value = val.yearData
} else if (curDemension.value === '发布时间' && selectedTime.value === '按季度统计') {
curChartData.value = val.quatarData
} else {
curChartData.value = val.data
}
})
}
const selectedTime = ref('按统计')
const selectedTime = ref('按年度统计')
const timeList = ref([
{
label: '按年度统计',
......@@ -293,6 +312,27 @@ const timeList = ref([
},
])
const handleChangeTime = value => {
let curChart = activeChart.value
activeChart.value = ''
if (value === '按月度统计') {
setTimeout(() => {
activeChart.value = curChart
curChartData.value = staticsDemensionList.value[0].data
})
} else if (value === '按季度统计') {
setTimeout(() => {
activeChart.value = curChart
curChartData.value = staticsDemensionList.value[0].quatarData
})
} else {
setTimeout(() => {
activeChart.value = curChart
curChartData.value = staticsDemensionList.value[0].yearData
})
}
}
// 激活的标签列表
const activeTagList = computed(() => {
const arr = []
......@@ -307,7 +347,7 @@ const activeTagList = computed(() => {
if (selectedDate.value === '自定义') {
arr.push(
{
tag: '提时间',
tag: '提时间',
name: customTime.value.join('至')
}
)
......@@ -372,7 +412,7 @@ const handleCloseCurTag = (tag, index) => {
case '科技领域':
selectedArea.value = '全部领域'
break
case '提时间':
case '提时间':
selectedDate.value = ''
break
case '所属党派':
......@@ -541,7 +581,7 @@ const handleSelectArea = (value) => {
selectedArea.value = value
}
// 提时间
// 提时间
const DatePlaceHolder = ref('请选择时间')
const selectedDate = ref('')
const dateList = ref([
......@@ -843,6 +883,14 @@ const fetchTableData = async () => {
dataX: Object.keys(res.data.aggregationsDate),
dataY: Object.values(res.data.aggregationsDate).map(value => Number(value))
}
staticsDemensionList.value[0].quatarData = {
dataX: Object.keys(res.data.aggregationsQuarter),
dataY: Object.values(res.data.aggregationsQuarter).map(value => Number(value))
}
staticsDemensionList.value[0].yearData = {
dataX: Object.keys(res.data.aggregationsYear),
dataY: Object.values(res.data.aggregationsYear).map(value => Number(value))
}
staticsDemensionList.value[1].data = Object.entries(res.data.aggregationsDomain).map(([key, value]) => ({
name: key,
value: Number(value)
......@@ -860,7 +908,7 @@ const fetchTableData = async () => {
value: Number(value)
}))
staticsDemensionList.value[5].data = Object.entries(res.data.aggregationsStatus).map(([key, value]) => ({
name: key === '1' ? '通过' : '提出',
name: key,
value: Number(value)
}))
}
......
......@@ -62,7 +62,9 @@ const getBarChart = (data) => {
type: 'bar',
data: data.dataY,
label: {
show: true,
position: 'top',
color: 'rgb(59, 65, 75)',
fontWeight: 'regular', // 文字加粗
......@@ -72,7 +74,7 @@ const getBarChart = (data) => {
return params.value
},
},
barWidth: 20,
barWidth: data.dataX.length < 60 ? 20 : 3,
itemStyle: {
color: function (params) {
return new echarts.graphic.LinearGradient(0, 1, 0, 0,
......
<template>
<div class="wrapper">
<div class="show" @click="handleSwitchShowAll">
<div v-if="isShowAllBtn" class="show" @click="handleSwitchShowAll">
<div class="text text-compact">{{ isShowAll ? '收起' : '展开全部' }}</div>
<div class="icon">
<img v-if="isShowAll" src="./arrow-up.svg" alt="">
......@@ -23,6 +23,10 @@ const props = defineProps({
isShowAll: {
type: Boolean,
default: false
},
isShowAllBtn: {
type: Boolean,
default: true
}
})
......
......@@ -53,6 +53,9 @@ const getLineChart = (dataX, dataY) => {
lineStyle: {
color: 'rgba(5, 95, 194, 1)'
},
label: {
show: true
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
......
import { MUTICHARTCOLORS } from "@/common/constant";
const getPieChart = (data) => {
const colorList = MUTICHARTCOLORS
let showData = data
if(data.length > 14) {
showData = data.slice(0,13)
let num = 0
data.slice(13,).forEach(item => {
num = num + item.value
})
showData = [...showData, {name: '其他', value: num}]
}
let option = {
color: colorList,
legend: {
show: false
},
series: [
{
type: 'pie',
......@@ -50,7 +62,7 @@ const getPieChart = (data) => {
labelLinePoints: points
};
},
data: data
data: showData
}]
}
return option
......
......@@ -89,4 +89,5 @@ const customTimeValue = computed({
.select-wrapper-custom {
width: 738px;
}
</style>
\ No newline at end of file
......@@ -197,7 +197,7 @@ const handleSwitchChartData = () => {
const curDemensionItem = staticsDemensionList.value.filter(item => {
return item.name === curDemension.value
})[0]
setTimeout(() => {
// setTimeout(() => {
activeChart.value = curDemensionItem.chartTypeList[0]
if (curDemension.value === '发布时间') {
if (selectedTime.value === '按月度统计') {
......@@ -210,7 +210,7 @@ const handleSwitchChartData = () => {
} else {
curChartData.value = curDemensionItem.data
}
})
// })
}
}
......@@ -289,7 +289,7 @@ const handleClickDemensionItem = (val) => {
}
// 时间图表 当前选择时间
const selectedTime = ref('按统计')
const selectedTime = ref('按年度统计')
// 时间图表-时间列表
const timeList = ref([
{
......
<template>
<div class="countrybill-wrapper">
<div class="header-box">我是商业管制清单</div>
<div class="main-box">
<div class="header-box">
<div class="header-top">
<SelectBox :placeholder-name="areaPlaceHolder" select-title="科技领域" :select-list="areaList"
:select-name="selectedArea" @update:select-text="handleSelectArea" />
<SelectBox :placeholder-name="DatePlaceHolder" select-title="制裁时间" :select-list="dateList"
:select-name="selectedDate" :custom-time="customTime" @update:select-text="handleSelectDate"
@update:custom-time="handleCustomDate" />
<SelectBox v-if="isFolderAll" :placeholder-name="typePlaceHolder" select-title="物项类别" :select-list="typeList"
:select-name="selectedType" @update:select-text="handleSelectType" />
<SelectBox v-if="isFolderAll" :placeholder-name="controlReasonPlaceHolder" select-title="管控原因"
:select-list="controlReasonList" :select-name="selectedControlReason"
@update:select-text="handleSelectControlReason" />
<InputBox input-title="物项名称" :input-name="categoryName" @update:input-text="handleInputCategoryName"
placeholder-name="请输入物项名称" />
</div>
<div class="header-footer">
<div class="header-footer-left">
<ActiveTag v-for="tag, index in activeTagList" :key="index" :tagName="tag.name"
@close="handleCloseCurTag(tag, index)" />
</div>
<div class="header-footer-right">
<HeaderBtnBox :isShowAll="isFolderAll" @show-all="handleSwitchFolderAll" @clear="handleClear"
@confirm="handleConfirm" />
</div>
</div>
</div>
<div class="chart-main-box" v-if="isShowChart">
<div class="info-box">
<div class="switch-box" @click="handleSwitchChartData">
<img v-if="!isShowChart" src="@/views/dataLibrary/assets/icons/chart-active.svg" alt="">
<img v-else src="@/views/dataLibrary/assets/icons/data-active.svg" alt="">
<img src="@/views/dataLibrary/assets/icons/chart-active.svg" alt="">
</div>
<div class="num-box text-title-3-bold">
{{ `共 ${totalNum} 条数据` }}
</div>
</div>
<div class="content-box"></div>
<div class="content-box">
<div class="content-header">
<ChartHeader :list="staticsDemensionList" @clickItem="handleClickDemensionItem">
<template #chart-header-right>
<el-select v-model="selectedTime" placeholder="选择时间" style="width: 150px" v-show="curDemension === '制裁时间'"
@change="handleChangeTime">
<el-option v-for="item in timeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
</ChartHeader>
</div>
<div class="content-main">
<ChartContainer :chartTitle="curChartTitle" :chartTypeList="curChartTypeList"
@clickChartItem="handleSwitchActiveChart" @download="handleDownloadCurChartData">
<template #chart-box>
<LineChart v-if="activeChart === '折线图'" :lineChartData="curChartData" />
<BarChart v-if="activeChart === '柱状图'" :barChartData="curChartData" />
<PieChart v-if="activeChart === '饼状图'" :pieChartData="curChartData" />
<RaderChart v-if="activeChart === '雷达图'" :radarChartData="curChartData" />
</template>
</ChartContainer>
</div>
</div>
</div>
<div class="data-main-box" v-else>
<div class="data-main-box-header">
<div class="switch-box" @click="handleSwitchChartData">
<img src="@/views/dataLibrary/assets/icons/data-active.svg" alt="">
</div>
<div class="num-box text-title-3-bold">
{{ `共 ${totalNum} 条数据` }}
</div>
</div>
<div class="data-main-box-main">
<div class="data-main-box-main-header">
<div class="header-left">
<div class="header-left-item1">
<el-checkbox v-model="isSelectedAll" label="全选" @change="handleSelectAllChange" size="large" />
</div>
<div class="header-left-item2 text-tip-1">{{ `已选择${selectedCount}项` }}</div>
<div class="header-left-item2 text-tip-1 cancel" @click="handleClearAll" v-show="selectedCount">{{ '取消' }}
<div class="header-left-item3 text-tip-1" v-if="isShowAllDataMaxLengthTip">{{ `(当前最大选择不能超过1万条!)` }}</div>
</div>
</div>
<div class="header-right">
<div class="header-right-item item1" @click="handleExport">
<div class="icon">
<img src="../../assets/icons/download.svg" alt="">
</div>
<div class="text text-tip-1">{{ '导出' }}</div>
</div>
<div class="header-right-item2 item2">
<el-select v-model="curOperation" placeholder="批量操作" style="width: 120px">
<el-option v-for="item in operationList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</div>
<div class="header-right-item3 item3">
<el-select v-model="isSort" placeholder="制裁时间" style="width: 166px" @change="handlePxChange">
<template #prefix>
<div style="display: flex; align-items: center; height: 100%">
<img src="../../assets/icons/desc-icon.svg" style="width: 14px; height: 14px" />
</div>
</template>
<el-option v-for="item in releaseTimeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</div>
</div>
<div class="data-main-box-main-content" v-loading="loading" element-loading-text="数据加载中,请稍候...">
<el-table ref="tableRef" :data="tableData" row-key="id" @selection-change="handleSelectionChange"
@select="handleSelect" @select-all="handleSelectAll" style="width: 100%" :row-style="{ height: '52px' }">
<el-table-column type="selection" width="40" />
<el-table-column label="物项名称">
<template #default="scope">
<span class="title-item text-compact-bold" @click="handleClickToDetail(scope.row)">{{
scope.row.originalTitle
}}</span>
</template>
</el-table-column>
<el-table-column label="制裁时间" width="120" class-name="date-column">
<template #default="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column label="涉及领域" width="500" class-name="date-column">
<template #default="scope">
<div class="tag-box">
<AreaTag v-for="tag, index in scope.row.domains" :key="index" :tagName="tag" />
</div>
</template>
</el-table-column>
<el-table-column label="物项类别" width="180">
<template #default="scope">{{ scope.row.materialCategory }}</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="data-main-box-footer">
<el-pagination background layout="prev, pager, next" :total="totalNum" v-model:current-page="currentPage"
:page-size="pageSize" @current-change="handleCurrentChange" />
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ref, computed, watch, onMounted, nextTick } from 'vue'
import ChartContainer from '../../components/ChartContainer/index.vue'
import ChartHeader from '../../components/ChartHeader/index.vue'
import ActiveTag from '../../components/ActiveTag/index.vue'
import HeaderBtnBox from '../../components/HeaderBtnBox/index.vue'
import LineChart from '../../components/LineChart/index.vue'
import PieChart from '../../components/PieChart/index.vue'
import BarChart from '../../components/BarChart/index.vue'
import RaderChart from '../../components/RadarChart/idnex.vue'
import SelectBox from '../../components/SelectBox/index.vue'
import InputBox from '../../components/InputBox/index.vue'
import { useRoute } from "vue-router";
import router from '@/router'
// 图表/数据
const isShowChart = ref(true)
import { search } from '@/api/comprehensiveSearch'
import { ElMessage } from 'element-plus'
import getDateRange from '@/utils/getDateRange'
import { getMaterialCategory, getControlReason } from '@/api/comprehensiveSearch/index'
const route = useRoute();
// 图表/数据
const isShowChart = ref(false)
// 点击切换数据/图表
const handleSwitchChartData = () => {
isShowChart.value = !isShowChart.value
if (isShowChart.value) {
const curDemensionItem = staticsDemensionList.value.filter(item => {
return item.name === curDemension.value
})[0]
// setTimeout(() => {
activeChart.value = curDemensionItem.chartTypeList[0]
if (curDemension.value === '制裁时间') {
if (selectedTime.value === '按月度统计') {
curChartData.value = curDemensionItem.data
} else if (selectedTime.value === '按季度统计') {
curChartData.value = curDemensionItem.quatarData
} else {
curChartData.value = curDemensionItem.yearData
}
} else {
curChartData.value = curDemensionItem.data
}
// })
}
}
// 总计数据
const totalNum = ref(12)
const totalNum = ref(0)
// 统计维度列表
const staticsDemensionList = ref([
{
name: '制裁时间',
active: true,
chartTypeList: ['折线图', '柱状图'],
chartTitle: '商业管制清单制裁时间变化趋势',
data: {
dataX: [],
dataY: []
},
quatarData: {
dataX: [],
dataY: []
},
yearData: {
dataX: [],
dataY: []
}
},
{
name: '科技领域',
active: false,
chartTypeList: ['饼状图'],
chartTitle: '商业管制清单科技领域分布',
data: []
},
{
name: '物项类别',
active: false,
chartTypeList: ['饼状图'],
chartTitle: '商业管制清单物项类别分布',
data: []
}
])
// 当前维度下的图表列表
const curChartTypeList = computed(() => {
let arr = staticsDemensionList.value.filter(item => item.active)
return arr[0].chartTypeList
})
// 当前图表标题
const curChartTitle = computed(() => {
let arr = staticsDemensionList.value.filter(item => item.active)
return arr[0].chartTitle
})
// 当前维度
const curDemension = ref('制裁时间')
// 点击维度item
const handleClickDemensionItem = (val) => {
activeChart.value = ''
staticsDemensionList.value.forEach(item => {
item.active = false
})
val.active = true
curDemension.value = val.name
setTimeout(() => {
activeChart.value = val.chartTypeList[0]
if (curDemension.value === '制裁时间' && selectedTime.value === '按年度统计') {
curChartData.value = val.yearData
} else if (curDemension.value === '制裁时间' && selectedTime.value === '按季度统计') {
curChartData.value = val.quatarData
} else {
curChartData.value = val.data
}
})
}
// 时间图表 当前选择时间
const selectedTime = ref('按年度统计')
// 时间图表-时间列表
const timeList = ref([
{
label: '按年度统计',
value: '按年度统计'
},
{
label: '按季度统计',
value: '按季度统计'
},
{
label: '按月度统计',
value: '按月度统计'
},
])
const handleChangeTime = value => {
let curChart = activeChart.value
activeChart.value = ''
if (value === '按月度统计') {
setTimeout(() => {
activeChart.value = curChart
curChartData.value = staticsDemensionList.value[0].data
})
} else if (value === '按季度统计') {
setTimeout(() => {
activeChart.value = curChart
curChartData.value = staticsDemensionList.value[0].quatarData
})
} else {
setTimeout(() => {
activeChart.value = curChart
curChartData.value = staticsDemensionList.value[0].yearData
})
}
}
// 激活的标签列表
const activeTagList = computed(() => {
const arr = []
if (selectedArea.value && selectedArea.value !== '全部领域') {
arr.push(
{
tag: '科技领域',
name: selectedArea.value
}
)
}
if (selectedDate.value === '自定义') {
arr.push(
{
tag: '制裁时间',
name: customTime.value.join('至')
}
)
}
if (selectedType.value && selectedType.value !== '全部类别') {
const countryArr = typeList.value.filter(item => item.id === selectedType.value)
let countryStr = '全部类别'
if (countryArr && countryArr.length) {
countryStr = countryArr[0].name
}
arr.push(
{
tag: '物项类别',
name: countryStr
}
)
}
if (selectedControlReason.value && selectedControlReason.value !== '全部管控原因') {
arr.push(
{
tag: '管控原因',
name: selectedControlReason.value
}
)
}
if (categoryName.value) {
arr.push(
{
tag: '物项名称',
name: categoryName.value
}
)
}
return arr
})
// 关闭当前标签
const handleCloseCurTag = (tag, index) => {
switch (tag.tag) {
case '科技领域':
selectedArea.value = '全部领域'
break
case '制裁时间':
selectedDate.value = ''
customTime.value = []
break
case '物项类别':
selectedType.value = '全部类别'
break
case '管控原因':
selectedControlReason.value = '全部管控原因'
break
case '物项名称':
categoryName.value = ''
break
}
}
const activeChart = ref('') // 当前激活的图表
// 切换当前图表
const handleSwitchActiveChart = val => {
activeChart.value = val.name
}
// 数据- 是否全选
const isSelectedAll = ref(false)
// 批量操作-当前操作
const curOperation = ref('')
const operationList = ref([
])
// 科技领域
const areaPlaceHolder = ref('请选择领域')
const selectedArea = ref('全部领域')
const areaList = ref([
{
name: '全部领域',
id: '全部领域'
},
{
name: '人工智能',
id: '人工智能'
},
{
name: '生物科技',
id: '生物科技'
},
{
name: '新一代通信网络',
id: '新一代通信网络'
},
{
name: '量子科技',
id: '量子科技'
},
{
name: '新能源',
id: '新能源'
},
{
name: '集成电路',
id: '集成电路'
},
{
name: '海洋',
id: '海洋'
},
{
name: '先进制造',
id: '先进制造'
},
{
name: '新材料',
id: '新材料'
},
{
name: '航空航天',
id: '航空航天'
},
{
name: '太空',
id: '太空'
},
{
name: '深海',
id: '深海'
},
{
name: '极地',
id: '极地'
},
{
name: '核',
id: '核'
},
{
name: '其他',
id: '其他'
},
])
const handleSelectArea = (value) => {
selectedArea.value = value
}
// 制裁时间
const DatePlaceHolder = ref('请选择时间')
const selectedDate = ref('')
const dateList = ref([
{
name: '自定义',
id: '自定义'
},
{
name: '近一年',
id: '近一年'
},
{
name: '近半年',
id: '近半年'
},
{
name: '近三月',
id: '近三月'
},
{
name: '近一月',
id: '近一月'
}
])
const customTime = ref([]) // 自定义时间
const handleCustomDate = value => {
customTime.value = value
}
const handleSelectDate = (value) => {
selectedDate.value = value
if (selectedDate.value !== '自定义') {
customTime.value = getDateRange(selectedDate.value)
}
}
// 物项类别
const typeList = ref([
{
name: '全部类别',
id: '全部类别'
},
])
const selectedType = ref('全部类别')
const typePlaceHolder = ref('请选择物项类别')
const handleSelectType = value => {
selectedType.value = value
}
// 获取国家地区列表
const handleGetMaterialCategory = async () => {
try {
const res = await getMaterialCategory()
console.log('获取物项类别', res);
if (res && res.length) {
typeList.value = res.map(item => {
return {
name: item,
id: item
}
})
}
} catch (error) {
}
}
// 管控原因
const controlReasonList = ref([
{
name: '全部管控原因',
id: '全部管控原因',
}
])
const selectedControlReason = ref('全部管控原因')
const controlReasonPlaceHolder = ref('请选择管控原因')
const handleSelectControlReason = value => {
selectedControlReason.value = value
}
// 获取管控原因列表
const handleGetControlReason = async () => {
try {
const res = await getControlReason()
console.log('获取管控原因', res);
if (res && res.length) {
controlReasonList.value = res.map(item => {
return {
name: item,
id: item
}
})
}
} catch (error) {
}
}
// 物项名称
const categoryName = ref('')
const handleInputCategoryName = value => {
categoryName.value = value
}
// 清空条件
const handleClear = () => {
selectedArea.value = '全部领域'
selectedDate.value = ''
customTime.value = []
selectedType.value = '全部类别'
selectedControlReason.value = '全部管控原因'
categoryName.value = ''
ElMessage.success('已清空条件!')
}
// 确定
const handleConfirm = () => {
currentPage.value = 1
fetchTableData()
}
// 展开全部 / 收起
const isFolderAll = ref(false)
const handleSwitchFolderAll = () => {
isFolderAll.value = !isFolderAll.value
}
const tableRef = ref(null)
// 表格数据
const tableData = ref([
])
const releaseTimeList = ref([
{
label: "按发布时间倒序",
value: true
},
{
label: "按发布时间升序",
value: false
}
]);
const isSort = ref(true); // true 倒序 false 升序
const handlePxChange = val => {
fetchTableData()
};
const currentPage = ref(1);
const pageSize = ref(10)
// 存储选中的数据(跨页)[citation:3][citation:8]
const selectedMap = ref(new Map()) // 使用 Map 存储,key 为唯一 id
// 计算已选中的条数
const selectedCount = computed(() => selectedMap.value.size)
// 获取当前页表格数据(示例)
const fetchTableData = async () => {
// isSelectedAll.value = false
// selectedMap.value.clear()
loading.value = true
// 调用接口获取数据...
const params = {
page: currentPage.value,
size: pageSize.value,
type: 13, // 商业管制清单
domains: selectedArea.value === '全部领域' ? null : [selectedArea.value], // 科技领域
proposedDateStart: customTime.value[0] ? customTime.value[0] : null,
proposedDateEnd: customTime.value[1] ? customTime.value[1] : null,
materialCategory: selectedType.value === '全部类别' ? null : selectedType.value, // 物项类别
controlReason: selectedControlReason.value === '全部管控原因' ? null : selectedControlReason.value, // 管控原因
materialNameZh: categoryName.value ? categoryName.value : null, // 物项名称
sort: isSort.value ? 0 : 1 // 0 先按分数降序 后按时间降序 1 先按分数降序,再按时间升序
}
try {
const res = await search(params)
console.log('搜索结果', res);
if (res.code === 200 && res.data) {
tableData.value = res.data.records
totalNum.value = res.data.total
staticsDemensionList.value[0].data = {
dataX: Object.keys(res.data.aggregationsDate),
dataY: Object.values(res.data.aggregationsDate).map(value => Number(value))
}
staticsDemensionList.value[0].quatarData = {
dataX: Object.keys(res.data.aggregationsQuarter),
dataY: Object.values(res.data.aggregationsQuarter).map(value => Number(value))
}
staticsDemensionList.value[0].yearData = {
dataX: Object.keys(res.data.aggregationsYear),
dataY: Object.values(res.data.aggregationsYear).map(value => Number(value))
}
staticsDemensionList.value[1].data = Object.entries(res.data.aggregationsDomain).map(([key, value]) => ({
name: key,
value: Number(value)
}))
staticsDemensionList.value[2].data = Object.entries(res.data.aggregationMaterialCategory).map(([key, value]) => ({
name: key,
value: Number(value)
}))
}
const curDemensionItem = staticsDemensionList.value.filter(item => {
return item.name === curDemension.value
})[0]
activeChart.value = ''
setTimeout(() => {
activeChart.value = curDemensionItem.chartTypeList[0]
curChartData.value = curDemensionItem.data
})
loading.value = false
} catch (error) {
loading.value = false
}
// tableData.value = res.data
// total.value = res.total
// 数据加载后,回显已选中的行
nextTick(() => {
tableData.value.forEach(row => {
if (selectedMap.value.has(row.id)) {
tableRef.value?.toggleRowSelection(row, true)
}
})
})
}
const allData = ref([])
// 获取筛选条件下全部表格数据
const fetchAllData = async () => {
const params = {
page: 1,
size: 9999,
type: 13, // 商业管制清单
domains: selectedArea.value === '全部领域' ? null : [selectedArea.value], // 科技领域
proposedDateStart: customTime.value[0] ? customTime.value[0] : null,
proposedDateEnd: customTime.value[1] ? customTime.value[1] : null,
materialCategory: selectedType.value === '全部类别' ? null : selectedType.value, // 物项类别
controlReason: selectedControlReason.value === '全部管控原因' ? null : selectedControlReason.value, // 管控原因
materialNameZh: categoryName.value ? categoryName.value : null, // 物项名称
sort: isSort.value ? 0 : 1 // 0 先按分数降序 后按时间降序 1 先按分数降序,再按时间升序
}
try {
const res = await search(params)
console.log('搜索结果', res);
if (res.code === 200 && res.data) {
allData.value = res.data.records
}
} catch (error) {
ElMessage.error('加载全部数据出错!')
}
}
// 单选事件
const handleSelect = (selection, row) => {
if (selection.some(item => item.id === row.id)) {
// 选中:添加到 Map
selectedMap.value.set(row.id, row)
} else {
// 取消选中:从 Map 移除
selectedMap.value.delete(row.id)
}
}
// 表格自带 当前页 全选/全不选事件
const handleSelectAll = (selection) => {
if (selection.length > 0) {
// 全选:将当前页所有数据添加到 Map
tableData.value.forEach(row => {
if (!selectedMap.value.has(row.id)) {
selectedMap.value.set(row.id, row)
}
})
} else {
// 全不选:从 Map 中移除当前页的所有数据
tableData.value.forEach(row => {
selectedMap.value.delete(row.id)
})
}
}
// 处理选择变化(用于统计)
const handleSelectionChange = (val) => {
// 这里可以做一些额外的处理,但主要统计使用 selectedMap
console.log('当前页选中数量:', val.length)
}
// 全选当前页按钮
const handleSelectAllPage = () => {
if (tableData.value.length === 0) return
// 检查当前页是否已全选
const currentPageSelected = tableData.value.every(row =>
selectedMap.value.has(row.id)
)
if (currentPageSelected) {
// 已全选,则不动当前页的全选
tableData.value.forEach(row => {
tableRef.value.toggleRowSelection(row, false)
// selectedMap.value.delete(row.id)
})
} else {
// 未全选,则全选当前页
tableData.value.forEach(row => {
tableRef.value.toggleRowSelection(row, true)
if (!selectedMap.value.has(row.id)) {
selectedMap.value.set(row.id, row)
}
})
}
}
// 全选最大1万条提示
const isShowAllDataMaxLengthTip = ref(false)
const loading = ref(false) // 加载数据loading
// 处理 全选(全部数据)
const handleSelectAllChange = async () => {
if (isSelectedAll.value) {
if (totalNum.value > 10000) {
isShowAllDataMaxLengthTip.value = true
}
loading.value = true
await fetchAllData()
handleSelectAllPage()
allData.value.forEach(row => {
if (!selectedMap.value.has(row.id)) {
selectedMap.value.set(row.id, row)
}
})
loading.value = false
} else {
handleClearAll()
}
}
// 清空所有选择
const handleClearAll = () => {
isSelectedAll.value = false
selectedMap.value.clear()
tableRef.value?.clearSelection()
}
// 翻页
const handleCurrentChange = async (val) => {
currentPage.value = val
await fetchTableData()
if (isSelectedAll.value) {
handleSelectAllPage()
}
}
// 监听数据变化,回显选中状态 [citation:4][citation:8]
watch(tableData, () => {
nextTick(() => {
tableData.value.forEach(row => {
if (selectedMap.value.has(row.id)) {
tableRef.value?.toggleRowSelection(row, true)
}
})
})
})
// 当前图表数据
const curChartData = ref(null)
// 下载当前图表数据
const handleDownloadCurChartData = () => {
const jsonStr = JSON.stringify(curChartData.value, null, 2);
const blob = new Blob([jsonStr], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'chartData.json';
link.click();
URL.revokeObjectURL(url);
}
// 跳转到当前页 初始化筛选条件
const initParam = () => {
const hasQuery = Object.keys(route.query).length > 0;
if (hasQuery) {
selectedArea.value = route.query.domains ? route.query.domains : '全部领域'
if (route.query.selectedDate && Array.isArray(JSON.parse(route.query.selectedDate)) && JSON.parse(route.query.selectedDate).length) {
selectedDate.value = '自定义'
customTime.value = JSON.parse(route.query.selectedDate)
}
selectedType.value = route.query.orgnizationName ? route.query.orgnizationName : '全部类别'
const query = route.query;
if (Object.keys(query).length > 0) {
sessionStorage.setItem('decreeRouteQuery', JSON.stringify(query));
}
} else {
const savedQuery = JSON.parse(sessionStorage.getItem('decreeRouteQuery') || '{}');
selectedArea.value = savedQuery.domains ? savedQuery.domains : '全部领域'
if (savedQuery.selectedDate && Array.isArray(JSON.parse(savedQuery.selectedDate)) && JSON.parse(savedQuery.selectedDate).length) {
selectedDate.value = '自定义'
customTime.value = JSON.parse(savedQuery.selectedDate)
}
}
}
// 跳转政令详情
const handleClickToDetail = (curDecree) => {
console.log('curDecree', curDecree);
window.sessionStorage.setItem("decreeId", curDecree.id);
window.sessionStorage.setItem("curTabName", curDecree.title);
const route = router.resolve({
path: "/decreeLayout",
query: {
id: curDecree.id
}
});
window.open(route.href, "_blank");
};
// 跳转机构详情
const handleOrgClick = item => {
console.log('item', item);
window.sessionStorage.setItem("curTabName", item.organizationName);
const route = router.resolve({
path: "/institution",
query: {
id: item.organizationId
}
});
window.open(route.href, "_blank");
};
// 导出
const handleExport = () => {
if (!selectedCount.value) {
ElMessage.warning('请选择至少一项数据!')
return
}
console.log(selectedMap.value);
const arr = Array.from(selectedMap.value);
const jsonStr = JSON.stringify(arr, null, 2);
const blob = new Blob([jsonStr], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'export.json';
link.click();
URL.revokeObjectURL(url);
};
onMounted(async () => {
handleGetMaterialCategory() // 获取物项类别列表
handleGetControlReason() // 获取管控原因
initParam()
// 初始化
await fetchTableData()
})
</script>
......@@ -35,6 +957,8 @@ const totalNum = ref(12)
.countrybill-wrapper {
width: 1600px;
height: 968px;
overflow: hidden;
overflow-y: auto;
.headere-box {
width: 1568px;
......@@ -44,19 +968,53 @@ const totalNum = ref(12)
border: 1px solid var(--bg-black-5);
margin: 16px auto;
}
.header-box {
width: 1568px;
height: 112px;
min-height: 112px;
border-radius: 10px;
background: rgb(255, 255, 255);
border: 1px solid var(--bg-black-5);
margin: 16px auto;
box-sizing: border-box;
padding: 16px 24px;
.header-top {
min-height: 28px;
display: flex;
flex-wrap: wrap;
gap: 12px 42px;
// transition: all ease 1s;
.check-box {
display: flex;
width: 348px;
height: 28px;
align-items: center;
gap: 8px;
.check-box-left {
width: 100px;
color: var(--text-primary-65-color);
}
}
}
.main-box {
.header-footer {
margin-top: 16px;
display: flex;
justify-content: space-between;
.header-footer-left {
display: flex;
justify-content: space-between;
gap: 8px;
}
}
}
.chart-main-box {
.info-box {
margin: 0 auto;
width: 1568px;
......@@ -90,7 +1048,199 @@ const totalNum = ref(12)
border-radius: 10px;
background: rgba(255, 255, 255);
border: 1px solid var(--bg-black-5);
.content-header {
margin: 16px 24px;
width: 1520px;
height: 28px;
}
.content-main {
width: 1520px;
margin: 0 auto;
}
}
}
.data-main-box {
width: 1568px;
min-height: 810px;
border-radius: 10px;
background: var(--bg-white-100);
margin: 0 auto;
margin-bottom: 20px;
overflow: hidden;
.data-main-box-header {
margin: 16px auto;
width: 1520px;
height: 30px;
display: flex;
justify-content: space-between;
.switch-box {
width: 160px;
border-radius: 20px;
border: 1px solid var(--color-primary-100);
height: 30px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.num-box {
box-sizing: border-box;
padding: 2px 0;
color: var(--color-red-100);
}
}
.data-main-box-main {
width: 1520px;
// height: 633px;
min-height: 680px;
border-radius: 10px;
border: 1px solid var(--bg-black-5);
margin: 0 auto;
.data-main-box-main-header {
height: 48px;
background: var(--bg-black-2);
display: flex;
justify-content: space-between;
.header-left {
margin-left: 16px;
height: 48px;
display: flex;
gap: 16px;
align-items: center;
.header-left-item2 {
color: var(--color-primary-100);
display: flex;
gap: 8px;
}
.header-left-item3 {
color: var(--color-orange-100);
}
.cancel {
cursor: pointer;
}
}
.header-right {
margin-right: 16px;
display: flex;
gap: 8px;
align-items: center;
.header-right-item {
height: 30px;
padding: 5px 16px;
border: 1px solid var(--bg-black-10);
border-radius: 4px;
background: var(--bg-white-100);
cursor: pointer;
}
.item1 {
display: flex;
gap: 2px;
justify-content: center;
align-items: center;
&:hover {
background: var(--color-primary-2);
}
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.text {
color: var(--text-primary-65-color);
}
}
.item2 {}
.item3 {}
}
}
.data-main-box-main-content {}
}
.data-main-box-footer {
margin: 16px auto 0;
height: 40px;
width: 1520px;
display: flex;
align-items: center;
justify-content: flex-end;
}
}
}
.date-column {
background-color: #ecf5ff;
.tag-box {
display: flex;
flex-wrap: wrap;
gap: 8px;
width: 490px;
}
}
.date-column .cell {
color: #409eff !important;
font-weight: 500;
}
.title-item {
color: var(--text-primary-80-color);
cursor: pointer;
&:hover {
color: var(--color-primary-100);
text-decoration: underline;
}
}
.person-item {
color: var(--color-primary-100);
cursor: pointer;
&:hover {
font-weight: bold;
text-decoration: underline;
}
}
:deep(.el-table__header-wrapper) {
// background-color: #f5f7fa;
height: 48px;
}
:deep(.el-table__header th) {
// background-color: #f5f7fa;
color: var(--text-primary-50-color);
font-weight: bold;
}
</style>
\ No newline at end of file
<template>
<div class="countrybill-wrapper">
<div class="header-box">我是商业管制清单事件</div>
<div class="main-box">
<div class="header-box">
<div class="header-top">
<SelectBox :placeholder-name="areaPlaceHolder" select-title="科技领域" :select-list="areaList"
:select-name="selectedArea" @update:select-text="handleSelectArea" />
<SelectBox :placeholder-name="DatePlaceHolder" select-title="制裁时间" :select-list="dateList"
:select-name="selectedDate" :custom-time="customTime" @update:select-text="handleSelectDate"
@update:custom-time="handleCustomDate" />
<div class="check-box">
<div class="check-box-left text-tip-1">
{{ '是否涉华:' }}
</div>
<div class="check-box-right">
<el-checkbox v-model="isInvolveCnOnly" class="involve-checkbox">
{{ '只看涉华' }}
</el-checkbox>
</div>
</div>
</div>
<div class="header-footer">
<div class="header-footer-left">
<ActiveTag v-for="tag, index in activeTagList" :key="index" :tagName="tag.name"
@close="handleCloseCurTag(tag, index)" />
</div>
<div class="header-footer-right">
<HeaderBtnBox :isShowAll="isFolderAll" :isShowAllBtn="false" @show-all="handleSwitchFolderAll" @clear="handleClear"
@confirm="handleConfirm" />
</div>
</div>
</div>
<div class="chart-main-box" v-if="isShowChart">
<div class="info-box">
<div class="switch-box" @click="handleSwitchChartData">
<img v-if="!isShowChart" src="@/views/dataLibrary/assets/icons/chart-active.svg" alt="">
<img v-else src="@/views/dataLibrary/assets/icons/data-active.svg" alt="">
<img src="@/views/dataLibrary/assets/icons/chart-active.svg" alt="">
</div>
<div class="num-box text-title-3-bold">
{{ `共 ${totalNum} 条数据` }}
</div>
</div>
<div class="content-box">
<div class="content-header">
<ChartHeader :list="staticsDemensionList" @clickItem="handleClickDemensionItem">
<template #chart-header-right>
<el-select v-model="selectedTime" placeholder="选择时间" style="width: 150px" v-show="curDemension === '制裁时间'"
@change="handleChangeTime">
<el-option v-for="item in timeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
</ChartHeader>
</div>
<div class="content-main">
<ChartContainer :chartTitle="curChartTitle" :chartTypeList="curChartTypeList"
@clickChartItem="handleSwitchActiveChart" @download="handleDownloadCurChartData">
<template #chart-box>
<LineChart v-if="activeChart === '折线图'" :lineChartData="curChartData" />
<BarChart v-if="activeChart === '柱状图'" :barChartData="curChartData" />
<PieChart v-if="activeChart === '饼状图'" :pieChartData="curChartData" />
<RaderChart v-if="activeChart === '雷达图'" :radarChartData="curChartData" />
</template>
</ChartContainer>
</div>
</div>
</div>
<div class="data-main-box" v-else>
<div class="data-main-box-header">
<div class="switch-box" @click="handleSwitchChartData">
<img src="@/views/dataLibrary/assets/icons/data-active.svg" alt="">
</div>
<div class="num-box text-title-3-bold">
{{ `共 ${totalNum} 条数据` }}
</div>
</div>
<div class="content-box"></div>
<div class="data-main-box-main">
<div class="data-main-box-main-header">
<div class="header-left">
<div class="header-left-item1">
<el-checkbox v-model="isSelectedAll" label="全选" @change="handleSelectAllChange" size="large" />
</div>
<div class="header-left-item2 text-tip-1">{{ `已选择${selectedCount}项` }}</div>
<div class="header-left-item2 text-tip-1 cancel" @click="handleClearAll" v-show="selectedCount">{{ '取消' }}
<div class="header-left-item3 text-tip-1" v-if="isShowAllDataMaxLengthTip">{{ `(当前最大选择不能超过1万条!)` }}</div>
</div>
</div>
<div class="header-right">
<div class="header-right-item item1" @click="handleExport">
<div class="icon">
<img src="../../assets/icons/download.svg" alt="">
</div>
<div class="text text-tip-1">{{ '导出' }}</div>
</div>
<div class="header-right-item2 item2">
<el-select v-model="curOperation" placeholder="批量操作" style="width: 120px">
<el-option v-for="item in operationList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</div>
<div class="header-right-item3 item3">
<el-select v-model="isSort" placeholder="制裁时间" style="width: 166px" @change="handlePxChange">
<template #prefix>
<div style="display: flex; align-items: center; height: 100%">
<img src="../../assets/icons/desc-icon.svg" style="width: 14px; height: 14px" />
</div>
</template>
<el-option v-for="item in releaseTimeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</div>
</div>
<div class="data-main-box-main-content" v-loading="loading" element-loading-text="数据加载中,请稍候...">
<el-table ref="tableRef" :data="tableData" row-key="id" @selection-change="handleSelectionChange"
@select="handleSelect" @select-all="handleSelectAll" style="width: 100%" :row-style="{ height: '52px' }">
<el-table-column type="selection" width="40" />
<el-table-column label="事件名称">
<template #default="scope">
<span class="title-item text-compact-bold" @click="handleClickToDetail(scope.row)">{{
scope.row.originalTitle
}}</span>
</template>
</el-table-column>
<el-table-column label="制裁时间" width="240" class-name="date-column">
<template #default="scope">{{ scope.row.date }}</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="data-main-box-footer">
<el-pagination background layout="prev, pager, next" :total="totalNum" v-model:current-page="currentPage"
:page-size="pageSize" @current-change="handleCurrentChange" />
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ref, computed, watch, onMounted, nextTick } from 'vue'
import ChartContainer from '../../components/ChartContainer/index.vue'
import ChartHeader from '../../components/ChartHeader/index.vue'
import ActiveTag from '../../components/ActiveTag/index.vue'
import HeaderBtnBox from '../../components/HeaderBtnBox/index.vue'
import LineChart from '../../components/LineChart/index.vue'
import PieChart from '../../components/PieChart/index.vue'
import BarChart from '../../components/BarChart/index.vue'
import RaderChart from '../../components/RadarChart/idnex.vue'
import SelectBox from '../../components/SelectBox/index.vue'
import { useRoute } from "vue-router";
import router from '@/router'
// 图表/数据
const isShowChart = ref(true)
import { search } from '@/api/comprehensiveSearch'
import { ElMessage } from 'element-plus'
import getDateRange from '@/utils/getDateRange'
const route = useRoute();
// 图表/数据
const isShowChart = ref(false)
// 点击切换数据/图表
const handleSwitchChartData = () => {
isShowChart.value = !isShowChart.value
if (isShowChart.value) {
const curDemensionItem = staticsDemensionList.value.filter(item => {
return item.name === curDemension.value
})[0]
// setTimeout(() => {
activeChart.value = curDemensionItem.chartTypeList[0]
if (curDemension.value === '制裁时间') {
if (selectedTime.value === '按月度统计') {
curChartData.value = curDemensionItem.data
} else if (selectedTime.value === '按季度统计') {
curChartData.value = curDemensionItem.quatarData
} else {
curChartData.value = curDemensionItem.yearData
}
} else {
curChartData.value = curDemensionItem.data
}
// })
}
}
// 总计数据
const totalNum = ref(12)
const totalNum = ref(0)
// 统计维度列表
const staticsDemensionList = ref([
{
name: '制裁时间',
active: true,
chartTypeList: ['折线图', '柱状图'],
chartTitle: '实体清单制裁时间变化趋势',
data: {
dataX: [],
dataY: []
},
quatarData: {
dataX: [],
dataY: []
},
yearData: {
dataX: [],
dataY: []
}
}
])
// 当前维度下的图表列表
const curChartTypeList = computed(() => {
let arr = staticsDemensionList.value.filter(item => item.active)
return arr[0].chartTypeList
})
// 当前图表标题
const curChartTitle = computed(() => {
let arr = staticsDemensionList.value.filter(item => item.active)
return arr[0].chartTitle
})
// 当前维度
const curDemension = ref('制裁时间')
// 点击维度item
const handleClickDemensionItem = (val) => {
activeChart.value = ''
staticsDemensionList.value.forEach(item => {
item.active = false
})
val.active = true
curDemension.value = val.name
setTimeout(() => {
activeChart.value = val.chartTypeList[0]
if (curDemension.value === '制裁时间' && selectedTime.value === '按年度统计') {
curChartData.value = val.yearData
} else if (curDemension.value === '制裁时间' && selectedTime.value === '按季度统计') {
curChartData.value = val.quatarData
} else {
curChartData.value = val.data
}
})
}
// 时间图表 当前选择时间
const selectedTime = ref('按年度统计')
// 时间图表-时间列表
const timeList = ref([
{
label: '按年度统计',
value: '按年度统计'
},
{
label: '按季度统计',
value: '按季度统计'
},
{
label: '按月度统计',
value: '按月度统计'
},
])
const handleChangeTime = value => {
let curChart = activeChart.value
activeChart.value = ''
if (value === '按月度统计') {
setTimeout(() => {
activeChart.value = curChart
curChartData.value = staticsDemensionList.value[0].data
})
} else if (value === '按季度统计') {
setTimeout(() => {
activeChart.value = curChart
curChartData.value = staticsDemensionList.value[0].quatarData
})
} else {
setTimeout(() => {
activeChart.value = curChart
curChartData.value = staticsDemensionList.value[0].yearData
})
}
}
// 激活的标签列表
const activeTagList = computed(() => {
const arr = []
if (selectedArea.value && selectedArea.value !== '全部领域') {
arr.push(
{
tag: '科技领域',
name: selectedArea.value
}
)
}
if (selectedDate.value === '自定义') {
arr.push(
{
tag: '制裁时间',
name: customTime.value.join('至')
}
)
}
if (isInvolveCnOnly.value) {
const involveStr = '涉华'
arr.push(
{
tag: '涉华',
name: involveStr
}
)
}
return arr
})
// 关闭当前标签
const handleCloseCurTag = (tag, index) => {
switch (tag.tag) {
case '科技领域':
selectedArea.value = '全部领域'
break
case '制裁时间':
selectedDate.value = ''
customTime.value = []
break
case '涉华':
isInvolveCnOnly.value = false
break
}
}
const activeChart = ref('') // 当前激活的图表
// 切换当前图表
const handleSwitchActiveChart = val => {
activeChart.value = val.name
}
// 雷达图数据
const radarChartData = ref({
title: [
{
name: '航空航天',
max: 10
},
{
name: '先进制造',
max: 10
},
{
name: '量子科技',
max: 10
},
{
name: '人工智能',
max: 10
},
{
name: '新材料',
max: 10
},
{
name: '集成电路',
max: 10
},
],
data: [
{
name: "337调查",
value: [10, 5, 2, 8, 5, 7
]
},
{
name: "232调查",
value: [2, 5, 3, 8, 10, 2]
},
{
name: "301调查",
value: [5, 8, 2, 9, 1, 5]
}
]
}
)
// 数据- 是否全选
const isSelectedAll = ref(false)
// 批量操作-当前操作
const curOperation = ref('')
const operationList = ref([
{
name: 'aaa',
id: 'aaa'
},
{
name: 'bbb',
id: 'bbb'
},
{
name: 'ccc',
id: 'ccc'
},
])
// 科技领域
const areaPlaceHolder = ref('请选择领域')
const selectedArea = ref('全部领域')
const areaList = ref([
{
name: '全部领域',
id: '全部领域'
},
{
name: '人工智能',
id: '人工智能'
},
{
name: '生物科技',
id: '生物科技'
},
{
name: '新一代通信网络',
id: '新一代通信网络'
},
{
name: '量子科技',
id: '量子科技'
},
{
name: '新能源',
id: '新能源'
},
{
name: '集成电路',
id: '集成电路'
},
{
name: '海洋',
id: '海洋'
},
{
name: '先进制造',
id: '先进制造'
},
{
name: '新材料',
id: '新材料'
},
{
name: '航空航天',
id: '航空航天'
},
{
name: '太空',
id: '太空'
},
{
name: '深海',
id: '深海'
},
{
name: '极地',
id: '极地'
},
{
name: '核',
id: '核'
},
{
name: '其他',
id: '其他'
},
])
const handleSelectArea = (value) => {
selectedArea.value = value
}
// 制裁时间
const DatePlaceHolder = ref('请选择时间')
const selectedDate = ref('')
const dateList = ref([
{
name: '自定义',
id: '自定义'
},
{
name: '近一年',
id: '近一年'
},
{
name: '近半年',
id: '近半年'
},
{
name: '近三月',
id: '近三月'
},
{
name: '近一月',
id: '近一月'
}
])
const customTime = ref([]) // 自定义时间
const handleCustomDate = value => {
customTime.value = value
}
const handleSelectDate = (value) => {
selectedDate.value = value
if (selectedDate.value !== '自定义') {
customTime.value = getDateRange(selectedDate.value)
}
}
// 是否只看涉华
const isInvolveCnOnly = ref(false)
// 清空条件
const handleClear = () => {
selectedArea.value = '全部领域'
selectedDate.value = ''
customTime.value = []
isInvolveCnOnly.value = false
ElMessage.success('已清空条件!')
}
// 确定
const handleConfirm = () => {
currentPage.value = 1
fetchTableData()
}
// 展开全部 / 收起
const isFolderAll = ref(false)
const handleSwitchFolderAll = () => {
isFolderAll.value = !isFolderAll.value
}
const tableRef = ref(null)
// 表格数据
const tableData = ref([
])
const releaseTimeList = ref([
{
label: "按发布时间倒序",
value: true
},
{
label: "按发布时间升序",
value: false
}
]);
const isSort = ref(true); // true 倒序 false 升序
const handlePxChange = val => {
fetchTableData()
};
const currentPage = ref(1);
const pageSize = ref(10)
// 存储选中的数据(跨页)[citation:3][citation:8]
const selectedMap = ref(new Map()) // 使用 Map 存储,key 为唯一 id
// 计算已选中的条数
const selectedCount = computed(() => selectedMap.value.size)
// 获取当前页表格数据(示例)
const fetchTableData = async () => {
// isSelectedAll.value = false
// selectedMap.value.clear()
loading.value = true
// 调用接口获取数据...
const params = {
page: currentPage.value,
size: pageSize.value,
// keyword: '',
type: 13, // 实体清单事件
domains: selectedArea.value === '全部领域' ? null : [selectedArea.value], // 科技领域
proposedDateStart: customTime.value[0] ? customTime.value[0] : null,
proposedDateEnd: customTime.value[1] ? customTime.value[1] : null,
isInvolveCn: isInvolveCnOnly.value ? 'Y' : null, // 是否只看中国实体
sort: isSort.value ? 0 : 1 // 0 先按分数降序 后按时间降序 1 先按分数降序,再按时间升序
}
try {
const res = await search(params)
console.log('搜索结果', res);
if (res.code === 200 && res.data) {
tableData.value = res.data.records
totalNum.value = res.data.total
staticsDemensionList.value[0].data = {
dataX: Object.keys(res.data.aggregationsDate),
dataY: Object.values(res.data.aggregationsDate).map(value => Number(value))
}
staticsDemensionList.value[0].quatarData = {
dataX: Object.keys(res.data.aggregationsQuarter),
dataY: Object.values(res.data.aggregationsQuarter).map(value => Number(value))
}
staticsDemensionList.value[0].yearData = {
dataX: Object.keys(res.data.aggregationsYear),
dataY: Object.values(res.data.aggregationsYear).map(value => Number(value))
}
}
const curDemensionItem = staticsDemensionList.value.filter(item => {
return item.name === curDemension.value
})[0]
activeChart.value = ''
setTimeout(() => {
activeChart.value = curDemensionItem.chartTypeList[0]
curChartData.value = curDemensionItem.data
})
loading.value = false
} catch (error) {
loading.value = false
}
// tableData.value = res.data
// total.value = res.total
// 数据加载后,回显已选中的行
nextTick(() => {
tableData.value.forEach(row => {
if (selectedMap.value.has(row.id)) {
tableRef.value?.toggleRowSelection(row, true)
}
})
})
}
const allData = ref([])
// 获取筛选条件下全部表格数据
const fetchAllData = async () => {
const params = {
page: 1,
size: 9999,
type: 13, // 实体清单事件
domains: selectedArea.value === '全部领域' ? null : [selectedArea.value], // 科技领域
proposedDateStart: customTime.value[0] ? customTime.value[0] : null,
proposedDateEnd: customTime.value[1] ? customTime.value[1] : null,
isInvolveCn: isInvolveCnOnly.value ? 'Y' : null, // 是否只看中国实体
sort: isSort.value ? 0 : 1 // 0 先按分数降序 后按时间降序 1 先按分数降序,再按时间升序
}
try {
const res = await search(params)
console.log('搜索结果', res);
if (res.code === 200 && res.data) {
allData.value = res.data.records
}
} catch (error) {
ElMessage.error('加载全部数据出错!')
}
}
// 单选事件
const handleSelect = (selection, row) => {
if (selection.some(item => item.id === row.id)) {
// 选中:添加到 Map
selectedMap.value.set(row.id, row)
} else {
// 取消选中:从 Map 移除
selectedMap.value.delete(row.id)
}
}
// 表格自带 当前页 全选/全不选事件
const handleSelectAll = (selection) => {
if (selection.length > 0) {
// 全选:将当前页所有数据添加到 Map
tableData.value.forEach(row => {
if (!selectedMap.value.has(row.id)) {
selectedMap.value.set(row.id, row)
}
})
} else {
// 全不选:从 Map 中移除当前页的所有数据
tableData.value.forEach(row => {
selectedMap.value.delete(row.id)
})
}
}
// 处理选择变化(用于统计)
const handleSelectionChange = (val) => {
// 这里可以做一些额外的处理,但主要统计使用 selectedMap
console.log('当前页选中数量:', val.length)
}
// 全选当前页按钮
const handleSelectAllPage = () => {
if (tableData.value.length === 0) return
// 检查当前页是否已全选
const currentPageSelected = tableData.value.every(row =>
selectedMap.value.has(row.id)
)
if (currentPageSelected) {
// 已全选,则不动当前页的全选
tableData.value.forEach(row => {
tableRef.value.toggleRowSelection(row, false)
// selectedMap.value.delete(row.id)
})
} else {
// 未全选,则全选当前页
tableData.value.forEach(row => {
tableRef.value.toggleRowSelection(row, true)
if (!selectedMap.value.has(row.id)) {
selectedMap.value.set(row.id, row)
}
})
}
}
// 全选最大1万条提示
const isShowAllDataMaxLengthTip = ref(false)
const loading = ref(false) // 加载数据loading
// 处理 全选(全部数据)
const handleSelectAllChange = async () => {
if (isSelectedAll.value) {
if (totalNum.value > 10000) {
isShowAllDataMaxLengthTip.value = true
}
loading.value = true
await fetchAllData()
handleSelectAllPage()
allData.value.forEach(row => {
if (!selectedMap.value.has(row.id)) {
selectedMap.value.set(row.id, row)
}
})
loading.value = false
} else {
handleClearAll()
}
}
// 清空所有选择
const handleClearAll = () => {
isSelectedAll.value = false
selectedMap.value.clear()
tableRef.value?.clearSelection()
}
// 翻页
const handleCurrentChange = async (val) => {
currentPage.value = val
await fetchTableData()
if (isSelectedAll.value) {
handleSelectAllPage()
}
}
// 监听数据变化,回显选中状态 [citation:4][citation:8]
watch(tableData, () => {
nextTick(() => {
tableData.value.forEach(row => {
if (selectedMap.value.has(row.id)) {
tableRef.value?.toggleRowSelection(row, true)
}
})
})
})
// 当前图表数据
const curChartData = ref(null)
// 下载当前图表数据
const handleDownloadCurChartData = () => {
const jsonStr = JSON.stringify(curChartData.value, null, 2);
const blob = new Blob([jsonStr], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'chartData.json';
link.click();
URL.revokeObjectURL(url);
}
// 跳转到当前页 初始化筛选条件
const initParam = () => {
const hasQuery = Object.keys(route.query).length > 0;
if (hasQuery) {
selectedArea.value = route.query.domains ? route.query.domains : '全部领域'
if (route.query.selectedDate && Array.isArray(JSON.parse(route.query.selectedDate)) && JSON.parse(route.query.selectedDate).length) {
selectedDate.value = '自定义'
customTime.value = JSON.parse(route.query.selectedDate)
}
isInvolveCnOnly.value = route.query.isInvolveCnOnly ? true : false
const query = route.query;
if (Object.keys(query).length > 0) {
sessionStorage.setItem('decreeRouteQuery', JSON.stringify(query));
}
} else {
const savedQuery = JSON.parse(sessionStorage.getItem('decreeRouteQuery') || '{}');
selectedArea.value = savedQuery.domains ? savedQuery.domains : '全部领域'
if (savedQuery.selectedDate && Array.isArray(JSON.parse(savedQuery.selectedDate)) && JSON.parse(savedQuery.selectedDate).length) {
selectedDate.value = '自定义'
customTime.value = JSON.parse(savedQuery.selectedDate)
}
isInvolveCnOnly.value = savedQuery.isInvolveCnOnly ? true : false
}
}
// 跳转政令详情
const handleClickToDetail = (curDecree) => {
console.log('curDecree', curDecree);
window.sessionStorage.setItem("decreeId", curDecree.id);
window.sessionStorage.setItem("curTabName", curDecree.title);
const route = router.resolve({
path: "/decreeLayout",
query: {
id: curDecree.id
}
});
window.open(route.href, "_blank");
};
// 跳转机构详情
const handleOrgClick = item => {
console.log('item', item);
window.sessionStorage.setItem("curTabName", item.organizationName);
const route = router.resolve({
path: "/institution",
query: {
id: item.organizationId
}
});
window.open(route.href, "_blank");
};
// 导出
const handleExport = () => {
if (!selectedCount.value) {
ElMessage.warning('请选择至少一项数据!')
return
}
console.log(selectedMap.value);
const arr = Array.from(selectedMap.value);
const jsonStr = JSON.stringify(arr, null, 2);
const blob = new Blob([jsonStr], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'export.json';
link.click();
URL.revokeObjectURL(url);
};
onMounted(async () => {
initParam()
// 初始化
await fetchTableData()
})
</script>
......@@ -35,6 +882,8 @@ const totalNum = ref(12)
.countrybill-wrapper {
width: 1600px;
height: 968px;
overflow: hidden;
overflow-y: auto;
.headere-box {
width: 1568px;
......@@ -44,19 +893,53 @@ const totalNum = ref(12)
border: 1px solid var(--bg-black-5);
margin: 16px auto;
}
.header-box {
width: 1568px;
height: 112px;
min-height: 112px;
border-radius: 10px;
background: rgb(255, 255, 255);
border: 1px solid var(--bg-black-5);
margin: 16px auto;
box-sizing: border-box;
padding: 16px 24px;
.header-top {
min-height: 28px;
display: flex;
flex-wrap: wrap;
gap: 12px 42px;
// transition: all ease 1s;
.check-box {
display: flex;
width: 348px;
height: 28px;
align-items: center;
gap: 8px;
.check-box-left {
width: 100px;
color: var(--text-primary-65-color);
}
}
}
.main-box {
.header-footer {
margin-top: 16px;
display: flex;
justify-content: space-between;
.header-footer-left {
display: flex;
justify-content: space-between;
gap: 8px;
}
}
}
.chart-main-box {
.info-box {
margin: 0 auto;
width: 1568px;
......@@ -90,7 +973,199 @@ const totalNum = ref(12)
border-radius: 10px;
background: rgba(255, 255, 255);
border: 1px solid var(--bg-black-5);
.content-header {
margin: 16px 24px;
width: 1520px;
height: 28px;
}
.content-main {
width: 1520px;
margin: 0 auto;
}
}
}
.data-main-box {
width: 1568px;
min-height: 810px;
border-radius: 10px;
background: var(--bg-white-100);
margin: 0 auto;
margin-bottom: 20px;
overflow: hidden;
.data-main-box-header {
margin: 16px auto;
width: 1520px;
height: 30px;
display: flex;
justify-content: space-between;
.switch-box {
width: 160px;
border-radius: 20px;
border: 1px solid var(--color-primary-100);
height: 30px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.num-box {
box-sizing: border-box;
padding: 2px 0;
color: var(--color-red-100);
}
}
.data-main-box-main {
width: 1520px;
// height: 633px;
min-height: 680px;
border-radius: 10px;
border: 1px solid var(--bg-black-5);
margin: 0 auto;
.data-main-box-main-header {
height: 48px;
background: var(--bg-black-2);
display: flex;
justify-content: space-between;
.header-left {
margin-left: 16px;
height: 48px;
display: flex;
gap: 16px;
align-items: center;
.header-left-item2 {
color: var(--color-primary-100);
display: flex;
gap: 8px;
}
.header-left-item3 {
color: var(--color-orange-100);
}
.cancel {
cursor: pointer;
}
}
.header-right {
margin-right: 16px;
display: flex;
gap: 8px;
align-items: center;
.header-right-item {
height: 30px;
padding: 5px 16px;
border: 1px solid var(--bg-black-10);
border-radius: 4px;
background: var(--bg-white-100);
cursor: pointer;
}
.item1 {
display: flex;
gap: 2px;
justify-content: center;
align-items: center;
&:hover {
background: var(--color-primary-2);
}
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.text {
color: var(--text-primary-65-color);
}
}
.item2 {}
.item3 {}
}
}
.data-main-box-main-content {}
}
.data-main-box-footer {
margin: 16px auto 0;
height: 40px;
width: 1520px;
display: flex;
align-items: center;
justify-content: flex-end;
}
}
}
.date-column {
background-color: #ecf5ff;
.tag-box {
display: flex;
flex-wrap: wrap;
gap: 8px;
width: 490px;
}
}
.date-column .cell {
color: #409eff !important;
font-weight: 500;
}
.title-item {
color: var(--text-primary-80-color);
cursor: pointer;
&:hover {
color: var(--color-primary-100);
text-decoration: underline;
}
}
.person-item {
color: var(--color-primary-100);
cursor: pointer;
&:hover {
font-weight: bold;
text-decoration: underline;
}
}
:deep(.el-table__header-wrapper) {
// background-color: #f5f7fa;
height: 48px;
}
:deep(.el-table__header th) {
// background-color: #f5f7fa;
color: var(--text-primary-50-color);
font-weight: bold;
}
</style>
\ No newline at end of file
......@@ -9,7 +9,7 @@
@update:custom-time="handleCustomDate" />
<SelectBox v-if="isFolderAll" :placeholder-name="countryPlaceHolder" select-title="国家地区"
:select-list="countryList" :select-name="selectedCountry" @update:select-text="handleSelectCountry" />
<SelectBox v-if="isFolderAll" :placeholder-name="provincePlaceHolder" select-title="实体省份"
<SelectBox v-if="isShowProvinceBox" :placeholder-name="provincePlaceHolder" select-title="实体省份"
:select-list="provinceList" :select-name="selectedProvince" @update:select-text="handleSelectProvince" />
<SelectBox v-if="isFolderAll" :placeholder-name="entityTypePlaceHolder" select-title="实体类型"
:select-list="entityTypeList" :select-name="selectedEntityType"
......@@ -130,7 +130,7 @@
<el-table ref="tableRef" :data="tableData" row-key="id" @selection-change="handleSelectionChange"
@select="handleSelect" @select-all="handleSelectAll" style="width: 100%" :row-style="{ height: '52px' }">
<el-table-column type="selection" width="40" />
<el-table-column label="实体名称" width="720">
<el-table-column label="实体名称" width="620">
<template #default="scope">
<span class="title-item text-compact-bold" @click="handleClickToDetail(scope.row)">{{
scope.row.originalTitle
......@@ -146,7 +146,7 @@
}}</span>
</template>
</el-table-column>
<el-table-column label="涉及领域" width="350" class-name="date-column">
<el-table-column label="涉及领域" width="500" class-name="date-column">
<template #default="scope">
<div class="tag-box">
<AreaTag v-for="tag, index in scope.row.domains" :key="index" :tagName="tag" />
......@@ -185,9 +185,18 @@ import router from '@/router'
import { search } from '@/api/comprehensiveSearch'
import { ElMessage } from 'element-plus'
import getDateRange from '@/utils/getDateRange'
import { getProvinceList, getCountryList, getEntityTypes } from '@/api/comprehensiveSearch/index'
const route = useRoute();
const isShowProvinceBox = computed(() => {
let isShow = false
if(isFolderAll.value && (selectedCountry.value==='0101' || selectedCountry.value==='全部国家')) {
isShow = true
}
return isShow
})
// 图表/数据
const isShowChart = ref(false)
// 点击切换数据/图表
......@@ -197,7 +206,7 @@ const handleSwitchChartData = () => {
const curDemensionItem = staticsDemensionList.value.filter(item => {
return item.name === curDemension.value
})[0]
setTimeout(() => {
// setTimeout(() => {
activeChart.value = curDemensionItem.chartTypeList[0]
if (curDemension.value === '制裁时间') {
if (selectedTime.value === '按月度统计') {
......@@ -210,7 +219,7 @@ const handleSwitchChartData = () => {
} else {
curChartData.value = curDemensionItem.data
}
})
// })
}
}
......@@ -303,7 +312,7 @@ const handleClickDemensionItem = (val) => {
}
// 时间图表 当前选择时间
const selectedTime = ref('按统计')
const selectedTime = ref('按年度统计')
// 时间图表-时间列表
const timeList = ref([
{
......@@ -361,14 +370,19 @@ const activeTagList = computed(() => {
)
}
if (selectedCountry.value && selectedCountry.value !== '全部国家') {
const countryArr = countryList.value.filter(item => item.id === selectedCountry.value)
let countryStr = '全部国家'
if (countryArr && countryArr.length) {
countryStr = countryArr[0].name
}
arr.push(
{
tag: '实体国家地区',
name: selectedCountry.value
name: countryStr
}
)
}
if (selectedProvince.value && selectedProvince.value !== '全部省份') {
if (selectedProvince.value && selectedProvince.value !== '全部省份' && (selectedCountry.value === '0101' || selectedCountry.value === '全部国家')) {
arr.push(
{
tag: '实体省份',
......@@ -377,16 +391,21 @@ const activeTagList = computed(() => {
)
}
if (selectedEntityType.value && selectedEntityType.value !== '全部实体类型') {
const entityTypeArr = entityTypeList.value.filter(item => item.id === selectedEntityType.value)
let entityTypeStr = '全部类型'
if (entityTypeArr && entityTypeArr.length) {
entityTypeStr = entityTypeArr[0].name
}
arr.push(
{
tag: '实体类型',
name: selectedEntityType.value
name: entityTypeStr
}
)
}
if (isHalfRule.value) {
const halfRuleStr = '50%规则'
const halfRuleStr = '50%规则'
arr.push(
{
tag: '50%规则',
......@@ -631,6 +650,23 @@ const countryPlaceHolder = ref('请选择实体国家')
const handleSelectCountry = value => {
selectedCountry.value = value
}
// 获取国家地区列表
const handleGetCountryList = async () => {
try {
const res = await getCountryList()
console.log('获取国家列表', res);
if (res.code === 200 && res.data) {
countryList.value = res.data.map(item => {
return {
name: item.name,
id: item.id
}
})
}
} catch (error) {
}
}
// 实体省份(仅支持中国省份)
......@@ -645,6 +681,27 @@ const provincePlaceHolder = ref('请选择发布机构')
const handleSelectProvince = value => {
selectedProvince.value = value
}
// 获取全部省份列表
const handleGetProvinceList = async () => {
try {
const res = await getProvinceList()
console.log('获取省份列表', res);
if(res && res.length) {
provinceList.value = res.map(item => {
return {
name: item,
id: item
}
})
}
} catch (error) {
console.error(error);
} finally {
}
}
// 实体类型列表
const entityTypeList = ref([
......@@ -658,6 +715,24 @@ const entityTypePlaceHolder = ref('请选择实体类型')
const handleSelectEntityType = value => {
selectedEntityType.value = value
}
// 获取实体类型列表
const handleGetEntityTypes = async () => {
try {
const res = await getEntityTypes()
console.log('获取实体类型列表');
if (res.code === 200 && res.data) {
entityTypeList.value = res.data.map(item => {
return {
name: item.name,
id: item.code
}
})
}
} catch (error) {
}
}
// 是否50%规则
const isHalfRule = ref(false)
......@@ -729,14 +804,15 @@ const fetchTableData = async () => {
page: currentPage.value,
size: pageSize.value,
// keyword: '',
type: 2, // type 1= 法案 2= 政令 3 =智库 4=智库报告 5=实体清单【制裁记录】 6= 人物 7= 机构 8=新闻 9= 社媒
domains: selectedArea.value === '全部领域' ? null : [selectedArea.value],
type: 10, // 实体清单
domains: selectedArea.value === '全部领域' ? null : [selectedArea.value], // 科技领域
proposedDateStart: customTime.value[0] ? customTime.value[0] : null,
proposedDateEnd: customTime.value[1] ? customTime.value[1] : null,
organizationName: selectedCountry.value === '全部国家' ? null : selectedCountry.value,
decreeType: selectedEntityType.value === '全部实体类型' ? null : selectedEntityType.value,
isHalfRule: isHalfRule.value ? 'Y' : null,
isTechRelated: isCnEntityOnly.value ? 'Y' : null,
countryId: selectedCountry.value === '全部国家' ? null : selectedCountry.value, // 国家地区
provinceName: selectedProvince.value === '全部省份' ? null : selectedProvince.value, // 实体省份
entityTypeCode: selectedEntityType.value === '全部实体类型' ? null : selectedEntityType.value, // 实体类别
ratio: isHalfRule.value ? 'Y' : null, // 50%规则
isInvolveCn: isCnEntityOnly.value ? 'Y' : null, // 是否只看中国实体
sort: isSort.value ? 0 : 1 // 0 先按分数降序 后按时间降序 1 先按分数降序,再按时间升序
}
try {
......@@ -761,7 +837,15 @@ const fetchTableData = async () => {
name: key,
value: Number(value)
}))
staticsDemensionList.value[2].data = Object.entries(res.data.aggregationsorganizationName).map(([key, value]) => ({
staticsDemensionList.value[2].data = Object.entries(res.data.aggregationSentityTypeCode).map(([key, value]) => ({
name: key,
value: Number(value)
}))
staticsDemensionList.value[3].data = Object.entries(res.data.aggregationCountryId).map(([key, value]) => ({
name: key,
value: Number(value)
}))
staticsDemensionList.value[4].data = Object.entries(res.data.aggregationProvinceName).map(([key, value]) => ({
name: key,
value: Number(value)
}))
......@@ -801,16 +885,16 @@ const fetchAllData = async () => {
const params = {
page: 1,
size: 9999,
// keyword: '',
type: 2, // type 1= 法案 2= 政令 3 =智库 4=智库报告 5=实体清单【制裁记录】 6= 人物 7= 机构 8=新闻 9= 社媒
domains: selectedArea.value === '全部领域' ? null : [selectedArea.value],
proposedDateStart: customTime.value[0],
proposedDateEnd: customTime.value[1],
organizationName: selectedCountry.value === '全部国家' ? null : selectedCountry.value,
decreeType: selectedEntityType.value === '全部实体类型' ? null : selectedEntityType.value,
isHalfRule: isHalfRule.value ? 'Y' : null,
isTechRelated: isCnEntityOnly.value ? 'Y' : null,
sort: isSort.value ? 0 : 1
type: 10, // 实体清单
domains: selectedArea.value === '全部领域' ? null : [selectedArea.value], // 科技领域
proposedDateStart: customTime.value[0] ? customTime.value[0] : null,
proposedDateEnd: customTime.value[1] ? customTime.value[1] : null,
countryId: selectedCountry.value === '全部国家' ? null : selectedCountry.value, // 国家地区
provinceName: selectedProvince.value === '全部省份' ? null : selectedProvince.value, // 实体省份
entityTypeCode: selectedEntityType.value === '全部实体类型' ? null : selectedEntityType.value, // 实体类别
ratio: isHalfRule.value ? 'Y' : null, // 50%规则
isInvolveCn: isCnEntityOnly.value ? 'Y' : null, // 是否只看中国实体
sort: isSort.value ? 0 : 1 // 0 先按分数降序 后按时间降序 1 先按分数降序,再按时间升序
}
try {
const res = await search(params)
......@@ -1045,9 +1129,10 @@ const handleExport = () => {
};
onMounted(async () => {
handleGetDeparmentList()
handleGetProvinceList() // 获取省份列表
handleGetCountryList() // 获取国家列表
handleGetEntityTypes() // 获取实体类型列表
initParam()
// 初始化
await fetchTableData()
......@@ -1305,7 +1390,7 @@ onMounted(async () => {
display: flex;
flex-wrap: wrap;
gap: 8px;
width: 340px;
width: 490px;
}
}
......
<template>
<div class="countrybill-wrapper">
<div class="header-box">我是实体清单事件</div>
<div class="main-box">
<div class="header-box">
<div class="header-top">
<SelectBox :placeholder-name="areaPlaceHolder" select-title="科技领域" :select-list="areaList"
:select-name="selectedArea" @update:select-text="handleSelectArea" />
<SelectBox :placeholder-name="DatePlaceHolder" select-title="制裁时间" :select-list="dateList"
:select-name="selectedDate" :custom-time="customTime" @update:select-text="handleSelectDate"
@update:custom-time="handleCustomDate" />
<div class="check-box">
<div class="check-box-left text-tip-1">
{{ '是否涉华:' }}
</div>
<div class="check-box-right">
<el-checkbox v-model="isInvolveCnOnly" class="involve-checkbox">
{{ '只看涉华' }}
</el-checkbox>
</div>
</div>
</div>
<div class="header-footer">
<div class="header-footer-left">
<ActiveTag v-for="tag, index in activeTagList" :key="index" :tagName="tag.name"
@close="handleCloseCurTag(tag, index)" />
</div>
<div class="header-footer-right">
<HeaderBtnBox :isShowAll="isFolderAll" :isShowAllBtn="false" @show-all="handleSwitchFolderAll" @clear="handleClear"
@confirm="handleConfirm" />
</div>
</div>
</div>
<div class="chart-main-box" v-if="isShowChart">
<div class="info-box">
<div class="switch-box" @click="handleSwitchChartData">
<img v-if="!isShowChart" src="@/views/dataLibrary/assets/icons/chart-active.svg" alt="">
<img v-else src="@/views/dataLibrary/assets/icons/data-active.svg" alt="">
<img src="@/views/dataLibrary/assets/icons/chart-active.svg" alt="">
</div>
<div class="num-box text-title-3-bold">
{{ `共 ${totalNum} 条数据` }}
</div>
</div>
<div class="content-box">
<div class="content-header">
<ChartHeader :list="staticsDemensionList" @clickItem="handleClickDemensionItem">
<template #chart-header-right>
<el-select v-model="selectedTime" placeholder="选择时间" style="width: 150px" v-show="curDemension === '制裁时间'"
@change="handleChangeTime">
<el-option v-for="item in timeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
</ChartHeader>
</div>
<div class="content-main">
<ChartContainer :chartTitle="curChartTitle" :chartTypeList="curChartTypeList"
@clickChartItem="handleSwitchActiveChart" @download="handleDownloadCurChartData">
<template #chart-box>
<LineChart v-if="activeChart === '折线图'" :lineChartData="curChartData" />
<BarChart v-if="activeChart === '柱状图'" :barChartData="curChartData" />
<PieChart v-if="activeChart === '饼状图'" :pieChartData="curChartData" />
<RaderChart v-if="activeChart === '雷达图'" :radarChartData="curChartData" />
</template>
</ChartContainer>
</div>
</div>
</div>
<div class="data-main-box" v-else>
<div class="data-main-box-header">
<div class="switch-box" @click="handleSwitchChartData">
<img src="@/views/dataLibrary/assets/icons/data-active.svg" alt="">
</div>
<div class="num-box text-title-3-bold">
{{ `共 ${totalNum} 条数据` }}
</div>
</div>
<div class="content-box"></div>
<div class="data-main-box-main">
<div class="data-main-box-main-header">
<div class="header-left">
<div class="header-left-item1">
<el-checkbox v-model="isSelectedAll" label="全选" @change="handleSelectAllChange" size="large" />
</div>
<div class="header-left-item2 text-tip-1">{{ `已选择${selectedCount}项` }}</div>
<div class="header-left-item2 text-tip-1 cancel" @click="handleClearAll" v-show="selectedCount">{{ '取消' }}
<div class="header-left-item3 text-tip-1" v-if="isShowAllDataMaxLengthTip">{{ `(当前最大选择不能超过1万条!)` }}</div>
</div>
</div>
<div class="header-right">
<div class="header-right-item item1" @click="handleExport">
<div class="icon">
<img src="../../assets/icons/download.svg" alt="">
</div>
<div class="text text-tip-1">{{ '导出' }}</div>
</div>
<div class="header-right-item2 item2">
<el-select v-model="curOperation" placeholder="批量操作" style="width: 120px">
<el-option v-for="item in operationList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</div>
<div class="header-right-item3 item3">
<el-select v-model="isSort" placeholder="制裁时间" style="width: 166px" @change="handlePxChange">
<template #prefix>
<div style="display: flex; align-items: center; height: 100%">
<img src="../../assets/icons/desc-icon.svg" style="width: 14px; height: 14px" />
</div>
</template>
<el-option v-for="item in releaseTimeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</div>
</div>
<div class="data-main-box-main-content" v-loading="loading" element-loading-text="数据加载中,请稍候...">
<el-table ref="tableRef" :data="tableData" row-key="id" @selection-change="handleSelectionChange"
@select="handleSelect" @select-all="handleSelectAll" style="width: 100%" :row-style="{ height: '52px' }">
<el-table-column type="selection" width="40" />
<el-table-column label="事件名称">
<template #default="scope">
<span class="title-item text-compact-bold" @click="handleClickToDetail(scope.row)">{{
scope.row.originalTitle
}}</span>
</template>
</el-table-column>
<el-table-column label="制裁时间" width="240" class-name="date-column">
<template #default="scope">{{ scope.row.date }}</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="data-main-box-footer">
<el-pagination background layout="prev, pager, next" :total="totalNum" v-model:current-page="currentPage"
:page-size="pageSize" @current-change="handleCurrentChange" />
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ref, computed, watch, onMounted, nextTick } from 'vue'
import ChartContainer from '../../components/ChartContainer/index.vue'
import ChartHeader from '../../components/ChartHeader/index.vue'
import ActiveTag from '../../components/ActiveTag/index.vue'
import HeaderBtnBox from '../../components/HeaderBtnBox/index.vue'
import LineChart from '../../components/LineChart/index.vue'
import PieChart from '../../components/PieChart/index.vue'
import BarChart from '../../components/BarChart/index.vue'
import RaderChart from '../../components/RadarChart/idnex.vue'
import SelectBox from '../../components/SelectBox/index.vue'
import { useRoute } from "vue-router";
import router from '@/router'
// 图表/数据
const isShowChart = ref(true)
import { search } from '@/api/comprehensiveSearch'
import { ElMessage } from 'element-plus'
import getDateRange from '@/utils/getDateRange'
const route = useRoute();
// 图表/数据
const isShowChart = ref(false)
// 点击切换数据/图表
const handleSwitchChartData = () => {
isShowChart.value = !isShowChart.value
if (isShowChart.value) {
const curDemensionItem = staticsDemensionList.value.filter(item => {
return item.name === curDemension.value
})[0]
// setTimeout(() => {
activeChart.value = curDemensionItem.chartTypeList[0]
if (curDemension.value === '制裁时间') {
if (selectedTime.value === '按月度统计') {
curChartData.value = curDemensionItem.data
} else if (selectedTime.value === '按季度统计') {
curChartData.value = curDemensionItem.quatarData
} else {
curChartData.value = curDemensionItem.yearData
}
} else {
curChartData.value = curDemensionItem.data
}
// })
}
}
// 总计数据
const totalNum = ref(12)
const totalNum = ref(0)
// 统计维度列表
const staticsDemensionList = ref([
{
name: '制裁时间',
active: true,
chartTypeList: ['折线图', '柱状图'],
chartTitle: '实体清单制裁时间变化趋势',
data: {
dataX: [],
dataY: []
},
quatarData: {
dataX: [],
dataY: []
},
yearData: {
dataX: [],
dataY: []
}
}
])
// 当前维度下的图表列表
const curChartTypeList = computed(() => {
let arr = staticsDemensionList.value.filter(item => item.active)
return arr[0].chartTypeList
})
// 当前图表标题
const curChartTitle = computed(() => {
let arr = staticsDemensionList.value.filter(item => item.active)
return arr[0].chartTitle
})
// 当前维度
const curDemension = ref('制裁时间')
// 点击维度item
const handleClickDemensionItem = (val) => {
activeChart.value = ''
staticsDemensionList.value.forEach(item => {
item.active = false
})
val.active = true
curDemension.value = val.name
setTimeout(() => {
activeChart.value = val.chartTypeList[0]
if (curDemension.value === '制裁时间' && selectedTime.value === '按年度统计') {
curChartData.value = val.yearData
} else if (curDemension.value === '制裁时间' && selectedTime.value === '按季度统计') {
curChartData.value = val.quatarData
} else {
curChartData.value = val.data
}
})
}
// 时间图表 当前选择时间
const selectedTime = ref('按年度统计')
// 时间图表-时间列表
const timeList = ref([
{
label: '按年度统计',
value: '按年度统计'
},
{
label: '按季度统计',
value: '按季度统计'
},
{
label: '按月度统计',
value: '按月度统计'
},
])
const handleChangeTime = value => {
let curChart = activeChart.value
activeChart.value = ''
if (value === '按月度统计') {
setTimeout(() => {
activeChart.value = curChart
curChartData.value = staticsDemensionList.value[0].data
})
} else if (value === '按季度统计') {
setTimeout(() => {
activeChart.value = curChart
curChartData.value = staticsDemensionList.value[0].quatarData
})
} else {
setTimeout(() => {
activeChart.value = curChart
curChartData.value = staticsDemensionList.value[0].yearData
})
}
}
// 激活的标签列表
const activeTagList = computed(() => {
const arr = []
if (selectedArea.value && selectedArea.value !== '全部领域') {
arr.push(
{
tag: '科技领域',
name: selectedArea.value
}
)
}
if (selectedDate.value === '自定义') {
arr.push(
{
tag: '制裁时间',
name: customTime.value.join('至')
}
)
}
if (isInvolveCnOnly.value) {
const involveStr = '涉华'
arr.push(
{
tag: '涉华',
name: involveStr
}
)
}
return arr
})
// 关闭当前标签
const handleCloseCurTag = (tag, index) => {
switch (tag.tag) {
case '科技领域':
selectedArea.value = '全部领域'
break
case '制裁时间':
selectedDate.value = ''
customTime.value = []
break
case '涉华':
isInvolveCnOnly.value = false
break
}
}
const activeChart = ref('') // 当前激活的图表
// 切换当前图表
const handleSwitchActiveChart = val => {
activeChart.value = val.name
}
// 雷达图数据
const radarChartData = ref({
title: [
{
name: '航空航天',
max: 10
},
{
name: '先进制造',
max: 10
},
{
name: '量子科技',
max: 10
},
{
name: '人工智能',
max: 10
},
{
name: '新材料',
max: 10
},
{
name: '集成电路',
max: 10
},
],
data: [
{
name: "337调查",
value: [10, 5, 2, 8, 5, 7
]
},
{
name: "232调查",
value: [2, 5, 3, 8, 10, 2]
},
{
name: "301调查",
value: [5, 8, 2, 9, 1, 5]
}
]
}
)
// 数据- 是否全选
const isSelectedAll = ref(false)
// 批量操作-当前操作
const curOperation = ref('')
const operationList = ref([
{
name: 'aaa',
id: 'aaa'
},
{
name: 'bbb',
id: 'bbb'
},
{
name: 'ccc',
id: 'ccc'
},
])
// 科技领域
const areaPlaceHolder = ref('请选择领域')
const selectedArea = ref('全部领域')
const areaList = ref([
{
name: '全部领域',
id: '全部领域'
},
{
name: '人工智能',
id: '人工智能'
},
{
name: '生物科技',
id: '生物科技'
},
{
name: '新一代通信网络',
id: '新一代通信网络'
},
{
name: '量子科技',
id: '量子科技'
},
{
name: '新能源',
id: '新能源'
},
{
name: '集成电路',
id: '集成电路'
},
{
name: '海洋',
id: '海洋'
},
{
name: '先进制造',
id: '先进制造'
},
{
name: '新材料',
id: '新材料'
},
{
name: '航空航天',
id: '航空航天'
},
{
name: '太空',
id: '太空'
},
{
name: '深海',
id: '深海'
},
{
name: '极地',
id: '极地'
},
{
name: '核',
id: '核'
},
{
name: '其他',
id: '其他'
},
])
const handleSelectArea = (value) => {
selectedArea.value = value
}
// 制裁时间
const DatePlaceHolder = ref('请选择时间')
const selectedDate = ref('')
const dateList = ref([
{
name: '自定义',
id: '自定义'
},
{
name: '近一年',
id: '近一年'
},
{
name: '近半年',
id: '近半年'
},
{
name: '近三月',
id: '近三月'
},
{
name: '近一月',
id: '近一月'
}
])
const customTime = ref([]) // 自定义时间
const handleCustomDate = value => {
customTime.value = value
}
const handleSelectDate = (value) => {
selectedDate.value = value
if (selectedDate.value !== '自定义') {
customTime.value = getDateRange(selectedDate.value)
}
}
// 是否只看涉华
const isInvolveCnOnly = ref(false)
// 清空条件
const handleClear = () => {
selectedArea.value = '全部领域'
selectedDate.value = ''
customTime.value = []
isInvolveCnOnly.value = false
ElMessage.success('已清空条件!')
}
// 确定
const handleConfirm = () => {
currentPage.value = 1
fetchTableData()
}
// 展开全部 / 收起
const isFolderAll = ref(false)
const handleSwitchFolderAll = () => {
isFolderAll.value = !isFolderAll.value
}
const tableRef = ref(null)
// 表格数据
const tableData = ref([
])
const releaseTimeList = ref([
{
label: "按发布时间倒序",
value: true
},
{
label: "按发布时间升序",
value: false
}
]);
const isSort = ref(true); // true 倒序 false 升序
const handlePxChange = val => {
fetchTableData()
};
const currentPage = ref(1);
const pageSize = ref(10)
// 存储选中的数据(跨页)[citation:3][citation:8]
const selectedMap = ref(new Map()) // 使用 Map 存储,key 为唯一 id
// 计算已选中的条数
const selectedCount = computed(() => selectedMap.value.size)
// 获取当前页表格数据(示例)
const fetchTableData = async () => {
// isSelectedAll.value = false
// selectedMap.value.clear()
loading.value = true
// 调用接口获取数据...
const params = {
page: currentPage.value,
size: pageSize.value,
// keyword: '',
type: 12, // 实体清单事件
domains: selectedArea.value === '全部领域' ? null : [selectedArea.value], // 科技领域
proposedDateStart: customTime.value[0] ? customTime.value[0] : null,
proposedDateEnd: customTime.value[1] ? customTime.value[1] : null,
isInvolveCn: isInvolveCnOnly.value ? 'Y' : null, // 是否只看中国实体
sort: isSort.value ? 0 : 1 // 0 先按分数降序 后按时间降序 1 先按分数降序,再按时间升序
}
try {
const res = await search(params)
console.log('搜索结果', res);
if (res.code === 200 && res.data) {
tableData.value = res.data.records
totalNum.value = res.data.total
staticsDemensionList.value[0].data = {
dataX: Object.keys(res.data.aggregationsDate),
dataY: Object.values(res.data.aggregationsDate).map(value => Number(value))
}
staticsDemensionList.value[0].quatarData = {
dataX: Object.keys(res.data.aggregationsQuarter),
dataY: Object.values(res.data.aggregationsQuarter).map(value => Number(value))
}
staticsDemensionList.value[0].yearData = {
dataX: Object.keys(res.data.aggregationsYear),
dataY: Object.values(res.data.aggregationsYear).map(value => Number(value))
}
}
const curDemensionItem = staticsDemensionList.value.filter(item => {
return item.name === curDemension.value
})[0]
activeChart.value = ''
setTimeout(() => {
activeChart.value = curDemensionItem.chartTypeList[0]
curChartData.value = curDemensionItem.data
})
loading.value = false
} catch (error) {
loading.value = false
}
// tableData.value = res.data
// total.value = res.total
// 数据加载后,回显已选中的行
nextTick(() => {
tableData.value.forEach(row => {
if (selectedMap.value.has(row.id)) {
tableRef.value?.toggleRowSelection(row, true)
}
})
})
}
const allData = ref([])
// 获取筛选条件下全部表格数据
const fetchAllData = async () => {
const params = {
page: 1,
size: 9999,
type: 12, // 实体清单事件
domains: selectedArea.value === '全部领域' ? null : [selectedArea.value], // 科技领域
proposedDateStart: customTime.value[0] ? customTime.value[0] : null,
proposedDateEnd: customTime.value[1] ? customTime.value[1] : null,
isInvolveCn: isInvolveCnOnly.value ? 'Y' : null, // 是否只看中国实体
sort: isSort.value ? 0 : 1 // 0 先按分数降序 后按时间降序 1 先按分数降序,再按时间升序
}
try {
const res = await search(params)
console.log('搜索结果', res);
if (res.code === 200 && res.data) {
allData.value = res.data.records
}
} catch (error) {
ElMessage.error('加载全部数据出错!')
}
}
// 单选事件
const handleSelect = (selection, row) => {
if (selection.some(item => item.id === row.id)) {
// 选中:添加到 Map
selectedMap.value.set(row.id, row)
} else {
// 取消选中:从 Map 移除
selectedMap.value.delete(row.id)
}
}
// 表格自带 当前页 全选/全不选事件
const handleSelectAll = (selection) => {
if (selection.length > 0) {
// 全选:将当前页所有数据添加到 Map
tableData.value.forEach(row => {
if (!selectedMap.value.has(row.id)) {
selectedMap.value.set(row.id, row)
}
})
} else {
// 全不选:从 Map 中移除当前页的所有数据
tableData.value.forEach(row => {
selectedMap.value.delete(row.id)
})
}
}
// 处理选择变化(用于统计)
const handleSelectionChange = (val) => {
// 这里可以做一些额外的处理,但主要统计使用 selectedMap
console.log('当前页选中数量:', val.length)
}
// 全选当前页按钮
const handleSelectAllPage = () => {
if (tableData.value.length === 0) return
// 检查当前页是否已全选
const currentPageSelected = tableData.value.every(row =>
selectedMap.value.has(row.id)
)
if (currentPageSelected) {
// 已全选,则不动当前页的全选
tableData.value.forEach(row => {
tableRef.value.toggleRowSelection(row, false)
// selectedMap.value.delete(row.id)
})
} else {
// 未全选,则全选当前页
tableData.value.forEach(row => {
tableRef.value.toggleRowSelection(row, true)
if (!selectedMap.value.has(row.id)) {
selectedMap.value.set(row.id, row)
}
})
}
}
// 全选最大1万条提示
const isShowAllDataMaxLengthTip = ref(false)
const loading = ref(false) // 加载数据loading
// 处理 全选(全部数据)
const handleSelectAllChange = async () => {
if (isSelectedAll.value) {
if (totalNum.value > 10000) {
isShowAllDataMaxLengthTip.value = true
}
loading.value = true
await fetchAllData()
handleSelectAllPage()
allData.value.forEach(row => {
if (!selectedMap.value.has(row.id)) {
selectedMap.value.set(row.id, row)
}
})
loading.value = false
} else {
handleClearAll()
}
}
// 清空所有选择
const handleClearAll = () => {
isSelectedAll.value = false
selectedMap.value.clear()
tableRef.value?.clearSelection()
}
// 翻页
const handleCurrentChange = async (val) => {
currentPage.value = val
await fetchTableData()
if (isSelectedAll.value) {
handleSelectAllPage()
}
}
// 监听数据变化,回显选中状态 [citation:4][citation:8]
watch(tableData, () => {
nextTick(() => {
tableData.value.forEach(row => {
if (selectedMap.value.has(row.id)) {
tableRef.value?.toggleRowSelection(row, true)
}
})
})
})
// 当前图表数据
const curChartData = ref(null)
// 下载当前图表数据
const handleDownloadCurChartData = () => {
const jsonStr = JSON.stringify(curChartData.value, null, 2);
const blob = new Blob([jsonStr], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'chartData.json';
link.click();
URL.revokeObjectURL(url);
}
// 跳转到当前页 初始化筛选条件
const initParam = () => {
const hasQuery = Object.keys(route.query).length > 0;
if (hasQuery) {
selectedArea.value = route.query.domains ? route.query.domains : '全部领域'
if (route.query.selectedDate && Array.isArray(JSON.parse(route.query.selectedDate)) && JSON.parse(route.query.selectedDate).length) {
selectedDate.value = '自定义'
customTime.value = JSON.parse(route.query.selectedDate)
}
isInvolveCnOnly.value = route.query.isInvolveCnOnly ? true : false
const query = route.query;
if (Object.keys(query).length > 0) {
sessionStorage.setItem('decreeRouteQuery', JSON.stringify(query));
}
} else {
const savedQuery = JSON.parse(sessionStorage.getItem('decreeRouteQuery') || '{}');
selectedArea.value = savedQuery.domains ? savedQuery.domains : '全部领域'
if (savedQuery.selectedDate && Array.isArray(JSON.parse(savedQuery.selectedDate)) && JSON.parse(savedQuery.selectedDate).length) {
selectedDate.value = '自定义'
customTime.value = JSON.parse(savedQuery.selectedDate)
}
isInvolveCnOnly.value = savedQuery.isInvolveCnOnly ? true : false
}
}
// 跳转政令详情
const handleClickToDetail = (curDecree) => {
console.log('curDecree', curDecree);
window.sessionStorage.setItem("decreeId", curDecree.id);
window.sessionStorage.setItem("curTabName", curDecree.title);
const route = router.resolve({
path: "/decreeLayout",
query: {
id: curDecree.id
}
});
window.open(route.href, "_blank");
};
// 跳转机构详情
const handleOrgClick = item => {
console.log('item', item);
window.sessionStorage.setItem("curTabName", item.organizationName);
const route = router.resolve({
path: "/institution",
query: {
id: item.organizationId
}
});
window.open(route.href, "_blank");
};
// 导出
const handleExport = () => {
if (!selectedCount.value) {
ElMessage.warning('请选择至少一项数据!')
return
}
console.log(selectedMap.value);
const arr = Array.from(selectedMap.value);
const jsonStr = JSON.stringify(arr, null, 2);
const blob = new Blob([jsonStr], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'export.json';
link.click();
URL.revokeObjectURL(url);
};
onMounted(async () => {
initParam()
// 初始化
await fetchTableData()
})
</script>
......@@ -35,6 +882,8 @@ const totalNum = ref(12)
.countrybill-wrapper {
width: 1600px;
height: 968px;
overflow: hidden;
overflow-y: auto;
.headere-box {
width: 1568px;
......@@ -44,19 +893,53 @@ const totalNum = ref(12)
border: 1px solid var(--bg-black-5);
margin: 16px auto;
}
.header-box {
width: 1568px;
height: 112px;
min-height: 112px;
border-radius: 10px;
background: rgb(255, 255, 255);
border: 1px solid var(--bg-black-5);
margin: 16px auto;
box-sizing: border-box;
padding: 16px 24px;
.header-top {
min-height: 28px;
display: flex;
flex-wrap: wrap;
gap: 12px 42px;
// transition: all ease 1s;
.check-box {
display: flex;
width: 348px;
height: 28px;
align-items: center;
gap: 8px;
.check-box-left {
width: 100px;
color: var(--text-primary-65-color);
}
}
}
.main-box {
.header-footer {
margin-top: 16px;
display: flex;
justify-content: space-between;
.header-footer-left {
display: flex;
justify-content: space-between;
gap: 8px;
}
}
}
.chart-main-box {
.info-box {
margin: 0 auto;
width: 1568px;
......@@ -90,7 +973,199 @@ const totalNum = ref(12)
border-radius: 10px;
background: rgba(255, 255, 255);
border: 1px solid var(--bg-black-5);
.content-header {
margin: 16px 24px;
width: 1520px;
height: 28px;
}
.content-main {
width: 1520px;
margin: 0 auto;
}
}
}
.data-main-box {
width: 1568px;
min-height: 810px;
border-radius: 10px;
background: var(--bg-white-100);
margin: 0 auto;
margin-bottom: 20px;
overflow: hidden;
.data-main-box-header {
margin: 16px auto;
width: 1520px;
height: 30px;
display: flex;
justify-content: space-between;
.switch-box {
width: 160px;
border-radius: 20px;
border: 1px solid var(--color-primary-100);
height: 30px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.num-box {
box-sizing: border-box;
padding: 2px 0;
color: var(--color-red-100);
}
}
.data-main-box-main {
width: 1520px;
// height: 633px;
min-height: 680px;
border-radius: 10px;
border: 1px solid var(--bg-black-5);
margin: 0 auto;
.data-main-box-main-header {
height: 48px;
background: var(--bg-black-2);
display: flex;
justify-content: space-between;
.header-left {
margin-left: 16px;
height: 48px;
display: flex;
gap: 16px;
align-items: center;
.header-left-item2 {
color: var(--color-primary-100);
display: flex;
gap: 8px;
}
.header-left-item3 {
color: var(--color-orange-100);
}
.cancel {
cursor: pointer;
}
}
.header-right {
margin-right: 16px;
display: flex;
gap: 8px;
align-items: center;
.header-right-item {
height: 30px;
padding: 5px 16px;
border: 1px solid var(--bg-black-10);
border-radius: 4px;
background: var(--bg-white-100);
cursor: pointer;
}
.item1 {
display: flex;
gap: 2px;
justify-content: center;
align-items: center;
&:hover {
background: var(--color-primary-2);
}
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.text {
color: var(--text-primary-65-color);
}
}
.item2 {}
.item3 {}
}
}
.data-main-box-main-content {}
}
.data-main-box-footer {
margin: 16px auto 0;
height: 40px;
width: 1520px;
display: flex;
align-items: center;
justify-content: flex-end;
}
}
}
.date-column {
background-color: #ecf5ff;
.tag-box {
display: flex;
flex-wrap: wrap;
gap: 8px;
width: 490px;
}
}
.date-column .cell {
color: #409eff !important;
font-weight: 500;
}
.title-item {
color: var(--text-primary-80-color);
cursor: pointer;
&:hover {
color: var(--color-primary-100);
text-decoration: underline;
}
}
.person-item {
color: var(--color-primary-100);
cursor: pointer;
&:hover {
font-weight: bold;
text-decoration: underline;
}
}
:deep(.el-table__header-wrapper) {
// background-color: #f5f7fa;
height: 48px;
}
:deep(.el-table__header th) {
// background-color: #f5f7fa;
color: var(--text-primary-50-color);
font-weight: bold;
}
</style>
\ No newline at end of file
......@@ -92,6 +92,7 @@ import { ElMessage } from "element-plus";
const router = useRouter();
const route = useRoute();
const tagsViewStore = useTagsViewStore();
tagsViewStore.loadVisitedViewFromLocalStorage()
// 在路由全局守卫中处理
router.beforeEach((to, from, next) => {
......@@ -348,8 +349,7 @@ const handleSiderSecondItem = item => {
};
const openedTabList = computed(() => {
const arr = tagsViewStore.visitedViews;
return arr;
return tagsViewStore.visitedViews;
});
const handleClickTab = tab => {
......@@ -586,6 +586,7 @@ onBeforeUnmount(() => {
if (timer.value) {
clearTimeout(timer.value);
}
localStorage.setItem('visitedViews', [])
});
</script>
......
......@@ -189,7 +189,7 @@ const handleSwitchChartData = () => {
const curDemensionItem = staticsDemensionList.value.filter(item => {
return item.name === curDemension.value;
})[0];
setTimeout(() => {
// setTimeout(() => {
activeChart.value = curDemensionItem.chartTypeList[0];
if (curDemension.value === "发布时间") {
if (selectedTime.value === "按月度统计") {
......@@ -202,7 +202,7 @@ const handleSwitchChartData = () => {
} else {
curChartData.value = curDemensionItem.data;
}
});
// });
}
};
......@@ -281,7 +281,7 @@ const handleClickDemensionItem = val => {
};
// 时间图表 当前选择时间
const selectedTime = ref("按统计");
const selectedTime = ref("按年度统计");
// 时间图表-时间列表
const timeList = ref([
{
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论