Compare commits
No commits in common. "8ca3934de762888854de1619bc6234a729983892" and "cf1a91f38fe89a1497154c28b5739b6b216f0894" have entirely different histories.
8ca3934de7
...
cf1a91f38f
|
@ -9,7 +9,6 @@ lerna-debug.log*
|
||||||
|
|
||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
fakeServer
|
|
||||||
dist-ssr
|
dist-ssr
|
||||||
*.local
|
*.local
|
||||||
|
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
# 定义CI/CD流水线的阶段
|
|
||||||
stages:
|
|
||||||
- build # 第一阶段:构建应用程序
|
|
||||||
- build-docker # 第二阶段:构建Docker镜像
|
|
||||||
- deploy # 第三阶段:部署应用程序
|
|
||||||
|
|
||||||
cache: # 缓存内容
|
|
||||||
paths:
|
|
||||||
- node_modules/
|
|
||||||
- docker/dist/
|
|
||||||
|
|
||||||
# 定义全局变量
|
|
||||||
variables:
|
|
||||||
CONTAINER_NAME: 'central-monitor' # Docker容器名称
|
|
||||||
DOCKER_TAG: '1.0.0' # Docker镜像标签版本
|
|
||||||
|
|
||||||
# 构建任务
|
|
||||||
build-job:
|
|
||||||
stage: build # 指定此任务属于build阶段
|
|
||||||
script:
|
|
||||||
# 打印编译开始信息
|
|
||||||
- echo "Compiling the code..."
|
|
||||||
# 使用Maven编译Java项目,跳过测试
|
|
||||||
- npm i -g pnpm && pnpm i && pnpm build
|
|
||||||
# 打印编译完成信息
|
|
||||||
- echo "Compile complete."
|
|
||||||
# 从Docker Hub拉取OpenJDK基础镜像
|
|
||||||
- docker pull nginx:1.27.3
|
|
||||||
# 打印拉取完成信息
|
|
||||||
- echo "docker pull complete."
|
|
||||||
# 使用Dockerfile构建Docker镜像,并打上标签
|
|
||||||
- cd docker && docker build -f Dockerfile -t $CONTAINER_NAME:$DOCKER_TAG .
|
|
||||||
# 打印构建成功信息
|
|
||||||
- echo "Application successfully deployed."
|
|
||||||
|
|
||||||
# 部署任务
|
|
||||||
deploy-job:
|
|
||||||
stage: deploy # 指定此任务属于deploy阶段
|
|
||||||
environment: production # 指定部署环境为production
|
|
||||||
script:
|
|
||||||
# 打印部署开始信息
|
|
||||||
- echo "Deploying application..."
|
|
||||||
# 停止正在运行的容器(如果存在),|| true确保命令失败不会中断脚本
|
|
||||||
- docker stop $CONTAINER_NAME || true
|
|
||||||
# 删除容器(如果存在)
|
|
||||||
- docker rm $CONTAINER_NAME || true
|
|
||||||
# 运行新的Docker容器
|
|
||||||
# -d: 后台运行
|
|
||||||
# -p: 端口映射(7070和8000)
|
|
||||||
# --name: 容器名称
|
|
||||||
# --restart always: 总是自动重启
|
|
||||||
- docker run -d -p 8800:80 --name $CONTAINER_NAME --restart always $CONTAINER_NAME:$DOCKER_TAG
|
|
||||||
# 打印部署成功信息
|
|
||||||
- echo "Application successfully deployed."
|
|
|
@ -31,7 +31,7 @@ export const buildEnv = (): BuildOptions => {
|
||||||
// 规定触发警告的 chunk 大小, 当某个代码分块的大小超过该限制时,Vite 会发出警告
|
// 规定触发警告的 chunk 大小, 当某个代码分块的大小超过该限制时,Vite 会发出警告
|
||||||
chunkSizeWarningLimit: 2000,
|
chunkSizeWarningLimit: 2000,
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: ['echarts', 'fsevents'],
|
external: ['md-editor-v3', 'echarts'],
|
||||||
input: {
|
input: {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
index: pathResolve('../index.html', import.meta.url),
|
index: pathResolve('../index.html', import.meta.url),
|
||||||
|
|
|
@ -57,10 +57,7 @@ const useMock = (mode: string) => {
|
||||||
logger: true,
|
logger: true,
|
||||||
include: 'mock',
|
include: 'mock',
|
||||||
infixName: false,
|
infixName: false,
|
||||||
enableDev: true,
|
enableProd: true, // 线上支持mock
|
||||||
// enableProd: true,
|
|
||||||
// build: true,
|
|
||||||
// http2: true,
|
|
||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,13 +16,13 @@ server {
|
||||||
}
|
}
|
||||||
|
|
||||||
# 后端跨域请求
|
# 后端跨域请求
|
||||||
# location ~/api/ {
|
location ~/api/ {
|
||||||
# proxy_pass http://172.17.0.1:8000;
|
proxy_pass http://172.17.0.1:8000;
|
||||||
# proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
# proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
# proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
# }
|
}
|
||||||
|
|
||||||
error_page 404 404.html;
|
error_page 404 404.html;
|
||||||
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
import { defineFakeRoute } from 'vite-plugin-fake-server';
|
|
||||||
|
|
||||||
const randomNumber = (range: number = 100) => {
|
|
||||||
return parseInt((Math.random() * range).toFixed(0));
|
|
||||||
};
|
|
||||||
const BASE_URL = '/mock/data-analyse';
|
|
||||||
|
|
||||||
export default defineFakeRoute([
|
|
||||||
// 销售设备总量
|
|
||||||
{
|
|
||||||
url: `${BASE_URL}/device-sales-stats`,
|
|
||||||
method: 'GET',
|
|
||||||
response: () => ({
|
|
||||||
code: 200,
|
|
||||||
data: {
|
|
||||||
// 销售设备总量
|
|
||||||
totalDeviceSales: randomNumber(9999),
|
|
||||||
// 环比去年增长,如 "+15.2%"
|
|
||||||
yearlyGrowthRate: randomNumber(),
|
|
||||||
},
|
|
||||||
message: '操作成功',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
// 销售公司销售设备数量占比
|
|
||||||
{
|
|
||||||
url: `${BASE_URL}/company-sales-distribution`,
|
|
||||||
method: 'GET',
|
|
||||||
response: () => ({
|
|
||||||
code: 200,
|
|
||||||
data: [
|
|
||||||
{ name: '科技有限公司', amount: randomNumber(999999), percent: randomNumber() },
|
|
||||||
{ name: '科技有限公司', amount: randomNumber(999999), percent: randomNumber() },
|
|
||||||
{ name: '科技有限公司', amount: randomNumber(999999), percent: randomNumber() },
|
|
||||||
{ name: '科技有限公司', amount: randomNumber(999999), percent: randomNumber() },
|
|
||||||
{ name: '科技有限公司', amount: randomNumber(999999), percent: randomNumber() },
|
|
||||||
],
|
|
||||||
message: '操作成功',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
// 品牌占有率
|
|
||||||
{
|
|
||||||
url: `${BASE_URL}/brands-distribution`,
|
|
||||||
method: 'GET',
|
|
||||||
response: () => ({
|
|
||||||
code: 200,
|
|
||||||
data: [
|
|
||||||
{ value: randomNumber(), name: '品牌A' },
|
|
||||||
{ value: randomNumber(), name: '品牌B' },
|
|
||||||
{ value: randomNumber(), name: '品牌C' },
|
|
||||||
{ value: randomNumber(), name: '品牌D' },
|
|
||||||
{ value: randomNumber(), name: '品牌E' },
|
|
||||||
{ value: randomNumber(), name: '品牌F' },
|
|
||||||
{ value: randomNumber(), name: '品牌G' },
|
|
||||||
{ value: randomNumber(), name: '品牌H' },
|
|
||||||
],
|
|
||||||
message: '操作成功',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
]);
|
|
16
package.json
16
package.json
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "central-monitor",
|
"name": "vehicle-monitor",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
@ -95,18 +95,6 @@
|
||||||
"allowedVersions": {
|
"allowedVersions": {
|
||||||
"eslint": "9"
|
"eslint": "9"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"packageExtensions": {
|
|
||||||
"rollup@*": {
|
|
||||||
"optionalDependencies": {
|
|
||||||
"fsevents": "*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"onlyBuiltDependencies": [
|
|
||||||
"@parcel/watcher",
|
|
||||||
"esbuild",
|
|
||||||
"vue-demi"
|
|
||||||
]
|
|
||||||
}
|
}
|
|
@ -4,8 +4,6 @@ settings:
|
||||||
autoInstallPeers: true
|
autoInstallPeers: true
|
||||||
excludeLinksFromLockfile: false
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
packageExtensionsChecksum: sha256-P0QlM8/kU0utlq/9p9JMVRZfIyZpKq+o9SyM/Bghnd4=
|
|
||||||
|
|
||||||
importers:
|
importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
import request from '@/api/server/requestMock';
|
|
||||||
|
|
||||||
/* 销售设备总量 */
|
|
||||||
export const getDeviceSalesStats = () => {
|
|
||||||
return request.get('data-analyse/device-sales-stats');
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 销售公司销售设备数量占比 */
|
|
||||||
export const getCompanySalesDistribution = () => {
|
|
||||||
return request.get('data-analyse/company-sales-distribution');
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 品牌占有率 */
|
|
||||||
export const getBrandsDistribution = () => {
|
|
||||||
return request.get('data-analyse/brands-distribution');
|
|
||||||
};
|
|
|
@ -18,13 +18,10 @@ defineProps({
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 11px;
|
height: 11px;
|
||||||
border: 1px solid var(--color-primary-secondary);
|
border: 1px solid var(--color-primary-secondary);
|
||||||
border-radius: 2px;
|
|
||||||
|
|
||||||
&-inner {
|
&-inner {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-radius: 4px;
|
|
||||||
background: var(--color-primary);
|
background: var(--color-primary);
|
||||||
transition: all 0.4s;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useIntervalFn } from '@vueuse/core';
|
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
import LayoutHeaderNav from '@/layout/layout-header/components/layout-nav/LayoutHeaderNav.vue';
|
import LayoutHeaderNav from '@/layout/layout-header/components/LayoutHeaderNav.vue';
|
||||||
import dayjs from '@/plugins/dayjs';
|
import dayjs from '@/plugins/dayjs';
|
||||||
import { resetRouter } from '@/router';
|
import { resetRouter } from '@/router';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
const time = ref('');
|
const time = ref('');
|
||||||
|
@ -14,7 +14,7 @@ const time = ref('');
|
||||||
/** 显示时间 */
|
/** 显示时间 */
|
||||||
const displayTime = () => {
|
const displayTime = () => {
|
||||||
time.value = dayjs(new Date()).format('YYYY-MM-DD dddd HH:mm:ss');
|
time.value = dayjs(new Date()).format('YYYY-MM-DD dddd HH:mm:ss');
|
||||||
useIntervalFn(() => {
|
setInterval(() => {
|
||||||
time.value = dayjs(new Date()).format('YYYY-MM-DD dddd HH:mm:ss');
|
time.value = dayjs(new Date()).format('YYYY-MM-DD dddd HH:mm:ss');
|
||||||
}, 1000);
|
}, 1000);
|
||||||
};
|
};
|
||||||
|
@ -26,18 +26,18 @@ onMounted(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<header>
|
<header>
|
||||||
<div class="header-time">{{ time }}</div>
|
<div class="header-time c-primary">{{ time }}</div>
|
||||||
|
|
||||||
<div class="header-title">
|
<div class="header-title">
|
||||||
<h1 @click="resetRouter()">{{ route.meta.title }}</h1>
|
<h1>{{ route.meta.title }}</h1>
|
||||||
<h2>{{ route.meta.subtitle }}</h2>
|
<h2>{{ route.meta.subtitle }}</h2>
|
||||||
<!--<img-->
|
<img
|
||||||
<!-- alt="icon-setting"-->
|
alt="icon-setting"
|
||||||
<!-- class="ml-[-464px]"-->
|
class="ml-[-284px]"
|
||||||
<!-- src="../images/icon/icon-home.png"-->
|
src="../images/icon/icon-home.png"
|
||||||
<!-- @click="resetRouter()"-->
|
@click="resetRouter()"
|
||||||
<!--/>-->
|
/>
|
||||||
<!--<img alt="icon-home" class="ml-[464px]" src="../images/icon/icon-setting.png" />-->
|
<img alt="icon-home" class="ml-[284px]" src="../images/icon/icon-setting.png" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<LayoutHeaderNav />
|
<LayoutHeaderNav />
|
||||||
|
@ -47,7 +47,7 @@ onMounted(() => {
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
header {
|
header {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 80px;
|
height: 108px;
|
||||||
background: url('@/layout/layout-header/images/layout-header-2.png') no-repeat center;
|
background: url('@/layout/layout-header/images/layout-header-2.png') no-repeat center;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
@ -55,8 +55,7 @@ header {
|
||||||
.header-time {
|
.header-time {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin: 0 0 0 41px;
|
margin: 0 0 0 41px;
|
||||||
line-height: 50px;
|
line-height: 60px;
|
||||||
color: var(--color-info);
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,11 +65,11 @@ header {
|
||||||
|
|
||||||
img {
|
img {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
bottom: -14px;
|
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
width: 50px;
|
width: 60px;
|
||||||
height: 50px;
|
height: 60px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -78,15 +77,14 @@ header {
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 34px;
|
font-size: 42px;
|
||||||
line-height: 50px;
|
line-height: 60px;
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
color: var(--color-primary-secondary);
|
color: var(--color-primary-secondary);
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
line-height: 24px;
|
line-height: 45px;
|
||||||
font-weight: lighter;
|
font-weight: lighter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import LayoutHeaderNav from '@/layout/layout-header/components/layout-nav/LayoutHeaderNav.vue';
|
import LayoutHeaderNav from '@/layout/layout-header/components/LayoutHeaderNav.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="bar-op">
|
<div class="bar-op">
|
||||||
<ul>
|
<ul>
|
||||||
<!--<li><img alt="icon-1" src="../../images/icon/icon-1.png" /></li>-->
|
<li><img alt="icon-1" src="../images/icon/icon-1.png" /></li>
|
||||||
<!--<li><img alt="icon-2" src="../../images/icon/icon-2.png" /></li>-->
|
<li><img alt="icon-2" src="../images/icon/icon-2.png" /></li>
|
||||||
<!--<li><img alt="icon-3" src="../../images/icon/icon-3.png" /></li>-->
|
<li><img alt="icon-3" src="../images/icon/icon-3.png" /></li>
|
||||||
</ul>
|
</ul>
|
||||||
<span class="hover">小兔子🐇</span>
|
<span class="hover">王菠萝</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 4px;
|
top: 11px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
color: var(--color-info);
|
color: var(--color-primary);
|
||||||
float: left;
|
float: left;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 66 KiB |
|
@ -7,5 +7,3 @@ const store = createPinia();
|
||||||
export function setupStore(app: App<Element>) {
|
export function setupStore(app: App<Element>) {
|
||||||
app.use(store);
|
app.use(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { store };
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
import { defineStore } from 'pinia';
|
|
||||||
|
|
||||||
import {
|
|
||||||
getBrandsDistribution,
|
|
||||||
getCompanySalesDistribution,
|
|
||||||
getDeviceSalesStats,
|
|
||||||
} from '@/api/dataAnalyse';
|
|
||||||
|
|
||||||
import { store } from '..';
|
|
||||||
|
|
||||||
export const useDataAnalyseStore = defineStore('dataAnalyseStore', {
|
|
||||||
state: () => ({
|
|
||||||
// 销售设备总量
|
|
||||||
deviceSalesStats: {
|
|
||||||
totalDeviceSales: 0,
|
|
||||||
yearlyGrowthRate: 0,
|
|
||||||
},
|
|
||||||
// 销售公司销售设备数量占比
|
|
||||||
companySalesDistribution: [],
|
|
||||||
// 品牌占有率
|
|
||||||
brandsDistribution: [],
|
|
||||||
}),
|
|
||||||
actions: {
|
|
||||||
/* 销售设备总量 */
|
|
||||||
async fetchDeviceSaesStats() {
|
|
||||||
this.deviceSalesStats = await getDeviceSalesStats();
|
|
||||||
},
|
|
||||||
|
|
||||||
/* 销售公司销售设备数量占比 */
|
|
||||||
async fetchCompanySalesDistribution() {
|
|
||||||
this.companySalesDistribution = await getCompanySalesDistribution();
|
|
||||||
},
|
|
||||||
|
|
||||||
/* 品牌占有率 */
|
|
||||||
async fetchBrandsDistribution() {
|
|
||||||
this.brandsDistribution = await getBrandsDistribution();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export function useDataAnalyseHook() {
|
|
||||||
return useDataAnalyseStore(store);
|
|
||||||
}
|
|
|
@ -17,7 +17,7 @@ const option = ref<EChartsOption>({
|
||||||
{
|
{
|
||||||
name: '名称',
|
name: '名称',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: [14, 104],
|
radius: [14, 100],
|
||||||
center: ['50%', '50%'],
|
center: ['50%', '50%'],
|
||||||
roseType: 'area',
|
roseType: 'area',
|
||||||
itemStyle: { borderRadius: 4 },
|
itemStyle: { borderRadius: 4 },
|
||||||
|
|
|
@ -9,7 +9,10 @@ let myChart = null;
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
tooltip: { trigger: 'item' },
|
tooltip: { trigger: 'item' },
|
||||||
legend: { top: 'bottom', textStyle: { color: '#fff' } },
|
legend: {
|
||||||
|
top: 'bottom',
|
||||||
|
data: ['品牌A', '品牌B', '品牌C', '品牌D', '品牌E', '品牌F'],
|
||||||
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '品牌占比',
|
name: '品牌占比',
|
||||||
|
@ -24,7 +27,9 @@ const option = {
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
label: { formatter: '{b}: {c}%', color: '#fff' },
|
label: {
|
||||||
|
formatter: '{b}: {c}%',
|
||||||
|
},
|
||||||
data: [
|
data: [
|
||||||
{ value: 10.89, name: '品牌A' },
|
{ value: 10.89, name: '品牌A' },
|
||||||
{ value: 30.89, name: '品牌B' },
|
{ value: 30.89, name: '品牌B' },
|
||||||
|
@ -52,8 +57,9 @@ export const renderEcharts = (element: Ref<HTMLDivElement>) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 更新图表数据 */
|
/** 更新图表数据 */
|
||||||
export const updateChart = (data: any) => {
|
export const updateChart = (option: Array<Array<number>>) => {
|
||||||
const series = myChart.getOption().series;
|
const series = myChart.getOption().series;
|
||||||
series[0].data = data;
|
// series[0].data = option[0];
|
||||||
|
// series[1].data = option[1];
|
||||||
myChart.setOption({ series });
|
myChart.setOption({ series });
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,39 +1,23 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useIntervalFn } from '@vueuse/core';
|
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import Progress1 from '@/components/Progress/Progress1.vue';
|
import Progress1 from '@/components/Progress/Progress1.vue';
|
||||||
import { useDataAnalyseHook } from '@/store/modules/dataAnalyse';
|
import { renderEcharts } from '@/views/data-analyse/charts/left-brand';
|
||||||
import { renderEcharts, updateChart } from '@/views/data-analyse/charts/left-brand';
|
|
||||||
import PanelTitle from '@/views/data-analyse/components/PanelTitle.vue';
|
import PanelTitle from '@/views/data-analyse/components/PanelTitle.vue';
|
||||||
|
|
||||||
const dataAnalyseStore = useDataAnalyseHook();
|
|
||||||
const { deviceSalesStats, companySalesDistribution, brandsDistribution } =
|
|
||||||
storeToRefs(dataAnalyseStore);
|
|
||||||
|
|
||||||
/* 初始化数据获取 */
|
|
||||||
const initAppData = async () => {
|
|
||||||
// 销售设备总量
|
|
||||||
dataAnalyseStore.fetchDeviceSaesStats();
|
|
||||||
// 销售公司销售设备数量占比
|
|
||||||
dataAnalyseStore.fetchCompanySalesDistribution();
|
|
||||||
// 品牌占有率
|
|
||||||
await dataAnalyseStore.fetchBrandsDistribution();
|
|
||||||
|
|
||||||
// 更新图表
|
|
||||||
updateChart(brandsDistribution.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const brandChartRef = ref();
|
const brandChartRef = ref();
|
||||||
|
const deviceTotal = ref('1010');
|
||||||
|
|
||||||
|
const companyList = [
|
||||||
|
{ name: '科技有限公司', amount: 18888, percent: '40' },
|
||||||
|
{ name: '科技有限公司', amount: 18888, percent: '50' },
|
||||||
|
{ name: '科技有限公司', amount: 18888, percent: '10' },
|
||||||
|
{ name: '科技有限公司', amount: 18888, percent: '80' },
|
||||||
|
{ name: '科技有限公司', amount: 18888, percent: '50' },
|
||||||
|
];
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
renderEcharts(brandChartRef);
|
renderEcharts(brandChartRef);
|
||||||
initAppData();
|
|
||||||
|
|
||||||
useIntervalFn(() => {
|
|
||||||
initAppData();
|
|
||||||
}, 1000);
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -44,15 +28,13 @@ onMounted(() => {
|
||||||
<div>
|
<div>
|
||||||
<h1 class="font-size-[21px]">销售设备总量(台)</h1>
|
<h1 class="font-size-[21px]">销售设备总量(台)</h1>
|
||||||
<div class="data-analyse-left__top-percent">
|
<div class="data-analyse-left__top-percent">
|
||||||
<span>环比去年增长 {{ deviceSalesStats.yearlyGrowthRate }} %</span>
|
<span>环比去年增长 52%</span>
|
||||||
<i class="i-mdi-trending-up">s</i>
|
<i class="i-mdi-trending-up">s</i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="flex">
|
<ul class="flex">
|
||||||
<li v-for="(num, index) in deviceSalesStats.totalDeviceSales.toString()" :key="index">
|
<li v-for="(num, index) in deviceTotal" :key="index">{{ num }}</li>
|
||||||
{{ num }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -61,7 +43,7 @@ onMounted(() => {
|
||||||
<PanelTitle title="销售公司销售设备数量占比" />
|
<PanelTitle title="销售公司销售设备数量占比" />
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="(item, index) in companySalesDistribution" :key="index">
|
<li v-for="(item, index) in companyList" :key="index">
|
||||||
<div class="data-analyse-left__center-info">
|
<div class="data-analyse-left__center-info">
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ item.name }}</span>
|
||||||
<div class="info-left">
|
<div class="info-left">
|
||||||
|
|
Loading…
Reference in New Issue