提交 86617244 authored 作者: 张伊明's avatar 张伊明

合并分支 'zy-dev' 到 'pre'

Zy dev 查看合并请求 !342
流水线 #487 已通过 于阶段
in 4 分 50 秒
...@@ -11,10 +11,11 @@ export function getStatCount(params) { ...@@ -11,10 +11,11 @@ export function getStatCount(params) {
} }
// 分类接口 // 分类接口
export function getStatSort() { export function getStatSort(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/api/marketsearchHome/statSort` url: `/api/marketsearchHome/statSort`,
params
}) })
} }
...@@ -39,6 +40,18 @@ export function getStatNum(params) { ...@@ -39,6 +40,18 @@ export function getStatNum(params) {
}) })
} }
// 查询关税税率
/**
* @param {byYorM}
*/
export function getSearchTariff(params) {
return request({
method: 'GET',
url: `/api/marketsearchDetails/getSearchTariff`,
params
})
}
// 制裁领域分布 // 制裁领域分布
/** /**
* @param {years} * @param {years}
...@@ -178,6 +191,14 @@ export function getSearchBlurb(params) { ...@@ -178,6 +191,14 @@ export function getSearchBlurb(params) {
}) })
} }
// 获取原文
export function getOriginalUrl(params) {
return request({
method: 'GET',
url: `/api/marketsearchDetails/getOriginalUrl/${params.id}`,
})
}
// 获取相关事件 // 获取相关事件
export function getRelatedEvents(params) { export function getRelatedEvents(params) {
return request({ return request({
......
...@@ -3,7 +3,10 @@ ...@@ -3,7 +3,10 @@
<div class="icon"> <div class="icon">
<img src="./tip-icon.svg" alt=""> <img src="./tip-icon.svg" alt="">
</div> </div>
<div class="text text-tip-2 text-primary-50-clor">{{ tipText }}</div> <div class="text text-tip-2 text-primary-50-clor">
<div v-if="ellipsis" :title="tipText" class="one-line-ellipsis">{{ tipText }}</div>
<div v-else>{{ tipText }}</div>
</div>
</div> </div>
</template> </template>
...@@ -23,7 +26,10 @@ const props = defineProps({ ...@@ -23,7 +26,10 @@ const props = defineProps({
type: String, type: String,
default: '2023.1至2025.12' default: '2023.1至2025.12'
}, },
ellipsis: {
type: Boolean,
default: false
}
}) })
const tipText = computed(() => props.text || `数据来源:${props.dataSource},数据时间:${props.dataTime}`) const tipText = computed(() => props.text || `数据来源:${props.dataSource},数据时间:${props.dataTime}`)
...@@ -48,5 +54,9 @@ const tipText = computed(() => props.text || `数据来源:${props.dataSource} ...@@ -48,5 +54,9 @@ const tipText = computed(() => props.text || `数据来源:${props.dataSource}
height: 100%; height: 100%;
} }
} }
.text {
width: 20px;
flex: auto;
}
} }
</style> </style>
\ No newline at end of file
...@@ -6,6 +6,7 @@ const MarketAccessCase = () => import('@/views/marketAccessRestrictions/marketAc ...@@ -6,6 +6,7 @@ const MarketAccessCase = () => import('@/views/marketAccessRestrictions/marketAc
const MarketSingleCaseLayout = () => import('@/views/marketAccessRestrictions/singleCaseLayout/index.vue') const MarketSingleCaseLayout = () => import('@/views/marketAccessRestrictions/singleCaseLayout/index.vue')
const MarketSingleCaseOverview = () => import('@/views/marketAccessRestrictions/singleCaseLayout/overview/index.vue') const MarketSingleCaseOverview = () => import('@/views/marketAccessRestrictions/singleCaseLayout/overview/index.vue')
const MarketSingleCaseDeepdig = () => import('@/views/marketAccessRestrictions/singleCaseLayout/deepdig/index.vue') const MarketSingleCaseDeepdig = () => import('@/views/marketAccessRestrictions/singleCaseLayout/deepdig/index.vue')
const MarketSingleReportOriginal = () => import('@/views/marketAccessRestrictions/pages/reportOriginal.vue')
const marketAccessRestrictionsRoutes = [ const marketAccessRestrictionsRoutes = [
// 市场准入限制首页 // 市场准入限制首页
...@@ -42,7 +43,6 @@ const marketAccessRestrictionsRoutes = [ ...@@ -42,7 +43,6 @@ const marketAccessRestrictionsRoutes = [
} }
] ]
}, },
{ {
path: "/marketSingleCaseLayout", path: "/marketSingleCaseLayout",
name: "MarketSingleCaseLayout", name: "MarketSingleCaseLayout",
...@@ -67,7 +67,12 @@ const marketAccessRestrictionsRoutes = [ ...@@ -67,7 +67,12 @@ const marketAccessRestrictionsRoutes = [
} }
] ]
}, },
{
path: "reportOriginal",
name: "MarketSingleReportOriginal",
component: MarketSingleReportOriginal,
meta: { noTitle: true }
}
] ]
export default marketAccessRestrictionsRoutes export default marketAccessRestrictionsRoutes
\ No newline at end of file
...@@ -152,7 +152,7 @@ ...@@ -152,7 +152,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="summarize1" /> <AiPane :aiContent="aiContent.content1" />
</div> </div>
</div> </div>
...@@ -188,7 +188,7 @@ ...@@ -188,7 +188,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="summarize2" /> <AiPane :aiContent="aiContent.content2" />
</div> </div>
</div> </div>
</div> </div>
...@@ -442,6 +442,7 @@ import setChart from "@/utils/setChart"; ...@@ -442,6 +442,7 @@ import setChart from "@/utils/setChart";
import DefaultIcon2 from "@/assets/icons/default-icon2.png"; import DefaultIcon2 from "@/assets/icons/default-icon2.png";
import tipsTcon from "./assets/images/tips-icon.png"; import tipsTcon from "./assets/images/tips-icon.png";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { getAIReport, getNearYearList } from "@/views/marketAccessRestrictions/utils/index.ts"
import { useGotoNewsDetail } from '@/router/modules/news'; import { useGotoNewsDetail } from '@/router/modules/news';
...@@ -722,17 +723,16 @@ const handleClickPerson = async item => { ...@@ -722,17 +723,16 @@ const handleClickPerson = async item => {
} catch (error) { } } catch (error) { }
}; };
// 获取最近年份列表 const yearList = getNearYearList();
const currentYear = new Date().getFullYear();
const getYearList = (count = 6) => { // 获取AI智能报告
const yearOptions = []; const aiContent = reactive({
for (let i = 0; i < count; i++) { content1: "正在生成...",
const year = currentYear - i; content2: "正在生成...",
yearOptions.push({ label: year.toString(), value: year.toString() }); })
} const onAIReport = (data, key) => {
return yearOptions; getAIReport(data).then(res => { aiContent[key] = res })
}; }
const yearList = getYearList();
// 行政令发布频度 // 行政令发布频度
const chart1Data = ref({ const chart1Data = ref({
...@@ -745,7 +745,6 @@ const box5Params = reactive({ ...@@ -745,7 +745,6 @@ const box5Params = reactive({
proposeName: '', proposeName: '',
loading: false, loading: false,
}) })
const summarize1 = ref()
const handleGetDecreeYearOrder = async () => { const handleGetDecreeYearOrder = async () => {
box5Params.loading = true box5Params.loading = true
try { try {
...@@ -763,61 +762,17 @@ const handleGetDecreeYearOrder = async () => { ...@@ -763,61 +762,17 @@ const handleGetDecreeYearOrder = async () => {
chart1Data.value.dataY = res.data.map(item => { chart1Data.value.dataY = res.data.map(item => {
return item.count; return item.count;
}); });
onChartInterpretation({ type: "柱状图", name: "数量变化趋势", data: res.data }, summarize1) onAIReport({ type: "柱状图", name: "数量变化趋势", data: res.data }, "content1")
} else {
chart1Data.value.dataX = [];
chart1Data.value.dataY = [];
aiContent.content1 = ""
} }
} catch (error) { } catch (error) {
console.error("行政令发布频度error", error); console.error("行政令发布频度error", error);
} }
box5Params.loading = false box5Params.loading = false
}; };
// AI智能总结
const onChartInterpretation = async (text, param) => {
param.value = "正在生成..."
// 👇 新增:超时 + 终止请求(只加这一段)
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10000); // 10秒超时
try {
const response = await fetch('/aiAnalysis/chart_interpretation', {
method: 'POST',
headers: {
"X-API-Key": "aircasKEY19491001",
'Content-Type': 'application/json',
},
body: JSON.stringify({ text }),
signal: controller.signal // 👇 新增:绑定中断信号
});
clearTimeout(timeout); // 👇 新增:请求成功清除定时器
if (!response.ok) throw new Error(`HTTP 错误 ${response.status}`);
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
let summarize = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.startsWith('data: ')) {
const content = line.substring(6);
const textMatch = content.match(/"解读":\s*"([^"]*)"/);
if (textMatch && textMatch[1]) summarize = textMatch[1];
}
}
}
param.value = summarize
} catch (err) {
param.value = "系统异常,生成失败";
}
}
const handleBox5 = async () => { const handleBox5 = async () => {
await handleGetDecreeYearOrder(); await handleGetDecreeYearOrder();
...@@ -863,7 +818,6 @@ const box6Params = reactive({ ...@@ -863,7 +818,6 @@ const box6Params = reactive({
proposeName: '', proposeName: '',
loading: false, loading: false,
}); });
const summarize2 = ref()
const handleGetDecreeArea = async () => { const handleGetDecreeArea = async () => {
box6Params.loading = true box6Params.loading = true
try { try {
...@@ -880,7 +834,10 @@ const handleGetDecreeArea = async () => { ...@@ -880,7 +834,10 @@ const handleGetDecreeArea = async () => {
value: item.count value: item.count
}; };
}); });
onChartInterpretation({ type: "环形图", name: "领域分布情况", data: res.data }, summarize2) onAIReport({ type: "环形图", name: "领域分布情况", data: res.data }, "content2")
} else {
chart2Data.value = []
aiContent.content2 = ""
} }
} catch (error) { } catch (error) {
console.error("政令科技领域error", error); console.error("政令科技领域error", error);
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
<div v-for="(subSubItem, subSubIndex) in subItem.slaver" :key="subSubIndex" <div v-for="(subSubItem, subSubIndex) in subItem.slaver" :key="subSubIndex"
class="sub-sub-item"> class="sub-sub-item">
<div class="sub-sub-item-dot">{{ ALPHABET[subSubIndex % 26] }}.</div> <div class="sub-sub-item-dot">{{ ALPHABET[subSubIndex % 26] }}.</div>
<div class="sub-sub-item-word" v-html="subItem.content"></div> <div class="sub-sub-item-word" v-html="subSubItem.content"></div>
</div> </div>
</div> </div>
</div> </div>
...@@ -157,6 +157,7 @@ import ActionButton from '@/components/base/ActionButton/index.vue' ...@@ -157,6 +157,7 @@ import ActionButton from '@/components/base/ActionButton/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";
import defaultCom from "@/views/coopRestriction/assets/images/default-icon2.png" import defaultCom from "@/views/coopRestriction/assets/images/default-icon2.png"
import { onNumToChinese } from "@/views/marketAccessRestrictions/utils/index"
const route = useRoute(); const route = useRoute();
...@@ -185,70 +186,7 @@ const handleGetAreaList = async () => { ...@@ -185,70 +186,7 @@ const handleGetAreaList = async () => {
// 主要指令 // 主要指令
const isHighlight = ref(false); const isHighlight = ref(false);
const commandWord = ref(""); const commandWord = ref("");
const contentList = ref([ const contentList = ref([]);
// {
// content: "建立美国人工智能出口计划建立美国人工智能出口计划建立美国人工智能出口计划建立美国人工智能出口计划建立美国人工智能出口计划",
// slaver: [
// {
// content: '在本命令发布之日起 90 天内,商务部长应与国务卿及科学技术政策办公室(OSTP)主任协商,建立并实施美国人工智能出口计划(计划),以支持美国全栈人工智能出口软件包的开发和部署。'
// },
// {
// content: '商务部长应公开征集由行业主导的联盟提案,以纳入该计划。公开征集要求每项提案必须:',
// slaver: [
// {
// content: '包含一套全栈人工智能技术包,涵盖:',
// slaver: [
// {
// content: 'AI 优化的计算机硬件(如芯片、服务器和加速器)、数据中心存储、云服务和网络,以及这些设备是否以及在多大程度上在美国制造的描述;'
// },
// {
// content: '数据管道和标签系统;'
// },
// {
// content: '人工智能模型与系统;'
// },
// {
// content: '采取措施保障人工智能模型和系统的安全性和网络安全;'
// },
// {
// content: '针对特定用例的人工智能应用(如软件工程、教育、医疗保健、农业或交通运输);'
// }
// ]
// },
// {
// content: '确定出口参与者的具体目标国家或区域集团;'
// },
// {
// content: '描述一个业务和运营模型,以在高层次上说明哪些实体将建设、拥有和运营数据中心及相关基础设施;'
// },
// {
// content: '联邦激励和支持机制请求的细节;'
// },
// {
// content: '遵守所有相关的美国出口管制制度、出境投资法规和终端用户政策,包括美国法典第 50 编第 58 章及商务部工业与安全局的相关指导。'
// }
// ]
// },
// {
// content: '商务部要求提案须在公开征集后不超过 90 天内提交,并应滚动考虑提案纳入项目。'
// },
// {
// content: '商务部长应与国务卿、国防部长、能源部长及 OSTP 主任协商,评估提交的纳入计划提案。商务部长与国务卿、国防部长、能源部长及 OSTP 主任协商后选定的提案,将被指定为优先 AI 出口包,并通过优先访问本命令第 4 节指定的工具予以支持,符合适用法律。'
// }
// ]
// },
// {
// content: "动员联邦融资工具",
// slaver: [
// {
// content: '经济外交行动小组(EDAG),于 2024 年 6 月 21 日总统备忘录中成立,由国务卿主持,并与商务部长和美国贸易代表协商,并根据 2019 年《通过外交倡导美国企业法案》(公共法 116-94 J 部分第七章)第 708 条(CABDA)所述,应协调联邦融资工具的动员,以支持优先的人工智能出口方案。'
// },
// {
// content: '我将根据 CABDA α 第 708 (c) (3) 条授权小企业管理局局长和 OSTP 主任任命各自执行部门和机构的高级官员担任 EDAG 。'
// }
// ]
// }
]);
const ALPHABET = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]; const ALPHABET = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
const onMainContentData = async () => { const onMainContentData = async () => {
try { try {
...@@ -257,7 +195,7 @@ const onMainContentData = async () => { ...@@ -257,7 +195,7 @@ const onMainContentData = async () => {
console.log("主要指令", res); console.log("主要指令", res);
if (res && res.code === 200) { if (res && res.code === 200) {
contentList.value = res.data || []; contentList.value = res.data || [];
contentList.value.forEach((item, index) => { item.content = `(${simpleNumToChinese(index + 1)}) ${item.content}` }) contentList.value.forEach((item, index) => { item.content = `(${onNumToChinese(index + 1)}) ${item.content}` })
if (keyword) { if (keyword) {
let word = keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); let word = keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
contentList.value.forEach(item => { onHighlight(word, item) }) contentList.value.forEach(item => { onHighlight(word, item) })
...@@ -279,30 +217,6 @@ const onHighlight = (word, row) => { ...@@ -279,30 +217,6 @@ const onHighlight = (word, row) => {
row.slaver.forEach(item => { onHighlight(word, item) }) row.slaver.forEach(item => { onHighlight(word, item) })
} }
} }
// 数字转中文(支持 0-99 整数)
const simpleNumToChinese = (num) => {
// 1. 基础校验:只处理 0-99 的整数
if (!Number.isInteger(num) || num < 0 || num > 99) return '100';
// 2. 定义基础字符
const singleChars = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
const tenChar = '十';
// 3. 核心转换逻辑
if (num < 10) {
// 0-9 直接返回对应字符
return singleChars[num];
} else if (num === 10) {
// 10 特殊处理
return tenChar;
} else if (num < 20) {
// 11-19:十 + 个位(如十一、十九)
return tenChar + singleChars[num - 10];
} else {
// 20-99:十位 + 十 + 个位(个位为0则省略,如二十、二十九)
const ten = Math.floor(num / 10); // 十位数字
const unit = num % 10; // 个位数字
return singleChars[ten] + tenChar + (unit === 0 ? '' : singleChars[unit]);
}
}
// 思维导图 // 思维导图
const isTreeDialog = ref(false); const isTreeDialog = ref(false);
......
<template>
<div class="data-list">
<div class="data-item" v-for="(item, index) in props.list" :key="index">
<div class="item-head">
<div class="item-name">{{ `(${onNumToChinese(Number(index)+1)}). ${item.title}` }}</div>
<div class="button-box" @click="onNavigateTo()">
<div class="button-icon">
<img src="../assets/icons/open.png" alt="" />
</div>
<div class="button-text">跳转原文</div>
</div>
</div>
<Level2List :list="item.data"></Level2List>
</div>
</div>
</template>
<script setup lang="ts" name="Level2List">
import router from "@/router";
import { useRoute } from "vue-router";
import { onNumToChinese } from "@/views/marketAccessRestrictions/utils/index"
import Level2List from "@/views/marketAccessRestrictions/com/Level2List.vue";
const route = useRoute();
const props = defineProps({
list: {
type: Array as any,
default: () => ([])
},
})
const onNavigateTo = () => {
const page = router.resolve({
name: "MarketSingleReportOriginal",
query: { ...route.query }
});
window.open(page.href, "_blank");
}
</script>
<style scoped lang="scss">
.data-list {
margin-bottom: 16px;
border-top: 1px solid rgba(234, 236, 238, 1);
.data-item {
.item-head {
padding: 0 20px;
height: 48px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
background: rgba(247, 248, 249, 1);
display: flex;
align-items: center;
.item-name {
width: 20px;
flex: auto;
font-family: Source Han Sans CN;
font-size: 18px;
font-weight: bold;
line-height: 30px;
color: var(--text-primary-80-color);
}
.button-box {
display: flex;
align-items: center;
margin-left: 50px;
cursor: pointer;
.button-icon {
width: 16px;
height: 16px;
font-size: 0;
margin-right: 4px;
img {
width: 100%;
height: 100%;
}
}
.button-text {
color: var(--color-primary-100);
font-family: Microsoft YaHei;
font-size: 12px;
font-weight: 400;
line-height: 12px;
}
}
}
}
}
</style>
\ No newline at end of file
<template>
<div class="view-box">
<div class="item-info" v-for="(text, num) in props.list" :key="num">
<div class="item-num">{{ Number(num) + 1 }}.</div>
<div class="text-align-justify">{{ text }}</div>
</div>
</div>
</template>
<script setup lang="ts" name="Level2List">
const props = defineProps({
list: {
type: Array as any,
default: () => ([])
}
})
</script>
<style scoped lang="scss">
.view-box {
.item-info {
padding: 12px 20px 12px 50px;
color: rgba(59, 65, 75, 1);
font-family: Source Han Sans CN;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
position: relative;
.item-num {
position: absolute;
left: 26px;
top: 12px;
}
}
}
</style>
\ No newline at end of file
...@@ -2,29 +2,15 @@ ...@@ -2,29 +2,15 @@
<AnalysisBox :title="title" :showAllBtn="false" height="auto"> <AnalysisBox :title="title" :showAllBtn="false" height="auto">
<el-empty v-if="!props.listData?.length" description="暂无数据" :image-size="200" /> <el-empty v-if="!props.listData?.length" description="暂无数据" :image-size="200" />
<div v-else class="box-main"> <div v-else class="box-main">
<div class="data-list"> <Level1List :list="props.listData"></Level1List>
<div class="data-item" v-for="(item, index) in props.listData" :key="index"> <!-- <AiTips :tips="tips"></AiTips> -->
<div class="item-head">
<div class="item-name">{{ item.title }}</div>
<div class="button-box">
<div class="button-icon">
<img src="../assets/icons/open.png" alt="" />
</div>
<div class="button-text">跳转原文</div>
</div>
</div>
<div class="item-down">
<div class="item-text" v-for="(text, num) in item.data" :key="num">{{ text }}</div>
</div>
</div>
</div>
<AiTips :tips="tips"></AiTips>
</div> </div>
</AnalysisBox> </AnalysisBox>
</template> </template>
<script setup lang="ts" name="SurveyConclusion"> <script setup lang="ts" name="SurveyConclusion">
import AiTips from "@/views/marketAccessRestrictions/com/AiTips.vue"; import AiTips from "@/views/marketAccessRestrictions/com/AiTips.vue";
import Level1List from "@/views/marketAccessRestrictions/com/Level1List.vue";
const props = defineProps({ const props = defineProps({
listData: { listData: {
...@@ -46,62 +32,5 @@ const props = defineProps({ ...@@ -46,62 +32,5 @@ const props = defineProps({
<style scoped lang="scss"> <style scoped lang="scss">
.box-main { .box-main {
padding: 0 22px 20px; padding: 0 22px 20px;
.data-list {
margin-bottom: 16px;
border-top: 1px solid rgba(234, 236, 238, 1);
.data-item {
.item-head {
padding: 0 20px;
height: 48px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
background: rgba(247, 248, 249, 1);
display: flex;
align-items: center;
.item-name {
width: 20px;
flex: auto;
font-family: Source Han Sans CN;
font-size: 18px;
font-weight: bold;
line-height: 30px;
color: var(--text-primary-80-color);
}
.button-box {
display: flex;
align-items: center;
margin-left: 50px;
.button-icon {
width: 16px;
height: 16px;
font-size: 0;
margin-right: 4px;
img {
width: 100%;
height: 100%;
}
}
.button-text {
color: var(--color-primary-100);
font-family: Microsoft YaHei;
font-size: 12px;
font-weight: 400;
line-height: 12px;
}
}
}
.item-text {
letter-spacing: 1px;
padding: 12px 20px 12px 40px;
color: rgba(59, 65, 75, 1);
font-family: Source Han Sans CN;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
border-bottom: 1px solid rgba(234, 236, 238, 1);
}
}
}
} }
</style> </style>
\ No newline at end of file
...@@ -2,19 +2,19 @@ ...@@ -2,19 +2,19 @@
<div class="box-text-box"> <div class="box-text-box">
<div class="box-text-item"> <div class="box-text-item">
<div class="box-text-left">{{ "启动时间:" }}</div> <div class="box-text-left">{{ "启动时间:" }}</div>
<div class="box-text-right one-line-ellipsis">{{ props.baseInfo.searchnum }}</div> <div class="box-text-right one-line-ellipsis">{{ props.baseInfo.progressdate }}</div>
</div> </div>
<div class="box-text-item"> <div class="box-text-item">
<div class="box-text-left">{{ "调查概括:" }}</div> <div class="box-text-left">{{ "调查概括:" }}</div>
<div class="box-text-right two-line-ellipsis">{{ props.baseInfo.product }}</div> <div class="box-text-right two-line-ellipsis">{{ props.baseInfo.investSummary }}</div>
</div> </div>
<div class="box-text-item"> <div class="box-text-item">
<div class="box-text-left">{{ "调查阶段:" }}</div> <div class="box-text-left">{{ "调查阶段:" }}</div>
<div class="box-text-right one-line-ellipsis">{{ props.baseInfo.plaintiff }}</div> <div class="box-text-right one-line-ellipsis">{{ props.baseInfo.investStage }}</div>
</div> </div>
<div class="box-text-item"> <div class="box-text-item">
<div class="box-text-left">{{ "调查范围:" }}</div> <div class="box-text-left">{{ "调查范围:" }}</div>
<div class="box-text-right five-line-ellipsis">{{ props.baseInfo.defendant }}</div> <div class="box-text-right five-line-ellipsis">{{ props.baseInfo.investScope }}</div>
</div> </div>
</div> </div>
</template> </template>
......
...@@ -2,26 +2,25 @@ ...@@ -2,26 +2,25 @@
<div class="box-blue-box"> <div class="box-blue-box">
<div class="box-blue-name"> <div class="box-blue-name">
<div class="box-blue-time">{{ props.baseInfo.progressdate }}</div> <div class="box-blue-time">{{ props.baseInfo.progressdate }}</div>
<div class="box-blue-time">{{ props.baseInfo.progressresult }}</div>
</div> </div>
<div class="box-blue-text one-line-ellipsis">{{ props.baseInfo.progressdetails }}</div> <div class="box-blue-text one-line-ellipsis">{{ props.baseInfo.progressdetails }}</div>
</div> </div>
<div class="box-text-box"> <div class="box-text-box">
<div class="box-text-item"> <div class="box-text-item">
<div class="box-text-left">{{ "启动时间:" }}</div> <div class="box-text-left">{{ "启动时间:" }}</div>
<div class="box-text-right one-line-ellipsis">{{ props.baseInfo.searchnum }}</div> <div class="box-text-right one-line-ellipsis">{{ props.baseInfo.investDate }}</div>
</div> </div>
<div class="box-text-item"> <div class="box-text-item">
<div class="box-text-left">{{ "调查对象:" }}</div> <div class="box-text-left">{{ "调查对象:" }}</div>
<div class="box-text-right one-line-ellipsis">{{ props.baseInfo.product }}</div> <div class="box-text-right one-line-ellipsis">{{ props.baseInfo.investSubject }}</div>
</div> </div>
<div class="box-text-item"> <div class="box-text-item">
<div class="box-text-left">{{ "调查状态:" }}</div> <div class="box-text-left">{{ "调查状态:" }}</div>
<div class="box-text-right one-line-ellipsis">{{ props.baseInfo.plaintiff }}</div> <div class="box-text-right one-line-ellipsis">{{ props.baseInfo.investStatus }}</div>
</div> </div>
<div class="box-text-item"> <div class="box-text-item">
<div class="box-text-left">{{ "请愿方:" }}</div> <div class="box-text-left">{{ "请愿方:" }}</div>
<div class="box-text-right three-line-ellipsis">{{ props.baseInfo.product }}</div> <div class="box-text-right three-line-ellipsis">{{ props.baseInfo.petitioner }}</div>
</div> </div>
</div> </div>
</template> </template>
......
import { symbolCircle } from "d3";
import * as echarts from "echarts"; import * as echarts from "echarts";
const getBarChart = (nameList, valueList) => { const getBarChart = (nameList, valueList) => {
...@@ -15,27 +14,45 @@ const getBarChart = (nameList, valueList) => { ...@@ -15,27 +14,45 @@ const getBarChart = (nameList, valueList) => {
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
splitLine: { name: "项",
show: false nameLocation: 'end',
nameGap: 12,
nameTextStyle: {
color: '#666',
fontSize: 14,
fontWeight: 400,
padding: [0, 0, 6, -26]
}, },
show: false axisLabel: {
formatter: '{value}',
color: '#666',
fontSize: 14,
fontWeight: 400
}, },
xAxis: {
type: 'category',
data: nameList.map(item => {
return item.name
}),
splitLine: { splitLine: {
show: false show: true,
lineStyle: {
color: '#e7f3ff',
type: 'dashed',
}
}, },
axisTick: {
show: false
}, },
xAxis: {
type: 'category',
data: nameList.map(item => item.name),
axisLine: { axisLine: {
show: false show: true,
lineStyle: {
color: '#e7f3ff',
},
}, },
axisLabel: { axisLabel: {
show: true show: true,
textStyle: {
color: 'rgba(95, 101, 108, 1)',
fontFamily: 'Microsoft YaHei',
fontsize: 14,
}
} }
}, },
series: [{ series: [{
...@@ -57,8 +74,7 @@ const getBarChart = (nameList, valueList) => { ...@@ -57,8 +74,7 @@ const getBarChart = (nameList, valueList) => {
barWidth: 20, barWidth: 20,
markPoint: { markPoint: {
symbol: 'circle', symbol: 'circle',
symbolSize: 20, symbolSize: 0,
data: (function () { data: (function () {
const data = []; const data = [];
nameList.forEach((item, index) => { nameList.forEach((item, index) => {
...@@ -67,9 +83,7 @@ const getBarChart = (nameList, valueList) => { ...@@ -67,9 +83,7 @@ const getBarChart = (nameList, valueList) => {
xAxis: index, xAxis: index,
yAxis: valueList[index], yAxis: valueList[index],
symbol: `image://${item.img}`, symbol: `image://${item.img}`,
// symbolSize: [20, 20],
symbolSize: 20, symbolSize: 20,
// symbolOffset: [0, 20],
symbolCircle: 20, symbolCircle: 20,
itemStyle: { itemStyle: {
borderRadius: '50%', borderRadius: '50%',
......
...@@ -11,22 +11,24 @@ ...@@ -11,22 +11,24 @@
<el-option label="调查中" value="1" /> <el-option label="调查中" value="1" />
<el-option label="调查结束" value="0" /> <el-option label="调查结束" value="0" />
</el-select> </el-select>
<el-select v-model="filterParty" placeholder="全部原告/被告" class="filter-select" clearable> <!-- <el-select v-model="filterParty" placeholder="全部原告/被告" class="filter-select" clearable>
<el-option label="全部原告/被告" value="" /> <el-option label="全部原告/被告" value="" />
</el-select> </el-select>
<el-select v-model="filterReason" placeholder="全部原因" class="filter-select" clearable> <el-select v-model="filterReason" placeholder="全部原因" class="filter-select" clearable>
<el-option label="全部原因" value="" /> <el-option label="全部原因" value="" />
</el-select> </el-select> -->
</div> </div>
</div> </div>
<div class="select-box"> <div class="select-box">
<div class="paixu-btn" @click="handleSwithSort"> <el-select v-model="isSort" placeholder="发布时间" style="width: 166px">
<div class="text">{{ "发布时间" }}</div> <template #prefix>
<div class="icon2"> <div style="display: flex; align-items: center; height: 100%">
<img v-if="isSort" src="@/assets/icons/shengxu2.png" alt="" /> <img src="@/assets/icons/jiangxu1.png" style="width: 14px; height: 14px" />
<img v-else src="@/assets/icons/jiangxu2.png" alt="" />
</div>
</div> </div>
</template>
<el-option label="按发布时间降序" value="desc" />
<el-option label="按发布时间升序" value="asc" />
</el-select>
</div> </div>
</div> </div>
<div class="wrapper-main"> <div class="wrapper-main">
...@@ -95,11 +97,7 @@ const searchText = ref(""); ...@@ -95,11 +97,7 @@ const searchText = ref("");
const filterStage = ref(""); const filterStage = ref("");
const filterParty = ref(""); const filterParty = ref("");
const filterReason = ref(""); const filterReason = ref("");
const isSort = ref(false); // false 降序 const isSort = ref('desc'); // 降序
const handleSwithSort = () => {
isSort.value = !isSort.value;
};
// 科技领域过滤 // 科技领域过滤
const surveyAreaList = ref([]); const surveyAreaList = ref([]);
...@@ -166,20 +164,17 @@ const handleFetchSurveyList = async () => { ...@@ -166,20 +164,17 @@ const handleFetchSurveyList = async () => {
publishYear: checkedYearList.value.join(',') || null, publishYear: checkedYearList.value.join(',') || null,
Area: checkedAreaList.value.join(',') || null, Area: checkedAreaList.value.join(',') || null,
caseStatus: filterStage.value, caseStatus: filterStage.value,
keywords: searchText.value, keywords: searchText.value || null,
sortField: "date", sortField: "date",
sortOrder: isSort.value ? "asc" : "desc" sortOrder: isSort.value
}; };
const res = await getSurveyList(params); const res = await getSurveyList(params);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
surveyInfoList.value = res.data.content; surveyInfoList.value = res.data.content;
totalDiscussNum.value = res.data.totalElements || 0; totalDiscussNum.value = res.data.totalElements || 0;
} }
} catch (error) { } catch (error) {}
console.error("获取调查列表失败", error);
} finally {
listLoading.value = false; listLoading.value = false;
}
}; };
const handleCurrentChange = val => { const handleCurrentChange = val => {
...@@ -241,30 +236,6 @@ onMounted(async () => { ...@@ -241,30 +236,6 @@ onMounted(async () => {
} }
} }
} }
.select-box {
.paixu-btn {
display: flex;
align-items: center;
gap: 8px;
height: 32px;
border: 1px solid #e6e7e8;
border-radius: 4px;
background: #fff;
cursor: pointer;
padding: 0 12px;
.text {
font-size: 14px;
color: #5f656c;
}
.icon2 {
width: 10px;
img {
width: 100%;
}
}
}
}
} }
.wrapper-main { .wrapper-main {
...@@ -335,18 +306,26 @@ onMounted(async () => { ...@@ -335,18 +306,26 @@ onMounted(async () => {
height: 48px; height: 48px;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0 20px;
.icon { .icon {
width: 22px; width: 22px;
height: 18px;
margin-left: 19px;
img { img {
width: 100%; width: 100%;
height: 100%;
} }
} }
.title { .title {
height: 26px;
margin-left: 12px; margin-left: 12px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-style: Bold;
font-size: 20px; font-size: 20px;
font-weight: 700; font-weight: 700;
color: var(--color-main-active); line-height: 26px;
letter-spacing: 0px;
text-align: left;
} }
} }
......
<template> <template>
<div class="case-wrapper"> <div class="case-wrapper">
<div class="wrapper-header"> <div class="wrapper-header">
<div class="header-filters">
<div class="search-box"> <div class="search-box">
<el-input v-model="searchText" style="width: 360px; height: 32px" placeholder="搜索调查案件" @keyup.enter="handleSearch" :suffix-icon="Search"></el-input> <el-input v-model="searchText" style="width: 360px; height: 32px" placeholder="搜索调查案件" @keyup.enter="handleSearch" :suffix-icon="Search"></el-input>
</div> </div>
<div class="select-box">
<div class="paixu-btn" @click="handleSwithSort">
<div class="icon1">
<img v-if="isSort" src="@/assets/icons/shengxu1.png" alt="" />
<img v-else src="@/assets/icons/jiangxu1.png" alt="" />
</div>
<div class="text">{{ "发布时间" }}</div>
<div class="icon2">
<img v-if="isSort" src="@/assets/icons/shengxu2.png" alt="" />
<img v-else src="@/assets/icons/jiangxu2.png" alt="" />
</div> </div>
<div class="select-box">
<el-select v-model="isSort" placeholder="发布时间" style="width: 166px">
<template #prefix>
<div style="display: flex; align-items: center; height: 100%">
<img src="@/assets/icons/jiangxu1.png" style="width: 14px; height: 14px" />
</div> </div>
</template>
<el-option label="按发布时间降序" value="desc" />
<el-option label="按发布时间升序" value="asc" />
</el-select>
</div> </div>
</div> </div>
<div class="wrapper-main"> <div class="wrapper-main">
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
</div> </div>
<SurveyHistory v-loading="listLoading" :surveyList="surveyInfoList"></SurveyHistory> <SurveyHistory v-loading="listLoading" :surveyList="surveyInfoList"></SurveyHistory>
<div class="right-footer"> <div class="right-footer">
<div class="footer-left">{{ `共 ${totalDiscussNum}` }}</div> <div class="footer-left">{{ `共${totalDiscussNum}项调查` }}</div>
<div class="footer-right"> <div class="footer-right">
<el-pagination @current-change="handleCurrentChange" :pageSize="pageSize" :current-page="currentPage" background layout="prev, pager, next" :total="totalDiscussNum" /> <el-pagination @current-change="handleCurrentChange" :pageSize="pageSize" :current-page="currentPage" background layout="prev, pager, next" :total="totalDiscussNum" />
</div> </div>
...@@ -70,10 +70,8 @@ import { Search } from "@element-plus/icons-vue"; ...@@ -70,10 +70,8 @@ import { Search } from "@element-plus/icons-vue";
import { getSearchAllArea, getSearchAllYear, getSurveyList } from "@/api/marketAccessRestrictions"; import { getSearchAllArea, getSearchAllYear, getSurveyList } from "@/api/marketAccessRestrictions";
import SurveyHistory from "@/views/marketAccessRestrictions/com/SurveyHistory.vue" import SurveyHistory from "@/views/marketAccessRestrictions/com/SurveyHistory.vue"
const isSort = ref(true); // true 升序 false 倒序 const searchText = ref(''); // 搜索文本
const handleSwithSort = () => { const isSort = ref('desc'); // 降序
isSort.value = !isSort.value;
};
// 科技领域过滤 // 科技领域过滤
const surveyAreaList = ref([]); const surveyAreaList = ref([]);
...@@ -139,20 +137,17 @@ const handleFetchSurveyList = async () => { ...@@ -139,20 +137,17 @@ const handleFetchSurveyList = async () => {
sortCode: "301", sortCode: "301",
publishYear: checkedYearList.value.join(',') || null, publishYear: checkedYearList.value.join(',') || null,
Area: checkedAreaList.value.join(',') || null, Area: checkedAreaList.value.join(',') || null,
// keywords: searchText.value, keywords: searchText.value || null,
sortField: "date", sortField: "date",
sortOrder: isSort.value ? "asc" : "desc" sortOrder: isSort.value
}; };
const res = await getSurveyList(params); const res = await getSurveyList(params);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
surveyInfoList.value = res.data.content; surveyInfoList.value = res.data.content;
totalDiscussNum.value = res.data.totalElements || 0; totalDiscussNum.value = res.data.totalElements || 0;
} }
} catch (error) { } catch (error) {}
console.error("获取调查列表失败", error);
} finally {
listLoading.value = false; listLoading.value = false;
}
}; };
const handleCurrentChange = (val) => { const handleCurrentChange = (val) => {
...@@ -190,56 +185,24 @@ onMounted(async () => { ...@@ -190,56 +185,24 @@ onMounted(async () => {
display: flex; display: flex;
margin-bottom: 16px; margin-bottom: 16px;
justify-content: space-between; justify-content: space-between;
.header-filters {
display: flex;
gap: 16px;
align-items: center;
.search-box { .search-box {
background-color: #fff; background-color: #fff;
border: 1px solid rgba(234, 236, 238, 1); border: 1px solid rgba(234, 236, 238, 1);
border-radius: 4px; border-radius: 4px;
} }
.select-box {
height: 32px; .dropdown-filters {
box-sizing: border-box;
.paixu-btn {
display: flex; display: flex;
width: 120px; gap: 12px;
height: 32px; .filter-select {
box-sizing: border-box; width: 140px;
border: 1px solid rgba(230, 231, 232, 1); :deep(.el-input__wrapper) {
border-radius: 4px; background-color: #fff;
background: rgba(255, 255, 255, 1);
&:hover {
background: var(--color-bg-hover);
}
cursor: pointer;
.icon1 {
width: 11px;
height: 14px;
margin-top: 10px;
margin-left: 9px;
img {
width: 100%;
height: 100%;
}
}
.text {
height: 19px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
margin-top: 7px;
margin-left: 9px;
}
.icon2 {
width: 10px;
height: 5px;
margin-top: 5px;
margin-left: 13px;
img {
width: 100%;
height: 100%;
} }
} }
} }
...@@ -324,7 +287,7 @@ onMounted(async () => { ...@@ -324,7 +287,7 @@ onMounted(async () => {
} }
.title { .title {
height: 26px; height: 26px;
margin-left: 19px; margin-left: 12px;
color: var(--color-main-active); color: var(--color-main-active);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-style: Bold; font-style: Bold;
......
...@@ -11,12 +11,12 @@ ...@@ -11,12 +11,12 @@
<el-option label="调查中" value="1" /> <el-option label="调查中" value="1" />
<el-option label="调查结束" value="0" /> <el-option label="调查结束" value="0" />
</el-select> </el-select>
<el-select v-model="filterParty" placeholder="全部原告/被告" class="filter-select" clearable> <!-- <el-select v-model="filterParty" placeholder="全部原告/被告" class="filter-select" clearable>
<el-option label="全部原告/被告" value="" /> <el-option label="全部原告/被告" value="" />
</el-select> </el-select>
<el-select v-model="filterReason" placeholder="全部原因" class="filter-select" clearable> <el-select v-model="filterReason" placeholder="全部原因" class="filter-select" clearable>
<el-option label="全部原因" value="" /> <el-option label="全部原因" value="" />
</el-select> </el-select> -->
</div> </div>
</div> </div>
<div class="select-box"> <div class="select-box">
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
<img src="@/assets/icons/jiangxu1.png" style="width: 14px; height: 14px" /> <img src="@/assets/icons/jiangxu1.png" style="width: 14px; height: 14px" />
</div> </div>
</template> </template>
<el-option v-for="item in releaseTimeList" :key="item.value" :label="item.label" :value="item.value" /> <el-option label="按发布时间降序" value="desc" />
<el-option label="按发布时间升序" value="asc" />
</el-select> </el-select>
</div> </div>
</div> </div>
...@@ -99,19 +100,7 @@ const searchText = ref(""); ...@@ -99,19 +100,7 @@ const searchText = ref("");
const filterStage = ref(""); const filterStage = ref("");
const filterParty = ref(""); const filterParty = ref("");
const filterReason = ref(""); const filterReason = ref("");
const isSort = ref(false); // false 降序 const isSort = ref('desc'); // 降序
const releaseTimeList = ref([
{
label: "按发布时间倒序",
value: false
},
{
label: "按发布时间升序",
value: true
}
]);
// 科技领域过滤 // 科技领域过滤
const surveyAreaList = ref([]); const surveyAreaList = ref([]);
...@@ -203,18 +192,15 @@ const handleFetchSurveyList = async () => { ...@@ -203,18 +192,15 @@ const handleFetchSurveyList = async () => {
caseStatus: filterStage.value || null, caseStatus: filterStage.value || null,
keywords: searchText.value || null, keywords: searchText.value || null,
sortField: "date", sortField: "date",
sortOrder: isSort.value ? "asc" : "desc" sortOrder: isSort.value
}; };
const res = await getSurveyList(params); const res = await getSurveyList(params);
if (res.code === 200) { if (res.code === 200) {
surveyInfoList.value = res.data?.content || []; surveyInfoList.value = res.data?.content || [];
totalDiscussNum.value = res.data?.totalElements || 0; totalDiscussNum.value = res.data?.totalElements || 0;
} }
} catch (error) { } catch (error) {}
console.error("获取调查列表失败", error);
} finally {
listLoading.value = false; listLoading.value = false;
}
}; };
const handleCurrentChange = val => { const handleCurrentChange = val => {
...@@ -278,33 +264,6 @@ onMounted(async () => { ...@@ -278,33 +264,6 @@ onMounted(async () => {
} }
} }
} }
.select-box {
.paixu-btn {
display: flex;
align-items: center;
gap: 8px;
height: 32px;
border: 1px solid #e6e7e8;
border-radius: 4px;
background: #fff;
cursor: pointer;
padding: 0 12px;
.text {
font-size: 14px;
color: #5f656c;
}
.icon2 {
width: 10px;
img {
width: 100%;
}
}
}
}
} }
.wrapper-main { .wrapper-main {
......
...@@ -19,8 +19,7 @@ ...@@ -19,8 +19,7 @@
<div class="page-tabs"> <div class="page-tabs">
<div :class="['tab-item', {'tab-active': activeName==item.name}]" v-for="(item, index) in tabList" :key="index" @click="handleClickBtn(item)"> <div :class="['tab-item', {'tab-active': activeName==item.name}]" v-for="(item, index) in tabList" :key="index" @click="handleClickBtn(item)">
<div class="icon"> <div class="icon">
<img :src="item.activeIcon" alt="" v-if="activeName==item.name" /> <img :src="activeName==item.name ? item.activeIcon : item.icon" alt="" />
<img :src="item.icon" alt="" v-else />
</div> </div>
<div class="text" :class="{ textActive: activeName==item.name }"> <div class="text" :class="{ textActive: activeName==item.name }">
{{ item.name }} {{ item.name }}
......
...@@ -3,48 +3,56 @@ import * as echarts from "echarts"; ...@@ -3,48 +3,56 @@ import * as echarts from "echarts";
const getBarChart = (nameList, valueList) => { const getBarChart = (nameList, valueList) => {
const option = { const option = {
tooltip: {}, tooltip: {},
title: {
text: '单位:万人',
left: 660,
top: 10,
textStyle: {
color: 'rgba(95, 101, 108, 1)',
fontSize: 14,
fontFamily: 'Microsoft YaHei',
fontstyle: 'Regular',
fontWeight: 'normal'
}
},
grid: { grid: {
top: '5%', width: '100%',
right: '3%', height: '83%',
bottom: '1%', top: '15%',
right: '5%',
bottom: '2%',
left: '1%', left: '1%',
containLabel: true containLabel: true
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
splitLine: { name: "项",
show: false nameLocation: 'end',
nameGap: 12,
nameTextStyle: {
color: '#666',
fontSize: 14,
fontWeight: 400,
padding: [0, 0, 6, -26]
}, },
show: false axisLabel: {
formatter: '{value}',
color: '#666',
fontSize: 14,
fontWeight: 400
}, },
xAxis: {
type: 'category',
data: nameList.map(item => {
return item.name
}),
splitLine: { splitLine: {
show: false show: true,
lineStyle: {
color: '#e7f3ff',
type: 'dashed',
}
}, },
axisTick: {
show: false
}, },
xAxis: {
type: 'category',
data: nameList.map(item => item.name),
axisLine: { axisLine: {
show: false show: true,
lineStyle: {
color: '#e7f3ff',
},
}, },
axisLabel: { axisLabel: {
show: true show: true,
textStyle: {
color: 'rgba(95, 101, 108, 1)',
fontFamily: 'Microsoft YaHei',
fontsize: 14,
}
} }
}, },
series: [{ series: [{
...@@ -71,8 +79,7 @@ const getBarChart = (nameList, valueList) => { ...@@ -71,8 +79,7 @@ const getBarChart = (nameList, valueList) => {
const data = []; const data = [];
nameList.forEach((item, index) => { nameList.forEach((item, index) => {
data.push({ data.push({
name: 'icon', name: `icon${index}`,
// value: '',
xAxis: index, xAxis: index,
yAxis: valueList[index], yAxis: valueList[index],
symbol: `image://${item.img}`, symbol: `image://${item.img}`,
......
...@@ -43,7 +43,7 @@ const getBarChart = (nameList, valueList) => { ...@@ -43,7 +43,7 @@ const getBarChart = (nameList, valueList) => {
data: valueList, data: valueList,
label: { label: {
show: true, show: true,
position: [480, 0], position: [434, 0],
formatter: function (params) { formatter: function (params) {
return params.value + ' 次' return params.value + ' 次'
}, },
......
...@@ -2,10 +2,8 @@ ...@@ -2,10 +2,8 @@
<div class="wrapper"> <div class="wrapper">
<AnalysisBox title="行业背景" :showAllBtn="false" height="auto"> <AnalysisBox title="行业背景" :showAllBtn="false" height="auto">
<div class="box1-main"> <div class="box1-main">
<div class="data-list"> <Level2List :list="bgList"></Level2List>
<div class="data-item" v-for="(bg, index) in bgList" :key="index">{{ bg.title }}</div> <!-- <AiTips tips="钒作为被美国列为对经济与国家安全至关重要且供应链易受中断的关键矿产,广泛应用于国防、关键基础设施等多个领域,美国钒产业以二次生产为主、产业高度集中且依赖进口原料,同时通过征收反倾销税、加征关税及签订国际合作协议等方式管控钒进口。"></AiTips> -->
</div>
<AiTips tips="钒作为被美国列为对经济与国家安全至关重要且供应链易受中断的关键矿产,广泛应用于国防、关键基础设施等多个领域,美国钒产业以二次生产为主、产业高度集中且依赖进口原料,同时通过征收反倾销税、加征关税及签订国际合作协议等方式管控钒进口。"></AiTips>
</div> </div>
</AnalysisBox> </AnalysisBox>
<SurveyConclusion title="市场需求" :listData="demandList" tips="美国钒市场年均表观消费量约 8590 吨且进口依赖度超 80%,需求主要集中在钢铁产业(占 90%),钛产业和非冶金领域各占 5%,2020 年受新冠疫情冲击需求下滑;全球钒需求以钢铁产业为主(90%-93%),中国是最大消费国,航空航天领域需求稳定、钒液流电池为新兴增长点,化工领域提供稳定补充。"></SurveyConclusion> <SurveyConclusion title="市场需求" :listData="demandList" tips="美国钒市场年均表观消费量约 8590 吨且进口依赖度超 80%,需求主要集中在钢铁产业(占 90%),钛产业和非冶金领域各占 5%,2020 年受新冠疫情冲击需求下滑;全球钒需求以钢铁产业为主(90%-93%),中国是最大消费国,航空航天领域需求稳定、钒液流电池为新兴增长点,化工领域提供稳定补充。"></SurveyConclusion>
...@@ -17,7 +15,7 @@ ...@@ -17,7 +15,7 @@
<div class="data-item" v-for="(item, index) in suggestionList" :key="index"> <div class="data-item" v-for="(item, index) in suggestionList" :key="index">
<div class="item-head"> <div class="item-head">
<div class="item-name">{{ item.title }}</div> <div class="item-name">{{ item.title }}</div>
<div class="button-box"> <div class="button-box" @click="onNavigateTo()">
<div class="button-icon"> <div class="button-icon">
<img src="@/views/marketAccessRestrictions/assets/icons/open.png" alt="" /> <img src="@/views/marketAccessRestrictions/assets/icons/open.png" alt="" />
</div> </div>
...@@ -26,13 +24,12 @@ ...@@ -26,13 +24,12 @@
</div> </div>
<div class="item-down"> <div class="item-down">
<div class="content-item" v-for="(val, idx) in item.data" :key="idx"> <div class="content-item" v-for="(val, idx) in item.data" :key="idx">
<div class="content-item-title">{{val.title }}</div> <div class="content-item-title">{{val.TITLE }}</div>
<div class="content-item-info"> <div class="content-item-info">
<div class="desc">{{ val.info.desc }}</div> <Level2List :list="val.CONTENT"></Level2List>
<div class="info-bill" v-if="val.info.bill"> <div class="info-bill-box" v-if="val.BILLNAME && val.BILLID" @click="onNavigateToBill(val)">
<div class="info-bill-box">
<div class="info-bill-left">{{ "法案" }}</div> <div class="info-bill-left">{{ "法案" }}</div>
<div class="info-bill-center">{{ val.info.bill }}</div> <div class="info-bill-center">{{ val.BILLNAME }}</div>
<div class="info-bill-right"> <div class="info-bill-right">
<img src="@/assets/icons/box-footer-right-icon.png" alt="" /> <img src="@/assets/icons/box-footer-right-icon.png" alt="" />
</div> </div>
...@@ -42,8 +39,7 @@ ...@@ -42,8 +39,7 @@
</div> </div>
</div> </div>
</div> </div>
</div> <!-- <AiTips tips="美国为降低盟友及自身在钕铁硼磁体价值链对中国的依赖、保障国家安全,一方面推动关键矿物多边及双边合作,另一方面通过支持相关税收抵免法案、分配额外资金等立法与政策举措,强化稀土及非稀土磁体相关国内供应链建设。"></AiTips> -->
<AiTips tips="美国为降低盟友及自身在钕铁硼磁体价值链对中国的依赖、保障国家安全,一方面推动关键矿物多边及双边合作,另一方面通过支持相关税收抵免法案、分配额外资金等立法与政策举措,强化稀土及非稀土磁体相关国内供应链建设。"></AiTips>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -52,9 +48,11 @@ ...@@ -52,9 +48,11 @@
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import router from "@/router";
import { getReportAnalyze } from "@/api/marketAccessRestrictions/index.js"; import { getReportAnalyze } from "@/api/marketAccessRestrictions/index.js";
import SurveyConclusion from "@/views/marketAccessRestrictions/com/SurveyConclusion.vue"; import SurveyConclusion from "@/views/marketAccessRestrictions/com/SurveyConclusion.vue";
import AiTips from "@/views/marketAccessRestrictions/com/AiTips.vue"; import AiTips from "@/views/marketAccessRestrictions/com/AiTips.vue";
import Level2List from "@/views/marketAccessRestrictions/com/Level2List.vue";
const route = useRoute(); const route = useRoute();
const searchId = route.query.searchId || "232"; const searchId = route.query.searchId || "232";
...@@ -65,14 +63,19 @@ const supplyList = ref([]); ...@@ -65,14 +63,19 @@ const supplyList = ref([]);
const box4List = ref([]); const box4List = ref([]);
const suggestionList = ref([]); const suggestionList = ref([]);
const onNavigateTo = () => {
const page = router.resolve({
name: "MarketSingleReportOriginal",
query: { ...route.query }
});
window.open(page.href, "_blank");
}
const getData = async () => { const getData = async () => {
// 行业背景 // 行业背景
getReportAnalyze({ searchId, type: "01" }).then((res) => { getReportAnalyze({ searchId, type: "01" }).then((res) => {
if (res.data) { console.log('行业背景', res)
bgList.value = res.data.map((item) => ({ if (res.data) bgList.value = res.data.flatMap(item => item.CONTENT);
title: item.CONTENT
}));
}
}); });
// 市场需求 // 市场需求
...@@ -81,7 +84,7 @@ const getData = async () => { ...@@ -81,7 +84,7 @@ const getData = async () => {
demandList.value = res.data.map(item => { demandList.value = res.data.map(item => {
return { return {
title: item.TITLE, title: item.TITLE,
data: item.CONTENT?.split(/\r\n|\n/).filter(line => line.trim()) || [], data: item.CONTENT || [],
}; };
}); });
} }
...@@ -93,7 +96,7 @@ const getData = async () => { ...@@ -93,7 +96,7 @@ const getData = async () => {
supplyList.value = res.data.map(item => { supplyList.value = res.data.map(item => {
return { return {
title: item.TITLE, title: item.TITLE,
data: item.CONTENT?.split(/\r\n|\n/).filter(line => line.trim()) || [], data: item.CONTENT || [],
}; };
}); });
} }
...@@ -105,7 +108,7 @@ const getData = async () => { ...@@ -105,7 +108,7 @@ const getData = async () => {
box4List.value = res.data.map(item => { box4List.value = res.data.map(item => {
return { return {
title: item.TITLE, title: item.TITLE,
data: item.CONTENT?.split(/\r\n|\n/).filter(line => line.trim()) || [], data: item.CONTENT || [],
}; };
}); });
} }
...@@ -113,27 +116,20 @@ const getData = async () => { ...@@ -113,27 +116,20 @@ const getData = async () => {
// 调查建议 // 调查建议
getReportAnalyze({ searchId, type: "05" }).then((res) => { getReportAnalyze({ searchId, type: "05" }).then((res) => {
if (res.data) { console.log('调查建议', res)
if (res.code==200 && res.data) {
suggestionList.value = groupSuggestionData(res.data); suggestionList.value = groupSuggestionData(res.data);
} }
}); });
}; };
// 跳转科技法案详情页
const groupData = (data) => { const onNavigateToBill = (item) => {
const groups = {}; window.sessionStorage.setItem("curTabName", item.BILLNAME);
data.forEach((item) => { const route = router.resolve({
const title = item.TITLE || "其他"; path: "/billLayout",
if (!groups[title]) { query: { billId: item.BILLID }
groups[title] = [];
}
groups[title].push({
title: item.CONTENT
});
}); });
return Object.keys(groups).map((title) => ({ window.open(route.href, "_blank");
title,
data: groups[title]
}));
}; };
const groupSuggestionData = (data) => { const groupSuggestionData = (data) => {
...@@ -143,13 +139,7 @@ const groupSuggestionData = (data) => { ...@@ -143,13 +139,7 @@ const groupSuggestionData = (data) => {
if (!groups[groupTitle]) { if (!groups[groupTitle]) {
groups[groupTitle] = []; groups[groupTitle] = [];
} }
groups[groupTitle].push({ groups[groupTitle].push(item);
title: item.TITLE,
info: {
desc: item.CONTENT,
bill: item.BILLNAME
}
});
}); });
return Object.keys(groups).map((title) => ({ return Object.keys(groups).map((title) => ({
title, title,
...@@ -173,22 +163,6 @@ onMounted(() => { ...@@ -173,22 +163,6 @@ onMounted(() => {
.box1-main { .box1-main {
padding: 0 22px 20px; padding: 0 22px 20px;
.data-list {
margin-bottom: 16px;
border-top: 1px solid rgba(234, 236, 238, 1);
.data-item {
letter-spacing: 1px;
padding: 12px 20px 12px 40px;
color: rgba(59, 65, 75, 1);
font-family: Source Han Sans CN;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
border-bottom: 1px solid rgba(234, 236, 238, 1);
}
}
} }
.box5-main { .box5-main {
...@@ -217,6 +191,7 @@ onMounted(() => { ...@@ -217,6 +191,7 @@ onMounted(() => {
display: flex; display: flex;
align-items: center; align-items: center;
margin-left: 50px; margin-left: 50px;
cursor: pointer;
.button-icon { .button-icon {
width: 16px; width: 16px;
height: 16px; height: 16px;
...@@ -240,7 +215,7 @@ onMounted(() => { ...@@ -240,7 +215,7 @@ onMounted(() => {
margin-bottom: 10px; margin-bottom: 10px;
.content-item { .content-item {
.content-item-title { .content-item-title {
padding: 12px 23px 12px 44px; padding: 12px 23px 12px 30px;
box-sizing: border-box; box-sizing: border-box;
border-bottom: 1px solid rgba(234, 236, 238, 1); border-bottom: 1px solid rgba(234, 236, 238, 1);
color: rgba(59, 65, 75, 1); color: rgba(59, 65, 75, 1);
...@@ -252,26 +227,17 @@ onMounted(() => { ...@@ -252,26 +227,17 @@ onMounted(() => {
text-align: justify; text-align: justify;
} }
.content-item-info { .content-item-info {
padding: 12px 23px 12px 44px;
box-sizing: border-box;
border-bottom: 1px solid rgba(234, 236, 238, 1); border-bottom: 1px solid rgba(234, 236, 238, 1);
.desc { :deep(.item-info) {
color: rgba(59, 65, 75, 1); padding-left: 70px;
font-family: Source Han Sans CN; .item-num {
font-size: 16px; left: 46px;
font-weight: 400; }
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
padding-left: 15px;
} }
.info-bill {
border-radius: 4px;
display: inline-block;
background: rgba(246, 250, 255, 1);
.info-bill-box { .info-bill-box {
display: flex; cursor: pointer;
margin-top: 4px; margin: 10px 44px;
display: inline-flex;
height: 32px; height: 32px;
border-radius: 4px; border-radius: 4px;
background: rgba(246, 250, 255, 1); background: rgba(246, 250, 255, 1);
...@@ -304,7 +270,6 @@ onMounted(() => { ...@@ -304,7 +270,6 @@ onMounted(() => {
.info-bill-right { .info-bill-right {
width: 20px; width: 20px;
height: 20px; height: 20px;
cursor: pointer;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
...@@ -316,6 +281,5 @@ onMounted(() => { ...@@ -316,6 +281,5 @@ onMounted(() => {
} }
} }
} }
}
} }
</style> </style>
\ No newline at end of file
...@@ -14,18 +14,11 @@ ...@@ -14,18 +14,11 @@
</div> </div>
<div class="box-content"> <div class="box-content">
<div class="filter-row"> <div class="filter-row">
<el-select v-model="selectedArea" placeholder="全部领域" class="area-select" clearable @change="fetchEnterpriseList"> <el-select v-model="selectedArea" placeholder="全部领域" class="area-select" clearable @change="onEnterpriseList()">
<el-option label="全部领域" value="" /> <el-option label="全部领域" value="" />
<el-option v-for="item in areaOptions" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in areaOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
<el-input <el-input v-model="searchText" placeholder="搜索实体" class="search-input" :suffix-icon="Search" clearable @keyup.enter="onEnterpriseList()" />
v-model="searchText"
placeholder="搜索实体"
class="search-input"
:suffix-icon="Search"
clearable
@input="handleSearchInput"
/>
</div> </div>
<div class="enterprise-list" v-loading="listLoading"> <div class="enterprise-list" v-loading="listLoading">
<div class="list-label">企业名称</div> <div class="list-label">企业名称</div>
...@@ -179,7 +172,7 @@ const businessLabels = ref([]); ...@@ -179,7 +172,7 @@ const businessLabels = ref([]);
const businessData = ref([]); const businessData = ref([]);
// 获取企业列表 // 获取企业列表
const fetchEnterpriseList = async () => { const onEnterpriseList = async () => {
listLoading.value = true; listLoading.value = true;
try { try {
const params = { const params = {
...@@ -278,14 +271,6 @@ const updateBusinessChart = () => { ...@@ -278,14 +271,6 @@ const updateBusinessChart = () => {
} }
}; };
let searchTimer = null;
const handleSearchInput = () => {
if (searchTimer) clearTimeout(searchTimer);
searchTimer = setTimeout(() => {
fetchEnterpriseList();
}, 500);
};
const handleEnterpriseClick = (item, index) => { const handleEnterpriseClick = (item, index) => {
activeIndex.value = index; activeIndex.value = index;
if (item.ORGID) { if (item.ORGID) {
...@@ -432,7 +417,7 @@ const handleBusinessToggle = (type) => { ...@@ -432,7 +417,7 @@ const handleBusinessToggle = (type) => {
}; };
onMounted(() => { onMounted(() => {
fetchEnterpriseList(); onEnterpriseList();
nextTick(() => { nextTick(() => {
initCharts(); initCharts();
window.addEventListener('resize', () => { window.addEventListener('resize', () => {
...@@ -571,6 +556,9 @@ onMounted(() => { ...@@ -571,6 +556,9 @@ onMounted(() => {
.search-input { .search-input {
flex: auto; flex: auto;
width: 20px; width: 20px;
background-color: #fff;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 4px;
} }
} }
......
...@@ -12,15 +12,19 @@ ...@@ -12,15 +12,19 @@
<div :class="`item-tag tag-${codeInfo.sortCode}`">{{ codeInfo.sortName }}</div> <div :class="`item-tag tag-${codeInfo.sortCode}`">{{ codeInfo.sortName }}</div>
</div> </div>
<div class="page-tabs"> <div class="page-tabs">
<div :class="['tab-item', {'tab-active': activeName==item.name}]" v-for="(item, index) in tabList" :key="index" @click="handleClickBtn(item)"> <div :class="['tab-item', {'tab-active': activeName==1}]" @click="handleClickBtn(1)">
<div class="icon"> <div class="icon">
<img :src="item.activeIcon" alt="" v-if="activeName==item.name" /> <img :src="activeName==2 ? NavIcon1Active : NavIcon1" alt="" />
<img :src="item.icon" alt="" v-else />
</div> </div>
<div class="text" :class="{ textActive: activeName==item.name }"> <div class="text" :class="{ textActive: activeName==1 }">调查概况</div>
{{ item.name }}
</div> </div>
<div :class="['tab-item', {'tab-active': activeName==2}]" @click="handleClickBtn(2)" v-if="codeInfo.sortCode==337 || codeInfo.sortCode==232">
<div class="icon">
<img :src="activeName==2 ? NavIcon3Active : NavIcon3" alt="" />
</div>
<div class="text" :class="{ textActive: activeName==2 }">{{ codeInfo.sortCode==337 ? '影响分析' : '报告解析' }}</div>
</div> </div>
<div style="width:20px; flex:auto;"></div> <div style="width:20px; flex:auto;"></div>
<div class="head-button"> <div class="head-button">
<div class="button-icon"> <div class="button-icon">
...@@ -48,26 +52,12 @@ import { getSurvyInfo, getSearchBlurb } from "@/api/marketAccessRestrictions/ind ...@@ -48,26 +52,12 @@ import { getSurvyInfo, getSearchBlurb } from "@/api/marketAccessRestrictions/ind
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
const route = useRoute(); const route = useRoute();
const tabList = ref([
{
name: "调查概况",
icon: NavIcon1,
activeIcon: NavIcon1Active,
path: "/marketSingleCaseLayout/overview"
},
{
name: "影响分析",
icon: NavIcon3,
activeIcon: NavIcon3Active,
path: "/marketSingleCaseLayout/deepdig"
}
]);
const activeName = ref("调查案件"); const activeName = ref(1);
const handleClickBtn = item => { const handleClickBtn = index => {
activeName.value = item.name; activeName.value = index;
router.push({ router.push({
path: item.path, path: ['', "/marketSingleCaseLayout/overview", "/marketSingleCaseLayout/deepdig"][index],
query: { ...route.query } query: { ...route.query }
}); });
}; };
...@@ -102,10 +92,10 @@ const onSearchBlurb = async () => { ...@@ -102,10 +92,10 @@ const onSearchBlurb = async () => {
onMounted(() => { onMounted(() => {
onSurvyInfo() onSurvyInfo()
onSearchBlurb() onSearchBlurb()
if (route.path === "/marketSingleCaseLayout/deepdig") { if (route.path === "/marketSingleCaseLayout/overview") {
activeName.value = "影响分析"; activeName.value = 1;
} else { } else {
activeName.value = "调查概况"; activeName.value = 2;
} }
}); });
</script> </script>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论