From 8ca95304c1343c1eb266a265dcba9ad1c33b95f9 Mon Sep 17 00:00:00 2001 From: bunny <1319900154@qq.com> Date: Sun, 11 May 2025 20:48:41 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20feat:=20=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=88=86=E6=9E=90-=E5=9F=BA=E7=A1=80=E9=AA=A8=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 2 +- .env.development | 4 +- src/utils/copy.ts | 24 +++ src/utils/file.ts | 45 ++++++ .../big-data-left/components/left-bottom.vue | 21 +-- .../big-data-left/components/left-middle.vue | 15 +- .../components/big-data-right/index.vue | 2 - src/views/data-analyse/charts/left-brand.ts | 65 ++++++++ src/views/data-analyse/charts/right-header.ts | 97 ++++++++++++ .../components/data-analyse-content/index.vue | 52 ++++++- .../components/left-center.vue | 60 -------- .../data-analyse-left/components/left-top.vue | 37 ----- .../components/data-analyse-left/index.vue | 141 +++++++++++++++++- .../components/data-analyse-right/index.vue | 60 +++++++- src/views/data-analyse/index.vue | 2 - .../smart-park-sidebar-right/index.vue | 12 +- 16 files changed, 498 insertions(+), 141 deletions(-) create mode 100644 src/utils/copy.ts create mode 100644 src/utils/file.ts create mode 100644 src/views/data-analyse/charts/left-brand.ts create mode 100644 src/views/data-analyse/charts/right-header.ts delete mode 100644 src/views/data-analyse/components/data-analyse-left/components/left-center.vue delete mode 100644 src/views/data-analyse/components/data-analyse-left/components/left-top.vue diff --git a/.env b/.env index 223648d..8a9caef 100644 --- a/.env +++ b/.env @@ -14,7 +14,7 @@ VITE_APP_URL=http://localhost:8801 VITE_STRICT_PORT=false # 是否启用屏幕转vw适配,可以选择 postcss-px-to-viewport-8-plugin || autofit -VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="autofit" +; VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="postcss-px-to-viewport-8-plugin" # 是否在打包时使用cdn替换本地库 替换 true 不替换 false VITE_CDN=false diff --git a/.env.development b/.env.development index a33e5db..5c6161d 100644 --- a/.env.development +++ b/.env.development @@ -20,8 +20,8 @@ VITE_MOCK_DEV_SERVER=true VITE_STRICT_PORT=false # 是否启用屏幕转vw适配,可以选择 postcss-px-to-viewport-8-plugin || autofit -VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="autofit" -#VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="postcss-px-to-viewport-8-plugin" +# VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="autofit" +VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="postcss-px-to-viewport-8-plugin" # 是否在打包时使用cdn替换本地库 替换 true 不替换 false VITE_CDN=false diff --git a/src/utils/copy.ts b/src/utils/copy.ts new file mode 100644 index 0000000..03c2dd2 --- /dev/null +++ b/src/utils/copy.ts @@ -0,0 +1,24 @@ +/** + * 复制到剪切板 + * @param text 文本内容 + */ +export const copy = (text: string) => { + const textarea = document.createElement('textarea'); + textarea.value = text; + textarea.style.position = 'fixed'; + document.body.appendChild(textarea); + textarea.select(); + + try { + const success = document.execCommand('copy'); + if (success) { + (window as any as any).$message.success('复制成功!'); + } else { + (window as any).$message.success('复制失败!'); + } + } catch (err: any) { + (window as any).$message.success('复制失败!请手动复制'); + } finally { + document.body.removeChild(textarea); + } +}; diff --git a/src/utils/file.ts b/src/utils/file.ts new file mode 100644 index 0000000..20316f8 --- /dev/null +++ b/src/utils/file.ts @@ -0,0 +1,45 @@ +export function downloadTextAsFile(text: string, filename: string) { + // 直接创建 File 对象(比 Blob 更高级) + const file = new File([text], filename, { type: 'text/plain' }); + + // 创建下载链接 + const url = URL.createObjectURL(file); + const a = document.createElement('a'); + a.href = url; + a.download = filename; + + // 触发下载 + document.body.appendChild(a); + a.click(); + + // 清理 + requestIdleCallback(() => { + document.body.removeChild(a); + URL.revokeObjectURL(a.href); + }); +} + +export const downloadBlob = (response: any) => { + try { + // 从响应头获取文件名 + const contentDisposition = response.headers['content-disposition']; + let fileName = 'download.zip'; + if (contentDisposition) { + const fileNameMatch = contentDisposition.match(/filename="?(.+)"/); + if (fileNameMatch && fileNameMatch[1]) { + fileName = fileNameMatch[1]; + } + } + + const url = window.URL.createObjectURL(new Blob([response.data])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', fileName); + document.body.appendChild(link); + link.click(); + link.remove(); + window.URL.revokeObjectURL(url); + } catch (error) { + console.error(error); + } +}; diff --git a/src/views/big-data/components/big-data-left/components/left-bottom.vue b/src/views/big-data/components/big-data-left/components/left-bottom.vue index 14d93f5..1c1d43e 100644 --- a/src/views/big-data/components/big-data-left/components/left-bottom.vue +++ b/src/views/big-data/components/big-data-left/components/left-bottom.vue @@ -1,11 +1,12 @@ diff --git a/src/views/big-data/components/big-data-left/components/left-middle.vue b/src/views/big-data/components/big-data-left/components/left-middle.vue index bac8e35..3c2f4f5 100644 --- a/src/views/big-data/components/big-data-left/components/left-middle.vue +++ b/src/views/big-data/components/big-data-left/components/left-middle.vue @@ -1,10 +1,10 @@ diff --git a/src/views/big-data/components/big-data-right/index.vue b/src/views/big-data/components/big-data-right/index.vue index 382853c..87ce246 100644 --- a/src/views/big-data/components/big-data-right/index.vue +++ b/src/views/big-data/components/big-data-right/index.vue @@ -11,5 +11,3 @@ import RightTop from '@/views/big-data/components/big-data-right/components/righ - - diff --git a/src/views/data-analyse/charts/left-brand.ts b/src/views/data-analyse/charts/left-brand.ts new file mode 100644 index 0000000..8dadad4 --- /dev/null +++ b/src/views/data-analyse/charts/left-brand.ts @@ -0,0 +1,65 @@ +import 'echarts/lib/component/dataZoom'; + +import type { Ref } from 'vue'; + +import echarts from '@/plugins/echarts'; +import { debounceChart } from '@/utils/chart'; + +let myChart = null; + +const option = { + tooltip: { trigger: 'item' }, + legend: { + top: 'bottom', + data: ['品牌A', '品牌B', '品牌C', '品牌D', '品牌E', '品牌F'], + }, + series: [ + { + name: '品牌占比', + type: 'pie', + radius: [25, 100], + center: ['50%', '45%'], + roseType: 'area', + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)', + }, + }, + label: { + formatter: '{b}: {c}%', + }, + data: [ + { value: 10.89, name: '品牌A' }, + { value: 30.89, name: '品牌B' }, + { value: 38.38, name: '品牌C' }, + { value: 27.47, name: '品牌D' }, + { value: 29.79, name: '品牌E' }, + { value: 50, name: '品牌F' }, + { value: 50, name: '品牌G' }, + { value: 39.72, name: '品牌H' }, + ], + }, + ], +}; + +/** 渲染图表 */ +export const renderEcharts = (element: Ref) => { + myChart = echarts.init(element.value, null, { + renderer: 'canvas', + devicePixelRatio: window.devicePixelRatio, + }); + + debounceChart(myChart); + + myChart.setOption(option); +}; + +/** 更新图表数据 */ +export const updateChart = (option: Array>) => { + const series = myChart.getOption().series; + // series[0].data = option[0]; + // series[1].data = option[1]; + myChart.setOption({ series }); +}; diff --git a/src/views/data-analyse/charts/right-header.ts b/src/views/data-analyse/charts/right-header.ts new file mode 100644 index 0000000..c786568 --- /dev/null +++ b/src/views/data-analyse/charts/right-header.ts @@ -0,0 +1,97 @@ +import type { Ref } from 'vue'; + +import echarts from '@/plugins/echarts'; +import { debounceChart } from '@/utils/chart'; + +let myChart = null; +const myData = [ + { + value: 137, + name: '数学', + }, + { + value: 103, + name: '语文', + }, + { + value: 124, + name: '英语', + }, + { + value: 180, + name: '理综', + }, +]; + +const option = { + color: ['#1aa3ff', '#04f9fa', '#16bd87', '#c961ff', '#7cfc12'], + tooltip: { + trigger: 'item', + formatter: '{b}:{c} ({d}%)', + }, + legend: { + bottom: '20%', + itemWidth: 10, + itemHeight: 10, + textStyle: { + color: '#fff', + fontSize: '14', + }, + }, + series: [ + // 内圈 + { + type: 'pie', + center: ['50%', '40%'], + radius: ['33.5%', '35.5%'], + silent: true, //取消高亮 + label: { show: false, position: 'center' }, + data: myData, + }, + // 外圈 + { + type: 'pie', + center: ['50%', '40%'], + radius: ['40%', '50%'], + label: { show: false, position: 'center' }, + emphasis: { + label: { + show: true, + fontSize: 33, + lineHeight: 45, + formatter: (params) => { + return '{name|' + params.name + '}\n{value|' + params.value + '}'; + }, + rich: { + name: { + color: '#fff', + }, + value: { + color: '#04F9FA', + }, + }, + }, + }, + data: myData, + }, + ], +}; +/** 渲染图表 */ +export const renderEcharts = (element: Ref) => { + myChart = echarts.init(element.value, null, { + renderer: 'canvas', + devicePixelRatio: window.devicePixelRatio, + }); + + debounceChart(myChart); + + myChart.setOption(option); +}; + +/** 更新图表数据 */ +export const updateChart = (option: Array>) => { + const series = myChart.getOption().series; + // series[0].data = option[0]; + // series[1].data = option[1]; + myChart.setOption({ series }); +}; diff --git a/src/views/data-analyse/components/data-analyse-content/index.vue b/src/views/data-analyse/components/data-analyse-content/index.vue index b59098d..0b8df2d 100644 --- a/src/views/data-analyse/components/data-analyse-content/index.vue +++ b/src/views/data-analyse/components/data-analyse-content/index.vue @@ -1,7 +1,21 @@ - + diff --git a/src/views/data-analyse/components/data-analyse-left/components/left-center.vue b/src/views/data-analyse/components/data-analyse-left/components/left-center.vue deleted file mode 100644 index 094c9b5..0000000 --- a/src/views/data-analyse/components/data-analyse-left/components/left-center.vue +++ /dev/null @@ -1,60 +0,0 @@ - - - - - diff --git a/src/views/data-analyse/components/data-analyse-left/components/left-top.vue b/src/views/data-analyse/components/data-analyse-left/components/left-top.vue deleted file mode 100644 index 6e08fe2..0000000 --- a/src/views/data-analyse/components/data-analyse-left/components/left-top.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - - - diff --git a/src/views/data-analyse/components/data-analyse-left/index.vue b/src/views/data-analyse/components/data-analyse-left/index.vue index cc6fa2e..eb0e55e 100644 --- a/src/views/data-analyse/components/data-analyse-left/index.vue +++ b/src/views/data-analyse/components/data-analyse-left/index.vue @@ -1,12 +1,68 @@ @@ -15,5 +71,82 @@ import LeftTop from '@/views/data-analyse/components/data-analyse-left/component width: 496px; height: 970px; color: white; + + /* 顶部 */ + &__top { + display: flex; + justify-content: space-between; + align-items: center; + width: 496px; + height: 100px; + + &-percent { + display: flex; + justify-content: center; + align-items: center; + color: var(--color-primary-secondary); + font-size: 16px; + + span { + font-size: 18px; + } + + i { + font-size: 21px; + } + } + + li { + margin: 0 4px; + width: 56px; + height: 53px; + line-height: 53px; + text-align: center; + font-size: 47px; + border: 1px solid var(--color-primary-secondary); + background-color: rgba(39, 63, 86, 0.34); + } + } + + /* 中心区域 */ + &__center { + margin: 47px 0 0 0; + + li { + margin: 0 0 27px 0; + + &:nth-child(1) { + margin: 35px 0 27px 0; + } + } + + &-info { + display: flex; + justify-content: space-between; + + .info-left { + display: flex; + justify-content: space-between; + align-items: center; + + i { + color: var(--color-primary-secondary); + } + } + } + } + + /* 底部区域 */ + &__bottom { + margin: 25px 0 0 0; + width: 468px; + height: 387px; + + &-chart { + margin: 0 0 25px 0; + width: 100%; + height: 100%; + } + } } diff --git a/src/views/data-analyse/components/data-analyse-right/index.vue b/src/views/data-analyse/components/data-analyse-right/index.vue index 9dda4b7..937bdfe 100644 --- a/src/views/data-analyse/components/data-analyse-right/index.vue +++ b/src/views/data-analyse/components/data-analyse-right/index.vue @@ -1,13 +1,67 @@ - + diff --git a/src/views/data-analyse/index.vue b/src/views/data-analyse/index.vue index 0197669..b102855 100644 --- a/src/views/data-analyse/index.vue +++ b/src/views/data-analyse/index.vue @@ -20,7 +20,5 @@ import DataAnalyseRight from '@/views/data-analyse/components/data-analyse-right padding: 0 20px; width: 100%; height: 100%; - - background: cadetblue; } diff --git a/src/views/smart-park/components/smart-park-content/components/smart-park-sidebar-right/index.vue b/src/views/smart-park/components/smart-park-content/components/smart-park-sidebar-right/index.vue index 99bff17..eb5be62 100644 --- a/src/views/smart-park/components/smart-park-content/components/smart-park-sidebar-right/index.vue +++ b/src/views/smart-park/components/smart-park-content/components/smart-park-sidebar-right/index.vue @@ -1,12 +1,11 @@