提交 89579e0f authored 作者: 付康's avatar 付康

合并分支 'lzl-dev' 到 'master'

法案接口部分更新和样式优化 查看合并请求 !43
...@@ -14,13 +14,13 @@ export function getBillInfo(params) { ...@@ -14,13 +14,13 @@ export function getBillInfo(params) {
// 提出人-根据动议ID获取对应的提出人信息 // 提出人-根据动议ID获取对应的提出人信息
/** /**
* @param {id} * @param {billId}
* @header token * @header token
*/ */
export function getBillPerson(params) { export function getBillPerson(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/api/billInfoBean/person/${params.id}`, url: `/api/billInfoBean/person/${params.billId}`,
params, params,
}) })
} }
...@@ -63,6 +63,18 @@ export function getBillBackground(params) { ...@@ -63,6 +63,18 @@ export function getBillBackground(params) {
params, params,
}) })
} }
// 相关事件-根据法案ID获取相关事件信息
/**
* @param {id}
* @header token
*/
export function getBillInfoEvent(params) {
return request({
method: 'GET',
url: `/api/billInfoBean/event/${params.id}`,
params,
})
}
// 议员相关性-根据法案ID获取议员分析信息(现在只包括名称 支持 反对,没有标签和事件动态) // 议员相关性-根据法案ID获取议员分析信息(现在只包括名称 支持 反对,没有标签和事件动态)
/** /**
...@@ -92,20 +104,20 @@ export function getBillContentId(params) { ...@@ -92,20 +104,20 @@ export function getBillContentId(params) {
// 主要条款-根据原文ID获取条款内容 // 主要条款-根据原文ID获取条款内容
/** /**
* @param {id,cRelated,currentPage,pageSize} * @param {billid,id,cRelated,currentPage,pageSize}
* @header token * @header token
*/ */
export function getBillContentTk(params) { export function getBillContentTk(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/api/billInfoBean/content/tk/${params.id}`, url: `/api/billInfoBean/content/tk/${params.billid}/${params.id}`,
params, params,
}) })
} }
// 限制方式-根据法案原文ID获取限制方式列表 // 限制方式-根据法案原文ID获取限制方式列表
/** /**
* @param {id} * @param {billId}
* @header token * @header token
*/ */
export function getBillContentXzfs(params) { export function getBillContentXzfs(params) {
......
...@@ -13,11 +13,11 @@ export function getBillIndustry(params) { ...@@ -13,11 +13,11 @@ export function getBillIndustry(params) {
} }
// 涉华法案统计 // 涉华法案统计
export function getBillCount() { export function getBillCount(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/api/BillOverview/billCount`, url: `/api/BillOverview/billCount`,
params
}) })
} }
...@@ -64,4 +64,35 @@ export function getHylyList() { ...@@ -64,4 +64,35 @@ export function getHylyList() {
method: 'GET', method: 'GET',
url: `/api/billImpactAnalysis/industry/hylyList`, url: `/api/billImpactAnalysis/industry/hylyList`,
}) })
}
// 获取法案提出部门
/**
* @param {year}
*/
export function getBillPostOrg(params) {
return request({
method: 'GET',
url: `/api/BillOverview/billPostOrg/${params.year}`,
})
}
// 获取关键议员提案
/**
* @param {year}
*/
export function getMemberProposal(params) {
return request({
method: 'GET',
url: `/api/BillOverview/memberProposal/${params.year}`,
})
}
// 获取资源库
export function getBills(params) {
return request({
method: 'GET',
url: `/api/BillOverview/bills`,
params
})
} }
\ No newline at end of file
...@@ -12,6 +12,18 @@ export function getBillTimeAnalyze(params) { ...@@ -12,6 +12,18 @@ export function getBillTimeAnalyze(params) {
}) })
} }
// 修正案次数分析
/**
* @param {id}
*/
export function getBillAmeAnalyzeCount(params) {
return request({
method: 'GET',
url: `/api/billDeepDive/ameAnalyze/count/${params.id}`,
params,
})
}
// 根据法案ID获取党派政治献金 // 根据法案ID获取党派政治献金
/** /**
* @param {id, personCongress} * @param {id, personCongress}
......
...@@ -35,8 +35,8 @@ ...@@ -35,8 +35,8 @@
v-for="(item, index) in backgroundList" v-for="(item, index) in backgroundList"
:key="item.id" :key="item.id"
> >
<div class="id">{{ index + 1 }}</div> <div class="id">{{ (currentPage - 1) * 10 + index + 1 }}</div>
<div class="title">{{ item.bjnr }}</div> <div class="title">{{ item.backgroundTitle }}</div>
<div class="share"> <div class="share">
<img src="./assets/icons/open.png" alt="打开" /> <img src="./assets/icons/open.png" alt="打开" />
</div> </div>
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
<div class="box1-main-footer"> <div class="box1-main-footer">
<div class="info"> <div class="info">
{{ {{
`共有${backgroundList.length}条${ `共有${total}条${
box1BtnActive === 1 ? "涉华" : "全部" box1BtnActive === 1 ? "涉华" : "全部"
}背景` }背景`
}} }}
...@@ -54,7 +54,9 @@ ...@@ -54,7 +54,9 @@
<el-pagination <el-pagination
background background
layout="prev, pager, next" layout="prev, pager, next"
:total="backgroundList.length" :total="total"
v-model:current-page="currentPage"
@current-change="handleGetBillBackground"
/> />
</div> </div>
</div> </div>
...@@ -80,7 +82,7 @@ ...@@ -80,7 +82,7 @@
:key="index" :key="index"
> >
<div class="left"> <div class="left">
<img :src="item.image" alt="" /> <img :src="item.imageUrl || item.image" alt="" />
</div> </div>
<div class="center"> <div class="center">
<div class="title">{{ item.sjbt }}</div> <div class="title">{{ item.sjbt }}</div>
...@@ -157,7 +159,7 @@ ...@@ -157,7 +159,7 @@
/></el-icon> /></el-icon>
</div> </div>
<div class="right-box1-main-bottom"> <div class="right-box1-main-bottom">
<WordCloudMap :data="wordCloudData" :shape="circle" /> <WordCloudMap :data="wordCloudData" shape="circle" />
</div> </div>
</div> </div>
</div> </div>
...@@ -214,25 +216,26 @@ import { ...@@ -214,25 +216,26 @@ import {
getBillBackground, getBillBackground,
getBillEvent, getBillEvent,
getBillPersonAnalyze, getBillPersonAnalyze,
getBillInfoEvent
} from "@/api/bill"; } from "@/api/bill";
const box1BtnActive = ref(1); const box1BtnActive = ref(1);
const currentPage = ref(1);
const total = ref(0);
const handleClickBox1Btn = (index) => { const handleClickBox1Btn = (index) => {
box1BtnActive.value = index; box1BtnActive.value = index;
if (index === 2) { currentPage.value = 1;
handleGetBillBackground(false); handleGetBillBackground();
} else {
handleGetBillBackground(true);
}
}; };
const box2BtnActive = ref(1); const box2BtnActive = ref(1);
const handleClickBox2Btn = (index) => { const handleClickBox2Btn = (index) => {
box2BtnActive.value = index; box2BtnActive.value = index;
if (index === 1) { if (index === 1) {
handleGetBillPersonAnalyze(true);
} else {
handleGetBillPersonAnalyze(false); handleGetBillPersonAnalyze(false);
} else {
handleGetBillPersonAnalyze(true);
} }
}; };
...@@ -439,27 +442,29 @@ const wordCloudData = [ ...@@ -439,27 +442,29 @@ const wordCloudData = [
]; ];
// 获取立法背景内容 // 获取立法背景内容
const handleGetBillBackground = async (cRelated) => { const handleGetBillBackground = async () => {
const cRelated = box1BtnActive.value === 1 ? 'Y' : 'N';
const params = { const params = {
cRelated: cRelated, cRelated: cRelated,
id: window.sessionStorage.getItem("billId"), id: window.sessionStorage.getItem("billId"),
currentPage: 0, currentPage: currentPage.value - 1,
pageSize: 10, pageSize: 10,
}; };
try { try {
const res = await getBillBackground(params); const res = await getBillBackground(params);
console.log("立法背景", res); console.log("立法背景", res);
backgroundList.value = res.data.content; backgroundList.value = res.data.content;
total.value = res.data.totalElements; // 假设API返回totalElements
} catch (error) {} } catch (error) {}
}; };
// 获取相关事件 // 获取相关事件
const handleGetRelatedEvent = async () => { const handleGetRelatedEvent = async () => {
const params = { const params = {
id: 1, id: window.sessionStorage.getItem("billId"),
}; };
try { try {
const res = await getBillEvent(params); const res = await getBillInfoEvent(params);
console.log("相关事件", res); console.log("相关事件", res);
eventList.value = res.data; eventList.value = res.data;
eventList.value.forEach((item, index) => { eventList.value.forEach((item, index) => {
...@@ -488,8 +493,9 @@ const handleGetBillPersonAnalyze = async (isOppose) => { ...@@ -488,8 +493,9 @@ const handleGetBillPersonAnalyze = async (isOppose) => {
const res = await getBillPersonAnalyze(params); const res = await getBillPersonAnalyze(params);
console.log("议员相关性分析", res); console.log("议员相关性分析", res);
personList.value = res.data; personList.value = res.data;
personList.value.forEach((item) => { personList.value.forEach((item, index) => {
item.image = user1; const imgList = [user1, user2, user3, user4, user5];
item.image = imgList[index % imgList.length];
item.icon = userIcon; item.icon = userIcon;
item.icon1 = userIcon1; item.icon1 = userIcon1;
}); });
...@@ -497,9 +503,9 @@ const handleGetBillPersonAnalyze = async (isOppose) => { ...@@ -497,9 +503,9 @@ const handleGetBillPersonAnalyze = async (isOppose) => {
}; };
onMounted(() => { onMounted(() => {
handleGetBillBackground(true); handleGetBillBackground();
handleGetRelatedEvent(); handleGetRelatedEvent();
handleGetBillPersonAnalyze(true); handleGetBillPersonAnalyze(false);
}); });
</script> </script>
...@@ -572,7 +578,7 @@ onMounted(() => { ...@@ -572,7 +578,7 @@ onMounted(() => {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: space-between; justify-content: space-between;
align-content: flex-start;
.box1-main-item { .box1-main-item {
width: 544px; width: 544px;
height: 48px; height: 48px;
...@@ -598,11 +604,12 @@ onMounted(() => { ...@@ -598,11 +604,12 @@ onMounted(() => {
width: 440px; width: 440px;
height: 48px; height: 48px;
line-height: 48px; line-height: 48px;
color: rgba(95, 101, 108, 1); color: rgb(59, 65, 75);
font-family: Microsoft YaHei; font-family: "Microsoft YaHei";
font-size: 14px; font-size: 16px;
font-weight: 400; font-weight: 400;
text-align: left; text-align: left;
overflow: hidden;
} }
.share { .share {
margin-left: 13px; margin-left: 13px;
...@@ -626,8 +633,8 @@ onMounted(() => { ...@@ -626,8 +633,8 @@ onMounted(() => {
.info { .info {
height: 22px; height: 22px;
line-height: 22px; line-height: 22px;
color: rgba(132, 136, 142, 1); color: rgb(132, 136, 142);
font-family: Microsoft YaHei; font-family: "Microsoft YaHei";
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
text-align: left; text-align: left;
...@@ -645,6 +652,7 @@ onMounted(() => { ...@@ -645,6 +652,7 @@ onMounted(() => {
margin-top: 9px; margin-top: 9px;
margin-left: 23px; margin-left: 23px;
height: 300px; height: 300px;
overflow: auto;
.box2-main-item { .box2-main-item {
width: 1103px; width: 1103px;
height: 60px; height: 60px;
...@@ -659,9 +667,9 @@ onMounted(() => { ...@@ -659,9 +667,9 @@ onMounted(() => {
width: 64px; width: 64px;
height: 48px; height: 48px;
border-radius: 2px; border-radius: 2px;
image { img {
width: 100px; width: 64px;
height: 100%; height: 48px;
} }
} }
.center { .center {
......
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
<div class="btn-icon"> <div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" /> <img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div> </div>
</div> </div>
<div class="btn" @click="handleToPosi('position2')"> <div class="btn" @click="handleToPosi('position2')">
<div class="btn-text">{{ "资讯要闻" }}</div> <div class="btn-text">{{ "资讯要闻" }}</div>
...@@ -140,15 +141,15 @@ ...@@ -140,15 +141,15 @@
<div <div
class="info-box" class="info-box"
:class="{ :class="{
info1: item.status === 1, info1: index === 0,
info2: item.status === 2, info2: index === 1,
info3: item.status === 3, info3: index === 2,
info4: item.status === 4 info4: index === 3
}" }"
v-for="(item, index) in curBill.hylyList" v-for="(item, index) in curBill.hylyList"
:key="index" :key="index"
> >
{{ item }} {{ item.industryName }}
</div> </div>
</div> </div>
<div class="box1-main-left-info1"> <div class="box1-main-left-info1">
...@@ -307,6 +308,12 @@ ...@@ -307,6 +308,12 @@
<div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div> <div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div>
</div> </div>
</div> </div>
<div class="box5-select">
<el-select v-model="box5Select" placeholder="选择领域" @change="handleBox5Change" style="width: 150px">
<el-option label="全部领域" value="全部领域" />
<el-option v-for="item in categoryList.slice(1)" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</div>
<div class="box5-main" id="box5Chart"></div> <div class="box5-main" id="box5Chart"></div>
</div> </div>
<div class="box6"> <div class="box6">
...@@ -386,13 +393,13 @@ ...@@ -386,13 +393,13 @@
@click="handleClcikToCharacter(0)" @click="handleClcikToCharacter(0)"
> >
<div class="box8-main-item-left"> <div class="box8-main-item-left">
<img :src="item.img" alt="" /> <img :src="item.img" alt="" referrerpolicy="no-referrer" class="left-img" />
<div class="left-icon1"> <div class="left-icon1">
<img :src="item.dangpai" alt="" /> <img :src="item.dangpai" alt="" />
</div> </div>
<div class="left-icon2"> <div class="left-icon2">
<img :src="item.yuan" alt="" /> <img :src="item.yuan" alt="" />
</div> </div>
</div> </div>
<div class="box8-main-item-center"> <div class="box8-main-item-center">
<div class="box8-main-item-center-top">{{ item.name }}</div> <div class="box8-main-item-center-top">{{ item.name }}</div>
...@@ -448,16 +455,7 @@ ...@@ -448,16 +455,7 @@
{{ cate.name }} {{ cate.name }}
</div> </div>
</div> </div>
<div class="select-box">
<el-select v-model="releaseTime" placeholder="选择发布时间" style="width: 120px">
<el-option
v-for="item in releaseTimeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div> </div>
<div class="home-main-footer-main"> <div class="home-main-footer-main">
<div class="left"> <div class="left">
...@@ -467,17 +465,16 @@ ...@@ -467,17 +465,16 @@
<div class="title">{{ "科技领域" }}</div> <div class="title">{{ "科技领域" }}</div>
</div> </div>
<div class="select-main"> <div class="select-main">
<div class="checkbox-group"> <el-checkbox-group class="checkbox-group" v-model="activeAreaList">
<el-checkbox <el-checkbox
v-for="area in areaList" v-for="(area, index) in areaList"
:key="area.id" :key="area.id"
v-model="activeAreaList"
:label="area.id" :label="area.id"
class="filter-checkbox" class="filter-checkbox"
> >
{{ area.name }} {{ area.name }}
</el-checkbox> </el-checkbox>
</div> </el-checkbox-group>
</div> </div>
</div> </div>
<div class="select-box"> <div class="select-box">
...@@ -485,18 +482,17 @@ ...@@ -485,18 +482,17 @@
<div class="icon"></div> <div class="icon"></div>
<div class="title">{{ "党派" }}</div> <div class="title">{{ "党派" }}</div>
</div> </div>
<div class="select-main select-main1"> <div class="select-main">
<div class="checkbox-group"> <el-checkbox-group class="checkbox-group" v-model="activeDpList">
<el-checkbox <el-checkbox
v-for="dp in dpList" v-for="(dp, index) in dpList"
:key="dp.id" :key="dp.id"
v-model="activeDpList"
:label="dp.id" :label="dp.id"
class="filter-checkbox" class="filter-checkbox"
> >
{{ dp.name }} {{ dp.name }}
</el-checkbox> </el-checkbox>
</div> </el-checkbox-group>
</div> </div>
</div> </div>
<div class="select-box"> <div class="select-box">
...@@ -505,17 +501,16 @@ ...@@ -505,17 +501,16 @@
<div class="title">{{ "议院" }}</div> <div class="title">{{ "议院" }}</div>
</div> </div>
<div class="select-main"> <div class="select-main">
<div class="checkbox-group"> <el-checkbox-group class="checkbox-group" v-model="activeYyList">
<el-checkbox <el-checkbox
v-for="yy in yyList" v-for="(yy, index) in yyList"
:key="yy.id" :key="yy.id"
v-model="activeYyList"
:label="yy.id" :label="yy.id"
class="filter-checkbox" class="filter-checkbox"
> >
{{ yy.name }} {{ yy.name }}
</el-checkbox> </el-checkbox>
</div> </el-checkbox-group>
</div> </div>
</div> </div>
...@@ -525,17 +520,16 @@ ...@@ -525,17 +520,16 @@
<div class="title">{{ "发布时间" }}</div> <div class="title">{{ "发布时间" }}</div>
</div> </div>
<div class="select-main"> <div class="select-main">
<div class="checkbox-group"> <el-checkbox-group class="checkbox-group" v-model="activePubTime">
<el-checkbox <el-checkbox
v-for="time in pubTime" v-for="(time, index) in pubTime"
:key="time.id" :key="time.id"
v-model="activePubTime"
:label="time.id" :label="time.id"
class="filter-checkbox" class="filter-checkbox"
> >
{{ time.name }} {{ time.name }}
</el-checkbox> </el-checkbox>
</div> </el-checkbox-group>
</div> </div>
</div> </div>
</div> </div>
...@@ -561,6 +555,16 @@ ...@@ -561,6 +555,16 @@
/> />
</el-select> </el-select>
</div> </div>
<div class="right-header-box" style="margin-left: auto;">
<el-select v-model="releaseTime" placeholder="选择发布时间" style="width: 120px">
<el-option
v-for="item in releaseTimeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div> </div>
<div class="right-main"> <div class="right-main">
<div class="right-main-box" v-for="(item, index) in footerBillList" :key="index"> <div class="right-main-box" v-for="(item, index) in footerBillList" :key="index">
...@@ -620,7 +624,7 @@ ...@@ -620,7 +624,7 @@
</template> </template>
<script setup> <script setup>
import { onMounted, ref, computed, onUnmounted, nextTick } from "vue"; import { onMounted, ref, computed, onUnmounted, nextTick, watch } from "vue";
import router from "@/router/index"; import router from "@/router/index";
import setChart from "@/utils/setChart"; import setChart from "@/utils/setChart";
...@@ -631,7 +635,9 @@ import { ...@@ -631,7 +635,9 @@ import {
getBillsByType, getBillsByType,
getHylyList, getHylyList,
getBillOverviewKeyTK, getBillOverviewKeyTK,
getBillCount getBillCount,
getBillPostOrg,
getMemberProposal
} from "@/api/bill/billHome"; } from "@/api/bill/billHome";
import DivideHeader from "@/components/DivideHeader.vue"; import DivideHeader from "@/components/DivideHeader.vue";
...@@ -1138,6 +1144,7 @@ const handleGetBillsByType = async () => { ...@@ -1138,6 +1144,7 @@ const handleGetBillsByType = async () => {
}; };
// 涉华法案数量 // 涉华法案数量
const box5Select = ref("全部领域");
const box5Data = ref({ const box5Data = ref({
title: [ title: [
"2024-09", "2024-09",
...@@ -1166,11 +1173,31 @@ const box5Data = ref({ ...@@ -1166,11 +1173,31 @@ const box5Data = ref({
}); });
const handleGetBillCount = async () => { const handleGetBillCount = async () => {
try { try {
const res = await getBillCount(); let params = {};
if (box5Select.value !== "全部领域") {
params.industryId = box5Select.value;
}
const res = await getBillCount(params);
console.log("涉华法案统计", res); console.log("涉华法案统计", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
const sortedData = res.data.sort((a, b) => a.month.localeCompare(b.month));
box5Data.value = {
title: sortedData.map(item => item.month),
data: [
{
name: "提出法案",
value: sortedData.map(item => item.totalCount)
},
{
name: "通过法案",
value: sortedData.map(item => item.passCount)
}
],
percent: sortedData.map(item => item.percent)
};
} else { } else {
box5Data.value = {}; // 保持默认数据或清空
// box5Data.value = {};
} }
} catch (error) { } catch (error) {
console.error("获取涉华法案统计error", error); console.error("获取涉华法案统计error", error);
...@@ -1179,10 +1206,60 @@ const handleGetBillCount = async () => { ...@@ -1179,10 +1206,60 @@ const handleGetBillCount = async () => {
const handleBox5 = async () => { const handleBox5 = async () => {
await handleGetBillCount(); await handleGetBillCount();
let box5Chart = getMultiLineChart(box5Data.value.title, box5Data.value.data[0].value, box5Data.value.data[1].value); const proposed = box5Data.value.data[0].value;
const passed = box5Data.value.data[1].value;
const rate = box5Data.value.percent || proposed.map((p, i) => {
const pass = passed[i] || 0;
return p ? ((pass / p) * 100).toFixed(2) : 0;
});
let box5Chart = getMultiLineChart(box5Data.value.title, proposed, passed, rate);
setChart(box5Chart, "box5Chart"); setChart(box5Chart, "box5Chart");
}; };
const handleBox5Change = () => {
handleBox5();
};
// 法案提出部门
const handleBox7Data = async () => {
try {
const res = await getBillPostOrg({ year: box7selectetedTime.value });
console.log("法案提出部门", res);
if (res.code === 200 && res.data) {
const apiData = res.data;
const houseItems = apiData.filter(i => i.congressName === "House");
const senateItems = apiData.filter(i => i.congressName === "Senate");
const houseTotal = houseItems.reduce((sum, i) => sum + i.countBill, 0);
const senateTotal = senateItems.reduce((sum, i) => sum + i.countBill, 0);
const data1 = [];
if (houseItems.length > 0) {
data1.push({ name: "众议院", value: houseTotal });
}
if (senateItems.length > 0) {
data1.push({ name: "参议院", value: senateTotal });
}
const data2 = [...houseItems, ...senateItems].map(item => ({
name: item.originDepart,
value: item.countBill,
type: item.congressName === "House" ? "众议院" : "参议院"
}));
const box7Chart = getDoublePieChart(data1, data2);
setChart(box7Chart, "box7Chart");
}
} catch (error) {
console.error("获取法案提出部门数据失败", error);
}
};
watch(box7selectetedTime, () => {
handleBox7Data();
});
// 关键条款 // 关键条款
const wordCloudData = ref([ const wordCloudData = ref([
{ name: "限制中国获取能源技术", value: 100 }, { name: "限制中国获取能源技术", value: 100 },
...@@ -1379,48 +1456,30 @@ const box7Data = ref([ ...@@ -1379,48 +1456,30 @@ const box7Data = ref([
] ]
]); ]);
const box8Data = ref([ const box8Data = ref([]);
{
name: "汤姆·科顿", const handleBox8Data = async () => {
zhiwei: "参议院情报委员会主席", try {
img: Message3, const res = await getMemberProposal({ year: box8selectetedTime.value });
dangpai: Cyy, console.log("关键议员提案", res);
yuan: Ghd, if (res.code === 200 && res.data) {
num: 8 box8Data.value = res.data.map(item => ({
}, name: item.memberName,
{ zhiwei: item.position,
name: "吉姆·里施", img: item.imageUrl,
zhiwei: "参议院外交关系委员会主席", num: item.countProposal,
img: Message3, dangpai: Cyy,
dangpai: Cyy, yuan: item.position === "Democratic" ? Mzd : Ghd
yuan: Ghd, }));
num: 4 }
}, } catch (error) {
{ console.error("获取关键议员提案失败", error);
name: "特德·克鲁兹",
zhiwei: "参议院商务、科学和交通委员会主席",
img: Message3,
dangpai: Cyy,
yuan: Ghd,
num: 2
},
{
name: "里克·克劳福德",
zhiwei: "众议院美中战略竞争特设委员会主席",
img: Message3,
dangpai: Cyy,
yuan: Ghd,
num: 2
},
{
name: "布莱恩·马斯特",
zhiwei: "众议院情报委员会主席",
img: Message3,
dangpai: Cyy,
yuan: Ghd,
num: 2
} }
]); };
watch(box8selectetedTime, () => {
handleBox8Data();
});
const handleToPosi = id => { const handleToPosi = id => {
// 0 618 1240 2350 // 0 618 1240 2350
...@@ -1464,26 +1523,36 @@ const handleClickTab = tab => { ...@@ -1464,26 +1523,36 @@ const handleClickTab = tab => {
}; };
const areaList = [ const areaList = [
{ 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: "海洋" }
]; ];
const activeAreaList = ["人工智能"]; const activeAreaList = ref(["全部领域"]);
const dpList = ref([ const dpList = ref([
{ id: "全部党派", name: "全部党派" },
{ id: "民主党", name: "民主党" }, { id: "民主党", name: "民主党" },
{ id: "共和党", name: "共和党" } { id: "共和党", name: "共和党" }
]); ]);
const activeDpList = ["民主党"]; const activeDpList = ref(["全部党派"]);
const yyList = ref([ const yyList = ref([
{ id: "全部议院", name: "全部议院" },
{ id: "参议院", name: "参议院" }, { id: "参议院", name: "参议院" },
{ id: "众议院", name: "众议院" } { id: "众议院", name: "众议院" }
]); ]);
const activeYyList = ["参议院"]; const activeYyList = ref(["全部议院"]);
const pubTime = ref([ const pubTime = ref([
{ id: "全部时间", name: "全部时间" },
{ id: "2025年", name: "2025年" }, { id: "2025年", name: "2025年" },
{ id: "2024年", name: "2024年" }, { id: "2024年", name: "2024年" },
{ id: "2023年", name: "2023年" }, { id: "2023年", name: "2023年" },
...@@ -1491,7 +1560,7 @@ const pubTime = ref([ ...@@ -1491,7 +1560,7 @@ const pubTime = ref([
{ id: "2021年", name: "2021年" }, { id: "2021年", name: "2021年" },
{ id: "更早时间", name: "更早时间" } { id: "更早时间", name: "更早时间" }
]); ]);
const activePubTime = ref(["2025年"]); const activePubTime = ref(["全部时间"]);
const footerSelectList1 = ref([ const footerSelectList1 = ref([
{ {
...@@ -1549,8 +1618,9 @@ onMounted(async () => { ...@@ -1549,8 +1618,9 @@ onMounted(async () => {
handleBox5(); //涉华法案统计 handleBox5(); //涉华法案统计
handleBox6(); // 关键条款 handleBox6(); // 关键条款
const box7Chart = getDoublePieChart(box7Data.value[0], box7Data.value[1]); handleBox7Data();
setChart(box7Chart, "box7Chart");
handleBox8Data();
await handleGetHotBills(); await handleGetHotBills();
curBill.value = hotBillList.value[0]; curBill.value = hotBillList.value[0];
...@@ -1929,15 +1999,14 @@ onUnmounted(() => {}); ...@@ -1929,15 +1999,14 @@ onUnmounted(() => {});
padding-left: 31px; padding-left: 31px;
.box1-main-left { .box1-main-left {
margin-left: 39px; margin-left: 39px;
// flex: 1;
width: 484px; width: 484px;
.box1-main-left-title { .box1-main-left-title {
height: 22px;
color: rgba(20, 89, 187, 1); color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei; font-family: "Microsoft YaHei";
font-size: 20px; font-size: 20px;
font-weight: 700; font-weight: 700;
line-height: 22px; line-height: 22px;
margin-bottom: 14px;
} }
.box1-main-left-info { .box1-main-left-info {
margin-top: 17px; margin-top: 17px;
...@@ -2549,6 +2618,7 @@ onUnmounted(() => {}); ...@@ -2549,6 +2618,7 @@ onUnmounted(() => {});
border-radius: 10px; border-radius: 10px;
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1); box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
position: relative;
.box5-header { .box5-header {
height: 53px; height: 53px;
border-bottom: 1px solid rgba(240, 242, 244, 1); border-bottom: 1px solid rgba(240, 242, 244, 1);
...@@ -2605,6 +2675,12 @@ onUnmounted(() => {}); ...@@ -2605,6 +2675,12 @@ onUnmounted(() => {});
.box5-main { .box5-main {
height: 397px; height: 397px;
} }
.box5-select {
position: absolute;
top: 50px;
left: 100px;
z-index: 100;
}
} }
.box6 { .box6 {
margin-left: 20px; margin-left: 20px;
...@@ -2615,7 +2691,7 @@ onUnmounted(() => {}); ...@@ -2615,7 +2691,7 @@ onUnmounted(() => {});
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
.box6-header { .box6-header {
width: 521px; width: 521px;
height: 48px; height: 53px;
border-bottom: 1px solid rgba(240, 242, 244, 1); border-bottom: 1px solid rgba(240, 242, 244, 1);
display: flex; display: flex;
box-sizing: border-box; box-sizing: border-box;
...@@ -2665,8 +2741,8 @@ onUnmounted(() => {}); ...@@ -2665,8 +2741,8 @@ onUnmounted(() => {});
} }
} }
.box6-main { .box6-main {
width: 452px; width: 100%;
height: 402px; height: calc(100% - 53px);
} }
} }
} }
...@@ -2816,6 +2892,8 @@ onUnmounted(() => {}); ...@@ -2816,6 +2892,8 @@ onUnmounted(() => {});
} }
.box8-main { .box8-main {
height: 340px; height: 340px;
overflow-y: auto;
overflow-x: hidden;
.box8-main-item { .box8-main-item {
margin: 0 auto; margin: 0 auto;
width: 478px; width: 478px;
...@@ -2833,9 +2911,10 @@ onUnmounted(() => {}); ...@@ -2833,9 +2911,10 @@ onUnmounted(() => {});
position: relative; position: relative;
width: 42px; width: 42px;
height: 42px; height: 42px;
img { .left-img {
width: 100%; width: 42px;
height: 100%; height: 42px;
border-radius: 50%;
} }
.left-icon1 { .left-icon1 {
position: absolute; position: absolute;
...@@ -2892,11 +2971,10 @@ onUnmounted(() => {}); ...@@ -2892,11 +2971,10 @@ onUnmounted(() => {});
position: absolute; position: absolute;
top: 0; top: 0;
right: 10px; right: 10px;
width: 92px;
height: 51px; height: 51px;
text-align: right; text-align: right;
color: rgba(95, 101, 108, 1); color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei; font-family: "Microsoft YaHei";
font-size: 16px; font-size: 16px;
font-weight: 400; font-weight: 400;
line-height: 51px; line-height: 51px;
...@@ -3051,7 +3129,7 @@ onUnmounted(() => {}); ...@@ -3051,7 +3129,7 @@ onUnmounted(() => {});
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1); box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
.select-box { .select-box {
margin-top: 21px; margin-top: 20px;
.select-box-header { .select-box-header {
display: flex; display: flex;
gap: 17px; gap: 17px;
...@@ -3063,18 +3141,35 @@ onUnmounted(() => {}); ...@@ -3063,18 +3141,35 @@ onUnmounted(() => {});
border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0;
} }
.title { .title {
height: 24px; // height: 24px;
color: var(--color-main-active); color: var(--color-main-active);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 16px; font-size: 20px;
font-weight: 700; font-weight: 700;
line-height: 24px; line-height: 26px;
letter-spacing: 1px; letter-spacing: 1px;
text-align: left; text-align: left;
} }
} }
.select-main { .select-main {
margin-left: 25px; margin-left: 25px;
margin-top: 16px;
.checkbox-group {
display: flex;
flex-wrap: wrap;
.filter-checkbox {
width: 50%;
margin-right: 0;
margin-bottom: 4px;
:deep(.el-checkbox__label) {
color: rgb(95, 101, 108);
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
}
}
}
} }
.select-main1 { .select-main1 {
width: 100px; width: 100px;
......
import * as echarts from 'echarts' import * as echarts from 'echarts'
const getMultiLineChart = (dataX, dataY1, dataY2) => { const getMultiLineChart = (dataX, dataY1, dataY2, dataY3) => {
return { return {
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
...@@ -9,25 +9,34 @@ const getMultiLineChart = (dataX, dataY1, dataY2) => { ...@@ -9,25 +9,34 @@ const getMultiLineChart = (dataX, dataY1, dataY2) => {
label: { label: {
backgroundColor: '#6a7985' backgroundColor: '#6a7985'
} }
},
formatter: function (params) {
let res = params[0].name + '<br/>';
params.forEach(item => {
res += item.marker + item.seriesName + ': ' + item.value + (item.seriesName === '通过率' ? '%' : '') + '<br/>';
});
return res;
} }
}, },
grid: { grid: {
top: '8%', top: '15%',
right: '5%', right: '5%',
bottom: '5%', bottom: '5%',
left: '5%', left: '5%',
containLabel: true containLabel: true
}, },
legend: { legend: {
data: ['提出法案', '通过法案'], data: ['提出法案', '通过法案', '通过率'],
show: true, show: true,
top: 0,
icon: 'circle',
textStyle: { textStyle: {
color: 'rgba(95, 101, 108, 1)', color: 'rgba(95, 101, 108, 1)',
fontFamily: 'Microsoft YaHei', fontFamily: 'Microsoft YaHei',
fontSize: '16px', fontSize: '14px',
} }
}, },
color: ['#1459bb', '#fa8c16'], color: ['#1677FF', '#FA8C16', '#D9001B'],
xAxis: [ xAxis: [
{ {
type: 'category', type: 'category',
...@@ -37,47 +46,83 @@ const getMultiLineChart = (dataX, dataY1, dataY2) => { ...@@ -37,47 +46,83 @@ const getMultiLineChart = (dataX, dataY1, dataY2) => {
], ],
yAxis: [ yAxis: [
{ {
type: 'value' type: 'value',
position: 'left',
axisLabel: {
color: '#666'
}
},
{
type: 'value',
position: 'right',
min: 0,
max: 100,
interval: 20,
axisLabel: {
formatter: '{value}%',
color: '#666'
},
splitLine: {
show: false
}
} }
], ],
series: [ series: [
{ {
name: '提出法案', name: '提出法案',
type: 'line', type: 'line',
symbol: 'emptyCircle',
symbolSize: 6,
areaStyle: { areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0, offset: 0,
color: 'rgba(22, 119, 255, 1)' // 起始颜色 color: 'rgba(22, 119, 255, 0.4)' // 起始颜色
}, { }, {
offset: 1, offset: 1,
color: 'rgba(22, 119, 255, 0)' // 结束颜色 color: 'rgba(22, 119, 255, 0)' // 结束颜色
}]) }])
}, },
emphasis: { itemStyle: {
focus: 'series' color: '#1677FF'
}, },
data: dataY1 data: dataY1
}, },
{ {
name: '通过法案', name: '通过法案',
type: 'line', type: 'line',
symbol: 'emptyCircle',
symbolSize: 6,
areaStyle: { areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0, offset: 0,
color: 'rgba(255, 172, 77, 1)' // 起始颜色 color: 'rgba(250, 140, 22, 0.4)' // 起始颜色
}, { }, {
offset: 1, offset: 1,
color: 'rgba(255, 172, 77, 0)' // 结束颜色 color: 'rgba(250, 140, 22, 0)' // 结束颜色
}]) }])
}, },
emphasis: { itemStyle: {
focus: 'series' color: '#FA8C16'
}, },
data: dataY2 data: dataY2
},
{
name: '通过率',
type: 'line',
yAxisIndex: 1,
symbol: 'emptyCircle',
symbolSize: 4,
lineStyle: {
type: 'dashed',
width: 2
},
itemStyle: {
color: '#D9001B'
},
data: dataY3
} }
] ]
} }
} }
export default getMultiLineChart export default getMultiLineChart
\ No newline at end of file
...@@ -11,6 +11,8 @@ const getWordCloudChart = (data) => { ...@@ -11,6 +11,8 @@ const getWordCloudChart = (data) => {
series: [ series: [
{ {
type: "wordCloud", type: "wordCloud",
width: '80%',
height: '80%',
shape: "rect", // shape: "rect", //
// 其他形状你可以使用形状路径 // 其他形状你可以使用形状路径
// 或者自定义路径 // 或者自定义路径
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
<div class="box2"> <div class="box2">
<div class="box-header"> <div class="box-header">
<div class="header-left"></div> <div class="header-left"></div>
<div class="title">辩论投票时长</div> <div class="title">修正案次数分析</div>
<div class="header-right"> <div class="header-right">
<div class="icon"> <div class="icon">
<img src="@/assets/icons/box-header-icon1.png" alt="" /> <img src="@/assets/icons/box-header-icon1.png" alt="" />
...@@ -320,7 +320,7 @@ ...@@ -320,7 +320,7 @@
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { getBillTimeAnalyze, getBillXj, getBillTotalXj, getBillTp } from "@/api/deepdig"; import { getBillTimeAnalyze, getBillAmeAnalyzeCount, getBillTp } from "@/api/deepdig";
import getBoxPlotChcart from "./utils/boxplot"; import getBoxPlotChcart from "./utils/boxplot";
import * as echarts from "echarts"; import * as echarts from "echarts";
...@@ -563,20 +563,69 @@ const handleGetBillTimeAnalyze = async () => { ...@@ -563,20 +563,69 @@ const handleGetBillTimeAnalyze = async () => {
return item.lcmc; return item.lcmc;
}); });
chartData1.value.dataY = res.data.map(item => { chartData1.value.dataY = res.data.map(item => {
return [item.zdhs, item.zshs, item.pjs, item.pjx, item.zws, item.dysc]; return [item.zshs, item.pjx, item.zws, item.pjs, item.zdhs, item.dysc];
}); });
} catch (error) {} } catch (error) {}
}; };
// 辩论投票时长 // 修正案次数分析
const handleGetBillAmeAnalyzeCount = async () => {
const params = {
id: window.sessionStorage.getItem("billId")
};
try {
const res = await getBillAmeAnalyzeCount(params);
console.log("修正案次数分析", res);
chartData2.value.dataX = res.data.map(item => {
return item.lcmc;
});
chartData2.value.dataY = res.data.map(item => {
// 兼容多种字段名,防止字段不存在导致图表消失
// 顺序:最小(min), Q1(小), 中位数(median), Q3(大), 最大(max), 该法案(current)
return [
item.zsCount || item.zscs || item.zshs || 0,
item.jsx || item.pjx || 0,
item.zws || item.zwcs || 0,
item.pjs || item.pjcs || 0,
item.zdCount || item.zdcs || item.zdhs || 0,
item.dysc || item.dycs || 0
];
});
} catch (error) {
console.error("修正案次数分析 error", error);
}
};
// 获取投票分析
const handleGetBillVoteAnalyze = async () => {
const params = {
id: window.sessionStorage.getItem("billId")
};
try {
const res = await getBillTp(params);
console.log("投票分析", res);
} catch (error) {
console.error("投票分析 error", error);
}
};
onMounted(async () => { onMounted(async () => {
await handleGetBillTimeAnalyze(); await handleGetBillTimeAnalyze();
await handleGetBillAmeAnalyzeCount();
await handleGetBillVoteAnalyze();
let chart1 = getBoxPlotChcart(chartData1.value, "天"); let chart1 = getBoxPlotChcart(chartData1.value, "天");
setChart(chart1, "chart1"); setChart(chart1, "chart1");
let chart2 = getBoxPlotChcart(chartData2.value, "小时"); const countLabels = {
max: '最大次数',
q3: '平均次数大',
median: '次数中位数',
q1: '平均次数小',
min: '最小次数',
current: '该法案修正案数量'
};
let chart2 = getBoxPlotChcart(chartData2.value, "次", countLabels);
setChart(chart2, "chart2"); setChart(chart2, "chart2");
}); });
</script> </script>
......
const getBoxPlotChcart = (data,unit) => { const getBoxPlotChcart = (data, unit, labelConfig = {}) => {
const labels = {
max: labelConfig.max || '最大耗时',
q3: labelConfig.q3 || '平均耗时大',
median: labelConfig.median || '耗时中位数',
q1: labelConfig.q1 || '平均耗时小',
min: labelConfig.min || '最小耗时',
current: labelConfig.current || '该法案耗时'
};
let option = { let option = {
// title: [ // title: [
// { // {
...@@ -11,6 +20,22 @@ const getBoxPlotChcart = (data,unit) => { ...@@ -11,6 +20,22 @@ const getBoxPlotChcart = (data,unit) => {
trigger: 'item', trigger: 'item',
axisPointer: { axisPointer: {
type: 'shadow' type: 'shadow'
},
formatter: function (params) {
if (params.seriesType === 'scatter') {
return `${params.name}<br/>${labels.current}: ${params.data[1]} ${unit}`;
}
const { name, data } = params;
let tip = `${name}<br/>`;
tip += `${labels.max}: ${data[5]} ${unit}<br/>`;
tip += `${labels.q3}: ${data[4]} ${unit}<br/>`;
tip += `${labels.median}: ${data[3]} ${unit}<br/>`;
tip += `${labels.q1}: ${data[2]} ${unit}<br/>`;
tip += `${labels.min}: ${data[1]} ${unit}<br/>`;
if (data[6] !== undefined && data[6] !== null) {
tip += `${labels.current}: ${data[6]} ${unit}`;
}
return tip;
} }
}, },
grid: { grid: {
...@@ -48,13 +73,20 @@ const getBoxPlotChcart = (data,unit) => { ...@@ -48,13 +73,20 @@ const getBoxPlotChcart = (data,unit) => {
{ {
name: 'boxplot', name: 'boxplot',
type: 'boxplot', type: 'boxplot',
datasetIndex: 1,
data: data.dataY, data: data.dataY,
}, },
{ {
name: 'outlier', name: labels.current,
type: 'scatter', type: 'scatter',
datasetIndex: 2 data: data.dataY.map((item, index) => [index, item[5]]),
itemStyle: {
color: '#ff5722'
},
tooltip: {
formatter: function (params) {
return `${params.name}<br/>${labels.current}: ${params.data[1]} ${unit}`;
}
}
} }
] ]
} }
......
<template> <template>
<div class="container"> <div class="container">
<div class="svg-timeline"> <div class="svg-timeline">
<svg :width="svgWidth" :height="svgHeight"> <svg :viewBox="`0 0 ${svgWidth} ${svgHeight}`" width="100%" height="100%">
<!-- <line <!-- <line
:x1="lines[0].x1 - 100" :x1="lines[0].x1 - 100"
:y1="lines[0].y1" :y1="lines[0].y1"
...@@ -31,10 +31,11 @@ ...@@ -31,10 +31,11 @@
stroke-width="2" stroke-width="2"
/> --> /> -->
<line <line
:x1="lines[0].x1 - 100" v-if="nodes.length > 0"
:y1="lines[0].y1" :x1="nodes[0].x - 100"
:x2="lines[0].x1" :y1="nodes[0].y"
:y2="lines[0].y1" :x2="nodes[0].x"
:y2="nodes[0].y"
stroke="#e8f2ff" stroke="#e8f2ff"
stroke-width="2" stroke-width="2"
marker-end="url(#arrow)" marker-end="url(#arrow)"
...@@ -68,51 +69,60 @@ ...@@ -68,51 +69,60 @@
v-for="(node, idx) in nodes.slice(0, nodes.length)" v-for="(node, idx) in nodes.slice(0, nodes.length)"
:key="'line' + idx" :key="'line' + idx"
:x1="node.x" :x1="node.x"
:y1="node.y + 2" :y1="node.y + 4"
:x2="node.x" :x2="node.x"
:y2="node.dyms ? node.y + 80 : node.y + 50" :y2="node.y + verticalLineLength"
stroke="#1677ff" stroke="#1677ff"
stroke-width="2" :stroke-width="verticalLineWidth"
/> />
<text <foreignObject
v-for="(node, idx) in nodes" v-for="(node, idx) in nodes"
:key="'actionDate' + idx" :key="'fo-' + idx"
:x="node.x + 10" :x="node.x + 15"
:y="node.y + 30" :y="node.y + 5"
text-anchor="start" :width="nodeGapX - 30"
fill="#1677ff" height="100"
font-size="14" style="overflow: visible;"
font-weight="600"
> >
{{ node.actionDate }} <div class="node-content" xmlns="http://www.w3.org/1999/xhtml">
</text> <div class="date">{{ node.formattedDate }}</div>
<div class="title">{{ node.actionTitle }}</div>
<div class="votes" v-if="node.voteString">{{ node.voteString }}</div>
</div>
</foreignObject>
<text <text
v-for="(node, idx) in nodes" v-if="startMonth && nodes.length > 0"
:key="'actionTitle' + idx" :x="nodes[0].x - 110"
:x="node.x + 10" :y="nodes[0].y + 5"
:y="node.y + 50" text-anchor="end"
text-anchor="start" fill="rgb(5, 95, 194)"
fill="#3b414b" font-size="16"
font-size="14" font-weight="700"
textLength="170"
lengthAdjust="spacing"
font-weight="bold"
> >
{{ node.actionTitle.slice(0,24) }} {{ startMonth }}
</text> </text>
<line
v-if="nodes.length > 0"
:x1="nodes[nodes.length - 1].x"
:y1="nodes[nodes.length - 1].y"
:x2="nodes[nodes.length - 1].row % 2 === 0 ? nodes[nodes.length - 1].x + 100 : nodes[nodes.length - 1].x - 100"
:y2="nodes[nodes.length - 1].y"
stroke="#e8f2ff"
stroke-width="2"
marker-end="url(#arrow)"
/>
<text <text
v-for="(node, idx) in nodes" v-if="endMonth && nodes.length > 0"
:key="'actionTitle' + idx" :x="nodes[nodes.length - 1].row % 2 === 0 ? nodes[nodes.length - 1].x + 110 : nodes[nodes.length - 1].x - 110"
:x="node.x + 10" :y="nodes[nodes.length - 1].y + 5"
:y="node.y + 70" :text-anchor="nodes[nodes.length - 1].row % 2 === 0 ? 'start' : 'end'"
text-anchor="start" fill="rgb(5, 95, 194)"
fill="#84888e" font-size="16"
font-size="14" font-weight="700"
> >
{{ node.dyms ? node.dyms : "" }} {{ endMonth }}
</text> </text>
</svg> </svg>
</div> </div>
...@@ -134,26 +144,55 @@ export default { ...@@ -134,26 +144,55 @@ export default {
// ], // ],
maxPerRow: 5, maxPerRow: 5,
nodeGapX: 200, nodeGapX: 200,
nodeGapY: 100 nodeGapY: 180,
leftMargin: 150,
verticalLineLength: 80,
verticalLineWidth: 1
}; };
}, },
computed: { computed: {
startMonth() {
if (this.sortedDataList.length === 0) return '';
const date = new Date(this.sortedDataList[0].actionDate);
return `${date.getFullYear()}${date.getMonth() + 1}月`;
},
endMonth() {
if (this.sortedDataList.length === 0) return '';
const date = new Date(this.sortedDataList[this.sortedDataList.length - 1].actionDate);
return `${date.getFullYear()}${date.getMonth() + 1}月`;
},
sortedDataList() {
if (!this.dataList) return [];
// Clone and sort by date ascending (Old -> New)
return [...this.dataList].sort((a, b) => new Date(a.actionDate) - new Date(b.actionDate));
},
nodes() { nodes() {
// 计算每个节点的坐标(蛇形) // 计算每个节点的坐标(蛇形)
return this.dataList.map((item, idx) => { return this.sortedDataList.map((item, idx) => {
const row = Math.floor(idx / this.maxPerRow); const row = Math.floor(idx / this.maxPerRow);
const col = idx % this.maxPerRow; const col = idx % this.maxPerRow;
let x, y; let x, y;
const leftMargin = 10; // 你可以自定义这个值 // const leftMargin = 150; // 你可以自定义这个值
if (row % 2 === 0) { if (row % 2 === 0) {
x = leftMargin + col * this.nodeGapX + 50; x = this.leftMargin + col * this.nodeGapX + 50;
} else { } else {
x = leftMargin + (this.maxPerRow - 1 - col) * this.nodeGapX + 50; x = this.leftMargin + (this.maxPerRow - 1 - col) * this.nodeGapX + 50;
} }
// 节点纵坐标起始值 // 节点纵坐标起始值
y = 60 + row * this.nodeGapY; y = 60 + row * this.nodeGapY;
return { ...item, x, y, row };
// Format Date: 2025-07-04 -> 7月4日
const dateObj = new Date(item.actionDate);
const formattedDate = `${dateObj.getMonth() + 1}${dateObj.getDate()}日`;
// Format Votes
let voteString = '';
if (item.agreeVote !== null && item.disagreeVote !== null) {
voteString = `${item.agreeVote}票赞成 : ${item.disagreeVote}票反对`;
}
return { ...item, x, y, row, formattedDate, voteString };
}); });
}, },
lines() { lines() {
...@@ -194,7 +233,7 @@ export default { ...@@ -194,7 +233,7 @@ export default {
console.log("prev", prev); console.log("prev", prev);
// 判断是否是行尾转折点 // 判断是否是行尾转折点
const isTurnPoint = i % 5 === 0; const isTurnPoint = i % this.maxPerRow === 0;
if (isTurnPoint) { if (isTurnPoint) {
// 计算半圆路径 // 计算半圆路径
...@@ -221,7 +260,7 @@ export default { ...@@ -221,7 +260,7 @@ export default {
return path; return path;
}, },
svgWidth() { svgWidth() {
return this.maxPerRow * this.nodeGapX + 100; return this.leftMargin + this.maxPerRow * this.nodeGapX + 50;
}, },
svgHeight() { svgHeight() {
// SVG高度 // SVG高度
...@@ -240,7 +279,7 @@ export default { ...@@ -240,7 +279,7 @@ export default {
align-items: center; align-items: center;
} }
.svg-timeline { .svg-timeline {
width: 1000px; width: 100%;
// background-size: 100% 100%; // background-size: 100% 100%;
// position: relative; // position: relative;
// .title { // .title {
...@@ -264,5 +303,40 @@ export default { ...@@ -264,5 +303,40 @@ export default {
// height: 24px; // height: 24px;
// } // }
// } // }
.node-content {
font-family: Microsoft YaHei, sans-serif;
text-align: left;
padding-left: 4px;
.date {
color: rgb(5, 95, 194);
font-weight: 700;
font-size: 14px;
line-height: 22px;
margin-bottom: 0px;
margin-top: 6px;
}
.title {
color: rgb(59, 65, 75);
font-weight: 700;
font-size: 14px;
line-height: 22px;
margin-bottom: 0px;
white-space: nowrap; /* Keep text on one line */
overflow: hidden; /* Hide overflow */
text-overflow: ellipsis; /* Show ... for overflow */
width: 100%; /* Ensure it takes full width of container */
display: block; /* Block level for ellipsis to work */
}
.votes {
color: rgb(95, 101, 108);
font-size: 14px;
font-weight: 400;
line-height: 22px;
}
}
} }
</style> </style>
...@@ -31,9 +31,10 @@ ...@@ -31,9 +31,10 @@
<div class="box1-right-item"> <div class="box1-right-item">
<div class="item-left">相关领域:</div> <div class="item-left">相关领域:</div>
<div class="item-right1"> <div class="item-right1">
<div class="right1-item">跨境电商</div> <!-- <div class="right1-item">跨境电商</div>
<div class="right1-item">新能源产业</div> <div class="right1-item">新能源产业</div>
<div class="right1-item">半导体产业</div> <div class="right1-item">半导体产业</div> -->
<div class="right1-item" v-for="item in basicInfo.hylyList" :key="item">{{ item }}</div>
</div> </div>
</div> </div>
<div class="box1-right-item"> <div class="box1-right-item">
...@@ -81,7 +82,7 @@ ...@@ -81,7 +82,7 @@
<div class="box-header"> <div class="box-header">
<div class="header-left"></div> <div class="header-left"></div>
<div class="title">法案进展</div> <div class="title">法案进展</div>
<div class="header-btn-box"> <!-- <div class="header-btn-box">
<div class="btn" @click="handleClcikBox2Btn(1)"> <div class="btn" @click="handleClcikBox2Btn(1)">
<el-badge :value="warningNum"> <el-badge :value="warningNum">
<el-button type="primary" plain v-if="box2BtnActive === 1">最新进展</el-button> <el-button type="primary" plain v-if="box2BtnActive === 1">最新进展</el-button>
...@@ -92,7 +93,7 @@ ...@@ -92,7 +93,7 @@
<el-button type="primary" plain v-if="box2BtnActive === 2">前期进展</el-button> <el-button type="primary" plain v-if="box2BtnActive === 2">前期进展</el-button>
<el-button type="info" plain v-else>前期进展</el-button> <el-button type="info" plain v-else>前期进展</el-button>
</div> </div>
</div> </div> -->
<div class="header-right"> <div class="header-right">
<div class="icon"> <div class="icon">
<img src="@/assets/icons/box-header-icon2.png" alt="" /> <img src="@/assets/icons/box-header-icon2.png" alt="" />
...@@ -104,8 +105,8 @@ ...@@ -104,8 +105,8 @@
</div> </div>
<div class="box2-main"> <div class="box2-main">
<div class="box2-main-center"> <div class="box2-main-center">
<STimeline v-if="box2BtnActive == 2" :dataList="timelineData" /> <STimeline :dataList="timelineData" />
<div class="box2-center-item-box" v-if="box2BtnActive == 1"> <!-- <div class="box2-center-item-box" v-if="box2BtnActive == 1">
<div class="box2-center-item" v-for="(item, index) in progressList" :key="index"> <div class="box2-center-item" v-for="(item, index) in progressList" :key="index">
<div class="tip" :class="{ tipActive: item.fxdj }"></div> <div class="tip" :class="{ tipActive: item.fxdj }"></div>
<div class="date">{{ item.actionDate }}</div> <div class="date">{{ item.actionDate }}</div>
...@@ -128,7 +129,7 @@ ...@@ -128,7 +129,7 @@
<el-icon size="22" color="#777"><ArrowRightBold /></el-icon> <el-icon size="22" color="#777"><ArrowRightBold /></el-icon>
</div> </div>
</div> </div>
</div> </div> -->
</div> </div>
</div> </div>
<div class="box2-footer"> <div class="box2-footer">
...@@ -210,15 +211,15 @@ ...@@ -210,15 +211,15 @@
<div <div
class="tag-box" class="tag-box"
:class="{ :class="{
status0: tag.status === 0, status0: index === 0 || index === 4,
status1: tag.status === 1, status1: index === 1 || index === 5,
status2: tag.status === 2, status2: index === 2 || index === 6,
status3: tag.status === 3 status3: index === 3 || index === 7
}" }"
v-for="(tag, index) in tagList" v-for="(tag, index) in curPerson.tagList"
:key="index" :key="index"
> >
{{ tag.title }} {{ tag }}
</div> </div>
</div> </div>
<div class="right-main-box3"> <div class="right-main-box3">
...@@ -231,13 +232,13 @@ ...@@ -231,13 +232,13 @@
<div class="right-main-box3-main"> <div class="right-main-box3-main">
<el-timeline style="max-width: 500px"> <el-timeline style="max-width: 500px">
<el-timeline-item <el-timeline-item
:timestamp="item.sjsj" :timestamp="item.newsDate"
placement="top" placement="top"
v-for="(item, index) in personEventList" v-for="(item, index) in curPerson.newsList"
:key="index" :key="index"
> >
<div class="timeline-content"> <div class="timeline-content">
{{ item.sjnr }} {{ item.newsContent }}
</div> </div>
</el-timeline-item> </el-timeline-item>
<!-- <el-timeline-item timestamp="2018/4/3" placement="top"> <!-- <el-timeline-item timestamp="2018/4/3" placement="top">
...@@ -324,14 +325,14 @@ ...@@ -324,14 +325,14 @@
<div class="inner-right-main"> <div class="inner-right-main">
<el-timeline style="max-width: 840px"> <el-timeline style="max-width: 840px">
<el-timeline-item <el-timeline-item
:timestamp="item.sjsj" :timestamp="item.newsDate"
placement="top" placement="top"
v-for="(item, index) in personEventList" v-for="(item, index) in curPerson.newsList"
:key="index" :key="index"
> >
<div class="timeline-content1"> <div class="timeline-content1">
<div class="text"> <div class="text">
{{ item.sjnr }} {{ item.newsContent }}
</div> </div>
<div class="pic"> <div class="pic">
<img src="./assets/imgs/img1.png" alt="" /> <img src="./assets/imgs/img1.png" alt="" />
...@@ -544,6 +545,7 @@ const handleGetBasicInfo = async () => { ...@@ -544,6 +545,7 @@ const handleGetBasicInfo = async () => {
const res = await getBillInfo(params); const res = await getBillInfo(params);
console.log("基本信息", res); console.log("基本信息", res);
basicInfo.value = res.data basicInfo.value = res.data
basicInfo.value.stageList.reverse()
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
...@@ -552,24 +554,24 @@ const handleGetBasicInfo = async () => { ...@@ -552,24 +554,24 @@ const handleGetBasicInfo = async () => {
const warningNum = ref(0); const warningNum = ref(0);
// 法案进展 获取最新进展 // 法案进展 获取最新进展
const handleGetBillEvent = async () => { // const handleGetBillEvent = async () => {
warningNum.value = 0; // warningNum.value = 0;
const params = { // const params = {
id: window.sessionStorage.getItem("billId") // id: window.sessionStorage.getItem("billId")
}; // };
try { // try {
const res = await getBillEvent(params); // const res = await getBillEvent(params);
console.log("最新进展", res); // console.log("最新进展", res);
progressList.value = res.data; // progressList.value = res.data;
progressList.value.forEach(item => { // progressList.value.forEach(item => {
if (item.fxdj) { // if (item.fxdj) {
warningNum.value++; // warningNum.value++;
} // }
}); // });
} catch (error) { // } catch (error) {
console.error(error); // console.error(error);
} // }
}; // };
// 法案进展 获取前期进展 --也是提出人左上角列表 // 法案进展 获取前期进展 --也是提出人左上角列表
const handleGetBillDyqk = async () => { const handleGetBillDyqk = async () => {
...@@ -601,9 +603,26 @@ const curPerson = ref({}); ...@@ -601,9 +603,26 @@ const curPerson = ref({});
const personEventList = ref([]); const personEventList = ref([]);
// 提出人 --动议id // 提出人 --动议id
const handleGetBillPerson = async id => { // const handleGetBillPerson = async id => {
// const params = {
// id: id
// };
// try {
// const res = await getBillPerson(params);
// console.log("提出人", res);
// personList.value = res.data;
// box3BtnActive.value = res.data.length ? res.data[0].name : "";
// curPerson.value = res.data.length ? res.data[0] : {};
// personEventList.value = res.data.length ? res.data[0].eventList : [];
// } catch (error) {
// console.error(error);
// }
// };
// 法案提出人
const handleGetBillPerson = async () => {
const params = { const params = {
id: id billId: window.sessionStorage.getItem("billId")
}; };
try { try {
const res = await getBillPerson(params); const res = await getBillPerson(params);
...@@ -619,8 +638,9 @@ const handleGetBillPerson = async id => { ...@@ -619,8 +638,9 @@ const handleGetBillPerson = async id => {
onMounted(() => { onMounted(() => {
handleGetBasicInfo(); handleGetBasicInfo();
handleGetBillEvent(); // handleGetBillEvent();
handleGetBillDyqk(); handleGetBillDyqk();
handleGetBillPerson();
}); });
</script> </script>
...@@ -695,11 +715,11 @@ onMounted(() => { ...@@ -695,11 +715,11 @@ onMounted(() => {
.box1-right { .box1-right {
margin-left: 31px; margin-left: 31px;
margin-top: 5px; margin-top: 5px;
width: 623px; // width: 623px;
height: 350px; height: 350px;
.box1-right-item { .box1-right-item {
display: flex; display: flex;
margin-bottom: 24px; margin-bottom: 21px;
.item-left { .item-left {
width: 100px; width: 100px;
height: 14px; height: 14px;
...@@ -722,7 +742,23 @@ onMounted(() => { ...@@ -722,7 +742,23 @@ onMounted(() => {
} }
.item-right1 { .item-right1 {
display: flex; display: flex;
align-items: center;
width: 700px;
height: 40px;
overflow-x: auto;
overflow-y: hidden;
&::-webkit-scrollbar {
height: 4px;
}
&::-webkit-scrollbar-thumb {
border-radius: 4px;
background: #e1e1e1;
}
&::-webkit-scrollbar-track {
background: transparent;
}
.right1-item { .right1-item {
flex-shrink: 0;
margin-right: 10px; margin-right: 10px;
padding: 1px 8px; padding: 1px 8px;
box-sizing: border-box; box-sizing: border-box;
...@@ -774,10 +810,14 @@ onMounted(() => { ...@@ -774,10 +810,14 @@ onMounted(() => {
text-align: center; text-align: center;
position: relative; position: relative;
.step-box { .step-box {
padding: 0 10px 0 20px; padding: 4px 10px;
color: #333; color: #333;
position: relative; position: relative;
font-size: 14px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 14px;
margin-left: 10px;
.right-arrow { .right-arrow {
position: absolute; position: absolute;
right: -21px; right: -21px;
...@@ -792,7 +832,7 @@ onMounted(() => { ...@@ -792,7 +832,7 @@ onMounted(() => {
} }
} }
.step-box-active { .step-box-active {
padding: 0 12px; padding: 4 10px;
color: #fff; color: #fff;
background: #ce4f51; background: #ce4f51;
position: relative; position: relative;
...@@ -851,11 +891,13 @@ onMounted(() => { ...@@ -851,11 +891,13 @@ onMounted(() => {
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1); box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
.box2-main { .box2-main {
margin-top: 10px; margin-top: 10px;
height: calc(100% - 70px); // Subtract header height
width: 100%;
.box2-main-center { .box2-main-center {
margin-left: 23px; margin-left: 23px;
border-top: 1px solid rgba(243, 243, 244, 1); border-top: 1px solid rgba(243, 243, 244, 1);
// width: 100%; width: calc(100% - 46px); // Subtract margin
height: 300px; height: 100%;
// background: orange; // background: orange;
.box2-center-item { .box2-center-item {
display: flex; display: flex;
...@@ -1082,10 +1124,10 @@ onMounted(() => { ...@@ -1082,10 +1124,10 @@ onMounted(() => {
} }
} }
.right-main-box2 { .right-main-box2 {
width: 576px; // width: 576px;
height: 150px; // height: 150px;
box-sizing: border-box; box-sizing: border-box;
padding: 10px 26px; padding: 22px 26px;
// border-bottom: 1px solid rgb(243, 243, 244); // border-bottom: 1px solid rgb(243, 243, 244);
// display: flex; // display: flex;
// flex-wrap: wrap; // flex-wrap: wrap;
...@@ -1140,7 +1182,7 @@ onMounted(() => { ...@@ -1140,7 +1182,7 @@ onMounted(() => {
} }
.right-main-box3-main { .right-main-box3-main {
margin-top: 18px; margin-top: 18px;
height: 299px; height: 412px;
overflow-y: auto; overflow-y: auto;
} }
.right-main-box3-footer { .right-main-box3-footer {
...@@ -1330,6 +1372,10 @@ onMounted(() => { ...@@ -1330,6 +1372,10 @@ onMounted(() => {
color: var(--btn-active-text-color); color: var(--btn-active-text-color);
} }
} }
.inner-right-main {
height: 860px;
overflow: auto;
}
} }
} }
} }
......
...@@ -16,9 +16,15 @@ ...@@ -16,9 +16,15 @@
</div> </div>
<div class="left-top"> <div class="left-top">
<el-select v-model="curBill" placeholder="请选择" style="width: 240px" @change="handleChangeBill"> <el-select v-model="curBill" placeholder="请选择" style="width: 240px" @change="handleChangeBill">
<el-option v-for="item in billList" :key="item.value" :label="item.label" :value="item.id" /> <el-option v-for="item in billList" :key="item.id" :label="item.label" :value="item.value" />
</el-select> </el-select>
<el-checkbox style="margin-left: 30px" v-model="checkedValue" label="只看涉华条款" size="large" /> <el-checkbox
style="margin-left: 30px"
v-model="checkedValue"
label="只看涉华条款"
size="large"
@change="handleChangeCheckbox"
/>
<div class="search" style="width: 240px; margin-left: 475px"> <div class="search" style="width: 240px; margin-left: 475px">
<el-input v-model="searchValue" style="width: 240px" placeholder="搜索条款" /> <el-input v-model="searchValue" style="width: 240px" placeholder="搜索条款" />
<div class="icon"> <div class="icon">
...@@ -28,32 +34,32 @@ ...@@ -28,32 +34,32 @@
</div> </div>
<div class="left-main"> <div class="left-main">
<div class="left-main-item" v-for="(term, index) in mainTermsList" :key="index"> <div class="left-main-item" v-for="(term, index) in mainTermsList" :key="index">
<div class="id">{{ index + 1 }}</div> <div class="id">{{ (currentPage - 1) * pageSize + index + 1 }}</div>
<div class="info"> <div class="info">
<div class="title"> <div class="title">
<span class="title-active">{{ term.header }}</span> <span class="title-active">{{ term.tkxh }}条.</span>
{{ term.title }} {{ term.fynr }}
</div> </div>
<div class="content"> <div class="content">
<span class="content-active">{{ term.headerEn }}</span> <span class="content-active">Sec.{{ term.tkxh }}</span>
{{ term.content }} {{ term.ywnr }}
</div> </div>
</div> </div>
<div class="tags-box"> <div class="tags-box">
<div <div
class="tag" class="tag"
v-for="(val, idx) in term.tags" v-for="(val, idx) in (term.hylyList || []).slice(0, 2)"
:key="idx" :key="idx"
:class="{ :class="{
tag1: val.status === 1, 'tag1': val === '人工智能',
tag2: val.status === 2, 'tag2': val === '新一代信息技术' || !['人工智能', '政治', '经济', '军事', '科技'].includes(val),
tag3: val.status === 3, 'tag3': val === '政治',
tag4: val.status === 4, 'tag4': val === '经济',
tag5: val.status === 5, 'tag5': val === '军事',
tag6: val.status === 6 'tag6': val === '科技'
}" }"
> >
{{ val.name }} {{ val }}
</div> </div>
</div> </div>
<div class="open"> <div class="open">
...@@ -63,10 +69,17 @@ ...@@ -63,10 +69,17 @@
</div> </div>
<div class="left-footer"> <div class="left-footer">
<div class="left-footer-text"> <div class="left-footer-text">
{{ "共96条涉华条款" }} {{ `共${total}条${checkedValue ? "涉华" : ""}条款` }}
</div> </div>
<div class="left-footer-right"> <div class="left-footer-right">
<el-pagination background layout="prev, pager, next" :total="96" /> <el-pagination
background
layout="prev, pager, next"
:total="total"
v-model:current-page="currentPage"
v-model:page-size="pageSize"
@current-change="handleCurrentChange"
/>
</div> </div>
</div> </div>
</div> </div>
...@@ -137,16 +150,12 @@ import { getBillContentId, getBillContentTk, getBillContentXzfs, getBillHyly } f ...@@ -137,16 +150,12 @@ import { getBillContentId, getBillContentTk, getBillContentXzfs, getBillHyly } f
const curBill = ref(""); const curBill = ref("");
const curBillId = ref(null); const curBillId = ref(null);
const billList = ref([ const checkedValue = ref(false);
{ const searchValue = ref("");
value: "公法(2025年7月4日)", const billList = ref([]);
label: "公法(2025年7月4日)" const currentPage = ref(1);
}, const pageSize = ref(10);
{ const total = ref(0);
value: "公法(2025年7月8日)",
label: "公法(2025年7月8日)"
}
]);
const mainTermsList = ref([ const mainTermsList = ref([
{ {
...@@ -351,7 +360,13 @@ const setChart = (option, chartId) => { ...@@ -351,7 +360,13 @@ const setChart = (option, chartId) => {
// 切换原文 // 切换原文
const handleChangeBill = val => { const handleChangeBill = val => {
curBillId.value = val; curBill.value = val;
const item = billList.value.find(item => item.value === val);
if (item) {
curBillId.value = item.id;
currentPage.value = 1;
handleGetBillContentTk(checkedValue.value ? "Y" : "N");
}
}; };
// 获取法案id列表 // 获取法案id列表
...@@ -369,22 +384,69 @@ const handleGetBillList = async () => { ...@@ -369,22 +384,69 @@ const handleGetBillList = async () => {
id: item.ywid id: item.ywid
}; };
}); });
curBill.value = billList.value[0].label; if (billList.value.length > 0) {
curBillId.value = billList.value[0].id; curBill.value = billList.value[0].value;
curBillId.value = billList.value[0].id;
}
} catch (error) {} } catch (error) {}
}; };
const handleChangeCheckbox = val => {
currentPage.value = 1;
handleGetBillContentTk(val ? "Y" : "N");
};
const handleCurrentChange = val => {
currentPage.value = val;
handleGetBillContentTk(checkedValue.value ? "Y" : "N");
};
// 根据原文ID获取条款列表 // 根据原文ID获取条款列表
const handleGetBillContentTk = async cRelated => { const handleGetBillContentTk = async cRelated => {
const params = { const params = {
id: curBillId.value, billid: window.sessionStorage.getItem("billId"),
id: curBill.value,
cRelated: cRelated, cRelated: cRelated,
currentPage: 0, currentPage: currentPage.value - 1,
pageSize: 10 pageSize: pageSize.value
}; };
try { try {
const res = await getBillContentTk(params); const res = await getBillContentTk(params);
console.log("条款内容", res); console.log("条款内容", res);
mainTermsList.value = res.data.content.map(item => {
// 处理 fynr
if (item.fynr) {
const matchComplex = item.fynr.match(/^(?:正文内容[::]\s*)?[“"]?\s*第\s*([0-9a-zA-Z]+)\s*[条节][::\.\。]?[”"]?\s*/);
if (matchComplex) {
// 匹配 "第xxx条"、"正文内容:第xxx条"、"“第xxx条" 等
if (!item.tkxh) {
item.tkxh = matchComplex[1];
}
item.fynr = item.fynr.replace(matchComplex[0], "");
} else {
// 匹配 "xxx."
item.fynr = item.fynr.replace(/^\d+\.\s*/, "");
}
}
// 处理 ywnr
if (item.ywnr) {
const matchSec = item.ywnr.match(/^(?:SEC\.|SECTION)\s*([0-9a-zA-Z]+)[\.:]?\s*/i);
if (matchSec) {
if (!item.tkxh) {
item.tkxh = matchSec[1];
}
item.ywnr = item.ywnr.replace(matchSec[0], "");
} else {
item.ywnr = item.ywnr.replace(/^\d+\.\s*/, "");
}
}
// 处理 tkxh 末尾的点
if (item.tkxh) {
item.tkxh = item.tkxh.replace(/\.$/, "");
}
return item;
});
total.value = res.data.totalElements;
} catch (error) {} } catch (error) {}
}; };
...@@ -430,7 +492,7 @@ const handleGetBillHyly = async () => { ...@@ -430,7 +492,7 @@ const handleGetBillHyly = async () => {
onMounted(async () => { onMounted(async () => {
await handleGetBillList(); await handleGetBillList();
handleGetBillContentTk(false); handleGetBillContentTk("N");
await handleGetBillContentXzfs(); await handleGetBillContentXzfs();
await handleGetBillHyly(); await handleGetBillHyly();
let chart1 = getPieChart(chart1Data.value, chart1ColorList.value); let chart1 = getPieChart(chart1Data.value, chart1ColorList.value);
...@@ -528,6 +590,7 @@ onMounted(async () => { ...@@ -528,6 +590,7 @@ onMounted(async () => {
border-radius: 2px; border-radius: 2px;
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
display: flex; display: flex;
position: relative;
.id { .id {
margin-top: 20px; margin-top: 20px;
margin-left: 15px; margin-left: 15px;
...@@ -543,7 +606,7 @@ onMounted(async () => { ...@@ -543,7 +606,7 @@ onMounted(async () => {
.info { .info {
margin-left: 13px; margin-left: 13px;
margin-top: 15px; margin-top: 15px;
width: 813px; width: 780px;
.title { .title {
height: 14px; height: 14px;
color: rgba(59, 65, 75, 1); color: rgba(59, 65, 75, 1);
...@@ -577,20 +640,19 @@ onMounted(async () => { ...@@ -577,20 +640,19 @@ onMounted(async () => {
} }
} }
.tags-box { .tags-box {
margin-left: 20px;
margin-top: 21px;
width: 160px;
height: 22px;
display: flex; display: flex;
justify-content: flex-end; justify-content: right;
align-items: center;
flex: 1;
margin-right: 50px;
.tag { .tag {
height: 18px; text-align: right;
line-height: 18px; line-height: 18px;
padding: 0 8px; padding: 1px 8px;
border-radius: 4px; border-radius: 4px;
margin-left: 5px; margin-left: 5px;
font-size: 12px; font-size: 12px;
font-family: Microsoft YaHei; font-family: "Microsoft YaHei";
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
} }
...@@ -626,8 +688,9 @@ onMounted(async () => { ...@@ -626,8 +688,9 @@ onMounted(async () => {
} }
} }
.open { .open {
margin-left: 10px; position: absolute;
margin-top: 22px; top: 22px;
right: 23px;
width: 20px; width: 20px;
height: 20px; height: 20px;
img { img {
......
...@@ -4,6 +4,7 @@ const getPieChart = (data,colorList) => { ...@@ -4,6 +4,7 @@ const getPieChart = (data,colorList) => {
series: [ series: [
{ {
type: 'pie', type: 'pie',
minAngle: 28,
radius: [70, 100], radius: [70, 100],
height: '100%', height: '100%',
left: 'center', left: 'center',
...@@ -38,7 +39,9 @@ const getPieChart = (data,colorList) => { ...@@ -38,7 +39,9 @@ const getPieChart = (data,colorList) => {
? params.labelRect.x ? params.labelRect.x
: params.labelRect.x + params.labelRect.width; : params.labelRect.x + params.labelRect.width;
return { return {
labelLinePoints: points labelLinePoints: points,
hideOverlap: false,
moveOverlap: 'shiftY'
}; };
}, },
data: data data: data
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论