提交 b9aae742 authored 作者: coderBryanFu's avatar coderBryanFu

update

上级 635c86d8
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
"echarts-wordcloud": "^2.1.0", "echarts-wordcloud": "^2.1.0",
"element-plus": "^2.4.4", "element-plus": "^2.4.4",
"highlight.js": "^11.11.1", "highlight.js": "^11.11.1",
"json5": "^2.2.3",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"vue": "^3.4.0", "vue": "^3.4.0",
"vue-router": "^4.2.5" "vue-router": "^4.2.5"
...@@ -2899,6 +2900,7 @@ ...@@ -2899,6 +2900,7 @@
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmmirror.com/echarts-liquidfill/-/echarts-liquidfill-3.1.0.tgz", "resolved": "https://registry.npmmirror.com/echarts-liquidfill/-/echarts-liquidfill-3.1.0.tgz",
"integrity": "sha512-5Dlqs/jTsdTUAsd+K5LPLLTgrbbNORUSBQyk8PSy1Mg2zgHDWm83FmvA4s0ooNepCJojFYRITTQ4GU1UUSKYLw==", "integrity": "sha512-5Dlqs/jTsdTUAsd+K5LPLLTgrbbNORUSBQyk8PSy1Mg2zgHDWm83FmvA4s0ooNepCJojFYRITTQ4GU1UUSKYLw==",
"license": "MIT",
"peerDependencies": { "peerDependencies": {
"echarts": "^5.0.1" "echarts": "^5.0.1"
} }
...@@ -4026,6 +4028,18 @@ ...@@ -4026,6 +4028,18 @@
"sprintf-js": "~1.0.2" "sprintf-js": "~1.0.2"
} }
}, },
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"license": "MIT",
"bin": {
"json5": "lib/cli.js"
},
"engines": {
"node": ">=6"
}
},
"node_modules/jsonfile": { "node_modules/jsonfile": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz", "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz",
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
"echarts-wordcloud": "^2.1.0", "echarts-wordcloud": "^2.1.0",
"element-plus": "^2.4.4", "element-plus": "^2.4.4",
"highlight.js": "^11.11.1", "highlight.js": "^11.11.1",
"json5": "^2.2.3",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"vue": "^3.4.0", "vue": "^3.4.0",
"vue-router": "^4.2.5" "vue-router": "^4.2.5"
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
<el-dropdown-item command="/decree">政令首页</el-dropdown-item> <el-dropdown-item command="/decree">政令首页</el-dropdown-item>
<el-dropdown-item command="/thinkTank">智库首页</el-dropdown-item> <el-dropdown-item command="/thinkTank">智库首页</el-dropdown-item>
<el-dropdown-item command="/exportControl">出口管制</el-dropdown-item> <el-dropdown-item command="/exportControl">出口管制</el-dropdown-item>
<el-dropdown-item command="/finance">投融资限制</el-dropdown-item>
<el-dropdown-item command="/marketAccessRestrictions">市场准入限制</el-dropdown-item> <el-dropdown-item command="/marketAccessRestrictions">市场准入限制</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
......
...@@ -38,6 +38,52 @@ export function useMarkdownStream() { ...@@ -38,6 +38,52 @@ export function useMarkdownStream() {
) )
// 关键配置:自定义图片渲染规则
md.renderer.rules.image = function (tokens, idx, options, env, self) {
const token = tokens[idx];
const src = token.attrs[token.attrIndex('src')][1];
const alt = token.content;
const title = token.attrs[token.attrIndex('title')] ? token.attrs[token.attrIndex('title')][1] : '';
// 获取自定义样式参数
const maxWidth = env.maxWidth || '100%';
const height = env.height || 'auto';
const objectFit = env.objectFit || 'cover';
const borderRadius = env.borderRadius || '0px';
const boxShadow = env.boxShadow || 'none';
const display = env.display || 'block';
const margin = env.margin || '0 auto';
// 构建样式字符串
const style = `
max-width: ${maxWidth};
height: ${height};
object-fit: ${objectFit};
border-radius: ${borderRadius};
box-shadow: ${boxShadow};
display: ${display};
margin: ${margin};
`.replace(/\s+/g, ' ').trim();
return `<img src="${src}" alt="${alt}"${title ? ` title="${title}"` : ''} style="${style}" loading="lazy">`;
};
// 链接图片的特殊处理
md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
const token = tokens[idx];
const href = token.attrs[token.attrIndex('href')][1];
// 检查下一个token是否是图片
const nextToken = tokens[idx + 1];
if (nextToken && nextToken.type === 'image') {
// 为包含图片的链接添加特殊样式
const linkStyle = env.linkStyle || 'text-decoration: none; color: inherit;';
return `<a href="${href}" style="${linkStyle}" target="_blank" rel="noopener">`;
}
return self.renderToken(tokens, idx, options);
};
// 自定义代码块渲染规则 // 自定义代码块渲染规则
md.renderer.rules.fence = (tokens, idx, options, env, self) => { md.renderer.rules.fence = (tokens, idx, options, env, self) => {
const token = tokens[idx] const token = tokens[idx]
......
// composables/useMarkdownStream.js
import { ref, computed, nextTick } from 'vue'
import MarkdownIt from 'markdown-it'
import hljs from 'highlight.js'
// 引入 highlight.js 样式
import 'highlight.js/styles/github.css'
import mdKatex from '@traptitech/markdown-it-katex'
export function useStream() {
const rawContent = ref('')
const createMd = () => {
const md = new MarkdownIt(
{
html: true,
breaks: true, // 将换行符转换为 <br>
linkify: true, // 自动链接 URL
typographer: true, // 启用排版扩展
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return '<pre class="hljs" style="fontSize:14px"><code class="language-' + lang + '">' +
hljs.highlight(str, {
language: lang,
ignoreIllegals: true
}).value +
'</code></pre>'
} catch (err) {
console.warn(`代码高亮错误 (${lang}):`, err)
}
}
// 默认处理
return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>'
}
}
)
// 自定义代码块渲染规则
md.renderer.rules.fence = (tokens, idx, options, env, self) => {
const token = tokens[idx]
const lang = token.info.trim()
const code = token.content
// 使用 highlight.js 进行高亮
if (lang && hljs.getLanguage(lang)) {
try {
const highlighted = hljs.highlight(code, {
language: lang,
ignoreIllegals: true
})
return `
<div class="code-block-wrapper">
<div class="code-header">
<span class="code-lang">${lang}</span>
</div>
<pre class="hljs"><code class="language-${lang}">${highlighted.value}</code></pre>
</div>
`
} catch (err) {
console.warn(`代码高亮错误 (${lang}):`, err)
}
}
// 默认代码块
return `
<div class="code-block-wrapper">
<div class="code-header">
<span class="code-lang">${lang || 'text'}</span>
<button class="copy-btn" onclick="copyCode(this)">复制</button>
</div>
<pre class="hljs"><code>${md.utils.escapeHtml(code)}</code></pre>
</div>
`
}
// 自定义表格渲染规则
md.renderer.rules.table_open = () =>
'<div class="table-container"><table style="border-collapse: collapse; width: 100%; margin: 1em 0; border: 1px solid #dfe2e5;background: rgb(239 241 243); border-radius: 5px">'
md.renderer.rules.table_close = () => '</table></div>'
md.renderer.rules.thead_open = () => '<thead style="background: #e6e7e8">'
md.renderer.rules.th_open = () =>
'<th style="border: 1px solid #dfe2e5; padding: 12px; text-align: left; font-weight: 600;">'
md.renderer.rules.td_open = () =>
'<td style="border: 1px solid #dfe2e5; padding: 12px; text-align: left; vertical-align: top;">'
md.renderer.rules.th_close = () => '</th>'
md.renderer.rules.td_close = () => '</td>'
md.renderer.rules.tr_open = () => '<tr>'
md.renderer.rules.tr_close = () => '</tr>'
md.renderer.rules.thead_close = () => '</thead>'
md.renderer.rules.tbody_open = () => '<tbody>'
md.renderer.rules.tbody_close = () => '</tbody>'
return md
}
// 渲染 markdown
const renderedProcess = computed(() => {
const md = createMd()
// 预处理内容
return md.render(rawContent.value)
})
// 自动滚动
const scrollToBottom = async (scrollContainer) => {
await nextTick()
if (scrollContainer) {
scrollContainer.scrollTop = scrollContainer.scrollHeight
}
}
// 更新内容并滚动
const updateProcess = async (newContent, scrollContainer) => {
rawContent.value = newContent
await scrollToBottom(scrollContainer)
}
// 清空内容
const clearContent = () => {
rawContent.value = ''
}
return {
rawContent,
renderedProcess,
updateProcess,
clearContent
}
}
\ No newline at end of file
...@@ -19,9 +19,14 @@ ...@@ -19,9 +19,14 @@
<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">
<img src="./assets/images/header-icon.png" alt="" /> <div class="icon">
</div> <img src="@/assets/icons/box-header-icon2.png" alt="" />
</div>
<div class="icon">
<img src="@/assets/icons/box-header-icon3.png" alt="" />
</div>
</div>
</div> </div>
<div class="box1-main"> <div class="box1-main">
<div class="box1-main-center"> <div class="box1-main-center">
...@@ -59,9 +64,14 @@ ...@@ -59,9 +64,14 @@
<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">
<img src="./assets/images/header-icon.png" alt="" /> <div class="icon">
</div> <img src="@/assets/icons/box-header-icon2.png" alt="" />
</div>
<div class="icon">
<img src="@/assets/icons/box-header-icon3.png" alt="" />
</div>
</div>
</div> </div>
<div class="box2-main"> <div class="box2-main">
<div <div
...@@ -104,9 +114,14 @@ ...@@ -104,9 +114,14 @@
<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">
<img src="./assets/images/header-icon.png" alt="" /> <div class="icon">
</div> <img src="@/assets/icons/box-header-icon2.png" alt="" />
</div>
<div class="icon">
<img src="@/assets/icons/box-header-icon3.png" alt="" />
</div>
</div>
</div> </div>
<div class="background-wrap-right-main"> <div class="background-wrap-right-main">
<div class="right-box1"> <div class="right-box1">
...@@ -519,23 +534,28 @@ onMounted(() => { ...@@ -519,23 +534,28 @@ onMounted(() => {
.header-btn-box { .header-btn-box {
position: absolute; position: absolute;
top: 14px; top: 14px;
right: 52px; right: 84px;
display: flex; display: flex;
.btn { .btn {
margin-left: 8px; margin-left: 8px;
} }
} }
.header-right { .header-right {
position: absolute; position: absolute;
top: 14px; top: 14px;
right: 12px; right: 12px;
width: 32px; display: flex;
height: 32px; justify-content: flex-end;
img { gap: 4px;
width: 100%; .icon{
height: 100%; width: 28px;
height: 28px;
img{
width: 100%;
height: 100%;
}
} }
} }
} }
.background-wrap-left { .background-wrap-left {
width: 1150px; width: 1150px;
......
...@@ -31,8 +31,13 @@ ...@@ -31,8 +31,13 @@
</div> </div>
<div class="home-box" :class="{ scrollHomeBox: isShow }" ref="containerRef"> <div class="home-box" :class="{ scrollHomeBox: isShow }" ref="containerRef">
<div class="home-header" v-show="!isShow"> <div class="home-header" v-show="!isShow">
<span>国家科技安全 </span>> <span>中美博弈概览 </span>> <!-- <span>国家科技安全 </span>> <span style="cursor: pointer;">中美博弈概览 </span>>
<span>科技法案 </span> <span>科技法案 </span> -->
<div class="header-item">国家科技安全</div>
<div class="header-item">></div>
<div class="header-item back-item" @click="handleBackHome">中美博弈概览</div>
<div class="header-item">></div>
<div class="header-item">科技法案</div>
</div> </div>
<div class="home-main"> <div class="home-main">
<div class="home-main-header" v-show="!isShow"> <div class="home-main-header" v-show="!isShow">
...@@ -566,6 +571,13 @@ import Zyy from "@/assets/icons/zyy.png"; ...@@ -566,6 +571,13 @@ import Zyy from "@/assets/icons/zyy.png";
import Ghd from "@/assets/icons/ghd.png"; import Ghd from "@/assets/icons/ghd.png";
import Mzd from "@/assets/icons/mzd.png"; import Mzd from "@/assets/icons/mzd.png";
// 返回首页
const handleBackHome = () => {
router.push({
path: '/overview'
})
}
const currentPage = ref(1); const currentPage = ref(1);
// 处理页码改变事件 // 处理页码改变事件
const handleCurrentChange = page => { const handleCurrentChange = page => {
...@@ -1073,79 +1085,77 @@ const box9ChartData = ref([ ...@@ -1073,79 +1085,77 @@ const box9ChartData = ref([
const box7Data = ref([ const box7Data = ref([
[ [
{ {
name: '众议院', name: "众议院",
value: 298 value: 298
}, },
{ {
name: '参议院', name: "参议院",
value: 149 value: 149
} }
], ],
[ [
{ {
name: '拨款委员会', name: "拨款委员会",
value: 50, value: 50,
type: '众议院' type: "众议院"
}, },
{ {
name: '筹款委员会', name: "筹款委员会",
value: 50, value: 50,
type: '众议院' type: "众议院"
}, },
{ {
name: '外交事务委员会', name: "外交事务委员会",
value: 46, value: 46,
type: '众议院' type: "众议院"
}, },
{ {
name: '国土安全委员会', name: "国土安全委员会",
value: 40, value: 40,
type: '众议院' type: "众议院"
}, },
{ {
name: '司法委员会', name: "司法委员会",
value: 40, value: 40,
type: '众议院' type: "众议院"
}, },
{ {
name: '军事委员会', name: "军事委员会",
value: 40, value: 40,
type: '众议院' type: "众议院"
}, },
{ {
name: '能源和商业委员会', name: "能源和商业委员会",
value: 32, value: 32,
type: '众议院' type: "众议院"
}, },
{ {
name: '拨款委员会1', name: "拨款委员会1",
value: 32, value: 32,
type: '参议院' type: "参议院"
}, },
{ {
name: '财政委员会', name: "财政委员会",
value: 31, value: 31,
type: '参议院' type: "参议院"
}, },
{ {
name: '能源', name: "能源",
value: 30, value: 30,
type: '参议院' type: "参议院"
}, },
{ {
name: '能源1', name: "能源1",
value: 30, value: 30,
type: '参议院' type: "参议院"
}, },
{ {
name: '其他', name: "其他",
value: 24, value: 24,
type: '参议院' type: "参议院"
} }
] ]
]) ]);
const box8Data = ref([ const box8Data = ref([
{ {
...@@ -1203,8 +1213,8 @@ onMounted(async () => { ...@@ -1203,8 +1213,8 @@ onMounted(async () => {
const wordCloudChart = getWordCloudChart(wordCloudData.value); const wordCloudChart = getWordCloudChart(wordCloudData.value);
setChart(wordCloudChart, "wordCloudChart"); setChart(wordCloudChart, "wordCloudChart");
const box7Chart = getDoublePieChart(box7Data.value[0], box7Data.value[1]) const box7Chart = getDoublePieChart(box7Data.value[0], box7Data.value[1]);
setChart(box7Chart, 'box7Chart') setChart(box7Chart, "box7Chart");
const box9Chart = getPieChart(box9ChartData.value, box9ChartColorList.value); const box9Chart = getPieChart(box9ChartData.value, box9ChartColorList.value);
setChart(box9Chart, "box9Chart"); setChart(box9Chart, "box9Chart");
...@@ -1328,6 +1338,16 @@ onMounted(async () => { ...@@ -1328,6 +1338,16 @@ onMounted(async () => {
background: url("./assets/images/header-bg.png"); background: url("./assets/images/header-bg.png");
box-sizing: border-box; box-sizing: border-box;
padding-left: 160px; padding-left: 160px;
display: flex;
.header-item {
margin: 0 3px;
}
.back-item {
cursor: pointer;
&:hover {
color: #ccc;
}
}
} }
.home-main { .home-main {
width: 1600px; width: 1600px;
...@@ -1565,9 +1585,10 @@ onMounted(async () => { ...@@ -1565,9 +1585,10 @@ onMounted(async () => {
.box1-main-left-info { .box1-main-left-info {
margin-top: 17px; margin-top: 17px;
display: flex; display: flex;
gap: 8px;
.info-box { .info-box {
height: 30px; max-width: 80px;
width: 80px; height: 24px;
text-align: center; text-align: center;
overflow: hidden; overflow: hidden;
padding: 0 8px; padding: 0 8px;
...@@ -1579,8 +1600,7 @@ onMounted(async () => { ...@@ -1579,8 +1600,7 @@ onMounted(async () => {
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
line-height: 30px; line-height: 24px;
margin-right: 8px;
} }
.info1 { .info1 {
border: 1px solid rgba(135, 232, 222, 1); border: 1px solid rgba(135, 232, 222, 1);
...@@ -2335,7 +2355,7 @@ onMounted(async () => { ...@@ -2335,7 +2355,7 @@ onMounted(async () => {
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
} }
.box7-main{ .box7-main {
height: 340px; height: 340px;
} }
} }
...@@ -2592,15 +2612,18 @@ onMounted(async () => { ...@@ -2592,15 +2612,18 @@ onMounted(async () => {
.btn-wrapper { .btn-wrapper {
width: 1300px; width: 1300px;
overflow-x: auto; overflow-x: auto;
// background: skyblue;
.btn-box { .btn-box {
display: flex; display: flex;
gap: 4px;
// justify-content: space-between; // justify-content: space-between;
max-width: 2000px; max-width: 2000px;
// background: orange;
.btn { .btn {
max-width: 100px; max-width: 120px;
min-width: 80px; min-width: 80px;
height: 42px; height: 42px;
margin: 0 5px;
overflow: hidden; overflow: hidden;
color: rgba(95, 101, 108, 1); color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
...@@ -2610,7 +2633,7 @@ onMounted(async () => { ...@@ -2610,7 +2633,7 @@ onMounted(async () => {
text-align: center; text-align: center;
border-radius: 21px; border-radius: 21px;
background: rgba(20, 89, 187, 0); background: rgba(20, 89, 187, 0);
padding: 0 16px; padding: 0 20px;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background: rgba(20, 89, 187, 0.1); background: rgba(20, 89, 187, 0.1);
......
const getBoxPlotChcart = (data) => { const getBoxPlotChcart = (data,unit) => {
let option = { let option = {
// title: [ // title: [
// { // {
...@@ -34,7 +34,12 @@ const getBoxPlotChcart = (data) => { ...@@ -34,7 +34,12 @@ const getBoxPlotChcart = (data) => {
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
name: '单位:天', name: `单位:${unit}`,
nameTextStyle: {
padding: [0, 0, 0, 1520], // [上, 右, 下, 左]
verticalAlign: 'middle',
align: 'center'
},
splitArea: { splitArea: {
show: true show: true
} }
...@@ -46,7 +51,7 @@ const getBoxPlotChcart = (data) => { ...@@ -46,7 +51,7 @@ const getBoxPlotChcart = (data) => {
datasetIndex: 1, datasetIndex: 1,
data: data.dataY, data: data.dataY,
}, },
{ {
name: 'outlier', name: 'outlier',
type: 'scatter', type: 'scatter',
datasetIndex: 2 datasetIndex: 2
......
...@@ -3,9 +3,14 @@ ...@@ -3,9 +3,14 @@
<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">
<img src="./assets/images/header-icon.png" alt="" /> <div class="icon">
</div> <img src="@/assets/icons/box-header-icon2.png" alt="" />
</div>
<div class="icon">
<img src="@/assets/icons/box-header-icon3.png" alt="" />
</div>
</div>
</div> </div>
<div class="main"> <div class="main">
<div class="left"> <div class="left">
...@@ -754,17 +759,22 @@ const handleClickDetail = (isShow) => { ...@@ -754,17 +759,22 @@ const handleClickDetail = (isShow) => {
font-weight: 600; font-weight: 600;
line-height: 16px; line-height: 16px;
} }
.header-right { .header-right {
position: absolute; position: absolute;
top: 14px; top: 14px;
right: 12px; right: 12px;
width: 32px; display: flex;
height: 32px; justify-content: flex-end;
img { gap: 4px;
width: 100%; .icon {
height: 100%; width: 28px;
} height: 28px;
} img {
width: 100%;
height: 100%;
}
}
}
} }
.main { .main {
margin-left: 59px; margin-left: 59px;
......
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论