提交 47bc38c9 authored 作者: 张伊明's avatar 张伊明

feat 新增法案原文页面

feat 完成法案概况-内容概要页面 fix 修复法案首页某些bug
上级 fd608e1e
......@@ -117,7 +117,7 @@ export function getBillContentId(params) {
// 主要条款-根据原文ID获取条款内容
/**
* @param {billid,id,cRelated,currentPage,pageSize}
* @param {billId,id,cRelated,currentPage,pageSize,domainNameList,measuresNameList,content}
* @header token
*/
export function getBillContentTk(params) {
......
......@@ -145,6 +145,16 @@ export function getBillsPersonRel(params, signal) {
})
}
// 获取涉华委员会及其法案
export function getBillsIsCnCommittee(params, signal) {
return request({
method: 'GET',
url: `/api/BillOverview/billsIsCnCommittee`,
params,
signal
})
}
// 获取提出部门列表
export function getPostOrgList() {
return request({
......
......@@ -72,6 +72,15 @@ service.interceptors.response.use(
},
error => {
console.log('err' + error)
const isCanceledError =
error?.code === 'ERR_CANCELED' ||
error?.name === 'CanceledError' ||
error?.name === 'AbortError' ||
(typeof error?.message === 'string' && /canceled/i.test(error.message))
// 重复请求触发的取消不提示错误
if (isCanceledError) return Promise.reject(error)
// 处理token过期或无效的情况
if (error.response && (error.response.status === 401 || error.response.status === 403)) {
......
......@@ -2,14 +2,14 @@
<div class="sider-tabs-wrapper">
<div class="sider-item"
:class="{'sider-item-active': sider.active}"
v-for="sider, index in siderList" :key="index"
v-for="(sider, index) in siderList" :key="sider.name || index"
@click="handleClickSiderItem(sider)"
>
<div
class="sider-item-text text-primary-65-clor text-tip-1"
:class="{'sider-item-text-active': sider.active}">{{ sider.name }}</div>
<div class="sider-item-icon" v-show="sider.active">
<img src="./active-icon.svg" alt="">
<img src="./active-icon.svg" alt="" />
</div>
</div>
</div>
......@@ -20,7 +20,7 @@
const props = defineProps({
siderList: {
type: Array,
default: [
default: () => [
{
name: '分析内容1',
active: true
......
......@@ -47,21 +47,38 @@ const props = defineProps({
showAllBtn: {
type: Boolean,
default: true
},
// 当业务功能尚未实现时,点击右上角图标仅弹出统一提示
devTip: {
type: Boolean,
default: false
}
})
const handleSave = () => {
if (props.devTip) {
ElMessage.warning('当前功能正在开发中,敬请期待!')
return
}
ElMessage.success('保存当前内容')
// emit('save')
}
const handleDownload = () => {
if (props.devTip) {
ElMessage.warning('当前功能正在开发中,敬请期待!')
return
}
ElMessage.success('下载当前内容')
// emit('download')
}
const handleCollect = () => {
if (props.devTip) {
ElMessage.warning('当前功能正在开发中,敬请期待!')
return
}
ElMessage.success('收藏当前内容')
// emit('collect')
......
......@@ -13,6 +13,7 @@ const BillInfluenceLayout = () => import('@/views/bill/influence/index.vue')
const BillInfluenceIndustry = () => import('@/views/bill/influence/industry/index.vue')
const BillInfluenceScientificResearch = () => import('@/views/bill/influence/scientificResearch/index.vue')
const BillRelevantCircumstance = () => import('@/views/bill/relevantCircumstance/index.vue')
const BillOriginalText = () => import('@/views/bill/billOriginalText/index.vue')
const billRoutes = [
......@@ -35,6 +36,14 @@ const billRoutes = [
dynamicTitle: true // 标记需要动态设置标题
},
children: [
{
path: "originalText",
name: "BillOriginalText",
component: BillOriginalText,
meta: {
title: "法案原文"
}
},
// 法案分析路由
{
path: "bill",
......
......@@ -51,7 +51,7 @@ const initChart = () => {
color: "#fff",
backgroundColor: "rgba(189, 33, 33, 0.9)",
borderRadius: 20,
padding: [8, 16] // 适当增加 padding 以确保背景块足够大
padding: [10, 16] // 适当增加 padding 以确保背景块足够大
}
};
}
......
<template>
<div class="background-wrap">
<div class="background-wrap-left">
<AnalysisBox class="left-box left-box--background" title="立法背景" :showAllBtn="false">
<AnalysisBox class="left-box left-box--background" title="立法背景" :showAllBtn="false" :devTip="true">
<template #header-btn>
<div class="header-btn-box">
<el-button :type="box1Btn1Type" plain @click="handleClickBox1Btn(1)">涉华背景</el-button>
......@@ -28,7 +28,7 @@
</div>
</AnalysisBox>
<AnalysisBox class="left-box left-box--event" title="相关事件" :showAllBtn="false">
<AnalysisBox class="left-box left-box--event" title="相关事件" :showAllBtn="false" :devTip="true">
<div class="box2-main">
<div class="box2-main-item" v-for="item in eventDisplayList" :key="item.id" @click="handleClickEvent(item)">
<div class="left">
......@@ -47,7 +47,7 @@
</div>
</AnalysisBox>
</div>
<AnalysisBox class="right-panel" title="议员相关性分析" :showAllBtn="false">
<AnalysisBox class="right-panel" title="议员相关性分析" :showAllBtn="false" :devTip="true">
<template #header-btn>
<div class="header-btn-box">
<el-button :type="box2Btn1Type" plain @click="handleClickBox2Btn(1)">赞成议员</el-button>
......@@ -266,7 +266,7 @@ const handleGetRelatedEvent = async () => {
};
try {
const res = await getBillInfoEvent(params);
eventList.value = res.data;
eventList.value = res.data.slice(0, 5);
} catch (error) { }
};
......
......@@ -101,7 +101,13 @@
<DivideHeader id="position2" class="divide2" :titleText="'资讯要闻'"></DivideHeader>
<div class="center-center">
<NewsList :list="newsList" />
<NewsList
:newsList="newsList"
img="newsImage"
title="newsTitle"
from="from"
content="newsContent"
/>
<MessageBubble :messageList="messageList" imageUrl="personImage"
@more-click="handleToSocialDetail" @person-click="handleClickToCharacter" name="personName"
content="remarks" source="orgName" />
......@@ -116,9 +122,12 @@
<el-option v-for="item in categoryList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</template>
<div class="box5-main" :style="getEmptyStateStyle(box5HasData)">
<el-empty v-if="!box5HasData" description="暂无数据" :image-size="100" />
<div v-else id="box5Chart" style="width: 100%; height: 100%"></div>
<div class="overview-card-body box5-main">
<div class="overview-chart-wrap" :class="{ 'is-empty': !box5HasData }">
<el-empty v-if="!box5HasData" description="暂无数据" :image-size="100" />
<div v-else id="box5Chart" class="overview-chart"></div>
</div>
<TipTab class="overview-tip" />
</div>
</OverviewCard>
<OverviewCard class="overview-card--single box6" title="涉华法案领域分布" :icon="box6HeaderIcon">
......@@ -127,9 +136,12 @@
<el-option v-for="item in box9YearList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
<div class="box6-main" :style="getEmptyStateStyle(box9HasData)">
<el-empty v-if="!box9HasData" description="暂无数据" :image-size="100" />
<div v-else id="box9Chart" style="width: 100%; height: 100%"></div>
<div class="overview-card-body box6-main">
<div class="overview-chart-wrap" :class="{ 'is-empty': !box9HasData }">
<el-empty v-if="!box9HasData" description="暂无数据" :image-size="100" />
<div v-else id="box9Chart" class="overview-chart"></div>
</div>
<TipTab class="overview-tip" />
</div>
</OverviewCard>
</div>
......@@ -140,9 +152,12 @@
<el-option v-for="item in box7YearList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
<div class="box7-main" :style="getEmptyStateStyle(box7HasData)">
<el-empty v-if="!box7HasData" description="暂无数据" :image-size="100" />
<div v-else id="box7Chart" style="width: 100%; height: 100%"></div>
<div class="overview-card-body box7-main">
<div class="overview-chart-wrap" :class="{ 'is-empty': !box7HasData }">
<el-empty v-if="!box7HasData" description="暂无数据" :image-size="100" />
<div v-else id="box7Chart" class="overview-chart"></div>
</div>
<TipTab class="overview-tip" />
</div>
</OverviewCard>
<OverviewCard class="overview-card--single box8" title="涉华法案进展分布" :icon="box7HeaderIcon">
......@@ -151,16 +166,24 @@
<el-option v-for="item in box8YearList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
<div class="box8-main" :style="getEmptyStateStyle(box8HasData)">
<el-empty v-if="!box8HasData" description="暂无数据" :image-size="100" />
<template v-else>
<div class="box8-desc">• 通过涉华法案{{ box8Summary }}</div>
<div id="box8Chart" class="box8-chart"></div>
</template>
<div class="overview-card-body box8-main">
<div class="overview-chart-wrap" :class="{ 'is-empty': !box8HasData }">
<el-empty v-if="!box8HasData" description="暂无数据" :image-size="100" />
<template v-else>
<div class="box8-desc">• 通过涉华法案{{ box8Summary }}</div>
<div id="box8Chart" class="overview-chart box8-chart"></div>
</template>
</div>
<TipTab class="overview-tip" />
</div>
</OverviewCard>
<OverviewCard class="overview-card--single box9" title="涉华法案关键条款" :icon="box7HeaderIcon">
<div class="box9-main" id="wordCloudChart"></div>
<div class="overview-card-body box9-main">
<div class="overview-chart-wrap">
<div id="wordCloudChart" class="overview-chart"></div>
</div>
<TipTab class="overview-tip" />
</div>
</OverviewCard>
</div>
</div>
......@@ -196,6 +219,7 @@ import overviewMainBox from "@/components/base/boxBackground/overviewMainBox.vue
import OverviewCard from "./OverviewCard.vue";
import ResourceLibrarySection from "./ResourceLibrarySection.vue";
import { useContainerScroll } from "@/hooks/useScrollShow";
import TipTab from "@/components/base/TipTab/index.vue";
import getMultiLineChart from "./utils/multiLineChart";
import getWordCloudChart from "./utils/worldCloudChart";
......@@ -325,12 +349,6 @@ const handleToMoreRiskSignal = () => {
// 风险信号
const warningList = ref([]);
const getEmptyStateStyle = hasData => ({
display: hasData ? "block" : "flex",
justifyContent: "center",
alignItems: "center"
});
const box7selectetedTime = ref("2025");
const box7YearList = ref([
{
......@@ -420,15 +438,15 @@ const handleGetNews = async () => {
try {
const res = await getNews(params);
console.log("新闻资讯", res);
if (res.code === 200) {
newsList.value =
res.data ||
[].map(item => {
return {
...item,
from: `${item.newsOrg} · ${item.newsDate ? item.newsDate.slice(5) : ""}`
};
});
if (res.code === 200 && Array.isArray(res.data)) {
newsList.value = res.data.map(item => {
return {
...item,
from: `${item.newsOrg} · ${item.newsDate ? item.newsDate.slice(5) : ""}`
};
});
} else {
newsList.value = [];
}
} catch (error) { }
};
......@@ -568,17 +586,28 @@ const handleBox7Data = async () => {
await nextTick();
const data1 = [];
const houseTotal = Number(orgBillNumMap?.H || 0);
const senateTotal = Number(orgBillNumMap?.S || 0);
const houseTotal = Number(orgBillNumMap?.House || 0);
const senateTotal = Number(orgBillNumMap?.Senate || 0);
if (houseTotal > 0) data1.push({ name: "众议院", value: houseTotal });
if (senateTotal > 0) data1.push({ name: "参议院", value: senateTotal });
const data2 = orgBillNumList.map(item => ({
name: item.orgName,
value: Number(item.count || 0),
percent: typeof item.percent === "number" ? item.percent : Number(item.percent || 0),
type: item.orgType === "S" ? "参议院" : "众议院"
}));
const getOrgTypeLabel = orgType => (orgType === "Senate" ? "参议院" : "众议院");
const typeOrderMap = { 众议院: 0, 参议院: 1 };
const data2 = orgBillNumList
.map(item => ({
name: item.orgName,
value: Number(item.count || 0),
percent: typeof item.percent === "number" ? item.percent : Number(item.percent || 0),
type: getOrgTypeLabel(item.orgType)
}))
// 关键:外环顺序必须按内环(众→参)分组,否则扇区角度会交错导致“不对应”
.sort((a, b) => {
const t1 = typeOrderMap[a.type] ?? 99;
const t2 = typeOrderMap[b.type] ?? 99;
if (t1 !== t2) return t1 - t2;
return (b.value ?? 0) - (a.value ?? 0);
});
const box7Chart = getDoublePieChart(data1, data2);
setChart(box7Chart, "box7Chart");
......@@ -2051,13 +2080,13 @@ onUnmounted(() => {
.box9-main {
height: 100%;
box-sizing: border-box;
padding: 8px 30px;
padding: 8px 30px 20px;
}
.box8-main {
height: 100%;
box-sizing: border-box;
padding: 12px 30px 18px;
padding: 12px 30px 20px;
.box8-desc {
height: 24px;
......@@ -2069,14 +2098,41 @@ onUnmounted(() => {
}
.box8-chart {
width: 100%;
height: calc(100% - 30px);
cursor: pointer;
}
}
.box9-main {
padding: 10px 30px;
padding: 10px 30px 20px;
}
.overview-card-body {
display: flex;
flex-direction: column;
}
.overview-chart-wrap {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
align-items: stretch;
justify-content: flex-start;
&.is-empty {
align-items: center;
justify-content: center;
}
}
.overview-chart {
width: 100%;
height: 100%;
min-height: 0;
}
.overview-tip {
margin-top: 10px;
}
}
}
......
......@@ -7,9 +7,22 @@ const truncateLabel = (value, maxLen = 6) => {
return `${chars.slice(0, maxLen).join('')}...`
}
const getCssVar = (varName, fallback) => {
try {
if (typeof window === 'undefined') return fallback
const val = window.getComputedStyle(document.documentElement).getPropertyValue(varName)
return (val || '').trim() || fallback
} catch (e) {
return fallback
}
}
const getDoublePieChart = (data1, data2) => {
const colorList = ['#8AC4FF', '#FFD591']
const colorList1 = ['#055FC2', '#FFA940']
const senateInnerColor = getCssVar('--color-primary-100', '#055FC2')
const senateDeptColor = getCssVar('--color-primary-50', '#89C1FF')
const houseInnerColor = 'rgba(255, 169, 64, 1)'
const houseDeptColor = 'rgba(255, 213, 145, 1)'
const innerLabelColor = getCssVar('--text-primary-80-color', '#3b414b')
let option = {
series: [
{
......@@ -26,14 +39,16 @@ const getDoublePieChart = (data1, data2) => {
position: 'inside',
fontSize: '16px',
fontWeight: 700,
// color: '#333'
color: innerLabelColor,
textBorderColor: '#fff',
textBorderWidth: 1
},
data: data1.map(item => {
return {
name: item.name,
value: item.value,
itemStyle: {
color: item.name === '参议院' ? '#055FC2' : '#FFA940'
color: item.name === '参议院' ? senateInnerColor : houseInnerColor
}
}
})
......@@ -70,7 +85,7 @@ const getDoublePieChart = (data1, data2) => {
time: {
fontSize: 14,
fontFamily: 'Microsoft YaHei',
color: '#rgba(95, 101, 108, 1)',
color: 'rgba(95, 101, 108, 1)',
padding: [10,0,10,0]
}
}
......@@ -97,7 +112,7 @@ const getDoublePieChart = (data1, data2) => {
value: item.value,
percent: item.percent,
itemStyle: {
color: item.type === '参议院' ? '#8AC4FF' : '#FFD591'
color: item.type === '参议院' ? senateDeptColor : houseDeptColor
}
}
......
<template>
<div class="header-main">
<div class="layout-main-header">
<div class="layout-main-header-left-box">
<div class="left-box-top">
<el-skeleton :loading="isLoading" animated>
<template #template>
<div class="icon">
<el-skeleton-item class="skeleton-avatar" variant="image" />
</div>
<div class="info">
<el-skeleton-item class="skeleton-title" variant="h1" />
<el-skeleton-item class="skeleton-subtitle" variant="text" />
</div>
</template>
<template #default>
<div class="icon">
<img :src="billInfo?.imageUrl || defaultLogo" alt="" />
</div>
<div class="info">
<div class="info-box1">{{ billInfo?.billName }}</div>
<div class="info-box2">{{ billInfo?.description }} {{ billInfo?.billNameEn }}</div>
</div>
</template>
</el-skeleton>
</div>
<div class="left-box-bottom" v-if="showTabs">
<template v-if="isLoading">
<div class="left-box-bottom-item is-skeleton" v-for="n in 4" :key="n">
<div class="icon">
<el-skeleton-item class="skeleton-tab-icon" variant="text" />
</div>
<div class="name">
<el-skeleton-item class="skeleton-tab-text" variant="text" />
</div>
</div>
</template>
<template v-else>
<div
class="left-box-bottom-item"
:class="{ leftBoxBottomItemActive: activeTitle === item.name }"
v-for="item in tabs"
:key="item.path"
@click="emit('tab-click', item)"
>
<div class="icon">
<img v-if="activeTitle === item.name" :src="item.activeIcon" alt="" />
<img v-else :src="item.icon" alt="" />
</div>
<div class="name" :class="{ nameActive: activeTitle === item.name }">
{{ item.name }}
</div>
</div>
</template>
</div>
</div>
<div class="layout-main-header-right-box">
<div class="right-box-top">
<el-skeleton :loading="isLoading" animated>
<template #template>
<div class="time">
<el-skeleton-item class="skeleton-right-line" variant="text" />
</div>
<div class="name">
<el-skeleton-item class="skeleton-right-line" variant="text" />
</div>
</template>
<template #default>
<div class="time">{{ billInfo?.introductionDate }}</div>
<div class="name">{{ billInfo?.tarName }}</div>
</template>
</el-skeleton>
</div>
<div class="right-box-bottom" v-if="showActions">
<template v-if="isLoading">
<div class="btn1 is-skeleton">
<div class="icon">
<el-skeleton-item class="skeleton-action-icon" variant="text" />
</div>
<div class="text">
<el-skeleton-item class="skeleton-action-text" variant="text" />
</div>
</div>
<div class="btn3 is-skeleton">
<div class="icon">
<el-skeleton-item class="skeleton-action-icon" variant="text" />
</div>
<div class="text">
<el-skeleton-item class="skeleton-action-text" variant="text" />
</div>
</div>
</template>
<template v-else>
<div class="btn1" @click="emit('open-original-text')">
<div class="icon">
<img :src="btnIconOriginalText" alt="" />
</div>
<div class="text">{{ "法案原文" }}</div>
</div>
<div class="btn3" @click="emit('open-analysis')">
<div class="icon">
<img :src="btnIconAnalysis" alt="" />
</div>
<div class="text">{{ "分析报告" }}</div>
</div>
</template>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from "vue";
import btnIconOriginalText from "@/views/thinkTank/ReportDetail/images/btn-icon1.png";
import btnIconAnalysis from "@/views/thinkTank/ReportDetail/images/btn-icon3.png";
const props = defineProps({
billInfo: {
type: Object,
default: () => ({})
},
defaultLogo: {
type: String,
default: ""
},
tabs: {
type: Array,
default: () => []
},
activeTitle: {
type: String,
default: ""
},
showTabs: {
type: Boolean,
default: true
},
showActions: {
type: Boolean,
default: true
}
});
const isLoading = computed(() => !props.billInfo || !props.billInfo.billName);
const emit = defineEmits(["tab-click", "open-original-text", "open-analysis"]);
</script>
<style lang="scss" scoped>
.skeleton-avatar {
width: 64px;
height: 64px;
border-radius: 50%;
}
.skeleton-title {
width: 360px;
height: 20px;
}
.skeleton-subtitle {
width: 520px;
height: 14px;
margin-top: 8px;
}
.skeleton-right-line {
width: 140px;
height: 14px;
}
.skeleton-tab-icon,
.skeleton-action-icon {
width: 16px;
height: 16px;
border-radius: 4px;
}
.skeleton-tab-text,
.skeleton-action-text {
width: 80px;
height: 14px;
border-radius: 6px;
}
.header-main {
position: sticky;
top: 0;
z-index: 1000;
width: 100%;
background-color: #fff;
box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.05);
overflow: hidden;
}
.layout-main-header {
width: 1600px;
background: #fff;
display: flex;
justify-content: space-between;
margin: 0 auto;
padding-top: 10px;
.layout-main-header-left-box {
width: 2600px;
.left-box-top {
height: 64px;
display: flex;
align-items: center;
justify-content: left;
margin-bottom: 21px;
:deep(.el-skeleton) {
width: 100%;
display: flex;
align-items: center;
}
.icon {
width: 64px;
height: 64px;
flex: 0 0 64px;
flex-shrink: 0;
img {
width: 100%;
height: 100%;
display: block;
object-fit: contain;
}
}
.info {
margin-left: 8px;
display: flex;
align-items: left;
flex-direction: column;
.info-box1 {
color: rgba(59, 65, 75, 1);
font-family: "Microsoft YaHei";
font-size: 20px;
font-weight: 600;
letter-spacing: 0px;
text-align: left;
}
.info-box2 {
margin-top: 4px;
color: rgba(132, 136, 142, 1);
font-family: "Microsoft YaHei";
font-size: 14px;
font-weight: 400;
letter-spacing: 0px;
text-align: left;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
.left-box-bottom {
display: flex;
height: 40px;
// margin-top: 21px;
.left-box-bottom-item {
display: flex;
margin-right: 32px;
margin-top: 3px;
height: 36px;
cursor: pointer;
.icon {
margin-top: 4px;
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.name {
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
margin-left: 3px;
}
.nameActive {
color: rgba(20, 89, 187, 1);
font-weight: 700;
}
}
.leftBoxBottomItemActive {
border-bottom: 3px solid rgba(20, 89, 187, 1);
}
}
}
.layout-main-header-right-box {
width: 600px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: right;
.right-box-top {
height: 64px;
display: flex;
align-items: right;
flex-direction: column;
justify-content: center;
:deep(.el-skeleton) {
width: 100%;
}
.time {
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: right;
}
.name {
margin-top: 4px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: right;
}
}
.right-box-bottom {
margin-bottom: 8px;
display: flex;
justify-content: flex-end;
gap: 8px;
.btn1 {
cursor: pointer;
width: 120px;
height: 36px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 6px;
background: rgba(255, 255, 255, 1);
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.text {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
}
.btn3 {
cursor: pointer;
width: 120px;
height: 36px;
border-radius: 6px;
background: rgba(5, 95, 194, 1);
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.text {
height: 24px;
color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
}
.is-skeleton {
pointer-events: none;
}
}
}
}
</style>
<template>
<div class="bill-original-text-page">
<div class="page-header">
<div class="page-title">法案原文</div>
<div class="page-actions">
<div class="action-btn" @click="handleBack">返回</div>
</div>
</div>
<div class="page-content">
<iframe v-if="billFullText" :src="billFullText" width="100%" height="100%" frameborder="0"></iframe>
<div v-else class="empty-state">暂无原文</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { getBillFullText } from "@/api/bill";
const route = useRoute();
const router = useRouter();
const billFullText = ref("");
const getBillFullTextFn = async () => {
const res = await getBillFullText({
id: route.query.billId
});
if (res.code === 200 && res.data) {
billFullText.value = typeof res.data === "string" ? res.data.trim() : res.data;
}
};
const handleBack = () => {
router.back();
};
onMounted(() => {
getBillFullTextFn();
});
</script>
<style lang="scss" scoped>
.bill-original-text-page {
width: 100%;
box-sizing: border-box;
background: rgba(248, 249, 250, 1);
padding: 0 0 20px;
.page-header {
width: 100%;
height: 64px;
display: flex;
align-items: center;
justify-content: space-between;
.page-title {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 700;
}
.page-actions {
display: flex;
justify-content: flex-end;
.action-btn {
cursor: pointer;
height: 32px;
line-height: 32px;
padding: 0 12px;
border-radius: 6px;
border: 1px solid rgba(230, 231, 232, 1);
background: rgba(255, 255, 255, 1);
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
}
}
}
.page-content {
width: 100%;
height: calc(100vh - 320px);
min-height: 600px;
background: #fff;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
overflow: hidden;
iframe {
display: block;
}
.empty-state {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
}
}
}
</style>
......@@ -2,20 +2,7 @@
<div class="home-container">
<div class="home-center">
<div class="home-sider">
<div
class="sider-btn"
:class="{ siderBtnActive: siderBtnActive === item.name }"
@click="handleClickLeftSiderBtn(item)"
v-for="item,index in siderBtnList"
:key="index"
>
<div class="btn-text">{{item.name}}</div>
<div class="btn-icon">
<el-icon v-if="siderBtnActive === item.name" color="#fff"
><CaretRight
/></el-icon>
</div>
</div>
<SiderTabs :siderList="siderTabs" @clickSiderItem="handleClickLeftSiderBtn" />
</div>
<div class="home-main">
<router-view />
......@@ -25,9 +12,10 @@
</template>
<script setup>
import { onMounted, ref } from "vue";
import { onMounted, ref, computed, watch } from "vue";
import { useRoute } from "vue-router";
import router from '@/router'
import SiderTabs from "@/components/base/SiderTabs/index.vue";
const route = useRoute();
......@@ -47,6 +35,20 @@ const siderBtnList = ref([
])
const siderBtnActive = ref("法案简介");
const getSiderActiveByRoutePath = path => {
if (path.includes("/billLayout/bill/background")) return "法案背景";
if (path.includes("/billLayout/bill/template")) return "内容概要";
return "法案简介";
};
const siderTabs = computed(() =>
siderBtnList.value.map(item => ({
...item,
active: siderBtnActive.value === item.name
}))
);
const handleClickLeftSiderBtn = (item) => {
siderBtnActive.value = item.name
router.push({
......@@ -58,6 +60,14 @@ const handleClickLeftSiderBtn = (item) => {
}
onMounted(() => {});
watch(
() => route.path,
(newPath) => {
siderBtnActive.value = getSiderActiveByRoutePath(newPath);
},
{ immediate: true }
);
</script>
<style lang="scss" scoped>
......@@ -168,10 +178,10 @@ onMounted(() => {});
height: 879px;
position: relative;
.home-sider {
width: 160px;
width: 120px;
position: absolute;
top: 8px;
left: -160px;
top: 16px;
left: -140px;
.sider-btn {
margin-top: 20px;
margin-left: 20px;
......
......@@ -17,7 +17,7 @@
<div class="item-title">{{ item.actionTitle }}</div>
</el-tooltip>
<div class="right">
<div v-if="item.riskText" class="risk-tag" :class="item.riskClass">{{ item.riskText }}</div>
<!-- <div v-if="item.riskText" class="risk-tag" :class="item.riskClass">{{ item.riskText }}</div> -->
<div class="arrow">></div>
</div>
</div>
......
<svg viewBox="0 0 12.375 13.5" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12.375000" height="13.500000" fill="none" customFrame="#000000">
<path id="矢量 359" d="M10.125 1L10.125 5.0625L11.375 5.0625C11.9273 5.0625 12.375 5.51022 12.375 6.0625L12.375 12.5C12.375 13.0523 11.9273 13.5 11.375 13.5L3.8125 13.5C3.26022 13.5 2.8125 13.0523 2.8125 12.5L2.8125 11.25L1 11.25C0.447715 11.25 0 10.8023 0 10.25L0 1C0 0.447715 0.447715 0 1 0L9.125 0C9.67728 0 10.125 0.447715 10.125 1ZM11.25 6.1875L10.125 6.1875L10.125 10.25C10.125 10.8023 9.67729 11.25 9.125 11.25L3.9375 11.25L3.9375 12.375L11.25 12.375L11.25 6.1875ZM9 1.125L1.125 1.125L1.125 10.125L9 10.125L9 1.125ZM6.1875 7.3125L6.1875 8.4375L2.8125 8.4375L2.8125 7.3125L6.1875 7.3125ZM7.3125 5.0625L7.3125 6.1875L2.8125 6.1875L2.8125 5.0625L7.3125 5.0625ZM7.3125 2.8125L7.3125 3.9375L2.8125 3.9375L2.8125 2.8125L7.3125 2.8125Z" fill="rgb(5,95,194)" fill-rule="nonzero" />
</svg>
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16.000000" height="16.000000" fill="none">
<rect id="翻译 1" width="16.000000" height="16.000000" x="0.000000" y="0.000000" />
<path id="矢量 455" d="M3.33398 10.0007L3.33398 11.334C3.33397 11.3756 3.3359 11.4171 3.33977 11.4585C3.34364 11.4999 3.34943 11.541 3.35715 11.5819C3.36487 11.6227 3.37448 11.6632 3.38598 11.7031C3.39748 11.7431 3.41082 11.7824 3.426 11.8211C3.44119 11.8599 3.45814 11.8978 3.47687 11.9349C3.4956 11.9721 3.51602 12.0082 3.53814 12.0434C3.56026 12.0787 3.58397 12.1128 3.60927 12.1458C3.63458 12.1788 3.66137 12.2105 3.68965 12.241C3.71793 12.2715 3.74757 12.3006 3.77857 12.3283C3.80957 12.3561 3.8418 12.3823 3.87525 12.407C3.9087 12.4317 3.94324 12.4548 3.97885 12.4762C4.01447 12.4977 4.051 12.5175 4.08847 12.5355C4.12593 12.5536 4.16416 12.5699 4.20314 12.5843C4.24213 12.5988 4.2817 12.6114 4.32187 12.6222C4.36204 12.633 4.40262 12.6419 4.44362 12.6488C4.48461 12.6558 4.52585 12.6609 4.56732 12.664L4.66732 12.6673L6.66732 12.6673L6.66732 14.0007L4.66732 14.0007C4.57998 14.0007 4.49285 13.9964 4.40594 13.9878C4.31902 13.9792 4.23273 13.9665 4.14708 13.9494C4.06142 13.9324 3.9768 13.9112 3.89322 13.8858C3.80965 13.8605 3.72752 13.8311 3.64683 13.7977C3.56614 13.7642 3.48728 13.7269 3.41026 13.6858C3.33324 13.6446 3.25841 13.5998 3.1858 13.5512C3.11318 13.5027 3.04311 13.4508 2.9756 13.3953C2.90809 13.3399 2.84346 13.2814 2.7817 13.2196C2.71994 13.1578 2.66136 13.0932 2.60596 13.0257C2.55055 12.9582 2.49859 12.8881 2.45007 12.8155C2.40154 12.7429 2.3567 12.6681 2.31553 12.591C2.27436 12.514 2.23706 12.4352 2.20364 12.3545C2.17022 12.2738 2.14083 12.1917 2.11548 12.1081C2.09012 12.0245 2.06893 11.9399 2.05189 11.8542C2.03485 11.7686 2.02205 11.6823 2.01349 11.5954C2.00493 11.5084 2.00065 11.4213 2.00065 11.334L2.00065 10.0007L3.33398 10.0007L3.33398 10.0007ZM12.0007 6.66732L14.934 14.0007L13.4973 14.0007L12.6967 12.0007L9.96999 12.0007L9.17065 14.0007L7.73465 14.0007L10.6673 6.66732L12.0007 6.66732L12.0007 6.66732ZM11.334 8.59065L10.5027 10.6673L12.164 10.6673L11.334 8.59065ZM5.33398 1.33398L5.33398 2.66732L8.00065 2.66732L8.00065 7.33398L5.33398 7.33398L5.33398 9.33398L4.00065 9.33398L4.00065 7.33398L1.33398 7.33398L1.33398 2.66732L4.00065 2.66732L4.00065 1.33398L5.33398 1.33398ZM11.334 2.00065C11.4213 2.00065 11.5084 2.00493 11.5954 2.01349C11.6823 2.02205 11.7686 2.03485 11.8542 2.05189C11.9399 2.06893 12.0245 2.09012 12.1081 2.11548C12.1917 2.14083 12.2738 2.17022 12.3545 2.20364C12.4352 2.23706 12.514 2.27436 12.591 2.31553C12.6681 2.3567 12.7429 2.40154 12.8155 2.45007C12.8881 2.49859 12.9582 2.55055 13.0257 2.60596C13.0932 2.66136 13.1578 2.71994 13.2196 2.7817C13.2814 2.84346 13.3399 2.90809 13.3953 2.9756C13.4508 3.04311 13.5027 3.11318 13.5512 3.1858C13.5998 3.25841 13.6446 3.33324 13.6858 3.41026C13.7269 3.48728 13.7642 3.56614 13.7977 3.64683C13.8311 3.72752 13.8605 3.80965 13.8858 3.89323C13.9112 3.9768 13.9324 4.06142 13.9494 4.14708C13.9665 4.23274 13.9793 4.31902 13.9878 4.40594C13.9964 4.49286 14.0007 4.57998 14.0007 4.66732L14.0007 6.00065L12.6673 6.00065L12.6673 4.66732C12.6673 4.62365 12.6652 4.58009 12.6609 4.53663C12.6566 4.49317 12.6502 4.45003 12.6417 4.4072C12.6332 4.36437 12.6226 4.32206 12.6099 4.28027C12.5972 4.23848 12.5825 4.19742 12.5658 4.15707C12.5491 4.11673 12.5305 4.0773 12.5099 4.03879C12.4893 4.00028 12.4669 3.96287 12.4426 3.92656C12.4184 3.89025 12.3924 3.85522 12.3647 3.82146C12.337 3.7877 12.3077 3.75539 12.2768 3.72451C12.2459 3.69363 12.2136 3.66434 12.1798 3.63664C12.1461 3.60893 12.1111 3.58295 12.0747 3.55869C12.0384 3.53443 12.001 3.51201 11.9625 3.49142C11.924 3.47084 11.8846 3.45219 11.8442 3.43548C11.8039 3.41877 11.7628 3.40407 11.721 3.3914C11.6792 3.37872 11.6369 3.36812 11.5941 3.3596C11.5513 3.35108 11.5081 3.34468 11.4647 3.3404C11.4212 3.33612 11.3777 3.33398 11.334 3.33398L9.33399 3.33398L9.33399 2.00065L11.334 2.00065L11.334 2.00065ZM4.00065 4.00065L2.66732 4.00065L2.66732 6.00065L4.00065 6.00065L4.00065 4.00065ZM6.66732 4.00065L5.33398 4.00065L5.33398 6.00065L6.66732 6.00065L6.66732 4.00065Z" fill="rgb(95,101,108)" fill-rule="nonzero" />
</svg>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论