提交 b689b671 authored 作者: liujq23's avatar liujq23

修改冲突

......@@ -22,6 +22,7 @@
"element-plus": "^2.4.4",
"highlight.js": "^11.11.1",
"json5": "^2.2.3",
"lodash": "^4.17.21",
"markdown-it": "^14.1.0",
"vue": "^3.4.0",
"vue-router": "^4.2.5"
......@@ -4139,7 +4140,7 @@
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"license": "MIT"
},
......
......@@ -31,6 +31,7 @@
"element-plus": "^2.4.4",
"highlight.js": "^11.11.1",
"json5": "^2.2.3",
"lodash": "^4.17.21",
"markdown-it": "^14.1.0",
"vue": "^3.4.0",
"vue-router": "^4.2.5"
......
import request from "@/api/request.js";
import {
ElMessage
} from 'element-plus'
const request200 = (requestP) => {
return requestP.then((data) => {
if (data.code === 200) {
return data.data
}
ElMessage({
message: data.message,
type: 'error',
duration: 3 * 1000
})
return null
})
}
// 实体清单总条数统计
/**
* @returns {Promise<number>}
*/
export function getEntitiesDataCount() {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/countData',
}))
}
// 最新实体清单信息查询
/**
* @returns {Promise<{
* chNum: number
* entities:{
* entityNameZh: string
* entityName: string
* }[]
* organization:{
* orgName: string
* }
* domains: string[]
* startTime: string
*}>}
*/
export function getEntitiesDataInfo() {
return request200(request({
method: 'GET',
url: '/api/entitiesDataInfo/latestInfoSelect',
}))
}
/**
* 每年最多领域及该领域发布次数
* @returns {Promise<{
* year?: number
* maxDomain: string
* maxCount: number
* }[]>}
*/
export function getIndustryCountByYear() {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/industryCountByYear',
}))
}
/**
* 不同领域每年数量
* @returns {Promise<{
* data:{
* year?: number
* domainNum: {
* [ key: string]: number;
* }
* }[]
* domains: string[]
* }>}
*/
export function getCountDomainByYear() {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/countDomainByYear',
}))
}
/**
* 历次制裁过程(月份统计)
* @returns {Promise<{
* tittle: string
* entitiesChNum: string
* sanReason: string
* }[]>}
*/
export function getSanctionsInfoCount() {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/sanctionsInfoCount',
}))
}
/**
* 查询发布机构
* @returns {Promise<{
* orgName: string //机构名称
* orgIntroduction: string //相关措施
* orgIntroduction: string //机构职责
* }>}
*/
export function getOrganizationInfo() {
return request200(request({
method: 'GET',
url: '/api/entitiesDataInfo/getOrganizationInfo',
}))
}
/**
* 查询重点人物
* @returns {Promise<{
* name: string
* ename: string
* avatarUrl: string
* positionTitle: string
* }[]>}
*/
export function getPersonList() {
return request200(request({
method: 'GET',
url: '/api/entitiesDataInfo/getPersonList',
}))
}
/**
* 不同领域实体统计
* @param {string} startTime - 统计开始时间,格式为 'YYYY-MM-DD'
* @returns {Promise<{
* domain: string
* count: number
* }[]>}
*/
export function getCountByDomain(startTime) {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/countByDomain',
params: {
startTime
}
}))
}
/**
* 不同类型实体统计
* @param {string} startTime - 统计开始时间,格式为 'YYYY-MM-DD'
* @returns {Promise<{
* type: string
* count: number
* }[]>}
*/
export function getCountByType(startTime) {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/countByType',
params: {
startTime
}
}))
}
/**
* 查询制裁原因
* @param {string} startTime - 统计开始时间,格式为 'YYYY-MM-DD'
* @returns {Promise<string[]>}
*/
export function getSanReasonSelect(startTime) {
return request200(request({
method: 'GET',
url: '/api/entitiesDataInfo/sanReasonSelect',
params: {
startTime
}
}))
}
/**
* 查询实体清单列表
* @param {string} startTime - 统计开始时间,格式为 'YYYY-MM-DD'
* @returns {Promise<{
* entityNameZh: string
* techDomainList: string[]
* startTime: staring
* }[]>}
*/
export function getSelectEntitiesList(startTime) {
return request200(request({
method: 'GET',
url: '/api/entitiesDataInfo/selectEntitiesList',
params: {
startTime
}
}))
}
/**
* 数量比对分析
* @param {string} startTime - 统计开始时间,格式为 'YYYY-MM-DD'
* @returns {Promise<{
* countDomainLast: number
* countDomainNow: number
* countSanLast: number
* countSanNow: number
* countTypeLast: number
* countTypeNow: number
* }>}
*/
export function getCompareCountSan(startTime) {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/compareCountSan',
params: {
startTime
}
}))
}
/**
* 实体清单变化统计
* @param {number} domain
* @param {number} type
* @returns {Promise<{
* year:number
* count:number
* }[]>}
*/
export function getEntitiesChangeCount(domain, type) {
return request200(request({
method: 'GET',
// url: '/api/entitiesDataCount/entitiesChangeCount',
url: '/api/entitiesDataCount/sanCountByYear',
params: {
domain,
type
}
}))
}
/**
* 新增实体数量增长趋势
* @returns {Promise<{
* year: string
* percent: string //百分比'20%'
* }>}
*/
export function getEntitiesGrowthTrend() {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/entitiesGrowthTrend',
}))
}
/**
* 实体清单更新频率
* @returns {Promise<{
* series: number[]
* xAxis: string[]
* }>}
*/
export function getEntitiesUpdateCount() {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/entitiesUpdateCount',
}))
}
/**
* 新增实体领域分布情况
* @param {string} sanTime - 开始时间,格式为 'YYYY-MM-DD'
* @returns {Promise<{
* value: number
* name: string
* }[]>}
*/
export function getEntitiesAreaCountByYear(sanTime) {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/entitiesAreaCountByYear',
params: {
sanTime
}
}))
}
/**
* 历次制裁涉及领域数
* @returns {Promise<{
* series: number[]
* xAxis: string[]
* }>}
*/
export function getEntitiesDomainCount() {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/entitiesDomainCount'
}))
}
/**
* 指定领域每年实体数量查询
* @param {string} param
* @returns {Promise<{
* year: string
* count: number
* }[]>}
*/
export function getCountThisDomain(param) {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/countThisDomain',
params: {
param
}
}))
}
/**
* 历次制裁涉及类别数量
* @returns {Promise<{
* year: string
* count: number
* }[]>}
*/
export function getCountTypeByYear() {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/countTypeByYear',
}))
}
/**
* 新增实体类别统计
* @param {string} startTime - 开始时间,格式为 'YYYY-MM-DD'
* @returns {Promise<{
* type: string
* count: number
* }[]>}
*/
export function getCountSanTypeByTime(startTime) {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/countSanTypeByTime',
params: {
startTime
}
}))
}
/**
* 指定类别每年实体数量查询
* @param {string} param
* @returns {Promise<{
* year: number
* count: number
* }[]>}
*/
export function getCountThisType(param) {
return request200(request({
method: 'GET',
url: '/api/entitiesDataCount/countThisType',
params: {
param
}
}))
}
import { ref } from 'vue';
export function useRequest(apiFunction, immediate = true) {
const data = ref(null);
const loading = ref(false);
const error = ref(null);
const execute = async (...args) => {
loading.value = true;
error.value = null;
try {
data.value = await apiFunction(...args);
} catch (err) {
error.value = err;
} finally {
loading.value = false;
}
};
if (immediate) {
execute(); // 可选:是否立即执行
}
return {
data,
loading,
error,
execute, // 手动触发函数
};
}
\ No newline at end of file
......@@ -6,18 +6,20 @@
<el-select
:style="{ width: '120px', marginRight: '8px' }"
size="mini"
v-model="value1"
v-model="domainValue"
placeholder="领域选择"
>
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option>
<el-option v-for="item in domainOptions" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
<el-select
:style="{ width: '120px', marginRight: '18px' }"
size="mini"
v-model="value2"
v-model="typeValue"
placeholder="类型选择"
>
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option>
<el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</template>
<div class="subPanel1">
......@@ -82,28 +84,169 @@
</template>
<script setup>
import { ref, shallowRef, onMounted } from "vue";
import { ref, shallowRef, onMounted, watch } from "vue";
import CardCustom from "../../components/CardCustom.vue";
import { Search } from "@element-plus/icons-vue";
import Echarts from "@/components/Chart/index.vue";
import { getBarChart, getLineChart } from "../../utils/charts";
import Hint from "./hint.vue";
const options = [
import { getEntitiesChangeCount, getEntitiesGrowthTrend, getEntitiesUpdateCount } from "@/api/exportControl";
import _ from "lodash";
import { useRoute } from "vue-router";
const route = useRoute();
const line1Option = shallowRef({});
const bar2Option = shallowRef({});
onMounted(async () => {
try {
const [entitiesGrowthTrendData, entitiesUpdateCountData] = await Promise.all([
getEntitiesGrowthTrend(),
getEntitiesUpdateCount()
]);
const list = _.reverse(entitiesGrowthTrendData);
const xAxisData = _.map(list, "year");
const seriesData = _.map(list, item => {
return parseInt(item.percent);
});
line1Option.value = getLineChart({ xAxisData, seriesData, name: "增长趋势", color: "rgba(146, 84, 222, 1)" }, true);
bar2Option.value = getBarChart(
_.reverse(entitiesUpdateCountData.xAxis),
_.reverse(entitiesUpdateCountData.series),
["rgba(22, 119, 255, 1)", "rgba(22, 119, 255, 0)"],
"更新频率"
);
} catch (err) {
console.log(err);
}
});
const domainOptions = [
{
value: "1",
label: "人工智能"
},
{
value: "2",
label: "生物科技"
},
{
value: "3",
label: "新一代信息技术"
},
{
value: "4",
label: "量子科技"
},
{
value: "5",
label: "新能源"
},
{
value: "6",
label: "集成电路"
},
{
value: "7",
label: "海洋"
},
{
value: "8",
label: "先进制造"
},
{
value: "9",
label: "新材料"
},
{
value: "10",
label: "航空航天"
},
{
value: "11",
label: "深海"
},
{
value: "12",
label: "极地"
},
{
value: "13",
label: "太空"
},
{
value: "14",
label: "核"
},
{
value: "20",
label: "政治"
},
{
value: "21",
label: "外交"
},
{
value: "22",
label: "经济"
},
{
value: "23",
label: "军事"
},
{
value: "24",
label: "科技"
},
{
value: "25",
label: "安全"
},
{
value: "99",
label: "其他"
}
];
const value1 = ref("");
const value2 = ref("");
const value3 = ref("");
const typeOptions = [
{
value: "1",
label: "人物"
},
{
value: "2",
label: "机构"
},
{
value: "7",
label: "地址"
}
];
const domainValue = ref(domainOptions[0].value);
const typeValue = ref(typeOptions[0].value);
const bar1Option = shallowRef({});
const bar2Option = shallowRef({});
const line1Option = shallowRef({});
watch(
[domainValue, typeValue],
async ([domain, type]) => {
let EntitiesChangeCount = await getEntitiesChangeCount(domain, type);
EntitiesChangeCount = _.reverse(EntitiesChangeCount);
bar1Option.value = getBarChart(
_.map(EntitiesChangeCount, "year"),
_.map(EntitiesChangeCount, "count"),
["rgba(255, 159, 22, 1)", "rgba(255, 159, 22, 0)"],
"制裁强度"
);
},
{ immediate: true }
);
// const options = [
// {
// value: "1",
// label: "人工智能"
// },
// {
// value: "2",
// label: "航空航天"
// }
// ];
const subPanel4 = ref([
{
name: "中国科学技术大学",
......@@ -141,21 +284,7 @@ const subPanel4 = ref([
]
}
]);
onMounted(() => {
bar1Option.value = getBarChart(
["2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"],
[219, 228, 129, 159, 152, 157, 78, 34, 56, 78],
["rgba(255, 159, 22, 1)", "rgba(255, 159, 22, 0)"],
"制裁强度"
);
bar2Option.value = getBarChart(
["2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"],
[39, 28, 49, 19, 22, 25, 78, 34, 56, 28],
["rgba(22, 119, 255, 1)", "rgba(22, 119, 255, 0)"],
"更新频率"
);
line1Option.value = getLineChart();
});
const value3 = ref("");
</script>
<style lang="scss" scoped>
......
......@@ -121,9 +121,14 @@ onMounted(() => {
["2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"],
[39, 28, 49, 19, 22, 25, 78, 34, 56, 28],
["rgba(19, 188, 196, 1)", "rgba(19, 188, 196, 0)"],
"更新频率"
"市值变化"
);
line1Option.value = getLineChart();
line1Option.value = getLineChart({
xAxisData: [2013, 2023, 2024, 2015],
seriesData: [434, 24, 453, 322],
name: "融资变化",
color: "rgba(146, 84, 222, 1)"
});
});
</script>
......
......@@ -46,30 +46,51 @@ import { Search } from "@element-plus/icons-vue";
import Echarts from "@/components/Chart/index.vue";
import { getBarChart, getLineChart, getPieOption1 } from "../../utils/charts";
import Hint from "./hint.vue";
import { getEntitiesAreaCountByYear, getEntitiesDomainCount, getCountThisDomain } from "@/api/exportControl";
import _ from "lodash";
import { useRoute } from "vue-router";
const route = useRoute();
const pie1Option = shallowRef({});
const bar2Option = shallowRef({});
const line1Option = shallowRef({});
const line2Option = shallowRef({});
onMounted(() => {
pie1Option.value = getPieOption1(
[
{ name: "半导体与集成电路领域", value: 50 },
{ name: "生物技术与生命科学领域", value: 46 },
{ name: "航天遥感与量子技术领域", value: 12 },
{ name: "航空航天领域", value: 32 },
{ name: "人工智能领域", value: 31 },
{ name: "供应链与物流服务领域", value: 30 },
{ name: "工业软件领域", value: 24 }
]
);
onMounted(async () => {
try {
const [entitiesAreaCountByYearData, countThisDomainData4, entitiesDomainCountData, countThisDomainData10] =
await Promise.all([
getEntitiesAreaCountByYear(route.query.startTime),
getCountThisDomain("4"),
getEntitiesDomainCount(),
getCountThisDomain("10")
]);
pie1Option.value = getPieOption1(entitiesAreaCountByYearData ?? []);
const list4 = _.reverse(countThisDomainData4 ?? []);
line1Option.value = getLineChart({
xAxisData: _.map(list4, "year"),
seriesData: _.map(list4, "count"),
name: "量子科技领域",
color: "rgba(255, 149, 77, 1)"
});
bar2Option.value = getBarChart(
["2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"],
[39, 28, 49, 19, 22, 25, 78, 34, 56, 28],
_.reverse(entitiesDomainCountData?.xAxis ?? []),
_.reverse(entitiesDomainCountData?.series ?? []),
["rgba(19, 188, 196, 1)", "rgba(19, 188, 196, 0)"],
"更新频率"
"领域数"
);
line1Option.value = getLineChart("rgba(255, 149, 77, 1)");
line2Option.value = getLineChart("rgba(146, 84, 222, 1)");
const list10 = _.reverse(countThisDomainData10 ?? []);
line2Option.value = getLineChart({
xAxisData: _.map(list10, "year"),
seriesData: _.map(list10, "count"),
name: "航空航天领域",
color: "rgba(146, 84, 222, 1)"
});
} catch (err) {
console.log(err);
}
});
</script>
......
......@@ -46,28 +46,58 @@ import { Search } from "@element-plus/icons-vue";
import Echarts from "@/components/Chart/index.vue";
import { getBarChart, getLineChart, getPieOption1 } from "../../utils/charts";
import Hint from "./hint.vue";
import { getCountSanTypeByTime, getCountTypeByYear, getCountThisType } from "@/api/exportControl";
import _ from "lodash";
import { useRoute } from "vue-router";
const route = useRoute();
const pie1Option = shallowRef({});
const bar2Option = shallowRef({});
const line1Option = shallowRef({});
const line2Option = shallowRef({});
onMounted(() => {
onMounted(async () => {
try {
const [countSanTypeByTimeData, countThisTypeData1, countTypeByYearData, countThisTypeData2] = await Promise.all([
getCountSanTypeByTime(route.query.startTime),
getCountThisType("1"),
getCountTypeByYear(),
getCountThisType("2")
]);
pie1Option.value = getPieOption1(
[
{ name: "企业", value: 50 },
{ name: "科研院所", value: 40 },
{ name: "高校", value: 32 },
{ name: "政府官员", value: 30 },
{ name: "个人", value: 24},
]
_.map(countSanTypeByTimeData ?? [], item => {
return {
name: item?.type,
value: item?.count
};
})
);
const list1 = _.reverse(countThisTypeData1 ?? []);
line1Option.value = getLineChart({
xAxisData: _.map(list1, "year"),
seriesData: _.map(list1, "count"),
name: "科研院所类",
color: "rgba(255, 149, 77, 1)"
});
const list = _.reverse(countTypeByYearData ?? []);
bar2Option.value = getBarChart(
["2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"],
[39, 28, 49, 19, 22, 25, 78, 34, 56, 28],
_.map(list, "year"),
_.map(list, "count"),
["rgba(19, 188, 196, 1)", "rgba(19, 188, 196, 0)"],
"更新频率"
"实体数"
);
line1Option.value = getLineChart("rgba(255, 149, 77, 1)");
line2Option.value = getLineChart("rgba(146, 84, 222, 1)");
const list2 = _.reverse(countThisTypeData2 ?? []);
line2Option.value = getLineChart({
xAxisData: _.map(list2, "year"),
seriesData: _.map(list2, "count"),
name: "企业类",
color: "rgba(117, 29, 219, 1)"
});
} catch (err) {
console.log(err);
}
});
</script>
......
......@@ -13,31 +13,70 @@
import Echarts from "@/components/Chart/index.vue";
import { getPieOption } from "../../utils/charts";
import { ref, onMounted, shallowRef } from "vue";
import { getCountByDomain, getCountByType } from "@/api/exportControl";
import _ from "lodash";
import { useRoute } from "vue-router";
const route = useRoute();
const pie1Option = shallowRef({});
const pie2Option = shallowRef({});
onMounted(() => {
onMounted(async () => {
try {
const [countByDomainData, countByTypeData] = await Promise.all([
getCountByDomain(route.query.startTime),
getCountByType(route.query.startTime)
]);
pie1Option.value = getPieOption(
[
{ name: "能源领域", value: 30 },
{ name: "集成电路领域", value: 20 },
{ name: "人工智能领域", value: 12 },
{ name: "通信网络领域", value: 18 },
{ name: "量子科技领域", value: 10 },
{ name: "生物科技领域", value: 10 }
],
_.chain(countByDomainData)
.filter(item => item.count > 0)
.map(item => {
return {
name: item?.domain,
value: item?.count
};
})
.value(),
"领域分布"
);
pie2Option.value = getPieOption(
[
{ name: "能源领域", value: 30 },
{ name: "集成电路领域", value: 20 },
{ name: "人工智能领域", value: 12 },
{ name: "通信网络领域", value: 18 },
{ name: "量子科技领域", value: 10 },
{ name: "生物科技领域", value: 10 }
],
"类别分布"
_.chain(countByTypeData)
.filter(item => item.count > 0)
.map(item => {
return {
name: item?.type,
value: item?.count
};
})
.value(),
"类型分布"
);
} catch (err) {
console.log(err);
}
});
onMounted(() => {
// pie1Option.value = getPieOption(
// [
// { name: "能源领域", value: 30 },
// { name: "集成电路领域", value: 20 },
// { name: "人工智能领域", value: 12 },
// { name: "通信网络领域", value: 18 },
// { name: "量子科技领域", value: 10 },
// { name: "生物科技领域", value: 10 }
// ],
// "领域分布"
// );
// pie2Option.value = getPieOption(
// [
// { name: "能源领域", value: 30 },
// { name: "集成电路领域", value: 20 },
// { name: "人工智能领域", value: 12 },
// { name: "通信网络领域", value: 18 },
// { name: "量子科技领域", value: 10 },
// { name: "生物科技领域", value: 10 }
// ],
// "类别分布"
// );
});
</script>
......
......@@ -5,7 +5,7 @@
<div
class="item"
:class="{ activeItem: activePanelId === item.id }"
v-for="item in panelListData"
v-for="item in compareCountSan"
:key="item.id"
@click="setActivePanelId(item.id)"
>
......@@ -44,51 +44,67 @@
</div>
</div>
<div class="row">
<panel1 v-if="activePanelId === panelListData[0].id"></panel1>
<panel2 v-if="activePanelId === panelListData[1].id"></panel2>
<panel3 v-if="activePanelId === panelListData[2].id"></panel3>
<panel4 v-if="activePanelId === panelListData[3].id"></panel4>
<panel1 v-if="activePanelId === compareCountSan[0]?.id"></panel1>
<panel2 v-if="activePanelId === compareCountSan[1]?.id"></panel2>
<panel3 v-if="activePanelId === compareCountSan[2]?.id"></panel3>
<panel4 v-if="activePanelId === compareCountSan[3]?.id"></panel4>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import { ref, onMounted, shallowRef } from "vue";
import Panel1 from "../components/panel1.vue";
import Panel2 from "../components/panel2.vue";
import Panel3 from "../components/panel3.vue";
import Panel4 from "../components/panel4.vue";
const panelListData = [
import { getCompareCountSan } from "@/api/exportControl";
import { useRoute } from "vue-router";
const route = useRoute();
const compareCountSan = shallowRef([]);
const activePanelId = ref(null);
onMounted(async () => {
try {
const [compareCountSanData] = await Promise.all([getCompareCountSan(route.query.startTime)]);
const { countSanNow, countSanLast, countDomainNow, countDomainLast, countTypeNow, countTypeLast } =
compareCountSanData ?? {};
compareCountSan.value = [
{
id: 1,
name: "新增实体数量",
number: "37",
isUp: true,
ComparisonNumber: "31"
number: countSanNow,
isUp: countSanNow - countSanLast >= 0,
ComparisonNumber: Math.abs(countSanNow - countSanLast)
},
{
id: 2,
name: "上市企业数量",
number: "6",
number: "--",
isUp: true,
ComparisonNumber: "2"
ComparisonNumber: "--"
},
{
id: 3,
name: "涉及领域数量",
number: "2",
isUp: false,
ComparisonNumber: "1"
number: countDomainNow,
isUp: countDomainNow - countDomainLast >= 0,
ComparisonNumber: Math.abs(countDomainNow - countDomainLast)
},
{
id: 4,
name: "实体类别数量",
number: "4",
isUp: true,
ComparisonNumber: "1"
number: countTypeNow,
isUp: countTypeNow - countTypeLast >= 0,
ComparisonNumber: Math.abs(countTypeNow - countTypeLast)
}
];
const activePanelId = ref(panelListData[0].id);
];
activePanelId.value = compareCountSan.value[0].id;
} catch (err) {
console.log(err);
}
});
const setActivePanelId = id => {
activePanelId.value = id;
};
......
......@@ -3,26 +3,26 @@
<div class="row">
<CardCustom title="实体清单发布机构" :style="{ width: '984px', height: '284px' }">
<div class="panel1">
<img :src="panel1.img" alt="" class="img" />
<img :src="organizationInfo.img" alt="" class="img" />
<div class="infoWrap">
<div class="item">
<div class="name">机构名称:</div>
<div class="doc">{{ panel1.mingcheng }}</div>
<div class="doc">{{ organizationInfo.mingcheng }}</div>
</div>
<div class="item">
<div class="name">相关措施:</div>
<div class="doc">{{ panel1.cuoshi }}</div>
<div class="doc">{{ organizationInfo.cuoshi }}</div>
</div>
<div class="item">
<div class="name">机构职责:</div>
<div class="doc zhize">{{ panel1.zhize }}</div>
<div class="doc zhize">{{ organizationInfo.zhize }}</div>
</div>
</div>
</div>
</CardCustom>
<CardCustom title="重点人物" :style="{ width: '600px', height: '284px' }">
<div class="panel2">
<div class="item" v-for="(item, index) in panel2" :key="index">
<div class="item" v-for="(item, index) in personLis" :key="index">
<img :src="item.img" alt="" class="img" />
<div class="infoWrap">
<div class="name">{{ item.name }}</div>
......@@ -64,7 +64,7 @@
</CardCustom>
<CardCustom title="制裁原因" :style="{ width: '600px', height: '520px' }">
<div class="panel4">
<div class="item" v-for="(item, index) in panel4" :key="index">
<div class="item" v-for="(item, index) in sanReasonSelect" :key="index">
<div class="icon1">{{ index + 1 }}</div>
<div class="text">{{ item.text }}</div>
<div class="icon2"></div>
......@@ -96,7 +96,7 @@
</div>
<div class="tableWrap">
<el-table
:data="panel5MockData"
:data="selectEntitiesList"
class="sanction-table"
stripe
empty-text="暂无数据"
......@@ -106,7 +106,10 @@
<el-table-column prop="name" label="实体清单" min-width="180">
<template #default="{ row }">
<div style="font-weight: 500" class="name">
<img :src="row.img" alt="" class="img" />
<img v-if="row.img" :src="row.img" alt="" class="img" />
<div v-else class="imgUndefined">
{{ row.name?.match(/[\u4e00-\u9fa5a-zA-Z0-9]/)?.[0] }}
</div>
{{ row.name }}
</div>
</template>
......@@ -122,7 +125,7 @@
</template>
</el-table-column>
<el-table-column prop="address" label="上市地点" width="100" align="center">
<el-table-column prop="address" label="上市地点" width="90" align="center">
<template #default="{ row }">
{{ row.address }}
</template>
......@@ -180,8 +183,7 @@ import PieCharts from "../components/pieCharts.vue";
import MapCharts from "../components/mapCharts.vue";
import ButtonList from "@/components/buttonList/buttonList.vue";
import Hint from "../components/hint.vue";
import { onMounted, reactive, ref } from "vue";
import { onMounted, reactive, ref, shallowRef } from "vue";
import panel1_1 from "../../assets/images/panel1_1.png";
import panel2_1 from "../../assets/images/panel2_1.png";
import panel2_2 from "../../assets/images/panel2_2.png";
......@@ -195,43 +197,39 @@ import panel5_5 from "../../assets/images/panel5_5.png";
import panel5_6 from "../../assets/images/panel5_6.png";
import panel5_7 from "../../assets/images/panel5_7.png";
import panel5_8 from "../../assets/images/panel5_8.png";
const panel1 = ref({
img: panel1_1,
mingcheng: "美国商务部工业与安全局",
cuoshi: "出口管制条例(EAR)、实体清单、商业管制清单(CCL)、232调查等",
zhize: "美国商务部工业与安全局(BIS)是美国商务部下属机构,核心职责围绕国家安全与战略技术管控展开,具体包括:以维护商业管制清单(CCL)和出口管制分类号(ECCN)的方式,对敏感货物及两用技术实施出口管制并确定许可要求;通过出口执行局(OEE)执行出口管制、反抵制等相关法律,对违规行为采取行政、刑事等处罚措施;在出口管制和战略贸易问题上与其他国家合作,参与并领导国际出口管制制度。"
});
const panel2 = ref([
{
name: "吉娜·雷蒙多",
enName: "Gina Raimondo",
party: "美国民主党",
img: panel2_1
},
{
name: "迈克・约翰逊",
enName: "Mike Johnson",
party: "美国共和党",
img: panel2_2
},
{
name: "艾伦·埃斯特韦斯",
enName: "Alan Estevez",
party: "美国民主党",
img: panel2_3
},
{
name: "凯・格兰杰",
enName: "Kay Granger",
party: "美国共和党",
img: panel2_4
}
import { getOrganizationInfo, getPersonList, getSanReasonSelect, getSelectEntitiesList } from "@/api/exportControl";
import _ from "lodash";
import { useRoute } from "vue-router";
import { formatAnyDateToChinese } from "../../utils";
const route = useRoute();
const organizationInfo = shallowRef({});
const personLis = shallowRef([
// {
// name: "吉娜·雷蒙多",
// enName: "Gina Raimondo",
// party: "美国民主党",
// img: panel2_1
// },
// {
// name: "迈克・约翰逊",
// enName: "Mike Johnson",
// party: "美国共和党",
// img: panel2_2
// },
// {
// name: "艾伦·埃斯特韦斯",
// enName: "Alan Estevez",
// party: "美国民主党",
// img: panel2_3
// },
// {
// name: "凯・格兰杰",
// enName: "Kay Granger",
// party: "美国共和党",
// img: panel2_4
// }
]);
const panel3ActiveIndex = ref(1);
const setPanel3ActiveIndex = index => {
panel3ActiveIndex.value = index;
};
const panel4 = ref([
const sanReasonSelect = shallowRef([
{
text: "获取美国产物项,以支持中国量子技术;"
},
......@@ -248,6 +246,54 @@ const panel4 = ref([
text: "将中国定位为“通过强制技术转让获取先进制程的威胁”"
}
]);
const selectEntitiesList = shallowRef([]);
onMounted(async () => {
try {
const [organizationInfoData, personListData, sanReasonSelectData, selectEntitiesListData] = await Promise.all([
getOrganizationInfo(),
getPersonList(),
getSanReasonSelect(route.query.startTime),
getSelectEntitiesList(route.query.startTime)
]);
organizationInfo.value = {
img: panel1_1,
mingcheng: organizationInfoData?.orgName,
cuoshi: organizationInfoData?.cuoshi || "美国商务部工业与安全局",
zhize: organizationInfoData?.orgIntroduction || "--"
};
personLis.value = _.map(personListData, item => {
return {
name: item.name,
enName: item.enName,
party: item.positionTitle,
img: item.avatarUrl
};
});
sanReasonSelect.value = _.map(sanReasonSelectData, item => {
return { text: item };
});
selectEntitiesList.value = _.map(selectEntitiesListData, item => {
return {
name: item?.entityNameZh,
domains: item.techDomainList,
address: "--",
time: formatAnyDateToChinese(item?.startTime),
isUp: true,
revenue: "--",
subCompany: "--",
img: ""
};
});
} catch (err) {
console.log(err);
}
});
const panel3ActiveIndex = ref(1);
const setPanel3ActiveIndex = index => {
panel3ActiveIndex.value = index;
};
const panel5ButtonList = [
{ id: 1, text: "新增实体" },
......@@ -379,7 +425,7 @@ const panel6 = ref([
}
.panel1 {
height: 100%;
padding: 2px 24px 0 24px;
padding: 2px 35px 0 24px;
display: flex;
.img {
width: 90px;
......@@ -414,6 +460,11 @@ const panel6 = ref([
font-size: 16px;
font-weight: 400;
line-height: 24px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 5; /* 控制行数 */
overflow: hidden;
text-overflow: ellipsis;
}
}
}
......@@ -551,6 +602,10 @@ const panel6 = ref([
font-weight: 400;
line-height: 30px;
flex: 1;
overflow: hidden;
white-space: noWrap;
text-overflow: ellipsis;
min-width: 0;
}
.icon2 {
width: 16px;
......@@ -605,6 +660,7 @@ const panel6 = ref([
flex: 1;
margin-top: 14px;
min-height: 0;
overflow: auto;
}
.name {
display: flex;
......@@ -614,6 +670,20 @@ const panel6 = ref([
height: 40px;
margin-right: 6px;
margin-left: 6px;
flex-shrink: 0;
}
.imgUndefined {
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
flex-shrink: 0;
color: rgba(5, 95, 194, 1);
background-color: rgb(236, 245, 255);
border-radius: 20px;
margin-right: 6px;
margin-left: 6px;
}
}
.subCompany {
......
......@@ -125,7 +125,8 @@ import icon2 from "../assets/icons/icon2.png";
import icon2Active from "../assets/icons/icon2_active.png";
import icon3 from "../assets/icons/icon3.png";
import icon3Active from "../assets/icons/icon3_active.png";
import { useRoute } from "vue-router";
const route = useRoute();
const activeName = ref("分析报告");
const handleSwitchActiveName = name => {
......@@ -171,7 +172,12 @@ const activeTitle = ref("制裁概况");
const handleClickMainHeaderBtn = item => {
activeTitle.value = item.name;
// window.sessionStorage.setItem('activeTitle', activeTitle.value)
router.push(item.path);
router.push({
path: item.path,
query: {
...route.query
}
});
};
const activeNavIndex = ref(0);
......
......@@ -98,21 +98,27 @@
</div> -->
<div class="box1-top">
<div class="box1-top-title">2025年9月12日——BIS《实体清单增列与修订条目》</div>
<div class="box1-top-title">
{{ entitiesDataInfoReactive.startTime }}——BIS《实体清单增列与修订条目》
</div>
<div class="box1-top-content">
<div class="box1-top-content-item">
<span class="box1-top-content-item-title">· 发布机构:</span>
<span class="box1-top-content-item-content">美国商务部工业与安全局</span>
<span class="box1-top-content-item-content">{{
entitiesDataInfoReactive.orgName
}}</span>
</div>
<div class="box1-top-content-item">
<span class="box1-top-content-item-title">· 生效日期:</span>
<span class="box1-top-content-item-content">2025年9月12日</span>
<span class="box1-top-content-item-content">{{
entitiesDataInfoReactive.startTime
}}</span>
</div>
<div class="box1-top-content-item">
<span class="box1-top-content-item-title">· 涉及领域:</span>
<div
class="box1-top-content-item-tags"
v-for="item in ['航空航天', '人工智能', '集成电路']"
v-for="item in entitiesDataInfoReactive.domains"
:key="item"
>
<el-tag
......@@ -128,9 +134,21 @@
<div class="box1-bottom">
<div class="box1-bottom-title">· 涉及主要实体:</div>
<div class="box1-bottom-content">
<div class="box1-bottom-content-item" v-for="(item, index) in entityList" :key="index">
<el-image class="box1-bottom-content-item-img" :src="item.img" alt=""></el-image>
<div class="box1-bottom-content-item-txt">{{ item.name }}</div>
<div
class="box1-bottom-content-item"
v-for="(item, index) in entitiesDataInfoReactive.entityList"
:key="index"
>
<el-image
v-if="item.img"
class="box1-bottom-content-item-img"
:src="item.img"
alt=""
></el-image>
<div v-else class="box1-bottom-content-item-imgUndefined">
{{ (item.name || item.enName)?.match(/[\u4e00-\u9fa5a-zA-Z0-9]/)?.[0] }}
</div>
<div class="box1-bottom-content-item-txt">{{ item.name || item.enName }}</div>
</div>
</div>
</div>
......@@ -139,7 +157,7 @@
<el-icon><Warning color="rgba(206, 79, 81, 1)" /></el-icon>
<span>新增中国实体</span>
</div>
<div class="box1-absolute-num">23</div>
<div class="box1-absolute-num">{{ entitiesDataInfoReactive.chNum }}</div>
</div>
</div>
</template>
......@@ -404,7 +422,7 @@
</div>
</div>
</div>
<div class="box4-footer">
<div class="box4-footer" :style="{ marginTop: sanctionProcessList.length > 0 ? '0px' : 'auto' }">
<el-button type="primary" link :icon="DownRight"
>查看更多
<el-icon><DArrowRight /></el-icon>
......@@ -514,7 +532,7 @@
</template>
<script setup>
import { onMounted, ref, computed } from "vue";
import { onMounted, ref, computed, reactive, shallowRef } from "vue";
import scrollToTop from "@/utils/scrollToTop";
import * as echarts from "echarts";
import setChart from "@/utils/setChart";
......@@ -581,7 +599,78 @@ import shenggongIcon from "./assets/images/shenggong.png";
import shoushiIcon from "./assets/images/shoushi.png";
import tianyiIcon from "./assets/images/tianyi.png";
import aircasIcon from "./assets/images/aircas.png";
import {
getEntitiesDataCount,
getEntitiesDataInfo,
getIndustryCountByYear,
getCountDomainByYear,
getSanctionsInfoCount
} from "@/api/exportControl";
import { getMultipleBarChart_m } from "./utils/charts";
import { formatAnyDateToChinese } from "./utils";
import _ from "lodash";
//数据定义
const entitiesDataInfoReactive = shallowRef({
chNum: undefined,
entityList: [],
domains: [],
startTime: "",
rawStartTime: "",
orgName: ""
});
// 趋势图
const trendOption = ref({});
// 发布频度
const tableData1 = ref([]);
// 历次制裁过程
const sanctionProcessList = ref([]);
onMounted(async () => {
try {
const [dataCount, entitiesDataInfo, industryCountByYear, countDomainByYear, sanctionsInfoCount = []] = await Promise.all([
getEntitiesDataCount(),
getEntitiesDataInfo(),
getIndustryCountByYear(),
getCountDomainByYear(),
getSanctionsInfoCount()
]);
infoList.value[0].num = dataCount;
const entityList = _.map(entitiesDataInfo?.entities ?? [], ({ entityNameZh, entityName }) => {
return { name: entityNameZh, enName: entityName };
});
entitiesDataInfoReactive.value = {
entityList,
chNum: entitiesDataInfo?.chNum,
domains: entitiesDataInfo?.domains ?? [],
startTime: formatAnyDateToChinese(entitiesDataInfo?.startTime ?? ""),
rawStartTime: entitiesDataInfo?.startTime ?? "",
orgName: entitiesDataInfo?.organization?.orgName
};
const list = _.chain(industryCountByYear).filter("year").orderBy("year", "desc").value();
const total = _.sumBy(list, "maxCount");
tableData1.value = _.map(list, item => {
return {
year: item.year,
num: item.maxCount,
percent: item.maxCount / total,
tags: item.maxDomain.split(",")
};
});
trendOption.value = getMultipleBarChart_m(countDomainByYear);
sanctionProcessList.value = _.map(_.slice(sanctionsInfoCount, 0, 5), item => {
return {
title: item.tittle,
desc: `${item.entitiesChNum} 家中国实体`,
content:
item.sanReason ||
"2025年3月25日,美国商务部工业与安全局以从事有悖于美国国家安全和外交政策利益的活动为由,宣布将来自中国的54家实体新增至“实体清单”。"
};
});
} catch (err) {
console.log(err);
}
});
// 返回首页
const handleBackHome = () => {
router.push({
......@@ -597,7 +686,12 @@ const handleToDetail = () => {
// path: "/exportControl/analysis"
// });
const route = router.resolve("/exportControlAnalysis");
const route = router.resolve({
path: "/exportControlAnalysis",
query: {
startTime: entitiesDataInfoReactive.value.rawStartTime
}
});
window.open(route.href, "_blank");
};
......@@ -611,7 +705,7 @@ const infoList = ref([
title: "实体清单",
subTitle: "Entity List",
des: "美国商务部工业与安全局依据《出口管理条例》建立的出口管制机制",
num: 956,
num: null,
color: "rgba(206, 79, 81, 1)"
},
{
......@@ -712,40 +806,6 @@ const customNewsData = ref([
}
]);
// 发布频度
const tableData1 = ref([
{
year: "2025",
num: 5,
percent: 0.4,
tags: ["通信网络"]
},
{
year: "2024",
num: 12,
percent: 0.9,
tags: ["通信网络", "人工智能"]
},
{
year: "2023",
num: 2,
percent: 0.4,
tags: ["通信网络"]
},
{
year: "2022",
num: 6,
percent: 0.7,
tags: ["通信网络", "集成电路"]
},
{
year: "2021",
num: 7,
percent: 0.8,
tags: ["生物科技", "集成电路"]
}
]);
// 雷达图
const radarOption = ref({
title: {
......@@ -807,151 +867,6 @@ const radarOption = ref({
]
});
// 趋势图
const trendOption = ref({
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow"
}
},
grid: {
top: 50
},
legend: {
// type: "scroll",
// show: true,
// orient: "horizontal",
icon: "circle",
data: ["量子科技", "人工智能", "通信网络", "集成电路", "生物科技", "能源领域"]
},
xAxis: {
type: "category",
data: ["2021", "2022", "2023", "2024", "2025"]
},
yAxis: {
type: "value"
},
series: [
{
name: "量子科技",
data: [120, 200, 150, 80, 70, 110, 130],
type: "bar",
barWidth: 12,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "rgba(22, 119, 255, 1)" },
// { offset: 0.5, color: '#188df0' },
{ offset: 1, color: "rgba(22, 119, 255, 0)" }
]),
borderRadius: [6, 6, 0, 0]
}
},
{
name: "人工智能",
data: [20, 230, 100, 100, 30, 210, 180],
type: "bar",
barWidth: 12,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "rgba(206, 79, 81, 1)" },
// { offset: 0.5, color: '#188df0' },
{ offset: 1, color: "rgba(206, 79, 81, 0)" }
]),
borderRadius: [6, 6, 0, 0]
}
},
{
name: "通信网络",
data: [150, 100, 200, 130, 50, 190, 330],
type: "bar",
barWidth: 12,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "rgba(255, 197, 61, 1)" },
// { offset: 0.5, color: '#188df0' },
{ offset: 1, color: "rgba(255, 197, 61, 0)" }
]),
borderRadius: [6, 6, 0, 0]
}
},
{
name: "集成电路",
data: [220, 100, 250, 180, 170, 100, 80],
type: "bar",
barWidth: 12,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "rgba(255, 204, 199, 1)" },
// { offset: 0.5, color: '#188df0' },
{ offset: 1, color: "rgba(255, 204, 199, 0)" }
]),
borderRadius: [6, 6, 0, 0]
}
},
{
name: "生物科技",
data: [220, 300, 50, 180, 170, 210, 400],
type: "bar",
barWidth: 12,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "rgba(179, 127, 235, 1)" },
// { offset: 0.5, color: '#188df0' },
{ offset: 1, color: "rgba(179, 127, 235, 0)" }
]),
borderRadius: [6, 6, 0, 0]
}
},
{
name: "能源领域",
data: [120, 200, 150, 80, 70, 110, 130],
type: "bar",
barWidth: 12,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "rgba(127, 218, 235, 1)" },
// { offset: 0.5, color: '#188df0' },
{ offset: 1, color: "rgba(127, 214, 235, 0)" }
]),
borderRadius: [6, 6, 0, 0]
}
}
]
});
// 历次制裁过程
const sanctionProcessList = ref([
{
title: "2025年3月—实体清单(BIS)",
desc: "54家中国实体",
content:
"2025年3月25日,美国商务部工业与安全局以从事有悖于美国国家安全和外交政策利益的活动为由,宣布将来自中国的54家实体新增至“实体清单”。"
},
{
title: "2025年1月—实体清单(BIS)",
desc: "25家中国实体",
content:
"2025年1月15日,美国商务部工业和安全局宣布更新《出口管理条例》(EAR),并发布两项最终规则,将25家中国企业及其相关实体列入实体清单。"
},
{
title: "2024年12月—商业管制清单(BIS)",
desc: "12家中国实体",
content:
"2024年12月20日,美国商务部工业与安全局以从事有悖于美国国家安全和外交政策利益的活动为由,宣布将来自中国的12家实体新增至“商业管制清单”。"
},
{
title: "2024年10月—商业管制清单(BIS)",
desc: "6家中国实体",
content: "2024年10月21日,美国商务部将6个中国实体加入其“实体清单”,同时将 1 个中国实体移出该清单。"
},
{
title: "2024年8月—商业管制清单(BIS)",
desc: "39家中国实体",
content: "2024年8月23日,美国商务部工业安全局发布公告,将多个外国实体加入其“实体清单”,其中包括39个中国实体。"
}
]);
// 进度条状态
const getStatus = _percent => {
const percent = _percent * 100;
......@@ -1299,6 +1214,7 @@ const handleGetHylyList = async () => {
try {
const res = await getHylyList();
console.log("行业领域列表");
categoryList.value = res.data;
const obj = {
id: 0,
......@@ -1489,6 +1405,8 @@ onMounted(async () => {
flex-wrap: wrap;
justify-content: space-between;
padding-left: 10px;
height: 156px;
overflow: auto;
&-item {
display: flex;
align-items: center;
......@@ -1500,6 +1418,19 @@ onMounted(async () => {
&-img {
width: 24px;
height: 24px;
flex-shrink: 0;
}
&-imgUndefined {
width: 24px;
height: 24px;
font-size: 14px;
font-weight: 700;
flex-shrink: 0;
color: rgba(5, 95, 194, 1);
background-color: rgb(236, 245, 255);
line-height: 24px;
text-align: center;
border-radius: 12px;
}
&-txt {
font-size: 16px;
......@@ -1670,39 +1601,43 @@ onMounted(async () => {
}
.box4 {
height: 786px;
overflow: auto;
display: flex;
flex-direction: column;
padding-top: 16px;
.box4-item {
display: flex;
gap: 10px;
align-items: flex-start;
padding-bottom: 30px;
padding-bottom: 35px;
position: relative;
.box4-item-left {
display: flex;
flex-direction: column;
align-items: center;
padding-top: 8px;
position: relative;
.box4-item-left-icon {
width: 10px;
height: 10px;
}
.box4-item-left-line {
width: 1px;
height: 145px;
height: 100%;
position: absolute;
top: 15px;
border-left: 1px solid rgba(10, 87, 166, 0.3);
}
}
.box4-item-right {
display: flex;
flex-direction: column;
gap: 5px;
.box4-item-right-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 12px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
position: relative;
top: -7.5px;
padding-bottom: 8px;
&-title {
font-size: 18px;
color: $base-color;
......@@ -1715,7 +1650,6 @@ onMounted(async () => {
}
}
.box4-item-right-content {
margin-top: 10px;
font-size: 16px;
font-weight: 400;
color: rgba(95, 101, 108, 1);
......@@ -1724,20 +1658,19 @@ onMounted(async () => {
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
height: 70px;
line-height: 25px;
}
}
}
.box4-footer {
margin-top: 50px;
margin-top: auto;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
bottom: 30px;
left: 50%;
margin-left: -20px;
margin-bottom: 30px;
}
}
......
import * as echarts from 'echarts';
import chinaJson from './China.json'
import _ from 'lodash';
//饼图
export function getPieOption(data, title) {
let option = {
......@@ -85,7 +86,7 @@ export function getPieOption1(data, title) {
},
label: {
alignTo: 'edge',
formatter: '{b}\n{two|{c}家 {d}%}',
formatter: `{b}${data.length < 10 ? '\n' : ''} {two|{c}家 {d}%}`,
fontSize: 17.6,
fontWeight: 700,
minMargin: 5,
......@@ -104,12 +105,13 @@ export function getPieOption1(data, title) {
maxSurfaceAngle: 80
},
labelLayout: function (params) {
console.log('labelLayoutparams', params)
const isLeft = params.labelRect.x < 556 / 2;
const points = params.labelLinePoints;
// Update the end point.
points[2][0] = isLeft
? params.labelRect.x
: params.labelRect.x + params.labelRect.width;
? data.length < 10 ? params.labelRect.x : (params.labelRect.x + params.labelRect.width)
: data.length < 10 ? (params.labelRect.x + params.labelRect.width) : params.labelRect.x;
return {
labelLinePoints: points
};
......@@ -600,7 +602,7 @@ export const getBarChart = (nameList, valueList, color = ['rgba(255, 159, 22, 1)
}
return option
}
export const getLineChart = (color = 'rgba(146, 84, 222, 1)') => {
export const getLineChart = (object, isPercent) => {
const option = {
title: {
text: ""
......@@ -611,11 +613,11 @@ export const getLineChart = (color = 'rgba(146, 84, 222, 1)') => {
let result = params[0].name + '<br/>';
params.forEach(function (item, index) {
// 自定义颜色数组
const customColors = [color];
const customColors = [object.color];
const dotColor = customColors[index % customColors.length]; // 循环取色
// 创建彩色圆点图标
const dot = `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:${dotColor};"></span>`;
result += dot + `${item.seriesName}: ${item.value}<br/>`;
result += dot + `${item.seriesName}: ${item.value}${isPercent ? '%' : ''}<br/>`;
});
return result;
}
......@@ -648,7 +650,7 @@ export const getLineChart = (color = 'rgba(146, 84, 222, 1)') => {
// fontSize: 22,
// fontWeight: 400
},
data: ["2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023"]
data: object.xAxisData
},
yAxis: {
type: "value",
......@@ -662,7 +664,9 @@ export const getLineChart = (color = 'rgba(146, 84, 222, 1)') => {
color: "rgba(95, 101, 108, 1)",
// fontSize: 22,
// fontWeight: 400
formatter: `{value} ${isPercent ? '%' : ''}`
},
splitNumber: 8,
splitLine: {
lineStyle: {
......@@ -675,19 +679,19 @@ export const getLineChart = (color = 'rgba(146, 84, 222, 1)') => {
},
series: [
{
name: "增长趋势",
name: object.name,
type: "line",
symbolSize: 8,
symbol: 'circle',
itemStyle: {
color: "#ffffff",
borderColor: color,
borderColor: object.color,
borderWidth: 3
},
lineStyle: {
color: color,
color: object.color,
},
data: [3, 6, 4, 7, 9, 6, 5, 6, 6]
data: object.seriesData
}
]
};
......@@ -970,3 +974,61 @@ export const getMultipleLineChart = (obj) => {
};
return option;
}
//出口管制主页接口
export const getMultipleBarChart_m = (object) => {
const list = _.chain(object.data).filter('year').orderBy('year', 'asc').value();
const colors = [
['rgba(22, 119, 255, 1)', 'rgba(22, 119, 255, 0)'],
['rgba(206, 79, 81, 1)', 'rgba(206, 79, 81, 0)'],
['rgba(255, 197, 61, 1)', 'rgba(255, 197, 61, 0)'],
['rgba(255, 204, 199, 1)', 'rgba(255, 204, 199, 0)'],
['rgba(179, 127, 235, 1)', 'rgba(179, 127, 235, 0)'],
['rgba(127, 218, 235, 1)', 'rgba(127, 214, 235, 0)'],
];
const names = _.map(list, 'year');
const datas = _.chain(object.domains).splice(0, 6).map((name, index) => {
console.log(_.map(list, name))
return {
name,
data: _.map(list, `domainNum.${name}`),
type: "bar",
barWidth: 12,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: colors[index % colors.length][0] },
// { offset: 0.5, color: '#188df0' },
{ offset: 1, color: colors[index % colors.length][1] }
]),
borderRadius: [6, 6, 0, 0]
}
}
}).value();
console.log('names', names)
const option = {
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow"
}
},
grid: {
top: 50
},
legend: {
// type: "scroll",
// show: true,
// orient: "horizontal",
icon: "circle",
},
xAxis: {
type: "category",
data: names
},
yAxis: {
type: "value"
},
series: datas
}
return option;
}
export function formatAnyDateToChinese(dateStr) {
// 支持多种分隔符
const date = new Date(dateStr.replace(/\//g, '-'));
if (isNaN(date.getTime())) {
return ''
}
// 手动获取各部分,避免Intl可能存在的兼容性考虑
const year = date.getFullYear();
const month = date.getMonth() + 1; // 月份从0开始,需+1
const day = date.getDate();
return `${year}${month}${day}日`;
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论