提交 b8e3a1e9 authored 作者: 付康's avatar 付康

合并分支 'fk-dev' 到 'pre'

Fk dev 查看合并请求 !381
流水线 #591 已通过 于阶段
in 5 分 38 秒
<template>
<div class="time-filter">
<el-checkbox-group class="checkbox-group" v-model="selectedValues" @change="handleChange">
<el-checkbox class="filter-checkbox" v-for="option in options" :key="option.value" :label="option.value"
:disabled="option.disabled">
{{ option.label }}
</el-checkbox>
</el-checkbox-group>
<!-- 自定义日期选择器,仅在选中“自定义”时显示 -->
<div v-if="showCustomPicker" class="custom-date-picker">
<el-date-picker v-model="customDateRange" type="daterange" range-separator="至" start-placeholder="开始日期"
end-placeholder="结束日期" format="YYYY-MM-DD" value-format="YYYY-MM-DD" @change="handleCustomDateChange"
style="width: 100%;" />
</div>
</div>
</template>
<script setup>
import { ref, computed, watch, onMounted } from 'vue'
// Props 定义
const props = defineProps({
// 外部控制选中值(支持 v-model)
modelValue: {
type: Array,
default: () => []
},
// 外部控制自定义日期范围
customDate: {
type: Array,
default: () => []
}
})
// Emits 定义
const emit = defineEmits(['update:modelValue', 'update:customDate', 'change'])
// 响应式数据
const selectedValues = ref([]) // 当前选中的选项值数组
const customDateRange = ref([]) // 自定义日期范围 [start, end]
const options = ref([]) // 动态生成的选项列表
// 是否显示自定义日期选择器
const showCustomPicker = computed(() => {
return selectedValues.value.includes('custom')
})
// 生成选项列表:全部时间 + 最近5个年份 + 自定义
const initOptions = () => {
const currentYear = new Date().getFullYear()
// 生成最近5个年份(包含当前年份)
const recentYears = []
for (let i = 0; i < 5; i++) {
recentYears.push(currentYear - i)
}
// 年份选项(倒序展示,从大到小)
const yearOptions = recentYears.map(year => ({
label: `${year}年`,
value: String(year)
}))
options.value = [
{ label: '全部时间', value: 'all' },
...yearOptions,
{ label: '自定义', value: 'custom' }
]
}
// 向上层派发事件
const emitChange = () => {
const eventData = {
type: 'time',
value: selectedValues.value[0], // 单选,只有一个值
customRange: selectedValues.value.includes('custom') ? customDateRange.value : []
}
emit('update:modelValue', selectedValues.value)
emit('update:customDate', customDateRange.value)
emit('change', eventData)
}
// 选项变化处理(单选逻辑)
const handleChange = (selected) => {
// 实现单选逻辑
let lastSelected = null
if (selected.length > selectedValues.value.length) {
// 新增了选项:找到新增的那个
const added = selected.find(v => !selectedValues.value.includes(v))
lastSelected = added
} else if (selected.length < selectedValues.value.length) {
// 移除了选项:选中“全部时间”
lastSelected = 'all'
} else if (selected.length === 1 && selectedValues.value.length === 1 && selected[0] !== selectedValues.value[0]) {
// 直接替换场景
lastSelected = selected[0]
} else if (selected.length > 1) {
// 多选时,只保留最后一个选中的
lastSelected = selected[selected.length - 1]
}
if (lastSelected) {
selectedValues.value = [lastSelected]
} else if (selected.length === 0) {
// 全部取消,默认给“全部时间”
selectedValues.value = ['all']
} else {
// 确保只有一个
selectedValues.value = selected.slice(0, 1)
}
// 如果选中的不是“自定义”,清空自定义日期范围
if (!selectedValues.value.includes('custom')) {
customDateRange.value = []
}
emitChange()
}
// 自定义日期范围变化处理
const handleCustomDateChange = (val) => {
if (val && val.length === 2) {
customDateRange.value = [...val]
} else {
customDateRange.value = []
}
emitChange()
}
// 重置方法(供外部调用)
const reset = () => {
selectedValues.value = ['all']
customDateRange.value = []
emitChange()
}
// 获取当前筛选条件描述(供外部调用)
const getFilterDescription = () => {
const selectedVal = selectedValues.value[0]
if (selectedVal === 'all') {
return '全部时间'
} else if (selectedVal === 'custom') {
if (customDateRange.value && customDateRange.value.length === 2) {
return `${customDateRange.value[0]}${customDateRange.value[1]}`
} else {
return '自定义(未选择日期)'
}
} else {
return `${selectedVal}年`
}
}
// 暴露方法给父组件
defineExpose({
reset,
getFilterDescription
})
// 监听外部传入的 modelValue 变化
watch(() => props.modelValue, (newVal) => {
if (JSON.stringify(newVal) !== JSON.stringify(selectedValues.value)) {
selectedValues.value = [...newVal]
}
}, { immediate: true })
// 监听外部传入的自定义日期变化
watch(() => props.customDate, (newVal) => {
if (JSON.stringify(newVal) !== JSON.stringify(customDateRange.value)) {
customDateRange.value = [...newVal]
}
}, { immediate: true })
// 初始化
onMounted(() => {
initOptions()
// 初始化选中值:如果外部没有传入,默认选中“全部时间”
if (!props.modelValue || props.modelValue.length === 0) {
selectedValues.value = ['all']
} else {
selectedValues.value = [...props.modelValue]
}
})
</script>
<style lang="scss" scoped>
.time-filter {
// display: flex;
// flex-direction: column;
// gap: 12px;
width: 100%;
.checkbox-group {
display: flex;
flex-wrap: wrap;
width: 100%;
.filter-checkbox {
width: 50%;
margin-right: 0;
margin-bottom: 4px;
// background: orange;
:deep(.el-checkbox__label) {
color: var(--text-primary-65-color);
font-size: var(--font-size-base);
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
}
}
}
}
.custom-date-picker {
width: 100%;
margin-top: 8px;
}
</style>
\ No newline at end of file
<template>
<el-row class="wrapper layout-grid-line">
<el-col :span="span">
<pre>
{{
`
`
}}
</pre>
<div class="time-box">
<TimePickerBox />
</div>
</el-col>
</el-row>
</template>
<script setup>
import { ref } from 'vue'
import '@/styles/common.scss'
import TimePickerBox from '@/components/base/TimePickerBox/index.vue'
const span = 12
</script>
<style lang="scss" scoped>
.time-box {
width: 300px;
height: 700px;
background: #F2F8FF;
border: 1px solid var(--bg-black-5);
display: flex;
gap: 8px;
}
</style>
\ No newline at end of file
......@@ -9,7 +9,8 @@
<TextStyle />
<div class="text-title-1-show">通用样式/组件</div>
<div style="position: relative; height: 800px;">
<el-tabs tabPosition="left" style="position: relative; height: 700px;" class="tabs-nav-no-wrap left-float-nav-tabs dev-style-tabs">
<el-tabs tabPosition="left" style="position: relative; height: 700px;"
class="tabs-nav-no-wrap left-float-nav-tabs dev-style-tabs">
<el-tab-pane label="通用" lazy>
<common-page />
</el-tab-pane>
......@@ -76,6 +77,9 @@
<el-tab-pane label="自定义排序" lazy>
<TimeSortSelectBox />
</el-tab-pane>
<!-- <el-tab-pane label="时间筛选框" lazy>
<TimePickerBox />
</el-tab-pane> -->
</el-tabs>
</div>
</el-space>
......@@ -111,6 +115,7 @@ import RelationCenterChart from './RelationCenterChart/index.vue'
import RelationForceChart from './RelationForceChart/index.vue'
import WorkingBox from './WorkingBox/index.vue'
import TimeSortSelectBox from './TimeSortSelectBox/index.vue'
import TimePickerBox from './TimePickerBox/index.vue'
</script>
<style lang="scss" scoped>
......
差异被折叠。
......@@ -4,69 +4,7 @@ import getQuarterRange from './getQuarterRange';
import * as echarts from 'echarts'
import 'echarts-wordcloud';
import router from '@/router/index'
const LEGEND_ARROW_NAMES = new Set(['__legend_prev__', '__legend_next__'])
const shouldShowLegendPagingArrows = (chart, option) => {
const w = typeof chart?.getWidth === 'function' ? chart.getWidth() : 0
const legendOpt = option?.legend
const legend = Array.isArray(legendOpt) ? legendOpt[0] : legendOpt
if (!legend || legend.type !== 'scroll') return false
const names = Array.isArray(legend.data) ? legend.data : []
if (!names.length) return false
const resolveSize = (val, base) => {
if (val == null) return 0
if (typeof val === 'number' && Number.isFinite(val)) return val
const s = String(val).trim()
if (!s) return 0
if (s.endsWith('%')) {
const n = parseFloat(s.slice(0, -1))
return Number.isFinite(n) ? (base * n) / 100 : 0
}
const n = Number(s)
return Number.isFinite(n) ? n : 0
}
const available = resolveSize(legend.width, w) || Math.floor(w * 0.82)
if (!available || available <= 0) return true
const fontSize = Number(legend?.textStyle?.fontSize || 14)
const fontFamily = legend?.textStyle?.fontFamily || 'Source Han Sans CN'
const fontWeight = legend?.textStyle?.fontWeight || 400
const iconW = Number(legend?.itemWidth || 12)
const gap = 10
const paddingPerItem = iconW + gap + 10
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
if (!ctx) return true
ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`
const total = names.reduce((sum, n) => {
const text = String(n ?? '')
const textW = ctx.measureText(text).width || 0
return sum + textW + paddingPerItem
}, 0)
return total > available
}
const applyLegendPagingArrowVisibility = (chart, option) => {
const shouldShow = shouldShowLegendPagingArrows(chart, option)
const graphic = option?.graphic
if (!Array.isArray(graphic) || graphic.length === 0) return
const nextGraphic = graphic.map((g) => {
if (!g || !LEGEND_ARROW_NAMES.has(g.name)) return g
return {
...g,
invisible: !shouldShow,
silent: !shouldShow
}
})
chart.setOption({ graphic: nextGraphic }, false, true)
}
import { goToDataCountryBill } from './goToPage';
const setChart = (option, chartId, allowClick, selectParam) => {
let chartDom = document.getElementById(chartId);
if (!chartDom) {
......@@ -114,20 +52,22 @@ const setChart = (option, chartId, allowClick, selectParam) => {
// console.log('当前点击', selectParam, params.seriesName, params.name);
selectParam.selectedStatus = params.seriesName
selectParam.selectedDate = JSON.stringify(getMonthRange(params.name))
const route = router.resolve({
path: "/dataLibrary/countryBill",
query: selectParam
});
window.open(route.href, "_blank");
return
// const route = router.resolve({
// path: "/dataLibrary/countryBill",
// query: selectParam
// });
// window.open(route.href, "_blank");
// goToDataCountryBill(selectParam)
// return
} else if (selectParam.key === 2) {
selectParam.domains = params.name
const route = router.resolve({
path: "/dataLibrary/countryBill",
query: selectParam
});
window.open(route.href, "_blank");
return
// const route = router.resolve({
// path: "/dataLibrary/countryBill",
// query: selectParam
// });
// window.open(route.href, "_blank");
// goToDataCountryBill(selectParam)
// return
} else if (selectParam.key === 3) {
if (params.name === '众议院' || params.name === '参议院') {
selectParam.selectedCongress = params.name
......@@ -142,20 +82,26 @@ const setChart = (option, chartId, allowClick, selectParam) => {
selectParam.selectedDate = JSON.stringify([selectParam.selectedDate + '-01-01', selectParam.selectedDate + '-12-31'])
}
}
const route = router.resolve({
path: "/dataLibrary/countryBill",
query: selectParam
});
window.open(route.href, "_blank");
return
// const route = router.resolve({
// path: "/dataLibrary/countryBill",
// query: selectParam
// });
// window.open(route.href, "_blank");
// goToDataCountryBill(selectParam)
// return
} else {
selectParam.selectedStatus = params.name
const route = router.resolve({
path: "/dataLibrary/countryBill",
query: selectParam
});
window.open(route.href, "_blank");
// const route = router.resolve({
// path: "/dataLibrary/countryBill",
// query: selectParam
// });
// window.open(route.href, "_blank");
// goToDataCountryBill(selectParam)
}
goToDataCountryBill(selectParam)
break
case '政令':
......
......@@ -322,6 +322,7 @@ import iconILetter from "./assets/icons/icon-iLetter.png";
import { ElMessage } from "element-plus";
import { useGotoNewsDetail } from "@/router/modules/news";
import { goToBill } from "@/utils/goToPage";
// 跳转人物主页(MessageBubble 的 person-click 传入整条列表项,需取 personId)
const handleClickToCharacter = async item => {
......@@ -518,11 +519,12 @@ const handleClickToDetail = () => {
};
// 查看详情 传递参数
const handleClickToDetailO = item => {
window.sessionStorage.setItem("billId", item.billId);
window.sessionStorage.setItem("curTabName", item.name || item.signalTitle);
const route = router.resolve("/billLayout?billId=" + item.billId);
window.open(route.href, "_blank");
// window.sessionStorage.setItem("billId", item.billId);
// window.sessionStorage.setItem("curTabName", item.name || item.signalTitle);
// const route = router.resolve("/billLayout?billId=" + item.billId);
// window.open(route.href, "_blank");
// router.push("/billLayout?billId=" + item.billId)
goToBill(item.billId, item.signalTitle)
};
const isRiskOverviewDetailOpen = ref(false);
......
......@@ -173,6 +173,7 @@ import { getPostOrgList, getPostMemberList } from '@/api/bill/billHome'
import { search, getStatusList } from '@/api/comprehensiveSearch'
import { ElMessage } from 'element-plus'
import getDateRange from '@/utils/getDateRange'
import { getDecodedParams } from '@/utils/goToPage'
const route = useRoute();
......@@ -1151,33 +1152,36 @@ const handleDownloadCurChartData = () => {
// 跳转到当前页 初始化筛选条件
const initParam = () => {
const hasQuery = Object.keys(route.query).length > 0;
const routeQuery = getDecodedParams()
console.log('routeQuery',routeQuery);
const hasQuery = Object.keys(routeQuery).length > 0;
if (hasQuery) {
if (route.query.selectedAreaList) {
selectedArea.value = JSON.parse(route.query.selectedAreaList)
if (routeQuery.selectedAreaList) {
selectedArea.value = JSON.parse(routeQuery.selectedAreaList)
} else {
selectedArea.value = route.query.domains ? [route.query.domains] : ['全部领域']
selectedArea.value = routeQuery.domains ? [routeQuery.domains] : ['全部领域']
}
if (route.query.selectedDate && Array.isArray(JSON.parse(route.query.selectedDate)) && JSON.parse(route.query.selectedDate).length) {
if (routeQuery.selectedDate && Array.isArray(JSON.parse(routeQuery.selectedDate)) && JSON.parse(routeQuery.selectedDate).length) {
selectedDate.value = '自定义'
customTime.value = JSON.parse(route.query.selectedDate)
customTime.value = JSON.parse(routeQuery.selectedDate)
}
isInvolveCn.value = route.query.isInvolveCn ? true : false
if (route.query.selectedStatus && route.query.selectedStatus !== '全部阶段') {
isInvolveCn.value = routeQuery.isInvolveCn ? true : false
if (routeQuery.selectedStatus && routeQuery.selectedStatus !== '全部阶段') {
selectedStatus.value = statusList.value.filter(item => {
return item.name === route.query.selectedStatus
return item.name === routeQuery.selectedStatus
})[0].id
} else {
selectedStatus.value = '全部阶段'
}
selectedCongress.value = route.query.selectedCongress ? route.query.selectedCongress : '全部议院'
selectedOrg.value = route.query.selectedOrg ? [route.query.selectedOrg] : ['全部委员会']
selectedmember.value = route.query.selectedmember ? JSON.parse(route.query.selectedmember) : ['全部议员']
selectedCongress.value = routeQuery.selectedCongress ? routeQuery.selectedCongress : '全部议院'
selectedOrg.value = routeQuery.selectedOrg ? [routeQuery.selectedOrg] : ['全部委员会']
selectedmember.value = routeQuery.selectedmember ? JSON.parse(routeQuery.selectedmember) : ['全部议员']
const query = route.query;
const query = routeQuery;
if (Object.keys(query).length > 0) {
sessionStorage.setItem('countryBillRouteQuery', JSON.stringify(query));
}
......
......@@ -64,6 +64,7 @@ import PolicyTracking from "./PolicyTracking/index.vue";
import ThinkInfo from "./thinkInfo/index.vue";
import { getThinkTankSummary } from "@/api/thinkTank/overview";
import { useRouter } from "vue-router";
import { getDecodedParams } from "@/utils/goToPage";
const router = useRouter();
const tabActiveName = ref("智库动态");
......@@ -74,9 +75,13 @@ const switchTab = name => {
const thinkTank = ref({});
// 获取智库基本信息
const handleGetThinkTankSummary = async () => {
const id = getDecodedParams()
try {
const parmas = {
id: router.currentRoute._value.params.id
id: id
};
const res = await getThinkTankSummary(parmas);
console.log("智库信息", res);
......
......@@ -515,6 +515,7 @@ import { setCanvasCreator } from "echarts/core";
import { ElMessage } from "element-plus";
import { useRouter } from 'vue-router';
import { useGotoNewsDetail } from '@/router/modules/news';
import { goToThinkTank } from "@/utils/goToPage";
const gotoNewsDetail = useGotoNewsDetail()
const containerRef = ref(null);
const isRiskDetailVisible = ref(false);
......@@ -2284,14 +2285,17 @@ const handleGetetThinkTankReport = async () => {
const handleClick = tank => {
console.log(tank);
window.sessionStorage.setItem("curTabName", tank.name + "概览");
// router.push({ name: "ThinkTankDetail", params: { id: tank.id } });
if (!tank.id) {
ElMessage.warning("当前智库id为空,无法进入详情页");
return;
}
const curRoute = router.resolve({ name: "ThinkTankDetail", params: { id: tank.id, name: tank.name } });
window.open(curRoute.href, "_blank");
goToThinkTank(tank.id, tank.name + "概览")
// window.sessionStorage.setItem("curTabName", tank.name + "概览");
// const curRoute = router.resolve({ name: "ThinkTankDetail", params: { id: tank.id, name: tank.name } });
// window.open(curRoute.href, "_blank");
// router.push({ name: "ThinkTankDetail", params: { id: tank.id, name: tank.name } })
};
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论