提交 fda5d422 authored 作者: huhuiqing's avatar huhuiqing

Merge branch 'master' of http://8.140.26.4:10003/caijian/risk-monitor into dev_hhq

......@@ -247,6 +247,7 @@ const rightList = ref([
width: 100%;
height: 299px;
background: rgb(249, 249, 249);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.3);
display: flex;
.left {
margin-top: 35px;
......
......@@ -3,7 +3,7 @@
<!-- 公司导航栏 -->
<div class="company-nav">
<div class="company-logo-title">
<img :src="infoData.logoUrl" class="logo-img" />
<img :src="infoData.logoUrl?infoData.logoUrl:defaultCompanyIcon" class="logo-img" />
<div class="title-group">
<h1 class="company-name">{{ infoData.orgName }}</h1>
<p class="company-english">{{ infoData.orgNameEn }}</p>
......@@ -131,7 +131,7 @@
<div class="personnel-grid">
<div class="personnel-card" v-for="(person, idx) in mainPersonnel" :key="idx">
<div class="personnel-card-header">
<img :src="person.avatarUrl" class="person-avatar" />
<img :src="person.avatarUrl?person.avatarUrl:defaultUserIcon" class="person-avatar" />
<div class="person-info">
<h4 class="person-name">{{ person.name }}</h4>
<p class="person-position">{{ person.position }}</p>
......@@ -193,6 +193,9 @@ import TabIcon2Active from "./images/tab-icon2-active.png";
import TabIcon3Active from "./images/tab-icon3-active.png";
import TabIcon4Active from "./images/tab-icon4-active.png";
import defaultUserIcon from "@/assets/icons/default-icon1.png"
import defaultCompanyIcon from "@/assets/icons/default-icon2.png"
const router = useRouter();
const tabList = ref([
{
......
......@@ -1144,7 +1144,6 @@ const handleToPosi = id => {
// 0 618 1240 2350
switch (id) {
case "position2":
// containerRef.value.scrollTop = isShow.value ? 744 : 1090;
containerRef.value.scrollTop = isShow.value ? 844 : 1190;
break;
case "position3":
......@@ -1334,6 +1333,7 @@ onMounted(async () => {
height: 144px;
background: #fff;
overflow: hidden;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.3);
.home-main-header-center {
margin-top: 20px;
margin-left: 200px;
......
......@@ -408,7 +408,7 @@
</el-col>
</el-row>
<el-row :gutter="20" style="width: 1600px; margin: 0 auto; margin-top: 39px">
<el-row :gutter="20" style="width: 1600px; margin: 0 auto; margin-top: 39px;">
<CustomTitle id="position4" title="资源库" style="margin-top: 0px" />
<div class="resource-tabs">
<div
......@@ -1064,8 +1064,8 @@ const handleEntityClick = item => {
const route = router.resolve({
name: "companyPages",
params: {
startTime: item.startTime,
id: item.id
// startTime: item.startTime,
id: item.entityId
}
});
window.open(route.href, "_blank");
......@@ -2868,9 +2868,8 @@ const handleMediaClick = item => {
.home-main-footer {
// width: 100%;
height: 911px;
// height: 911px;
background: rgba(248, 249, 250, 1);
.home-main-footer-header {
margin-top: 37px;
margin-bottom: 36px;
......@@ -3156,7 +3155,7 @@ const handleMediaClick = item => {
.all-content {
width: 100%;
height: auto;
padding-bottom: 100px;
padding-bottom: 30px;
display: flex;
justify-content: space-between;
// align-items: center;
......
......@@ -37,7 +37,7 @@
<template #default="{ row }">
<div class="entity-name-cell">
<el-avatar class="avatar" :size="24" :src="row.avatar || defaultIcon" />
<div class="name" :title="row.name">{{ row.name }}</div>
<div class="name" @click="handleCompClick(row)" :title="row.name">{{ row.name }}</div>
</div>
</template>
</el-table-column>
......@@ -79,8 +79,9 @@
<script setup>
import { ref, defineProps, defineEmits, computed, watch } from "vue";
import router from "@/router";
import { Close } from "@element-plus/icons-vue";
import defaultIcon from "../../../../../assets/icons/default-avatar.png";
import defaultIcon from "@/assets/icons/default-icon1.png";
const props = defineProps({
modelValue: {
......@@ -149,6 +150,20 @@ const getTagStyle = tag => {
const index = Math.abs(hash) % colorPool.length;
return colorPool[index];
};
// 跳转公司详情页
const handleCompClick = item => {
console.log("item", item);
window.sessionStorage.setItem('curTabName', item.entityNameZh || item.entityName)
const route = router.resolve({
name: "companyPages",
params: {
id: item.id
}
});
window.open(route.href, "_blank");
};
</script>
<style lang="scss" scoped>
......@@ -271,6 +286,7 @@ const getTagStyle = tag => {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
cursor: pointer;
}
}
......
......@@ -127,7 +127,7 @@ const handleCompClick = item => {
const route = router.resolve({
name: "companyPages",
params: {
id: item.id
id: item.entityId
}
});
window.open(route.href, "_blank");
......
......@@ -475,34 +475,34 @@ const initDomainChart = () => {
{
name: "制裁实体领域分布",
type: "pie",
radius: [73.5, 89.5],
radius: [65, 81],
center: ["50%", "50%"],
startAngle: 90,
data: data,
label: {
show: true,
alignTo: "edge",
minMargin: 5,
edgeDistance: 10,
minMargin: 5,
edgeDistance: 10,
formatter: params => {
return "{name|" + params.name + "}\n{value|" + params.value + "家 " + params.percent + "%}";
return "{name|" + params.name + "} \n {value|" + params.value + "家 " + params.percent + "%}";
},
rich: {
name: {
fontSize: 18,
fontWeight: 700,
color: "rgb(59, 65, 75)",
padding: [0, 0, 5, 0],
padding: [10, 0, 10, 0],
fontFamily: "Microsoft YaHei",
lineHeight: 26
lineHeight: 22
},
value: {
fontSize: 16,
fontWeight: 400,
color: "rgb(95, 101, 108)",
fontFamily: "Microsoft YaHei",
lineHeight: 24,
padding: [5, 0, 0, 0]
lineHeight: 22,
padding: [10, 0, 10, 0]
}
}
},
......
<template>
<div class="deep-mining">
<div class="deep-mining" :class="{ deepMiningChartmode: isInChart }">
<div class="side-nav">
<div
v-for="(item, index) in activeTab"
......@@ -51,49 +51,49 @@
</el-input>
</div>
<div class="entity-tree custom-scrollbar">
<div class="tree-group" v-for="group in entityList" :key="group.id">
<div class="group-header" @click="toggleGroup(group)">
<el-icon class="arrow-icon" :class="{ expanded: group.expanded }">
<CaretRight />
</el-icon>
<span class="group-name">{{ group.name }}</span>
<span class="group-count">{{ group.count }}家</span>
</div>
<div class="group-children custom-scrollbar" v-show="group.expanded">
<div
class="entity-item"
v-for="item in group.children"
:key="item.id"
:class="{ active: activeEntityId === item.id }"
@click="selectEntity(item)"
>
<div class="item-icon">
<img :src="defaultTitle" alt="" class="item-img">
<div class="tree-group" v-for="group in entityList" :key="group.id">
<div class="group-header" @click="toggleGroup(group)">
<el-icon class="arrow-icon" :class="{ expanded: group.expanded }">
<CaretRight />
</el-icon>
<span class="group-name">{{ group.name }}</span>
<span class="group-count">{{ group.count }}家</span>
</div>
<div class="group-children custom-scrollbar" v-show="group.expanded">
<div
class="entity-item"
v-for="item in group.children"
:key="item.id"
:class="{ active: activeEntityId === item.id }"
@click="selectEntity(item)"
>
<div class="item-icon">
<img :src="defaultTitle" alt="" class="item-img" />
</div>
<span class="item-name">{{ item.name }}</span>
</div>
<span class="item-name">{{ item.name }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="right">
<div class="right" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
<div class="title-com custom-right-header">
<div class="toggle-group">
<div
class="toggle-btn"
<div
class="toggle-btn"
:class="{ active: rightActiveTab === 'supplyChain' }"
@click="rightActiveTab = 'supplyChain'"
>
<img :src="rightActiveTab === 'supplyChain' ? icon01Active : icon01" alt="">
<img :src="rightActiveTab === 'supplyChain' ? icon01Active : icon01" alt="" />
<span>供应链</span>
</div>
<div
class="toggle-btn"
<div
class="toggle-btn"
:class="{ active: rightActiveTab === 'equity' }"
@click="rightActiveTab = 'equity'"
>
<img :src="rightActiveTab === 'equity' ? icon02Active : icon02" alt="">
<img :src="rightActiveTab === 'equity' ? icon02Active : icon02" alt="" />
<span>股权</span>
</div>
</div>
......@@ -131,20 +131,38 @@
<div class="right-echarts">
<div class="chart-wrapper">
<div class="chart-controls">
<div class="control-btn"><img :src="echartsIcon01" /></div>
<div class="control-btn"><img :src="echartsIcon02" /></div>
<div class="control-btn"><img :src="echartsIcon03" /></div>
<div
class="control-btn"
:class="{ controlBtnActive: controlActive === 1 }"
@click="handleClickControlBtn(1)"
>
<img :src="echartsIcon01" />
</div>
<div
class="control-btn"
:class="{ controlBtnActive: controlActive === 2 }"
@click="handleClickControlBtn(2)"
>
<img :src="echartsIcon02" />
</div>
<div
class="control-btn"
:class="{ controlBtnActive: controlActive === 3 }"
@click="handleClickControlBtn(3)"
>
<img :src="echartsIcon03" />
</div>
</div>
<div class="chart-legend">
<div class="legend-item"><span class="dot blue"></span>已被制裁实体</div>
<div class="legend-item"><span class="dot grey"></span>未被制裁实体</div>
</div>
<div ref="chartRef" class="chart-container"></div>
<div ref="chartRef" id="chartbox" class="chart-container"></div>
<div class="node-popup" v-if="selectedNode">
<div class="popup-header">
<img :src="defaultTitle" class="popup-icon" />
<span class="popup-title">{{ selectedNode.name.replace(/\n/g, '') }}</span>
<span class="popup-title">{{ selectedNode.name.replace(/\n/g, "") }}</span>
<el-icon class="close-icon" @click="selectedNode = null"><Close /></el-icon>
</div>
<div class="popup-body">
......@@ -152,12 +170,12 @@
<span class="red-dot"></span>
<span class="red-text">
<!-- 2025年7月15日 《实体清单》 -->
暂无数据
暂无数据
</span>
</div>
<div class="desc">
<!-- 因获取和试图获取美国原产物品以支持中国军事和国防相关空间领域活动以及中国量子技术能力而被列入。 -->
暂无数据
暂无数据
</div>
</div>
</div>
......@@ -174,103 +192,149 @@ import { debounce } from "lodash";
import * as echarts from "echarts";
import { Search, CaretRight, Close } from "@element-plus/icons-vue";
import defaultTitle from "../../assets/default-icon2.png";
import icon01 from "./assets/icon01.png"
import icon02 from "./assets/icon02.png"
import icon01Active from "./assets/icon01-active.png"
import icon02Active from "./assets/icon02-active.png"
import echartsIcon01 from "./assets/echartsIcon01.png"
import echartsIcon02 from "./assets/echartsIcon02.png"
import echartsIcon03 from "./assets/echartsIcon03.png"
import company from "./assets/company.png"
import companyActive from "./assets/company-active.png"
import { getSingleSanctionEntityList, getSingleSanctionEntitySupplyChain, getSingleSanctionEntityEquity } from "@/api/exportControlV2.0";
import icon01 from "./assets/icon01.png";
import icon02 from "./assets/icon02.png";
import icon01Active from "./assets/icon01-active.png";
import icon02Active from "./assets/icon02-active.png";
import echartsIcon01 from "./assets/echartsIcon01.png";
import echartsIcon02 from "./assets/echartsIcon02.png";
import echartsIcon03 from "./assets/echartsIcon03.png";
import company from "./assets/company.png";
import companyActive from "./assets/company-active.png";
import {
getSingleSanctionEntityList,
getSingleSanctionEntitySupplyChain,
getSingleSanctionEntityEquity
} from "@/api/exportControlV2.0";
import getTreeChart from "./utils/treeChart";
import setChart from "@/utils/setChart";
const controlActive = ref(1);
const treeData = ref([{}]);
const handleClickControlBtn = btn => {
controlActive.value = btn;
if (btn === 1 || btn === 3) {
isInChart.value = true;
initChart();
} else if (btn === 2) {
isInChart.value = false;
if (chartInstance.value) {
chartInstance.value.dispose();
}
console.log("treeData", treeData.value);
let treeChart = getTreeChart(treeData.value);
setChart(treeChart, "chartbox");
}
};
const isInChart = ref(false);
const handleMouseEnter = () => {
if (controlActive.value !== 2) {
isInChart.value = true;
} else {
isInChart.value = false;
}
};
const handleMouseLeave = () => {
isInChart.value = false;
};
// 单次制裁-深度挖掘-制裁实体股权信息-列表
const singleSanctionEntityEquityData = ref(null);
// 单次制裁-深度挖掘-制裁实体股权信息-请求
const getSingleSanctionEntityEquityRequest = async () => {
try {
const res = await getSingleSanctionEntityEquity({
orgId: activeEntityId.value,
rule: is50PercentRule.value,
})
if (res.code === 200) {
singleSanctionEntityEquityData.value = res.data || null;
initChart();
}
} catch (error) {
console.log(error)
}
}
try {
const res = await getSingleSanctionEntityEquity({
orgId: activeEntityId.value,
rule: is50PercentRule.value
});
if (res.code === 200) {
singleSanctionEntityEquityData.value = res.data || null;
initChart();
}
} catch (error) {
console.log(error);
}
};
// 单次制裁-深度挖掘-制裁实体供应链信息-列表
const singleSanctionEntitySupplyChainData = ref(null);
// 单次制裁-深度挖掘-制裁实体供应链信息-请求
const getSingleSanctionEntitySupplyChainRequest = async () => {
try {
const res = await getSingleSanctionEntitySupplyChain({
orgId: activeEntityId.value,
})
if (res.code === 200) {
singleSanctionEntitySupplyChainData.value = res.data || null;
initChart();
}
} catch (error) {
console.log(error)
}
}
try {
const res = await getSingleSanctionEntitySupplyChain({
orgId: activeEntityId.value
});
if (res.code === 200) {
singleSanctionEntitySupplyChainData.value = res.data || null;
initChart();
treeData.value[0].id = res.data.orgId;
treeData.value[0].name = res.data.orgName;
treeData.value[0].symbol = "image://" + companyActive;
treeData.value[0].symbolSize = 50;
treeData.value[0].value = 10;
treeData.value[0].children = res.data.parentOrgList.map(item => {
return {
id: item.id,
name: item.name,
symbolSize: 30,
value: 10,
symbol: `image://${company}`
};
});
console.log("treeData0", treeData.value);
}
} catch (error) {
console.log(error);
}
};
// 单次制裁-深度挖掘-本次制裁实体清单列表
const singleSanctionEntityList = ref([]);
// 单次制裁-深度挖掘-本次制裁实体清单列表-请求
const getSingleSanctionEntityListRequest = async () => {
try {
const res = await getSingleSanctionEntityList({
sanRecordId: sanRecordId.value,
isOnlyCn: false,
domainId: searchDomain.value || undefined,
searchText: searchText.value || undefined,
})
if (res.code === 200) {
entityList.value = (res.data || []).map((group, index) => ({
id: `group-${index}`,
name: group.orgType,
count: group.orgInfoList ? group.orgInfoList.length : 0,
expanded: index === 0, // 默认展开第一个分组
children: (group.orgInfoList || []).map(org => ({
id: org.id,
name: org.orgNameZh
}))
}));
// 如果有数据,且当前没有选中的实体,默认选中第一个分组的第一个实体
if (entityList.value.length > 0 && entityList.value[0].children && entityList.value[0].children.length > 0) {
const firstEntity = entityList.value[0].children[0];
if (!activeEntityId.value) {
activeEntityId.value = firstEntity.id;
currentEntityName.value = firstEntity.name;
}
}
}
} catch (error) {
console.log(error)
}
}
try {
const res = await getSingleSanctionEntityList({
sanRecordId: sanRecordId.value,
isOnlyCn: false,
domainId: searchDomain.value || undefined,
searchText: searchText.value || undefined
});
if (res.code === 200) {
entityList.value = (res.data || []).map((group, index) => ({
id: `group-${index}`,
name: group.orgType,
count: group.orgInfoList ? group.orgInfoList.length : 0,
expanded: index === 0, // 默认展开第一个分组
children: (group.orgInfoList || []).map(org => ({
id: org.id,
name: org.orgNameZh
}))
}));
// 如果有数据,且当前没有选中的实体,默认选中第一个分组的第一个实体
if (entityList.value.length > 0 && entityList.value[0].children && entityList.value[0].children.length > 0) {
const firstEntity = entityList.value[0].children[0];
if (!activeEntityId.value) {
activeEntityId.value = firstEntity.id;
currentEntityName.value = firstEntity.name;
}
}
}
} catch (error) {
console.log(error);
}
};
const sanRecordId = ref("")
const sanRecordId = ref("");
const getUrlParams = () => {
const urlParams = new URLSearchParams(window.location.search);
sanRecordId.value = urlParams.get("id") || ""
}
const urlParams = new URLSearchParams(window.location.search);
sanRecordId.value = urlParams.get("id") || "";
};
// const activeTab = ref(["实体穿透分析", "重点实体识别"]);
const activeTab = ref(["实体穿透分析"]);
......@@ -287,11 +351,11 @@ const is50PercentRule = ref(false);
const entityList = ref([]);
const toggleGroup = (group) => {
const toggleGroup = group => {
group.expanded = !group.expanded;
};
const selectEntity = (item) => {
const selectEntity = item => {
activeEntityId.value = item.id;
currentEntityName.value = item.name;
};
......@@ -302,7 +366,7 @@ const selectedNode = ref(null);
const initChart = () => {
if (!chartRef.value) return;
if (chartInstance.value) {
chartInstance.value.dispose();
}
......@@ -310,24 +374,24 @@ const initChart = () => {
chartInstance.value = echarts.init(chartRef.value);
let option = {};
if (rightActiveTab.value === 'supplyChain') {
if (rightActiveTab.value === "supplyChain") {
option = getSupplyChainOption();
} else {
option = getEquityOption();
}
chartInstance.value.setOption(option);
chartInstance.value.on('click', (params) => {
if (params.dataType === 'node') {
chartInstance.value.on("click", params => {
if (params.dataType === "node") {
selectedNode.value = params.data;
} else {
selectedNode.value = null;
}
});
chartInstance.value.getZr().on('click', (params) => {
chartInstance.value.getZr().on("click", params => {
if (!params.target) {
selectedNode.value = null;
}
......@@ -337,7 +401,7 @@ const initChart = () => {
const getSupplyChainOption = () => {
if (!singleSanctionEntitySupplyChainData.value) return {};
const data = singleSanctionEntitySupplyChainData.value;
const nodes = [];
const links = [];
const centerX = 550;
......@@ -345,21 +409,21 @@ const getSupplyChainOption = () => {
// 中心节点
nodes.push({
id: '0',
id: "0",
name: data.orgName,
category: 0, // 强制为制裁中
symbol: 'image://' + companyActive, // 强制使用制裁中图标
symbol: "image://" + companyActive, // 强制使用制裁中图标
x: centerX,
y: centerY,
symbolSize: 50,
label: {
fontSize: 16,
fontWeight: 'bold',
color: '#055FC2', // 使用制裁蓝,在图标下方更清晰
position: 'bottom',
label: {
fontSize: 16,
fontWeight: "bold",
color: "#055FC2", // 使用制裁蓝,在图标下方更清晰
position: "bottom",
distance: 10,
width: 150,
overflow: 'break'
overflow: "break"
}
});
......@@ -372,28 +436,28 @@ const getSupplyChainOption = () => {
const radius = index % 2 === 0 ? 340 : 440;
const x = centerX + radius * Math.cos(angle);
const y = centerY + radius * Math.sin(angle);
// 动态计算标签位置:根据余弦值判断左右,根据正弦值判断上下
let position = 'right';
let align = 'left';
let position = "right";
let align = "left";
const cosA = Math.cos(angle);
const sinA = Math.sin(angle);
if (Math.abs(cosA) < 0.3) {
// 顶部区域
position = 'top';
align = 'center';
position = "top";
align = "center";
} else if (cosA < 0) {
// 左侧区域
position = 'left';
align = 'right';
position = "left";
align = "right";
}
nodes.push({
id: `p-${item.id}`,
name: item.name,
category: item.isSanctioned ? 0 : 1,
symbol: 'image://' + (item.isSanctioned ? companyActive : company),
symbol: "image://" + (item.isSanctioned ? companyActive : company),
x: x,
y: y,
isSanctioned: item.isSanctioned,
......@@ -402,7 +466,7 @@ const getSupplyChainOption = () => {
align: align,
distance: 8,
width: 110,
overflow: 'break',
overflow: "break",
lineHeight: 14,
fontSize: 11
}
......@@ -410,8 +474,8 @@ const getSupplyChainOption = () => {
links.push({
source: `p-${item.id}`,
target: '0',
value: '供应商',
target: "0",
value: "供应商",
isSanctioned: item.isSanctioned && data.isSanctioned
});
});
......@@ -426,26 +490,26 @@ const getSupplyChainOption = () => {
const y = centerY + radius * Math.sin(angle);
// 动态计算标签位置
let position = 'right';
let align = 'left';
let position = "right";
let align = "left";
const cosA = Math.cos(angle);
const sinA = Math.sin(angle);
if (Math.abs(cosA) < 0.3) {
// 底部区域
position = 'bottom';
align = 'center';
position = "bottom";
align = "center";
} else if (cosA < 0) {
// 左侧区域
position = 'left';
align = 'right';
position = "left";
align = "right";
}
nodes.push({
id: `c-${item.id}`,
name: item.name,
category: item.isSanctioned ? 0 : 1,
symbol: 'image://' + (item.isSanctioned ? companyActive : company),
symbol: "image://" + (item.isSanctioned ? companyActive : company),
x: x,
y: y,
isSanctioned: item.isSanctioned,
......@@ -454,62 +518,62 @@ const getSupplyChainOption = () => {
align: align,
distance: 8,
width: 110,
overflow: 'break',
overflow: "break",
lineHeight: 14,
fontSize: 11
}
});
links.push({
source: '0',
source: "0",
target: `c-${item.id}`,
value: '客户',
value: "客户",
isSanctioned: item.isSanctioned && data.isSanctioned
});
});
return {
tooltip: {
tooltip: {
show: true,
formatter: (params) => {
if (params.dataType === 'node') {
formatter: params => {
if (params.dataType === "node") {
return `<div style="padding: 8px; max-width: 300px; white-space: normal; word-break: break-all;">${params.data.name}</div>`;
}
return '';
return "";
}
},
series: [
{
type: 'graph',
layout: 'none',
type: "graph",
layout: "none",
symbolSize: 36,
roam: true,
label: {
show: true,
formatter: '{b}',
formatter: "{b}",
fontSize: 12,
hideOverlap: true
},
edgeSymbol: ['none', 'arrow'],
edgeSymbol: ["none", "arrow"],
edgeSymbolSize: [4, 8],
edgeLabel: {
position: 'middle',
position: "middle",
offset: [0, 13],
fontSize: 12,
fontWeight: 400,
fontFamily: 'Microsoft YaHei',
fontFamily: "Microsoft YaHei",
lineHeight: 16,
show: true,
formatter: '{c}',
color: 'rgba(170, 173, 177, 1)',
backgroundColor: 'rgba(234, 236, 238, 1)',
formatter: "{c}",
color: "rgba(170, 173, 177, 1)",
backgroundColor: "rgba(234, 236, 238, 1)",
padding: [4, 8],
borderRadius: 20
},
data: nodes.map(node => ({
...node,
label: {
color: node.category === 0 ? '#055FC2' : '#5F656C',
color: node.category === 0 ? "#055FC2" : "#5F656C",
...node.label
}
})),
......@@ -517,24 +581,26 @@ const getSupplyChainOption = () => {
return {
...link,
lineStyle: {
color: link.isSanctioned ? 'rgba(100, 180, 255, 1)' : 'rgb(180, 181, 182)',
color: link.isSanctioned ? "rgba(100, 180, 255, 1)" : "rgb(180, 181, 182)",
width: 1,
curveness: 0
},
label: link.isSanctioned ? {
show: true,
formatter: '{c}',
backgroundColor: 'rgba(231, 243, 255, 1)',
color: 'rgba(50, 150, 250, 1)',
borderRadius: 20,
padding: [4, 8],
fontSize: 12,
fontWeight: 400,
fontFamily: 'Microsoft YaHei',
lineHeight: 16
} : undefined
label: link.isSanctioned
? {
show: true,
formatter: "{c}",
backgroundColor: "rgba(231, 243, 255, 1)",
color: "rgba(50, 150, 250, 1)",
borderRadius: 20,
padding: [4, 8],
fontSize: 12,
fontWeight: 400,
fontFamily: "Microsoft YaHei",
lineHeight: 16
}
: undefined
};
}),
})
}
]
};
......@@ -543,7 +609,7 @@ const getSupplyChainOption = () => {
const getEquityOption = () => {
if (!singleSanctionEntityEquityData.value) return {};
const data = singleSanctionEntityEquityData.value;
const nodes = [];
const links = [];
const centerX = 550;
......@@ -551,21 +617,21 @@ const getEquityOption = () => {
// 中心节点
nodes.push({
id: '0',
id: "0",
name: data.orgName,
category: 0, // 强制为制裁中
symbol: 'image://' + companyActive, // 强制使用制裁中图标
symbol: "image://" + companyActive, // 强制使用制裁中图标
x: centerX,
y: centerY,
symbolSize: 50,
label: {
fontSize: 16,
fontWeight: 'bold',
color: '#055FC2', // 使用制裁蓝,在图标下方更清晰
position: 'bottom',
label: {
fontSize: 16,
fontWeight: "bold",
color: "#055FC2", // 使用制裁蓝,在图标下方更清晰
position: "bottom",
distance: 10,
width: 150,
overflow: 'break'
overflow: "break"
}
});
......@@ -583,15 +649,15 @@ const getEquityOption = () => {
id: `p-${index}`,
name: item.name,
category: item.isSanctioned ? 0 : 1,
symbol: 'image://' + (item.isSanctioned ? companyActive : company),
symbol: "image://" + (item.isSanctioned ? companyActive : company),
x: x,
y: y,
isSanctioned: item.isSanctioned,
label: {
position: 'top',
position: "top",
distance: 8,
width: 110,
overflow: 'break',
overflow: "break",
lineHeight: 14,
fontSize: 11
}
......@@ -599,8 +665,8 @@ const getEquityOption = () => {
links.push({
source: `p-${index}`,
target: '0',
value: item.type || '持股', // 使用 type 字段
target: "0",
value: item.type || "持股", // 使用 type 字段
isSanctioned: item.isSanctioned // 中心节点强制制裁,高亮取决于对方
});
});
......@@ -619,70 +685,70 @@ const getEquityOption = () => {
id: `c-${index}`,
name: item.name,
category: item.isSanctioned ? 0 : 1,
symbol: 'image://' + (item.isSanctioned ? companyActive : company),
symbol: "image://" + (item.isSanctioned ? companyActive : company),
x: x,
y: y,
isSanctioned: item.isSanctioned,
label: {
position: 'bottom',
position: "bottom",
distance: 8,
width: 110,
overflow: 'break',
overflow: "break",
lineHeight: 14,
fontSize: 11
}
});
links.push({
source: '0',
source: "0",
target: `c-${index}`,
value: item.type || '持股', // 使用 type 字段
value: item.type || "持股", // 使用 type 字段
isSanctioned: item.isSanctioned // 中心节点强制制裁,高亮取决于对方
});
});
return {
tooltip: {
tooltip: {
show: true,
formatter: (params) => {
if (params.dataType === 'node') {
formatter: params => {
if (params.dataType === "node") {
return `<div style="padding: 8px; max-width: 300px; white-space: normal; word-break: break-all;">${params.data.name}</div>`;
}
return '';
return "";
}
},
series: [
{
type: 'graph',
layout: 'none',
type: "graph",
layout: "none",
symbolSize: 36,
roam: true,
label: {
show: true,
formatter: '{b}',
formatter: "{b}",
fontSize: 12,
hideOverlap: true
},
edgeSymbol: ['none', 'arrow'],
edgeSymbol: ["none", "arrow"],
edgeSymbolSize: [4, 8],
edgeLabel: {
position: 'middle',
position: "middle",
offset: [0, 13],
fontSize: 12,
fontWeight: 400,
fontFamily: 'Microsoft YaHei',
fontFamily: "Microsoft YaHei",
lineHeight: 16,
show: true,
formatter: '{c}',
color: 'rgba(170, 173, 177, 1)',
backgroundColor: 'rgba(234, 236, 238, 1)',
formatter: "{c}",
color: "rgba(170, 173, 177, 1)",
backgroundColor: "rgba(234, 236, 238, 1)",
padding: [4, 8],
borderRadius: 20
},
data: nodes.map(node => ({
...node,
label: {
color: node.category === 0 ? '#055FC2' : '#5F656C',
color: node.category === 0 ? "#055FC2" : "#5F656C",
...node.label
}
})),
......@@ -690,24 +756,26 @@ const getEquityOption = () => {
return {
...link,
lineStyle: {
color: link.isSanctioned ? 'rgba(100, 180, 255, 1)' : 'rgb(180, 181, 182)',
color: link.isSanctioned ? "rgba(100, 180, 255, 1)" : "rgb(180, 181, 182)",
width: 1,
curveness: 0
},
label: link.isSanctioned ? {
show: true,
formatter: '{c}',
backgroundColor: 'rgba(231, 243, 255, 1)',
color: 'rgba(50, 150, 250, 1)',
borderRadius: 20,
padding: [4, 8],
fontSize: 12,
fontWeight: 400,
fontFamily: 'Microsoft YaHei',
lineHeight: 16
} : undefined
label: link.isSanctioned
? {
show: true,
formatter: "{c}",
backgroundColor: "rgba(231, 243, 255, 1)",
color: "rgba(50, 150, 250, 1)",
borderRadius: 20,
padding: [4, 8],
fontSize: 12,
fontWeight: 400,
fontFamily: "Microsoft YaHei",
lineHeight: 16
}
: undefined
};
}),
})
}
]
};
......@@ -725,11 +793,11 @@ watch(searchDomain, () => {
getSingleSanctionEntityListRequest();
});
watch(activeIndex, (val) => {
watch(activeIndex, val => {
if (val === 0) {
nextTick(() => {
if (activeEntityId.value) {
if (rightActiveTab.value === 'supplyChain') {
if (rightActiveTab.value === "supplyChain") {
getSingleSanctionEntitySupplyChainRequest();
} else {
getSingleSanctionEntityEquityRequest();
......@@ -740,9 +808,9 @@ watch(activeIndex, (val) => {
}
});
watch(activeEntityId, (val) => {
watch(activeEntityId, val => {
if (val) {
if (rightActiveTab.value === 'supplyChain') {
if (rightActiveTab.value === "supplyChain") {
getSingleSanctionEntitySupplyChainRequest();
} else {
getSingleSanctionEntityEquityRequest();
......@@ -752,24 +820,27 @@ watch(activeEntityId, (val) => {
});
watch(is50PercentRule, () => {
if (rightActiveTab.value === 'equity' && activeEntityId.value) {
if (rightActiveTab.value === "equity" && activeEntityId.value) {
getSingleSanctionEntityEquityRequest();
}
});
watch(rightActiveTab, (val) => {
if (activeEntityId.value) {
if (val === 'supplyChain') {
getSingleSanctionEntitySupplyChainRequest();
} else {
getSingleSanctionEntityEquityRequest();
watch(
rightActiveTab,
val => {
if (activeEntityId.value) {
if (val === "supplyChain") {
getSingleSanctionEntitySupplyChainRequest();
} else {
getSingleSanctionEntityEquityRequest();
}
}
}
nextTick(() => {
initChart();
});
}, { immediate: true });
nextTick(() => {
initChart();
});
},
{ immediate: true }
);
onMounted(() => {
// 获取URL参数
......@@ -777,7 +848,7 @@ onMounted(() => {
// 单次制裁-深度挖掘-本次制裁实体清单列表-请求
getSingleSanctionEntityListRequest();
window.addEventListener('resize', handleResize);
window.addEventListener("resize", handleResize);
});
onUnmounted(() => {
......@@ -787,7 +858,7 @@ onUnmounted(() => {
if (debouncedGetList && debouncedGetList.cancel) {
debouncedGetList.cancel();
}
window.removeEventListener('resize', handleResize);
window.removeEventListener("resize", handleResize);
});
const handleResize = () => {
......@@ -802,7 +873,12 @@ const handleResize = () => {
margin: 0;
padding: 0;
}
.deepMiningChartmode {
height: calc(100vh - 220px) !important;
// overflow: hidden;
}
.deep-mining {
overflow: hidden;
width: 1601px;
margin: 0 auto;
position: relative;
......@@ -882,7 +958,7 @@ const handleResize = () => {
padding-right: 4px;
.tree-group {
// margin-bottom: 16px;
// margin-bottom: 16px;
border: 1px solid rgb(234, 236, 238);
border-radius: 4px;
overflow: hidden;
......@@ -898,13 +974,13 @@ const handleResize = () => {
border-bottom: 1px solid rgb(234, 236, 238);
&:hover {
background-color: #F2F3F5;
background-color: #f2f3f5;
}
.arrow-icon {
margin-right: 8px;
font-size: 14px;
color: #86909C;
color: #86909c;
transition: transform 0.3s;
&.expanded {
......@@ -916,37 +992,36 @@ const handleResize = () => {
flex: 1;
font-size: 14px;
font-weight: 700;
color: #1D2129;
color: #1d2129;
font-family: "Microsoft YaHei";
}
.group-count {
font-size: 14px;
color: #4E5969;
color: #4e5969;
}
}
.group-children {
.entity-item {
display: flex;
align-items: center;
height: 48px;
height: 48px;
padding: 0 12px 0 29px;
cursor: pointer;
margin-bottom: 0;
transition: all 0.2s;
box-sizing: border-box;
box-sizing: border-box;
&:hover {
background-color: #F7F8FA;
background-color: #f7f8fa;
}
&.active {
background-color: rgba(5, 95, 194, 0.05);
border-top: 1px solid rgba(174, 214, 255, 1);
border-bottom: 1px solid rgba(174, 214, 255, 1);
.item-name {
color: rgb(5, 95, 194);
font-weight: 700;
......@@ -958,7 +1033,7 @@ const handleResize = () => {
display: flex;
align-items: center;
flex-shrink: 0;
.item-img {
width: 24px;
height: 24px;
......@@ -967,13 +1042,12 @@ const handleResize = () => {
}
.item-name {
font-size: 16px;
font-size: 16px;
color: rgb(59, 65, 75);
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
word-break: break-all;
}
}
}
......@@ -991,18 +1065,18 @@ const handleResize = () => {
width: 100%;
height: calc(100% - 56px);
position: relative;
.chart-wrapper {
width: 100%;
height: 100%;
position: relative;
}
.chart-container {
width: 100%;
height: 100%;
}
.chart-controls {
position: absolute;
top: 0px;
......@@ -1017,19 +1091,27 @@ const handleResize = () => {
background: #fff;
border-radius: 4px;
box-shadow: 0 0px 8px rgba(0, 0, 0, 0.1);
.control-btn {
width: 14px;
height: 14px;
width: 24px;
height: 24px;
box-sizing: border-box;
padding: 5px;
cursor: pointer;
&:hover {
background: var(--color-bg-hover);
}
img {
width: 14px;
height: 14px;
}
}
.controlBtnActive {
background: var(--color-bg-hover);
}
}
.chart-legend {
position: absolute;
top: 4px;
......@@ -1037,7 +1119,7 @@ const handleResize = () => {
display: flex;
gap: 20px;
z-index: 10;
.legend-item {
display: flex;
align-items: center;
......@@ -1045,29 +1127,29 @@ const handleResize = () => {
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: #5F656C;
color: #5f656c;
&:first-child {
color: #055FC2;
color: #055fc2;
}
.dot {
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 8px;
&.blue {
background: #055FC2;
background: #055fc2;
}
&.grey {
background: rgb(95, 101, 108);
}
}
}
}
.node-popup {
position: absolute;
right: 20px;
......@@ -1078,7 +1160,7 @@ const handleResize = () => {
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
padding: 16px;
z-index: 20;
.popup-header {
display: flex;
align-items: center;
......@@ -1086,13 +1168,13 @@ const handleResize = () => {
padding-bottom: 12px;
border-bottom: 1px solid rgb(234, 236, 238);
position: relative;
.popup-icon {
width: 24px;
height: 24px;
margin-right: 8px;
}
.popup-title {
font-size: 16px;
font-weight: 700;
......@@ -1100,23 +1182,23 @@ const handleResize = () => {
color: rgb(59, 65, 75);
padding-right: 20px;
}
.close-icon {
cursor: pointer;
font-size: 16px;
color: #86909C;
color: #86909c;
position: absolute;
right: 0;
top: 0;
}
}
.popup-body {
.tag-row {
display: flex;
align-items: center;
margin-bottom: 8px;
.red-dot {
width: 8px;
height: 8px;
......@@ -1124,7 +1206,7 @@ const handleResize = () => {
border-radius: 50%;
margin-right: 23px;
}
.red-text {
color: rgb(206, 79, 81);
font-size: 16px;
......@@ -1132,7 +1214,7 @@ const handleResize = () => {
font-family: "Microsoft YaHei";
}
}
.desc {
padding-left: 31px;
font-size: 16px;
......@@ -1174,27 +1256,27 @@ const handleResize = () => {
margin-left: auto;
display: flex;
align-items: center;
.rule-checkbox {
margin-right: 20px;
:deep(.el-checkbox__label) {
font-size: 16px;
color: #5F656C;
color: #5f656c;
font-family: "Microsoft YaHei";
}
:deep(.el-checkbox__inner) {
border-color: #C9CDD4;
border-color: #c9cdd4;
}
:deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
background-color: #055FC2;
border-color: #055FC2;
background-color: #055fc2;
border-color: #055fc2;
}
:deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
color: #5F656C;
color: #5f656c;
}
}
......@@ -1257,12 +1339,11 @@ const handleResize = () => {
}
}
.custom-scrollbar::-webkit-scrollbar {
width: 6px;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: #DCDFE6;
background: #dcdfe6;
border-radius: 3px;
}
.custom-scrollbar::-webkit-scrollbar-track {
......@@ -1270,19 +1351,20 @@ const handleResize = () => {
}
.title-com.custom-right-header {
.box, .text {
.box,
.text {
display: none;
}
.toggle-group {
display: flex;
background: #fff;
border: 1px solid #055FC2;
border: 1px solid #055fc2;
border-radius: 20px;
height: 32px;
overflow: hidden;
margin-left: 16px;
.toggle-btn {
height: 100%;
padding: 4px 16px;
......@@ -1301,31 +1383,31 @@ const handleResize = () => {
height: 14px;
margin-right: 8px;
}
&.active {
background: rgb(5, 95, 194);
color: #fff;
}
}
}
.right-group {
.header-select {
width: 120px;
height: 32px;
margin-right: 12px;
&.last-select {
margin-right: 19px;
}
:deep(.el-input__wrapper) {
height: 32px;
min-height: 32px;
box-shadow: 0 0 0 1px #dcdfe6 inset;
padding: 0 11px;
}
:deep(.el-input__inner) {
height: 32px;
line-height: 32px;
......
const getTreeChart = (treeData) => {
const option = {
series: [{
type: 'tree',
layout: 'orthogonal', // 从上到下布局
orient: 'TB', // Top to Bottom
data: treeData,
top: '10%',
bottom: '5%',
left: '10%',
right: '10%',
symbol: 'circle',
symbolSize: 40,
label: {
position: 'bottom',
verticalAlign: 'middle',
align: 'center'
},
leaves: {
label: {
position: 'top',
verticalAlign: 'middle',
align: 'center'
}
},
lineStyle: {
color: '#ccc',
width: 2,
type: 'dashed' // 虚线
},
emphasis: {
focus: 'descendant'
},
expandAndCollapse: true,
initialTreeDepth: 3
}]
};
return option
}
export default getTreeChart
\ No newline at end of file
......@@ -93,7 +93,7 @@
</div>
</div>
</div>
<div class="right">
<div class="right" v-loading="isLoading">
<div class="title-com">
<div class="box"></div>
<div class="text">制裁清单</div>
......@@ -239,8 +239,11 @@ const addRuleCount = ref(0)
const removeCount = ref(0)
const removeRuleCount = ref(0)
const isLoading = ref(false)
// 调用单次制裁-制裁概况-制裁清单接口
const getSanctionOverviewList = async () => {
isLoading.value = true
try {
const res = await getSingleSanctionOverviewList({
sanRecordId: sanRecordId.value,
......@@ -249,6 +252,7 @@ const getSanctionOverviewList = async () => {
searchText: searchKeyword.value || undefined,
searchType: searchType.value
})
isLoading.value = false
if (res.code === 200) {
const data = res.data || {}
addCount.value = data.addCount || 0
......
<template>
<div class="home-wrapper">
<div class="home-main">
<div class="search-header" v-show="isShow">
<div class="home-main-header-center">
<el-input
v-model="searchThinktankText"
@keyup.enter="handleSearch"
style="width: 680px; height: 100%"
placeholder="搜索智库报告"
/>
<div class="search">
<div class="search-icon">
<img src="./assets/images/search-icon.png" alt="" />
</div>
<div class="search-text" @click="handleSearch">搜索</div>
</div>
</div>
<div class="home-main-header-btn-box">
<div class="btn" @click="handleToPosi('position1')">
<div class="btn-text">{{ "最新动态" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="handleToPosi('position2')">
<div class="btn-text">{{ "资讯要闻" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="handleToPosi('position3')">
<div class="btn-text">{{ "数据总览" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="handleToPosi('position4')">
<div class="btn-text">{{ "资源库" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
</div>
</div>
<div class="home-main" :class="{ scrollHomeMain: isShow }" ref="containerRef">
<div class="home-main-header">
<div class="home-main-header-top">
<div class="home-main-header-top" v-show="!isShow">
<div class="header-left">
<HeaderMenu></HeaderMenu>
</div>
......@@ -10,8 +52,13 @@
<headerInfo curTitleName="科技智库"></headerInfo>
</div>
</div>
<div class="home-main-header-center">
<el-input v-model="searchThinktankText" @keyup.enter="handleSearch" style="width: 838px; height: 100%" placeholder="搜索智库报告" />
<div class="home-main-header-center" v-show="!isShow">
<el-input
v-model="searchThinktankText"
@keyup.enter="handleSearch"
style="width: 838px; height: 100%"
placeholder="搜索智库报告"
/>
<div class="search">
<div class="search-icon">
<img src="./assets/images/search-icon.png" alt="" />
......@@ -37,26 +84,26 @@
<div class="item-footer">热点科技领域</div>
</div>
</div> -->
<div class="home-main-header-btn-box">
<div class="btn" @click="scrollToTop('position1')">
<div class="home-main-header-btn-box" v-show="!isShow">
<div class="btn" @click="handleToPosi('position1')">
<div class="btn-text">{{ "最新动态" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="scrollToTop('position2')">
<div class="btn" @click="handleToPosi('position2')">
<div class="btn-text">{{ "资讯要闻" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="scrollToTop('position3')">
<div class="btn" @click="handleToPosi('position3')">
<div class="btn-text">{{ "数据总览" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="scrollToTop('position4')">
<div class="btn" @click="handleToPosi('position4')">
<div class="btn-text">{{ "资源库" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
......@@ -275,17 +322,16 @@
</div>
</div> -->
<div class="box4-main">
<MessageBubble
v-for="(item, index) in messageList"
@click="handleClickPerson(item)"
:key="index"
:avatar="item.personImage ? item.personImage : defaultHeaderIcin"
:name="item.personName"
:time="item.time"
:source="item.orgName"
:content="item.remarks"
/>
<MessageBubble
v-for="(item, index) in messageList"
@click="handleClickPerson(item)"
:key="index"
:avatar="item.personImage ? item.personImage : defaultHeaderIcin"
:name="item.personName"
:time="item.time"
:source="item.orgName"
:content="item.remarks"
/>
<!-- <div class="box4-main-item" v-for="(item, index) in messageList" :key="index">
<div class="left" @click="handleClickPerson(item)">
<img :src="item.personImage ? item.personImage : defaultHeaderIcin" alt="" />
......@@ -607,6 +653,29 @@ import Box1Logo from "./assets/images/box1-logo.png";
import { setCanvasCreator } from "echarts/core";
import { ElMessage } from "element-plus";
import { useContainerScroll } from "@/hooks/useScrollShow";
const containerRef = ref(null);
const { isShow } = useContainerScroll(containerRef);
const handleToPosi = id => {
// 0 618 1240 2350
switch (id) {
case "position2":
// containerRef.value.scrollTop = isShow.value ? 744 : 1090;
containerRef.value.scrollTop = isShow.value ? 900 : 1150;
break;
case "position3":
containerRef.value.scrollTop = isShow.value ? 1480 : 1730;
break;
case "position4":
containerRef.value.scrollTop = isShow.value ? 2545 : 2795;
break;
default:
containerRef.value.scrollTop = 0;
}
};
const searchThinktankText = ref(""); //搜索科技人物及观点
// 智库列表
const cardList = ref([
......@@ -886,8 +955,8 @@ const handleGetThinkTankReportRemarks = async () => {
if (res.code === 200 && res.data) {
messageList.value = res.data;
messageList.value.forEach(item => {
item.time = item.time.replace('T', ' ')
})
item.time = item.time.replace("T", " ");
});
}
} catch (error) {
console.error("获取智库人物动态error", error);
......@@ -1536,7 +1605,7 @@ const handleGetetThinkTankReport = async () => {
const handleClick = tank => {
console.log(tank);
window.sessionStorage.setItem("curTabName", tank.name+'概览');
window.sessionStorage.setItem("curTabName", tank.name + "概览");
// router.push({ name: "ThinkTankDetail", params: { id: tank.id } });
if (!tank.id) {
ElMessage.warning("当前智库id为空,无法进入详情页");
......@@ -1684,7 +1753,102 @@ onMounted(async () => {
height: 100%;
position: relative;
overflow-y: hidden;
.search-header {
width: 100%;
height: 144px;
background: #fff;
overflow: hidden;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.3);
.home-main-header-center {
margin-top: 20px;
margin-left: 200px;
width: 800px;
height: 48px;
border-radius: 10px;
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
padding: 1px;
position: relative;
border: 1px solid transparent;
&:hover {
border: 1px solid var(--color-main-active);
}
.search {
position: absolute;
right: -1px;
top: 0px;
width: 120px;
height: 46px;
border-radius: 10px;
background: var(--color-main-active);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.search-icon {
width: 18px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
.search-text {
margin-left: 8px;
height: 22px;
color: #fff;
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 22px;
}
}
}
.home-main-header-btn-box {
margin-top: 20px;
margin-left: 200px;
display: flex;
gap: 16px;
.btn {
display: flex;
align-items: center;
gap: 9px;
width: 160px;
height: 48px;
border: 1px solid #aed6ff;
box-sizing: border-box;
border-radius: 24px;
background: #e7f3ff;
cursor: pointer;
position: relative;
&:hover {
background: #cae3fc;
}
.btn-text {
width: 80px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 400;
line-height: 48px;
margin-left: 36px;
text-align: center;
}
.btn-icon {
position: absolute;
top: 16px;
right: 19px;
width: 6px;
height: 12px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
.home-main {
width: 100%;
height: 100%;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论