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

feat 抽取政令原文组件形成公共组件

上级 0b438adc
<template>
<div class="layout-container">
<div class="layout-main">
<div class="header-main">
<div class="layout-main-header">
<div class="icon">
<img :src="summaryInfo?.imageUrl" alt="" />
</div>
<div class="info">
<div class="info-box1 one-line-ellipsis">{{ summaryInfo?.name || "--" }}</div>
<div class="info-box2">
<div class="info-box2-item">{{ summaryInfo?.postDate || "--" }}</div>
|
<div class="info-box2-item">{{ summaryInfo?.orgName || "--" }}</div>
|
<div class="info-box2-item one-line-ellipsis">{{ summaryInfo?.ename || "--" }}</div>
</div>
</div>
<div class="layout-main-header-right-box">
<div class="right-box-top">
<div class="time">{{ summaryInfo?.postDate || "--" }}</div>
<div class="name">{{ summaryInfo?.orgName || "--" }}</div>
</div>
</div>
</div>
</div>
<div class="layout-main-center">
<div class="report-header">
<div class="report-title">政令原文</div>
<el-switch v-model="isHighlight" />
<div class="switch-label switch-label-left">高亮实体</div>
<el-switch v-model="isTranslate" />
<div class="switch-label">原文显示</div>
<div class="btn" @click="emits('download')">
<div class="icon icon-gap-4">
<img :src="defaultDownloadIcon" alt="" />
</div>
<div class="text">下载</div>
</div>
<div class="btn" @click="handleFindWord('open')">
<div class="icon icon-gap-6">
<img :src="defaultSearchIcon" alt="" />
</div>
<div class="text">查找</div>
</div>
<div class="find-word-box" v-if="findWordBox">
<div class="find-word-input">
<el-input
v-model="findWordTxt"
placeholder="查找原文内容"
@input="handleUpdateWord"
/>
</div>
<div class="find-word-limit">{{ findWordNum }}/{{ findWordMax }}</div>
<div class="find-word-icon" @click="handleFindWord('last')">
<el-icon><ArrowUp /></el-icon>
</div>
<div class="find-word-icon" @click="handleFindWord('next')">
<el-icon><ArrowDown /></el-icon>
</div>
<div class="find-word-icon" @click="handleFindWord('close')">
<el-icon><Close /></el-icon>
</div>
</div>
</div>
<div class="report-main">
<div v-if="!displayReportData.length" class="noContent">{{ "暂无数据" }}</div>
<el-scrollbar height="100%" v-else>
<div
v-for="item in displayReportData"
:key="item.num"
:class="['content-row', { 'high-light': isHighlight }]"
>
<div :class="['content-cn', { 'translate-cn': !isTranslate }]" v-html="item.content"></div>
<div class="content-en" v-html="item.contentEn" v-if="isTranslate"></div>
</div>
</el-scrollbar>
</div>
</div>
</div>
</div>
</template>
<script setup>
import defaultDownloadIcon from "./assets/icons/download.png";
import defaultSearchIcon from "./assets/icons/search.png";
import { nextTick, ref, watch } from "vue";
import { debounce } from "lodash";
// 该组件为公共展示组件:网络请求/下载等业务由父组件处理;查找、高亮、显示切换等通用交互在组件内部封装。
// 图标资源固定使用组件内置文件,保证组件资源自包含。
/**
* 父组件需传入的数据结构说明
*
* @prop {Object} summaryInfo - 顶部摘要信息(用于展示 + 下载)
* @prop {string} summaryInfo.imageUrl - 左上角图标/封面 URL
* @prop {string} summaryInfo.name - 标题
* @prop {string} summaryInfo.postDate - 发布时间(展示在头部与右侧信息)
* @prop {string} summaryInfo.orgName - 发布机构(展示在头部与右侧信息)
* @prop {string} summaryInfo.ename - 英文名/别名(头部展示)
* @prop {string} [summaryInfo.url] - 原文 PDF 下载地址(父组件下载逻辑使用;组件点击“下载”仅触发事件)
*
* @prop {Array<Object>} reportData - 正文分段数组(用于原文渲染/查找高亮)
* @prop {number|string} reportData[].num - 段落序号/唯一标识(用于列表 key)
* @prop {string} reportData[].content - 中文段落 HTML 字符串(组件内使用 v-html 渲染)
* @prop {string} reportData[].contentEn - 英文段落 HTML 字符串(组件内使用 v-html 渲染;关闭“原文显示”时不展示)
*/
const props = defineProps({
summaryInfo: { type: Object, default: () => ({}) },
reportData: { type: Array, default: () => [] },
});
const emits = defineEmits(["download"]);
const isHighlight = ref(false);
const isTranslate = ref(true);
const findWordTxt = ref("");
const findWordBox = ref(false);
const findWordNum = ref(0);
const findWordMax = ref(0);
const originReportData = ref([]);
const displayReportData = ref([]);
function escapeRegExp(text) {
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function applyHighlightToText(text, searchTerm) {
if (!text || !searchTerm) {
return { html: text || "", count: 0 };
}
const escapedTerm = escapeRegExp(searchTerm);
let count = 0;
const html = String(text).replace(new RegExp(escapedTerm, "g"), (match) => {
count += 1;
return `<span class="highlight">${match}</span>`;
});
return { html, count };
}
function setDisplayFromOrigin() {
displayReportData.value = originReportData.value.map((item) => ({
...item,
content: item.content || "",
contentEn: item.contentEn || "",
}));
}
function updateActiveHighlight() {
const spans = document.querySelectorAll("span.highlight");
spans.forEach((span, index) => {
if (index + 1 === findWordNum.value) {
span.scrollIntoView({});
span.style.backgroundColor = "#ff9632";
} else {
span.style.backgroundColor = "#ffff00";
}
});
}
const doUpdateWord = () => {
findWordNum.value = 0;
findWordMax.value = 0;
const term = findWordTxt.value?.trim();
if (!term) {
setDisplayFromOrigin();
return;
}
displayReportData.value = originReportData.value.map((item) => {
const cn = applyHighlightToText(item.content, term);
const en = isTranslate.value ? applyHighlightToText(item.contentEn, term) : { html: item.contentEn, count: 0 };
findWordMax.value += cn.count + en.count;
return {
...item,
content: cn.html,
contentEn: en.html,
};
});
if (findWordMax.value > 0) {
nextTick(() => {
findWordNum.value = 1;
updateActiveHighlight();
});
}
};
const handleUpdateWord = debounce(() => {
doUpdateWord();
}, 300);
function handleFindWord(event) {
switch (event) {
case "open":
findWordBox.value = true;
break;
case "last":
if (findWordMax.value > 1) {
findWordNum.value = findWordNum.value === 1 ? findWordMax.value : findWordNum.value - 1;
updateActiveHighlight();
}
break;
case "next":
if (findWordMax.value > 1) {
findWordNum.value = findWordNum.value === findWordMax.value ? 1 : findWordNum.value + 1;
updateActiveHighlight();
}
break;
case "close":
findWordBox.value = false;
findWordTxt.value = "";
doUpdateWord();
break;
}
}
watch(
() => props.reportData,
(val) => {
originReportData.value = (val || []).map((item) => ({
content: item?.content || "",
contentEn: item?.contentEn || "",
num: item?.num,
}));
setDisplayFromOrigin();
doUpdateWord();
},
{ deep: true, immediate: true },
);
watch(isTranslate, () => {
doUpdateWord();
});
</script>
<style lang="scss" scoped>
.high-light {
:deep(span.highlight) {
background-color: #ffff00;
}
}
.layout-container {
width: 100%;
height: 100%;
background-color: #f7f8f9;
.layout-main {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
.header-main {
padding: 17px 0;
width: 100%;
border-bottom: 1px solid rgba(234, 236, 238, 1);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
}
.layout-main-header {
width: 1600px;
display: flex;
align-items: center;
margin: 0 auto;
.icon {
width: 64px;
height: 40px;
overflow: hidden;
img {
width: 100%;
height: 100%;
}
}
.info {
margin-left: 10px;
margin-right: 40px;
width: 20px;
flex: auto;
.info-box1 {
width: 100%;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 600;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
margin-top: 5px;
}
.info-box2 {
margin-top: 5px;
height: 22px;
line-height: 22px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
display: flex;
.info-box2-item {
white-space: nowrap;
padding: 0 10px;
}
.info-box2-item:first-child {
padding-left: 0px;
}
}
}
.layout-main-header-right-box {
.right-box-top {
white-space: nowrap;
.time {
height: 24px;
line-height: 24px;
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 {
height: 24px;
line-height: 24px;
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;
}
}
}
}
.layout-main-center {
width: 1600px;
background-color: white;
padding: 0 60px;
height: 20px;
flex: auto;
display: flex;
flex-direction: column;
.report-header {
height: 80px;
display: flex;
align-items: center;
border-bottom: solid 1px rgba(234, 236, 238, 1);
margin: 0 20px 10px;
position: relative;
.find-word-box {
position: absolute;
top: -50px;
right: 0px;
width: 430px;
height: 60px;
border: 1px solid rgba(230, 231, 232, 1);
background-color: white;
border-radius: 6px;
display: flex;
align-items: center;
.find-word-input {
width: 20px;
flex: auto;
}
.find-word-limit {
border-right: solid 1px rgba(230, 231, 232, 1);
color: #5f656c;
padding-right: 16px;
}
.find-word-icon {
padding: 10px 12px;
margin: 0 2px;
cursor: pointer;
}
}
.report-title {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
line-height: 20px;
font-weight: 700;
width: 20px;
flex: auto;
}
.btn {
margin-left: 10px;
width: 88px;
height: 32px;
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;
cursor: pointer;
.text {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 14px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
.icon {
width: 16px;
height: 16px;
font-size: 0px;
img {
width: 100%;
height: 100%;
}
}
.icon-gap-4 {
margin-right: 4px;
}
.icon-gap-6 {
margin-right: 6px;
}
}
}
.report-main {
height: 20px;
flex: auto;
box-sizing: border-box;
padding-top: 10px;
&::-webkit-scrollbar {
display: none;
}
&::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 4px;
}
&::-webkit-scrollbar-track {
background: #f1f1f1;
}
.noContent {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 20px;
font-weight: 400;
}
.content-row {
display: flex;
width: 100%;
padding: 0 20px;
min-height: 100px;
gap: 80px;
&:last-child {
border-bottom: none;
}
.content-en,
.content-cn {
width: 50%;
flex: auto;
padding-bottom: 40px;
box-sizing: border-box;
font-size: 16px;
line-height: 1.8;
color: #3b414b;
font-family: Microsoft YaHei;
text-align: justify;
white-space: pre-wrap;
}
.translate-cn {
padding-bottom: 10px;
}
}
}
}
}
}
.switch-label {
margin-left: 6px;
}
.switch-label-left {
margin-right: 10px;
}
:deep(.el-scrollbar__bar.is-vertical) {
right: 0px;
width: 4px;
background: transparent;
border-radius: 2px;
& > div {
background: #c5c7c9;
opacity: 1;
}
& > div:hover {
background: #505357;
}
}
</style>
<template> <template>
<div class="layout-container"> <BaseDecreeOriginal
<!-- 导航菜单 --> :summary-info="summaryInfo"
<div class="layout-main"> :report-data="reportData"
<div class="header-main"> @download="handleDownload"
<div class="layout-main-header"> />
<div class="icon">
<img :src="summaryInfo.imageUrl" alt="" />
</div>
<div class="info">
<div class="info-box1 one-line-ellipsis">{{ summaryInfo.name || "--" }}</div>
<div class="info-box2">
<div class="info-box2-item">{{ summaryInfo.postDate || "--" }}</div>
|
<div class="info-box2-item">{{ summaryInfo.orgName || "--" }}</div>
|
<div class="info-box2-item one-line-ellipsis">{{ summaryInfo.ename || "--" }}</div>
</div>
</div>
<div class="layout-main-header-right-box">
<div class="right-box-top">
<div class="time">{{ summaryInfo.postDate || "--" }}</div>
<div class="name">{{ summaryInfo.orgName || "--" }}</div>
</div>
</div>
</div>
</div>
<div class="layout-main-center">
<div class="report-header">
<div class="report-title">政令原文</div>
<el-switch v-model="isHighlight" />
<div style="margin-left: 6px; margin-right: 10px;">高亮实体</div>
<el-switch v-model="isTranslate" />
<div style="margin-left: 6px;">原文显示</div>
<div class="btn" @click="handleDownload">
<div class="icon" style="margin-right: 4px;">
<img :src="download" alt="">
</div>
<div class="text">下载</div>
</div>
<div class="btn" @click="handleFindWord('open')">
<div class="icon" style="margin-right: 6px;">
<img :src="search" alt="">
</div>
<div class="text">查找</div>
</div>
<div class="find-word-box" v-if="findWordBox">
<div class="find-word-input">
<el-input v-model="findWordTxt" placeholder="查找原文内容" @input="handleUpdateWord()" />
</div>
<div class="find-word-limit">{{ findWordNum }}/{{ findWordMax }}</div>
<div class="find-word-icon" @click="handleFindWord('last')">
<el-icon><ArrowUp /></el-icon>
</div>
<div class="find-word-icon" @click="handleFindWord('next')">
<el-icon><ArrowDown /></el-icon>
</div>
<div class="find-word-icon" @click="handleFindWord('close')">
<el-icon><Close /></el-icon>
</div>
</div>
</div>
<div class="report-main">
<div v-if="!reportData.length" class="noContent">{{ "暂无数据" }}</div>
<el-scrollbar height="100%" v-else>
<div v-for="(item, index) in reportData" :key="index" :class="['content-row', {'high-light':isHighlight}]">
<!-- 右侧:中文 -->
<div :class="['content-cn', {'translate-cn':!isTranslate}]" v-html="item.content"></div>
<!-- 左侧:英文 -->
<div class="content-en" v-html="item.contentEn" v-if="isTranslate"></div>
</div>
</el-scrollbar>
</div>
</div>
</div>
</div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted, nextTick } from "vue"; import { ref, onMounted } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { debounce } from "lodash";
import { getDecreeSummary } from "@/api/decree/introduction"; import { getDecreeSummary } from "@/api/decree/introduction";
import { getDecreeReport } from "@/api/decree/introduction"; import { getDecreeReport } from "@/api/decree/introduction";
import download from "./assets/icons/download.png"; import BaseDecreeOriginal from "@/components/base/DecreeOriginal/index.vue";
import search from "./assets/icons/search.png";
const route = useRoute(); const route = useRoute();
// 政令原文操作
const isHighlight = ref(false);
const isTranslate = ref(true);
const findWordTxt = ref("")
const findWordBox = ref(false);
const findWordNum = ref(0);
const findWordMax = ref(0);
const handleDownload = async () => { const handleDownload = async () => {
if (summaryInfo.value?.url) { if (summaryInfo.value?.url) {
try { try {
...@@ -134,76 +54,6 @@ const handleDownload = async () => { ...@@ -134,76 +54,6 @@ const handleDownload = async () => {
ElMessage.warning("暂无下载链接!"); ElMessage.warning("暂无下载链接!");
} }
} }
const handleHighlight = () => {
let spans = document.querySelectorAll(`span.highlight`);
spans.forEach((span, index) => {
if (index+1 === findWordNum.value) {
// 平滑滚动 behavior: 'smooth'
span.scrollIntoView({})
span.style.backgroundColor = "#ff9632";
} else {
span.style.backgroundColor = "#ffff00";
}
})
}
const handleFindWord = (event) => {
switch (event) {
case "open":
findWordBox.value = true;
break;
case "last":
if (findWordMax.value > 1) {
findWordNum.value = findWordNum.value==1 ? findWordMax.value : findWordNum.value-1;
handleHighlight()
}
break;
case "next":
if (findWordMax.value > 1) {
findWordNum.value = findWordNum.value==findWordMax.value ? 1 : findWordNum.value+1;
handleHighlight()
}
break;
case "close":
findWordBox.value = false;
findWordTxt.value = "";
handleUpdateWord()
break;
}
}
const handleUpdateWord = debounce(() => {
console.log("更新查找词", findWordTxt.value);
findWordNum.value = 0;
findWordMax.value = 0;
if (findWordTxt.value) {
originData.forEach((item, index) => {
if (item.content) {
reportData.value[index].content = highlightText(item.content, findWordTxt.value);
}
if (isTranslate.value && item.contentEn) {
reportData.value[index].contentEn = highlightText(item.contentEn, findWordTxt.value);
}
});
if (findWordMax.value > 0) {
nextTick(() => {
findWordNum.value = findWordNum.value==findWordMax.value ? 1 : findWordNum.value+1;
handleHighlight()
})
}
} else {
originData.forEach((item, index) => {
reportData.value[index].content = item.content;
reportData.value[index].contentEn = item.contentEn;
});
}
}, 300)
const highlightText = (text, searchTerm) => {
const escapedTerm = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
return text.replace(new RegExp(escapedTerm, 'g'), (match) => {
findWordMax.value++;
return `<span class="highlight">${match}</span>`;
});
}
// 获取全局信息 // 获取全局信息
const summaryInfo = ref({}); const summaryInfo = ref({});
...@@ -222,13 +72,12 @@ const handleGetSummary = async () => { ...@@ -222,13 +72,12 @@ const handleGetSummary = async () => {
// 获取报告原文 - 修改为获取分段数组 // 获取报告原文 - 修改为获取分段数组
const reportData = ref([]); const reportData = ref([]);
let originData = [];
const handleGetReport = async () => { const handleGetReport = async () => {
try { try {
const res = await getDecreeReport({id: route.query.id}); const res = await getDecreeReport({id: route.query.id});
console.log("报告原文", res); console.log("报告原文", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
originData = []; const originData = [];
let num = Math.max(res.data.content.length, res.data.contentEn.length) let num = Math.max(res.data.content.length, res.data.contentEn.length)
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
let obj = { let obj = {
...@@ -250,278 +99,4 @@ onMounted(() => { ...@@ -250,278 +99,4 @@ onMounted(() => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.high-light {
:deep(span.highlight) {
// color: #055FC2;
background-color: #ffff00;
}
}
.layout-container {
width: 100%;
height: 100%;
background-color: #F7F8F9;
.layout-main {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
.header-main {
padding: 17px 0;
width: 100%;
border-bottom: 1px solid rgba(234, 236, 238, 1);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
}
.layout-main-header {
width: 1600px;
display: flex;
align-items: center;
margin: 0 auto;
.icon {
width: 64px;
height: 40px;
overflow: hidden;
img {
width: 100%;
height: 100%;
}
}
.info {
margin-left: 10px;
margin-right: 40px;
width: 20px;
flex: auto;
.info-box1 {
width: 100%;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 600;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
margin-top: 5px;
}
.info-box2 {
margin-top: 5px;
height: 22px;
line-height: 22px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
display: flex;
.info-box2-item {
white-space: nowrap;
padding: 0 10px;
}
.info-box2-item:first-child {
padding-left: 0px;
}
}
}
.layout-main-header-right-box {
.right-box-top {
white-space: nowrap;
.time {
height: 24px;
line-height: 24px;
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 {
height: 24px;
line-height: 24px;
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;
}
}
}
}
.layout-main-center {
width: 1600px;
background-color: white;
padding: 0 60px;
height: 20px;
flex: auto;
display: flex;
flex-direction: column;
.report-header {
height: 80px;
display: flex;
align-items: center;
border-bottom: solid 1px rgba(234, 236, 238, 1);
margin: 0 20px 10px;
position: relative;
.find-word-box {
position: absolute;
top: -50px;
right: 0px;
width: 430px;
height: 60px;
border: 1px solid rgba(230, 231, 232, 1);
background-color: white;
border-radius: 6px;
display: flex;
align-items: center;
.find-word-input {
width: 20px;
flex: auto;
}
.find-word-limit {
border-right: solid 1px rgba(230, 231, 232, 1);
color: #5F656C;
padding-right: 16px;
}
.find-word-icon {
padding: 10px 12px;
margin: 0 2px;
cursor: pointer;
}
}
.report-title {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
line-height: 20px;
font-weight: 700;
width: 20px;
flex: auto;
}
.btn {
margin-left: 10px;
width: 88px;
height: 32px;
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;
cursor: pointer;
.text {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 14px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
.icon {
width: 16px;
height: 16px;
font-size: 0px;
img {
width: 100%;
height: 100%;
}
}
}
}
.report-main {
height: 20px;
flex: auto;
box-sizing: border-box;
padding-top: 10px;
// 滚动条样式
&::-webkit-scrollbar {
display: none;
}
&::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 4px;
}
&::-webkit-scrollbar-track {
background: #f1f1f1;
}
.noContent {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 20px;
font-weight: 400;
}
.content-row {
display: flex;
width: 100%;
padding: 0 20px;
min-height: 100px;
gap: 80px;
&:last-child {
border-bottom: none;
}
.content-en,
.content-cn {
width: 50%;
flex: auto;
padding-bottom: 40px;
box-sizing: border-box;
font-size: 16px;
line-height: 1.8;
color: #3B414B;
font-family: Microsoft YaHei;
text-align: justify;
white-space: pre-wrap; // 保留换行格式
}
.translate-cn {
padding-bottom: 10px;
}
}
}
}
}
}
// 修改element-plus滚动条样式
:deep(.el-scrollbar__bar.is-vertical) {
right: 0px;
width: 4px;
background: transparent;
border-radius: 2px;
&>div {
background: #c5c7c9;
opacity: 1;
}
&>div:hover {
background: #505357;
}
}
</style> </style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论