提交 6eb0131b authored 作者: 张烨's avatar 张烨

fix:政令模块细节优化

上级 6b9cc944
......@@ -20,6 +20,14 @@ export function getDecreehylyList() {
})
}
// 获取受影响实体列表
export function getDecreeEntities(params) {
return request({
method: 'GET',
url: `/api/administrativeOrderInfo/relatedEntities/${params.id}`,
})
}
// 根据政行业领域ID获取公司列表
/**
* @param {cRelated, id}
......
......@@ -324,8 +324,8 @@ watch(isTranslate, () => {
.report-main {
flex: auto;
box-sizing: border-box;
padding-top: 10px;
height: 20px;
padding: 10px 0;
.no-content {
height: 100%;
......
......@@ -5,25 +5,25 @@
<div class="box1-main">
<div class="data-filter">
<div class="filter-select">
<el-select v-model="curAreaId" :empty-values="[null, undefined]" style="width: 100%">
<el-select v-model="areaInfo.id" :empty-values="[null, undefined]" style="width: 100%">
<el-option label="全部领域" value="" />
<el-option v-for="item in areaList" :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>
</div>
<div class="filter-input">
<el-input v-model="commandWord" @keyup.enter="handleSearch" style="width: 100%; height: 100%;" :suffix-icon="Search" placeholder="搜索实体" />
<el-input v-model="entityInfo.keyword" @keyup.enter="onDecreeEntities(1)" :suffix-icon="Search" placeholder="搜索实体" />
</div>
</div>
<div class="data-title">实体名称</div>
<div style="height: 20px; flex: auto;">
<el-empty v-if="!showCompanyList?.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>
<div class="list-data">
<div class="list-item" v-for="item in showCompanyList" :key="item.id" :class="{ 'item-active': activeEntityId === 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="handleToCompanyDetail(item)">
<div class="item-icon">
<img :src="defaultIcon2" alt="" class="item-img" />
</div>
<div class="item-name one-line-ellipsis">{{ item.name }}</div>
<div class="item-name one-line-ellipsis">{{ item.companyName }}</div>
<div class="item-icon item-icon-tag">
<img :src="noticeIcon" alt="" class="item-img" />
</div>
......@@ -33,16 +33,16 @@
</el-scrollbar>
</div>
<div class="pagination-info">
<div class="pagination-left">{{ `共 ${companyTotalNum} 家企业` }}</div>
<div class="pagination-left">{{ `共 ${entityInfo.total} 家企业` }}</div>
<div class="pagination-right">
<el-pagination
@current-change="handleCurrentChange"
:pageSize="pageSize"
:current-page="currentPage"
@current-change="onDecreeEntities"
:pageSize="entityInfo.pageSize"
:current-page="entityInfo.pageNum"
background
layout="prev, pager, next"
size="small"
:total="companyTotalNum"
:total="entityInfo.total"
/>
</div>
</div>
......@@ -68,9 +68,8 @@
</div>
</div>
<div class="title-right" v-if="contentType==1">
<el-select v-model="curAreaId" :empty-values="[null, undefined]" style="width: 100%">
<el-option label="全部领域" value="" />
<el-option v-for="item in areaList" :key="item.id" :label="item.name" :value="item.id" />
<el-select v-model="industryChain.id" style="width: 100%">
<el-option v-for="item in industryChain.list" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</div>
</div>
......@@ -78,10 +77,10 @@
<div class="box2-main">
<AiTips :tips="tips" />
<div class="graph-box" v-if="contentType==1">
<ChartChain />
<ChartChain :listData="fishbone.list" :baseData="fishbone.base" />
</div>
<div class="graph-box" v-if="contentType==2">
<GraphChart :nodes="graphData.nodes" :links="graphData.links" layoutType="force" />
<GraphChart :nodes="graphInfo.nodes" :links="graphInfo.links" layoutType="force" />
</div>
</div>
</AnalysisBox>
......@@ -91,8 +90,9 @@
<script setup>
import { ref, onMounted, reactive } from "vue";
import { useRoute } from "vue-router";
import { Search } from '@element-plus/icons-vue'
import { getDecreehylyList, getDecreeCompany } from "@/api/decree/influence";
import { getDecreehylyList, getDecreeEntities } from "@/api/decree/influence";
import ChartChain from "./com/ChartChain.vue";
import AiTips from "./com/AiTips.vue";
import GraphChart from "@/components/base/GraphChart/index.vue";
......@@ -104,9 +104,73 @@ import icon1620 from "./assets/images/icon1620.png";
import icon1621 from "./assets/images/icon1621.png";
import company from "./assets/images/company.png";
const route = useRoute();
const tips = "这项政令标志着中美AI竞争进入一个新阶段,其核心特征是 “精准封锁”与“体系输出”相结合。它短期内无疑会给中国AI产业链带来压力,但长期看,这场竞争更可能是一场围绕技术路线、生态系统和治理规则的持久战。"
// 关系图数据
const graphData = reactive({
// 行业领域
const areaInfo = reactive({
list: [],
id: "",
})
const handleGetHylyList = async () => {
try {
const res = await getDecreehylyList();
console.log("行业领域:", res);
if (res.code === 200) {
areaInfo.list = res.data || [];
}
} catch (error) {
areaInfo.list = [];
}
};
// 受影响实体
const entityInfo = reactive({
keyword: "",
pageSize: 10,
pageNum: 1,
total: 0,
list: [],
id: '',
})
const onDecreeEntities = async (page=1) => {
entityInfo.pageNum = page;
try {
const res = await getDecreeEntities({id: route.query.id});
console.log("受影响实体:", res);
if (res.code === 200 && res.data) {
entityInfo.list = res.data.companies;
entityInfo.total = res.data.companies.length;
}
} catch (error) {
console.log("获取受影响实体失败", error);
}
};
const handleToCompanyDetail = (item) => {
entityInfo.id = item.id;
};
const contentType = ref(1);
const headerContentType = (type) => {
contentType.value = type;
};
// 产业链
const industryChain = reactive({
list: [],
id: "",
})
// 产业链鱼骨图
const fishbone = reactive({
list: [],
base: {},
})
// 实体关系
const graphInfo = reactive({
leader: { id: 0, name: "泰丰先行" },
list: [
{ id: 1, name: "国轩高科", formatter: '持股' },
......@@ -122,9 +186,9 @@ const graphData = reactive({
links: [],
});
const initGraphChart = () => {
graphData.links = graphData.list.map(onFormatLink)
graphData.nodes = graphData.list.map(onFormatNode)
graphData.nodes.unshift(onFormatNode(graphData.leader))
graphInfo.links = graphInfo.list.map(onFormatLink)
graphInfo.nodes = graphInfo.list.map(onFormatNode)
graphInfo.nodes.unshift(onFormatNode(graphInfo.leader))
}
const onFormatLink = (item, index) => {
return {
......@@ -163,86 +227,8 @@ const onWordWrap = (word, num) => {
return label;
}
// 受影响实体
const companyList = ref([]);
const activeEntityId = ref(1);
const currentPage = ref(1);
const pageSize = ref(10);
const handleToCompanyDetail = (item) => {
activeEntityId.value = item.id;
};
const handleCurrentChange = page => {
currentPage.value = page;
};
const showCompanyList = ref([
{ id: 1, name: "北京市", status: "上市" },
{ id: 2, name: "上海市", status: "上市" },
{ id: 3, name: "广州市", status: "上市" },
{ id: 4, name: "深圳市", status: "上市" },
{ id: 5, name: "成都市", status: "上市" },
{ id: 7, name: "天津市", status: "上市" },
{ id: 9, name: "武汉市", status: "上市" },
{ id: 10, name: "西安市", status: "上市" },
]);
const handleGetCompanyListByArea = async () => {
const params = {
id: curAreaId.value
};
try {
const res = await getDecreeCompany(params);
console.log("行业领域公司列表", res);
if (res.code === 200 && res.data) {
companyList.value = res.data.map(item => {
return {
name: item.name,
id: item.id,
status: item.marketChange
};
});
companyTotalNum.value = companyList.value.length;
if (res.data?.length) handleToCompanyDetail(res.data[0])
} else {
companyList.value = [];
companyTotalNum.value = 0;
}
} catch (error) {
companyList.value = [];
companyTotalNum.value = 0;
}
};
// 指令搜索
const commandWord = ref("");
const handleSearch = () => {
};
// 行业领域
const curAreaId = ref("");
const areaList = ref([]);
const handleGetHylyList = async () => {
try {
const res = await getDecreehylyList();
console.log("行业领域列表", res);
if (res.code === 200 && res.data) {
areaList.value = res.data;
}
} catch (error) {
areaList.value = [];
}
};
// 产业链/实体关系
const contentType = ref(1);
const headerContentType = (type) => {
contentType.value = type;
};
// 企业影响分析
const companyTotalNum = ref(0); // 企业数量
onMounted(() => {
// handleGetCompanyListByArea();
onDecreeEntities();
initGraphChart()
handleGetHylyList();
});
......@@ -283,6 +269,11 @@ onMounted(() => {
box-shadow: 0 0 0 1px var(--el-border-color) inset;
box-sizing: border-box;
height: 32px;
:deep(.el-input) {
height: 100%;
width: 100%;
}
}
}
......
......@@ -53,7 +53,7 @@ export default defineConfig({
'/api': {
target: 'http://8.140.26.4:9085/',
// target: 'http://192.168.0.6:28080/',
// target: 'http://172.20.10.3:28080/',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
},
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论