提交 8b28a867 authored 作者: 张烨's avatar 张烨

feat:政令影响分析增加产业链关系图

上级 403bb405
...@@ -22,9 +22,26 @@ export function getDecreehylyList() { ...@@ -22,9 +22,26 @@ export function getDecreehylyList() {
// 获取受影响实体列表 // 获取受影响实体列表
export function getDecreeEntities(params) { export function getDecreeEntities(params) {
return request({
method: 'POST',
url: `/api/administrativeOrderInfo/relatedEntities`,
data: params
})
}
// 获取实体产业链列表
export function getDecreeRelatedChain(params) {
return request({
method: 'GET',
url: `/api/administrativeOrderInfo/relatedChain/${params.id}`,
})
}
// 获取产业链节点列表
export function getDecreeChainNodes(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/api/administrativeOrderInfo/relatedEntities/${params.id}`, url: `/api/administrativeOrderInfo/relatedChainNodes/${params.id}`,
}) })
} }
......
...@@ -12,98 +12,61 @@ ...@@ -12,98 +12,61 @@
<div class="fishbone-container" :style="{ transform: `translate(${translateX}px, ${translateY}px) scale(${scale})`, transformOrigin: 'center center' }"> <div class="fishbone-container" :style="{ transform: `translate(${translateX}px, ${translateY}px) scale(${scale})`, transformOrigin: 'center center' }">
<!-- 主轴上的标签 --> <!-- 主轴上的标签 -->
<div class="main-line" :style="{ width: listData.length * 200 + 300 + 'px' }"> <div class="main-line" :style="{ width: listData.length * 200 + 300 + 'px' }">
<div class="main-line-text" v-for="(item, index) in listData" :key="'label-' + index" <div v-for="(item, index) in listData" :key="item.id" class="main-line-text" :class="getThemeClass(item.level)" :style="{ left: index * 200 + 220 + 'px' }">
:class="{ {{ item.name }}
'blue-theme': index < 2,
'green-theme': index >= 2 && index < 4,
'purple-theme': index >= 4
}" :style="{ left: index * 200 + 220 + 'px' }">
{{ item.text }}
</div> </div>
</div> </div>
<!-- 奇数索引的数据组放在上方 --> <!-- 奇数索引的数据组放在上方 -->
<div v-for="(causeGroup, groupIndex) in onFilterData(1)" :key="groupIndex" <div v-for="(causeGroup, groupIndex) in onFilterData(1)" :key="groupIndex"
class="top-bone" :style="{ left: groupIndex * 400 + 510 + 'px', height: (causeGroup.causes?.length) * 22 + 100 + 'px' }"> class="top-bone" :style="{ left: groupIndex * 400 + 510 + 'px', height: (causeGroup.children?.length) * 22 + 100 + 'px' }">
<div class="left-bone"> <div class="left-bone">
<div class="left-bone-item" v-for="item in getLeftItems(causeGroup.causes)" :key="item.id"> <div class="left-bone-item" v-for="item in getLeftItems(causeGroup.children)" :key="item.id">
<img :src="defaultIcon2 || item.picture" alt="" class="company-icon" /> <img :src="item.image || defaultIcon2" alt="" class="company-icon" />
<div class="text" :title="item.name">{{ item.name }}</div> <div class="text" :style="{color: item.isEntity==1? '#ce4f51' : '#3b414b'}" :title="item.companyName">{{ item.companyName }}</div>
<div class="line"></div> <div class="line"></div>
</div> </div>
</div> </div>
<div class="right-bone"> <div class="right-bone">
<div class="right-bone-item" v-for="item in getRightItems(causeGroup.causes)" :key="item.id"> <div class="right-bone-item" v-for="item in getRightItems(causeGroup.children)" :key="item.id">
<div class="line"></div> <div class="line"></div>
<img :src="defaultIcon2 || item.picture" alt="" class="company-icon" /> <img :src="item.image || defaultIcon2" alt="" class="company-icon" />
<div class="text" :title="item.name">{{ item.name }}</div> <div class="text" :style="{color: item.isEntity==1? '#ce4f51' : '#3b414b'}" :title="item.companyName">{{ item.companyName }}</div>
</div> </div>
</div> </div>
</div> </div>
<!-- 偶数索引的数据组放在下方 --> <!-- 偶数索引的数据组放在下方 -->
<div v-for="(causeGroup, groupIndex) in onFilterData(0)" :key="groupIndex" <div v-for="(causeGroup, groupIndex) in onFilterData(0)" :key="groupIndex"
class="bottom-bone" :style="{ left: groupIndex * 400 + 310 + 'px', height: (causeGroup.causes?.length) * 22 + 100 + 'px' }"> class="bottom-bone" :style="{ left: groupIndex * 400 + 310 + 'px', height: (causeGroup.children?.length) * 22 + 100 + 'px' }">
<div class="left-bone"> <div class="left-bone">
<div class="left-bone-item" v-for="item in getRightItems(causeGroup.causes)" :key="item.id"> <div class="left-bone-item" v-for="item in getRightItems(causeGroup.children)" :key="item.id">
<img :src="defaultIcon2 || item.picture" alt="" class="company-icon" /> <img :src="item.image || defaultIcon2" alt="" class="company-icon" />
<div class="text" :title="item.name">{{ item.name }}</div> <div class="text" :style="{color: item.isEntity==1? '#ce4f51' : '#3b414b'}" :title="item.companyName">{{ item.companyName }}</div>
<div class="line"></div> <div class="line"></div>
</div> </div>
</div> </div>
<div class="right-bone"> <div class="right-bone">
<div class="right-bone-item" v-for="item in getLeftItems(causeGroup.causes)" :key="item.id"> <div class="right-bone-item" v-for="item in getLeftItems(causeGroup.children)" :key="item.id">
<div class="line"></div> <div class="line"></div>
<img :src="defaultIcon2 || item.picture" alt="" class="company-icon" /> <img :src="item.image || defaultIcon2" alt="" class="company-icon" />
<div class="text" :title="item.name">{{ item.name }}</div> <div class="text" :style="{color: item.isEntity==1? '#ce4f51' : '#3b414b'}" :title="item.companyName">{{ item.companyName }}</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div v-if="listData.length" class="main-content-footer"> <div v-if="listData.length" class="main-content-footer">
<div class="footer-item footer-item1"> <div v-for="(item, index) in props.baseData" :key="index" class="footer-item">
<div class="footer-item-bottom"> <div class="footer-item-bottom">
<div class="icon"> <div class="icon">
<img :src="noticeIcon" alt="" /> <img :src="noticeIcon" alt="" />
</div> </div>
<div class="text"> <div class="text">
{{ {{
`中国企业${baseData.upstreamInternalCount || `中国企业${item.isChinaCount}家(${formatRate(item, 'isChinaCount')}%),受制裁${item.sanCount}家(${formatRate(item, 'sanCount')}%)`
0}家(${formatRate(baseData.upstreamInternalRate)}%),受制裁${baseData.upstreamEntityCount
|| 0}家(${formatRate(baseData.upstreamEntityRate)}%)`
}} }}
</div> </div>
</div> </div>
<div class="footer-item-top">{{ "上游" }}</div> <div class="footer-item-top" :class="getThemeClass(item.name)">{{ item.name }}</div>
</div>
<div class="footer-item footer-item2">
<div class="footer-item-bottom">
<div class="icon">
<img :src="noticeIcon" alt="" />
</div>
<div class="text">
{{
`中国企业${baseData.midstreamInternalCount ||
0}家(${formatRate(baseData.midstreamInternalRate)}%),受制裁${baseData.midstreamEntityCount
|| 0}家(${formatRate(baseData.midstreamEntityRate)}%)`
}}
</div>
</div>
<div class="footer-item-top">{{ "中游" }}</div>
</div>
<div class="footer-item footer-item3">
<div class="footer-item-bottom">
<div class="icon">
<img :src="noticeIcon" alt="" />
</div>
<div class="text">
{{
`中国企业${baseData.downstreamInternalCount ||
0}家(${formatRate(baseData.downstreamInternalRate)}%),受制裁${baseData.downstreamEntityCount
|| 0}家(${formatRate(baseData.downstreamEntityRate)}%)`
}}
</div>
</div>
<div class="footer-item-top">{{ "下游" }}</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -114,23 +77,16 @@ import { ref } from "vue"; ...@@ -114,23 +77,16 @@ import { ref } from "vue";
import defaultIcon2 from "@/assets/icons/default-icon2.png"; import defaultIcon2 from "@/assets/icons/default-icon2.png";
import noticeIcon from "../assets/images/notice-icon.png"; import noticeIcon from "../assets/images/notice-icon.png";
let arr = [
{ id: 1, name: "上游" },
{ id: 2, name: "中游" },
{ id: 3, name: "下游" },
]
const props = defineProps({ const props = defineProps({
baseData: { baseData: {
type: Object, type: Object,
default: () => ({ default: () => ([])
upstreamInternalCount: 0,
upstreamInternalRate: 0,
upstreamEntityCount: 0,
upstreamEntityRate: 0,
midstreamInternalCount: 0,
midstreamInternalRate: 0,
midstreamEntityCount: 0,
midstreamEntityRate: 0,
downstreamInternalCount: 0,
downstreamInternalRate: 0,
downstreamEntityCount: 0,
downstreamEntityRate: 0
})
}, },
listData: { listData: {
type: Array, type: Array,
...@@ -138,6 +94,12 @@ const props = defineProps({ ...@@ -138,6 +94,12 @@ const props = defineProps({
} }
}); });
const getThemeClass = (name) => {
if (name=="上游") return "blue-theme";
if (name=="中游") return "green-theme";
if (name=="下游") return "purple-theme";
}
// #region 缩放功能处理 // #region 缩放功能处理
const scale = ref(1) const scale = ref(1)
const minScale = 0.1 const minScale = 0.1
...@@ -178,7 +140,7 @@ const handleMouseUp = () => { ...@@ -178,7 +140,7 @@ const handleMouseUp = () => {
// 奇数索引的数据组放在上方, 偶数索引的数据组放在下方 // 奇数索引的数据组放在上方, 偶数索引的数据组放在下方
const onFilterData = (num) => { const onFilterData = (num) => {
return listData.value.filter((_, index) => index % 2 === num); return props.listData.filter((_, index) => index % 2 === num);
}; };
// 获取左侧显示的项目(前半部分) // 获取左侧显示的项目(前半部分)
const getLeftItems = items => { const getLeftItems = items => {
...@@ -191,9 +153,9 @@ const getRightItems = items => { ...@@ -191,9 +153,9 @@ const getRightItems = items => {
return items.slice(midpoint); return items.slice(midpoint);
}; };
// 格式化比率 // 格式化比率
const formatRate = (rate) => { const formatRate = (item, key) => {
if (!rate) return '0.00'; if (!item[key] || !item.total) return "0.00"
return (rate * 100).toFixed(2); return (item[key]*100/item.total).toFixed(2)
}; };
</script> </script>
...@@ -229,41 +191,21 @@ const formatRate = (rate) => { ...@@ -229,41 +191,21 @@ const formatRate = (rate) => {
background: rgb(230, 231, 232); background: rgb(230, 231, 232);
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center;
// 添加中间的文字块 // 添加中间的文字块
.main-line-text { .main-line-text {
top: -16px;
position: absolute; position: absolute;
// top: -14px;
font-size: 16px; font-size: 16px;
color: #055FC2;
font-weight: bold; font-weight: bold;
background-color: #f7f8f9;
padding: 0 10px; padding: 0 10px;
z-index: 2; z-index: 2;
// 箭头背景 // 箭头背景
height: 32px; height: 32px;
line-height: 32px; line-height: 32px;
width: 160px; width: 160px;
text-align: center; text-align: center;
background: rgba(231, 243, 255, 1);
clip-path: polygon(0% 0%, 90% 0%, 100% 50%, 90% 100%, 0% 100%, 10% 50%); clip-path: polygon(0% 0%, 90% 0%, 100% 50%, 90% 100%, 0% 100%, 10% 50%);
&.blue-theme {
background: rgba(231, 243, 255, 1);
color: rgba(22, 119, 255, 1);
}
&.green-theme {
background: rgba(225, 255, 251, 1);
color: rgba(19, 168, 168, 1);
}
&.purple-theme {
background: rgba(246, 235, 255, 1);
color: rgba(146, 84, 222, 1);
}
} }
} }
} }
...@@ -314,7 +256,7 @@ const formatRate = (rate) => { ...@@ -314,7 +256,7 @@ const formatRate = (rate) => {
.line { .line {
margin-left: 7px; margin-left: 7px;
width: 40px; width: 30px;
height: 2px; height: 2px;
background: rgb(230, 231, 232); background: rgb(230, 231, 232);
} }
...@@ -340,13 +282,6 @@ const formatRate = (rate) => { ...@@ -340,13 +282,6 @@ const formatRate = (rate) => {
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
.line {
margin-right: 7px;
width: 30px;
height: 2px;
background: rgb(230, 231, 232);
}
.text { .text {
max-width: 100px; max-width: 100px;
margin-right: 4px; margin-right: 4px;
...@@ -356,6 +291,13 @@ const formatRate = (rate) => { ...@@ -356,6 +291,13 @@ const formatRate = (rate) => {
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.line {
margin-right: 7px;
width: 30px;
height: 2px;
background: rgb(230, 231, 232);
}
} }
} }
} }
...@@ -400,7 +342,7 @@ const formatRate = (rate) => { ...@@ -400,7 +342,7 @@ const formatRate = (rate) => {
.line { .line {
margin-left: 7px; margin-left: 7px;
width: 40px; width: 30px;
height: 2px; height: 2px;
background: rgb(230, 231, 232); background: rgb(230, 231, 232);
} }
...@@ -494,25 +436,19 @@ const formatRate = (rate) => { ...@@ -494,25 +436,19 @@ const formatRate = (rate) => {
} }
} }
} }
}
.footer-item1 { .blue-theme {
color: rgba(22, 119, 255, 1);
.footer-item-top {
background: rgba(231, 243, 255, 1); background: rgba(231, 243, 255, 1);
color: rgba(22, 119, 255, 1);
} }
} .green-theme {
.footer-item2 {
color: rgba(19, 168, 168, 1);
.footer-item-top {
background: rgba(225, 255, 251, 1); background: rgba(225, 255, 251, 1);
color: rgba(19, 168, 168, 1);
} }
} .purple-theme {
.footer-item3 {
color: rgba(146, 84, 222, 1);
.footer-item-top {
background: rgba(246, 235, 255, 1); background: rgba(246, 235, 255, 1);
} color: rgba(146, 84, 222, 1);
}
} }
} }
</style> </style>
\ No newline at end of file
...@@ -5,13 +5,13 @@ ...@@ -5,13 +5,13 @@
<div class="box1-main"> <div class="box1-main">
<div class="data-filter"> <div class="data-filter">
<div class="filter-select"> <div class="filter-select">
<el-select v-model="areaInfo.id" :empty-values="[null, undefined]" style="width: 100%"> <el-select v-model="areaInfo.id" :empty-values="[null, undefined]" @change="onDecreeEntities()" style="width:100%">
<el-option label="全部领域" value="" /> <el-option label="全部领域" value="" />
<el-option v-for="item in areaInfo.list" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in areaInfo.list" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</div> </div>
<div class="filter-input"> <div class="filter-input">
<el-input v-model="entityInfo.keyword" @keyup.enter="onDecreeEntities(1)" :suffix-icon="Search" placeholder="搜索实体" /> <el-input v-model="entityInfo.keyword" @keyup.enter="onDecreeEntities()" :suffix-icon="Search" placeholder="搜索实体" />
</div> </div>
</div> </div>
<div class="data-title">实体名称</div> <div class="data-title">实体名称</div>
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
<el-empty v-if="!entityInfo.list?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" /> <el-empty v-if="!entityInfo.list?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" />
<el-scrollbar height="100%" always> <el-scrollbar height="100%" always>
<div class="list-data"> <div class="list-data">
<div class="list-item" v-for="item in entityInfo.list" :key="item.id" :class="{ 'item-active': entityInfo.id==item.id }" @click="handleToCompanyDetail(item)"> <div class="list-item" v-for="item in entityInfo.list" :key="item.id" :class="{ 'item-active': entityInfo.id==item.id }" @click="onDecreeRelatedChain(item)">
<div class="item-icon"> <div class="item-icon">
<img :src="defaultIcon2" alt="" class="item-img" /> <img :src="defaultIcon2" alt="" class="item-img" />
</div> </div>
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
</div> </div>
</div> </div>
<div class="title-right" v-if="contentType==1"> <div class="title-right" v-if="contentType==1">
<el-select v-model="industryChain.id" style="width: 100%"> <el-select v-model="industryChain.id" style="width: 100%" @change="onDecreeChainNodes">
<el-option v-for="item in industryChain.list" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in industryChain.list" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</div> </div>
...@@ -92,7 +92,7 @@ ...@@ -92,7 +92,7 @@
import { ref, onMounted, reactive } from "vue"; import { ref, onMounted, reactive } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { Search } from '@element-plus/icons-vue' import { Search } from '@element-plus/icons-vue'
import { getDecreehylyList, getDecreeEntities } from "@/api/decree/influence"; import { getDecreehylyList, getDecreeEntities, getDecreeRelatedChain, getDecreeChainNodes } from "@/api/decree/influence";
import ChartChain from "./com/ChartChain.vue"; import ChartChain from "./com/ChartChain.vue";
import AiTips from "./com/AiTips.vue"; import AiTips from "./com/AiTips.vue";
import GraphChart from "@/components/base/GraphChart/index.vue"; import GraphChart from "@/components/base/GraphChart/index.vue";
...@@ -137,19 +137,20 @@ const entityInfo = reactive({ ...@@ -137,19 +137,20 @@ const entityInfo = reactive({
const onDecreeEntities = async (page=1) => { const onDecreeEntities = async (page=1) => {
entityInfo.pageNum = page; entityInfo.pageNum = page;
try { try {
const res = await getDecreeEntities({id: route.query.id}); let { pageSize, pageNum, keyword } = entityInfo;
const res = await getDecreeEntities({id: route.query.id, pageSize, pageNum:pageNum-1, keyword});
console.log("受影响实体:", res); console.log("受影响实体:", res);
if (res.code === 200 && res.data) { if (res.code === 200) {
entityInfo.list = res.data.companies; entityInfo.list = res.data.companyInfos;
entityInfo.total = res.data.companies.length; entityInfo.total = res.data.total;
if (entityInfo.total && entityInfo.list.every(item => item.id!=entityInfo.id)) {
onDecreeRelatedChain(entityInfo.list[0])
}
} }
} catch (error) { } catch (error) {
console.log("获取受影响实体失败", error); console.log("获取受影响实体失败", error);
} }
}; };
const handleToCompanyDetail = (item) => {
entityInfo.id = item.id;
};
const contentType = ref(1); const contentType = ref(1);
const headerContentType = (type) => { const headerContentType = (type) => {
...@@ -161,13 +162,52 @@ const industryChain = reactive({ ...@@ -161,13 +162,52 @@ const industryChain = reactive({
list: [], list: [],
id: "", id: "",
}) })
const onDecreeRelatedChain = async ({ id }) => {
entityInfo.id = id;
try {
const res = await getDecreeRelatedChain({ id });
console.log("产业链:", res);
if (res.code === 200) {
industryChain.id = "";
industryChain.list = res.data;
if (industryChain.list.length) onDecreeChainNodes(industryChain.list[0].id)
}
} catch (error) {
console.log("获取产业链失败", error);
}
};
// 产业链鱼骨图 // 产业链鱼骨图
const fishbone = reactive({ const fishbone = reactive({
list: [], list: [],
base: {}, base: [],
}) })
const onDecreeChainNodes = async (id) => {
industryChain.id = id;
fishbone.list = []
fishbone.base = []
try {
const res = await getDecreeChainNodes({ id });
console.log("产业链鱼骨图:", res);
if (res.code === 200) {
let obj = res.data.chains.reduce((result, item) => {
result['chain-'+item.id] = {...item, children: []};
return result;
}, {});
res.data.children.forEach(item => {
if (obj['chain-'+item.chainId]?.children?.length < 10) {
obj['chain-'+item.chainId].children.push(item)
}
})
fishbone.list = Object.values(obj);
fishbone.base = res.data.levelInfos.map((item, index) => {
return {...item, name: ['上游', '中游', '下游'][index]}
});
}
} catch (error) {
console.log("获取产业链鱼骨图失败", error);
}
};
// 实体关系 // 实体关系
const graphInfo = reactive({ const graphInfo = reactive({
......
...@@ -66,12 +66,11 @@ ...@@ -66,12 +66,11 @@
<AnalysisBox title="报告内容摘要" :showAllBtn="false"> <AnalysisBox title="报告内容摘要" :showAllBtn="false">
<el-empty v-if="false" style="margin: 20px 0;" description="暂无数据" :image-size="100" /> <el-empty v-if="false" style="margin: 20px 0;" description="暂无数据" :image-size="100" />
<div class="box5-main"> <div class="box5-main">
<div class="box5-back"> <AiSummary>
<div class="box5-top"> <template #summary-content>
<div class="box5-image"></div> <div class="box5-text">{{ box1Data }}</div>
</div> </template>
<div class="box5-text text-align-justify">{{ box1Data }}</div> </AiSummary>
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -170,6 +169,7 @@ import { ...@@ -170,6 +169,7 @@ import {
getDecreeIssueOrganization getDecreeIssueOrganization
} from "@/api/decree/introduction"; } from "@/api/decree/introduction";
import { getDecreeRelatedEvent } from "@/api/decree/background"; import { getDecreeRelatedEvent } from "@/api/decree/background";
import AiSummary from '@/components/base/Ai/AiSummary/index.vue'
import DefaultIcon1 from "@/assets/icons/default-icon1.png"; import DefaultIcon1 from "@/assets/icons/default-icon1.png";
import DefaultIcon2 from "@/assets/icons/default-icon2.png"; import DefaultIcon2 from "@/assets/icons/default-icon2.png";
...@@ -456,24 +456,9 @@ onMounted(() => { ...@@ -456,24 +456,9 @@ onMounted(() => {
} }
.box5-main { .box5-main {
padding: 10px 22px 22px; padding: 0px 22px 22px;
.box5-back {
border: solid 1px #E7F3FF;
.box5-top {
display: flex;
padding: 18px 20px;
background: linear-gradient(rgb(137, 193, 255, 0.1), rgb(255, 255, 255));
.box5-image {
width: 199px;
height: 32px;
font-size: 0px;
background-image: url('./assets/images/title-image.png');
background-size: 100% 100%;
cursor: pointer;
}
}
.box5-text { .box5-text {
padding: 0 20px 20px; padding-bottom: 20px;
font-family: "Source Han Sans CN"; font-family: "Source Han Sans CN";
font-weight: 400; font-weight: 400;
font-size: 16px; font-size: 16px;
...@@ -481,7 +466,6 @@ onMounted(() => { ...@@ -481,7 +466,6 @@ onMounted(() => {
min-height: 300px; min-height: 300px;
} }
} }
}
.box2-main { .box2-main {
padding: 0 22px; padding: 0 22px;
......
...@@ -52,8 +52,8 @@ export default defineConfig({ ...@@ -52,8 +52,8 @@ export default defineConfig({
}, },
'/api': { '/api': {
target: 'http://8.140.26.4:9085/', // target: 'http://8.140.26.4:9085/',
// target: 'http://172.20.10.3:28080/', target: 'http://172.20.10.3:28080/',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '') rewrite: (path) => path.replace(/^\/api/, '')
}, },
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论