| | |
| | | <template> |
| | | <div ref="screenRoot" class="sales-statistics-container" :class="{ 'is-fullscreen': isFullscreen }"> |
| | | <div ref="screenRoot" |
| | | class="sales-statistics-container" |
| | | :class="{ 'is-fullscreen': isFullscreen }"> |
| | | <div class="bi-bg"></div> |
| | | |
| | | <div class="bi-topbar"> |
| | | <img class="bi-topbar-title-bg" src="@/assets/BI/biaoti.png" alt="销售看板统计" /> |
| | | <img class="bi-topbar-title-bg" |
| | | src="@/assets/BI/biaoti.png" |
| | | alt="销售看板统计" /> |
| | | <div class="bi-topbar-content"> |
| | | <div class="bi-topbar-left"> |
| | | <span class="status-sun">☀</span> |
| | | <button class="fullscreen-btn" |
| | | @click="toggleFullscreen" |
| | | :title="isFullscreen ? '退出全屏' : '全屏显示'"> |
| | | <svg v-if="!isFullscreen" |
| | | width="1.6vh" |
| | | height="1.6vh" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | stroke="currentColor" |
| | | stroke-width="2"> |
| | | <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3" /> |
| | | </svg> |
| | | <svg v-else |
| | | width="1.6vh" |
| | | height="1.6vh" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | stroke="currentColor" |
| | | stroke-width="2"> |
| | | <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" /> |
| | | </svg> |
| | | </button> |
| | | <!-- <span class="status-sun">☀</span> |
| | | <span>26℃</span> |
| | | <span class="bi-topbar-sep">湿度:1</span> |
| | | <span class="bi-topbar-sep">湿度:1</span> --> |
| | | </div> |
| | | <div class="bi-topbar-title">销售看板统计</div> |
| | | <div class="bi-topbar-meta"> |
| | |
| | | <span class="bi-topbar-sep">|</span> |
| | | <span class="bi-topbar-date">{{ currentDateText }}</span> |
| | | </div> |
| | | <button class="fullscreen-btn" @click="toggleFullscreen" :title="isFullscreen ? '退出全屏' : '全屏显示'"> |
| | | <svg v-if="!isFullscreen" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| | | <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"/> |
| | | </svg> |
| | | <svg v-else width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| | | <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/> |
| | | </svg> |
| | | </button> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="bi-dashboard-grid"> |
| | | <!-- 左上:销量趋势 --> |
| | | <div class="bi-panel bi-panel-top-left"> |
| | | <PanelHeader title="销售分析-砌块" /> |
| | | <PanelHeader :isFullscreen="true" |
| | | title="销售分析-砌块" /> |
| | | <div class="panel-tabs"> |
| | | <span class="tab-item active">年</span> |
| | | <span class="tab-item">月</span> |
| | |
| | | <span>单位:立方米</span> |
| | | <span class="dot-legend">板材</span> |
| | | </div> |
| | | <div ref="salesVolumeChart" class="echart-fill"></div> |
| | | <div ref="salesVolumeChart" |
| | | class="echart-fill"></div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 右上:销售金额 --> |
| | | <div class="bi-panel bi-panel-top-right"> |
| | | <PanelHeader title="销售分析-板材" /> |
| | | <PanelHeader :isFullscreen="true" |
| | | title="销售分析-板材" /> |
| | | <div class="panel-tabs"> |
| | | <span class="tab-item active">年</span> |
| | | <span class="tab-item">月</span> |
| | |
| | | <span>单位:件</span> |
| | | <span class="dot-legend">板材</span> |
| | | </div> |
| | | <div ref="salesAmountChart" class="echart-fill"></div> |
| | | <div ref="salesAmountChart" |
| | | class="echart-fill"></div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 中间中心环 --> |
| | | <div class="center-ring"> |
| | | <img |
| | | class="center-ring-bg" |
| | | src="@/assets/BI/zonghetongbingtubiankuang@2x.png" |
| | | alt="" |
| | | /> |
| | | <div class="center-ring-content"> |
| | | <div class="center-ring-title">销售<br />中心</div> |
| | | |
| | | <!-- <img class="center-ring-bg" |
| | | src="@/assets/BI/zonghetongbingtubiankuang@2x.png" |
| | | alt="" /> --> |
| | | <!-- <div class="center-ring-content"> --> |
| | | <!-- <div class="center-ring-title">销售<br />中心</div> |
| | | <div class="center-metric m1"> |
| | | <div class="center-metric-label">新增客户</div> |
| | | <div class="center-metric-value">{{ centerNewCustomerCount }}</div> |
| | | <div class="center-metric-unit">人</div> |
| | | </div> |
| | | |
| | | <div class="center-metric m2"> |
| | | <div class="center-metric-label">成交总订单</div> |
| | | <div class="center-metric-value">{{ completedOrders }}</div> |
| | | <div class="center-metric-unit">单</div> |
| | | </div> |
| | | |
| | | <div class="center-metric m3"> |
| | | <div class="center-metric-label">新增订单</div> |
| | | <div class="center-metric-value">{{ salesOrderCount }}</div> |
| | | <div class="center-metric-unit">单</div> |
| | | </div> |
| | | |
| | | <div class="center-metric m4"> |
| | | <div class="center-metric-label">总销售区</div> |
| | | <div class="center-metric-value">{{ totalSalesAreaCount }}</div> |
| | | <div class="center-metric-unit">区</div> |
| | | </div> --> |
| | | <!-- </div> --> |
| | | <div class="center-ring-box"> |
| | | <div class="center-metric m1"> |
| | | <div class="center-metric-label">新增客户</div> |
| | | <div class="center-metric-value">{{ centerNewCustomerCount }}</div> |
| | | <div class="center-metric-unit">人</div> |
| | | </div> |
| | | <div class="center-metric m2"> |
| | | <div class="center-metric-label">成交总订单</div> |
| | | <div class="center-metric-value">{{ completedOrders }}</div> |
| | | <div class="center-metric-unit">单</div> |
| | | </div> |
| | | <div class="center-metric m3"> |
| | | <div class="center-metric-label">新增订单</div> |
| | | <div class="center-metric-value">{{ salesOrderCount }}</div> |
| | | <div class="center-metric-unit">单</div> |
| | | </div> |
| | | <div class="center-metric m4"> |
| | | <div class="center-metric-label">总销售区</div> |
| | | <div class="center-metric-value">{{ totalSalesAreaCount }}</div> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 左下:产品类型销量 --> |
| | | <div class="bi-panel bi-panel-bottom-left"> |
| | | <PanelHeader title="客户销量排名分析-砌块" /> |
| | | <PanelHeader :isFullscreen="true" |
| | | title="客户销量排名分析-砌块" /> |
| | | <div class="panel-tabs"> |
| | | <span class="tab-item active">年</span> |
| | | <span class="tab-item">月</span> |
| | |
| | | <span class="cf-tab">xxx销售区</span> |
| | | <span class="cf-tab">xxx销售区</span> |
| | | </div> |
| | | <div ref="productTypeChart" class="echart-fill"></div> |
| | | <div ref="productTypeChart" |
| | | class="echart-fill"></div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 中下:新增客户分析(分产品类型趋势) --> |
| | | <div class="bi-panel bi-panel-bottom-center"> |
| | | <PanelHeader title="新增客户趋势分析" /> |
| | | <PanelHeader :isFullscreen="true" |
| | | title="新增客户趋势分析" /> |
| | | <div class="panel-tabs"> |
| | | <span class="tab-item active">年</span> |
| | | <span class="tab-item">月</span> |
| | |
| | | <div class="chart-unit-row chart-unit-single"> |
| | | <span>单位:人</span> |
| | | </div> |
| | | <div ref="productTypeTrendChart" class="echart-fill"></div> |
| | | <div ref="productTypeTrendChart" |
| | | class="echart-fill"></div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 右下:销售区域销量 --> |
| | | <div class="bi-panel bi-panel-bottom-right"> |
| | | <PanelHeader title="客户销量排名分析-板材" /> |
| | | <PanelHeader :isFullscreen="true" |
| | | title="客户销量排名分析-板材" /> |
| | | <div class="panel-tabs"> |
| | | <span class="tab-item active">年</span> |
| | | <span class="tab-item">月</span> |
| | |
| | | <span class="cf-tab">xxx销售区</span> |
| | | <span class="cf-tab">xxx销售区</span> |
| | | </div> |
| | | <div ref="salesAreaChart" class="echart-fill"></div> |
| | | <div ref="salesAreaChart" |
| | | class="echart-fill"></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | const isFullscreen = ref(false); |
| | | |
| | | // 顶部栏时间(用于匹配BI大屏效果图) |
| | | const now = ref(dayjs()) |
| | | const currentTime = computed(() => now.value.format("HH:mm:ss")) |
| | | const now = ref(dayjs()); |
| | | const currentTime = computed(() => now.value.format("HH:mm:ss")); |
| | | const currentDateText = computed(() => { |
| | | const weekMap = { |
| | | 0: "星期日", |
| | |
| | | 4: "星期四", |
| | | 5: "星期五", |
| | | 6: "星期六", |
| | | } |
| | | return `${now.value.format("YYYY-MM-DD")} ${weekMap[now.value.day()] || ""}` |
| | | }) |
| | | let timeTicker = null |
| | | }; |
| | | return `${now.value.format("YYYY-MM-DD")} ${weekMap[now.value.day()] || ""}`; |
| | | }); |
| | | let timeTicker = null; |
| | | |
| | | const handleFullscreenChange = () => { |
| | | isFullscreen.value = !!document.fullscreenElement; |
| | |
| | | trigger: "axis", |
| | | backgroundColor: "rgba(0,0,0,0.55)", |
| | | borderColor: "rgba(64,158,255,0.25)", |
| | | borderWidth: 1, |
| | | textStyle: { color: "#B8C8E0" }, |
| | | borderWidth: getResponsiveValue(1), |
| | | textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | formatter: "{b}: {c} 立方米", |
| | | }, |
| | | grid: { |
| | |
| | | data: periods, |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: 11, margin: 10 }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(10), |
| | | }, |
| | | splitLine: { show: false }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | name: "", |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: 11, margin: 8 }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(8), |
| | | }, |
| | | splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } }, |
| | | }, |
| | | series: [ |
| | |
| | | data: values, |
| | | type: "line", |
| | | smooth: true, |
| | | symbolSize: 8, |
| | | lineStyle: { width: 3, color: "#00A4ED" }, |
| | | symbolSize: getResponsiveValue(8), |
| | | lineStyle: { width: getResponsiveValue(3), color: "#00A4ED" }, |
| | | itemStyle: { color: "#00A4ED" }, |
| | | areaStyle: { |
| | | opacity: 1, |
| | |
| | | trigger: "axis", |
| | | backgroundColor: "rgba(0,0,0,0.55)", |
| | | borderColor: "rgba(64,158,255,0.25)", |
| | | borderWidth: 1, |
| | | textStyle: { color: "#B8C8E0" }, |
| | | borderWidth: getResponsiveValue(1), |
| | | textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | formatter: "{b}: {c} 万元", |
| | | }, |
| | | grid: { |
| | |
| | | data: periods, |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: 11, margin: 10 }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(10), |
| | | }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | name: "", |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: 11, margin: 8 }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(8), |
| | | }, |
| | | splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } }, |
| | | }, |
| | | series: [ |
| | |
| | | data: values, |
| | | type: "line", |
| | | smooth: true, |
| | | symbolSize: 8, |
| | | symbolSize: getResponsiveValue(8), |
| | | itemStyle: { |
| | | color: "#00A4ED", |
| | | }, |
| | | lineStyle: { width: 3, color: "#00A4ED" }, |
| | | lineStyle: { width: getResponsiveValue(3), color: "#00A4ED" }, |
| | | areaStyle: { |
| | | opacity: 1, |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | |
| | | const productTypeChartOption = computed(() => { |
| | | const types = ["客户BB", "客户AA", "客户CC", "客户DD", "客户DD", "客户DD"]; |
| | | const values = [130, 120, 102, 90, 90, 70]; |
| | | const barColors = ["#34D8F7", "#4A8BFF", "#8A6BFF", "#C8C447", "#C8C447", "#C8C447"]; |
| | | const barColors = [ |
| | | "#34D8F7", |
| | | "#4A8BFF", |
| | | "#8A6BFF", |
| | | "#C8C447", |
| | | "#C8C447", |
| | | "#C8C447", |
| | | ]; |
| | | |
| | | return { |
| | | backgroundColor: "transparent", |
| | |
| | | axisPointer: { type: "shadow" }, |
| | | backgroundColor: "rgba(0,0,0,0.55)", |
| | | borderColor: "rgba(64,158,255,0.25)", |
| | | borderWidth: 1, |
| | | textStyle: { color: "#B8C8E0" }, |
| | | borderWidth: getResponsiveValue(1), |
| | | textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | formatter: "{b}: {c} 立方米", |
| | | }, |
| | | grid: { |
| | |
| | | xAxis: { |
| | | type: "value", |
| | | axisLine: { show: false }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: 11 }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } }, |
| | | }, |
| | | yAxis: { |
| | |
| | | data: types, |
| | | axisTick: { show: false }, |
| | | axisLine: { show: false }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: 11, margin: 8 }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(8), |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "销量(立方米)", |
| | | type: "bar", |
| | | barWidth: 14, |
| | | barWidth: getResponsiveValue(14), |
| | | data: values, |
| | | itemStyle: { |
| | | color: params => barColors[params.dataIndex] || "#00A4ED", |
| | | borderRadius: [6, 6, 6, 6], |
| | | borderRadius: [ |
| | | getResponsiveValue(6), |
| | | getResponsiveValue(6), |
| | | getResponsiveValue(6), |
| | | getResponsiveValue(6), |
| | | ], |
| | | }, |
| | | label: { |
| | | show: false, |
| | |
| | | const salesAreaChartOption = computed(() => { |
| | | const areas = ["客户BB", "客户AA", "客户CC", "客户DD", "客户DD", "客户DD"]; |
| | | const values = [130, 120, 102, 90, 90, 70]; |
| | | const barColors = ["#34D8F7", "#4A8BFF", "#8A6BFF", "#C8C447", "#C8C447", "#C8C447"]; |
| | | const barColors = [ |
| | | "#34D8F7", |
| | | "#4A8BFF", |
| | | "#8A6BFF", |
| | | "#C8C447", |
| | | "#C8C447", |
| | | "#C8C447", |
| | | ]; |
| | | |
| | | return { |
| | | backgroundColor: "transparent", |
| | |
| | | axisPointer: { type: "shadow" }, |
| | | backgroundColor: "rgba(0,0,0,0.55)", |
| | | borderColor: "rgba(64,158,255,0.25)", |
| | | borderWidth: 1, |
| | | textStyle: { color: "#B8C8E0" }, |
| | | borderWidth: getResponsiveValue(1), |
| | | textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | formatter: "{b}: {c} 立方米", |
| | | }, |
| | | grid: { |
| | |
| | | xAxis: { |
| | | type: "value", |
| | | axisLine: { show: false }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: 11 }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } }, |
| | | }, |
| | | yAxis: { |
| | |
| | | data: areas, |
| | | axisTick: { show: false }, |
| | | axisLine: { show: false }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: 11, margin: 8 }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(8), |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "销量(立方米)", |
| | | type: "bar", |
| | | barWidth: 14, |
| | | barWidth: getResponsiveValue(14), |
| | | data: values, |
| | | itemStyle: { |
| | | color: params => barColors[params.dataIndex] || "#00A4ED", |
| | | borderRadius: [6, 6, 6, 6], |
| | | borderRadius: [ |
| | | getResponsiveValue(6), |
| | | getResponsiveValue(6), |
| | | getResponsiveValue(6), |
| | | getResponsiveValue(6), |
| | | ], |
| | | }, |
| | | }, |
| | | ], |
| | |
| | | const productTypeTrendChartOption = computed(() => { |
| | | const typeOrder = ["AAA销售区", "BBB销售区", "CCC销售区", "DDD销售区"]; |
| | | const colorMap = { |
| | | "AAA销售区": "#65A0FF", |
| | | "BBB销售区": "#33F5FF", |
| | | "CCC销售区": "#FFD54A", |
| | | "DDD销售区": "#EE52FF", |
| | | AAA销售区: "#65A0FF", |
| | | BBB销售区: "#33F5FF", |
| | | CCC销售区: "#FFD54A", |
| | | DDD销售区: "#EE52FF", |
| | | }; |
| | | const areaColorMap = { |
| | | "AAA销售区": "rgba(101,160,255,0.28)", |
| | | "BBB销售区": "rgba(51,245,255,0.30)", |
| | | "CCC销售区": "rgba(255,213,74,0.25)", |
| | | "DDD销售区": "rgba(238,82,255,0.25)", |
| | | AAA销售区: "rgba(101,160,255,0.28)", |
| | | BBB销售区: "rgba(51,245,255,0.30)", |
| | | CCC销售区: "rgba(255,213,74,0.25)", |
| | | DDD销售区: "rgba(238,82,255,0.25)", |
| | | }; |
| | | const periods = ["6/9", "6/10", "6/11", "6/12", "6/12", "6/13", "6/14", "6/15"]; |
| | | const periods = [ |
| | | "6/9", |
| | | "6/10", |
| | | "6/11", |
| | | "6/12", |
| | | "6/12", |
| | | "6/13", |
| | | "6/14", |
| | | "6/15", |
| | | ]; |
| | | const map = { |
| | | "AAA销售区": [85, 112, 112, 112, 140, 112, 112, 140], |
| | | "BBB销售区": [140, 180, 180, 180, 230, 180, 180, 230], |
| | | "CCC销售区": [112, 140, 140, 140, 180, 140, 140, 180], |
| | | "DDD销售区": [200, 165, 200, 200, 165, 165, 140, 140], |
| | | AAA销售区: [85, 112, 112, 112, 140, 112, 112, 140], |
| | | BBB销售区: [140, 180, 180, 180, 230, 180, 180, 230], |
| | | CCC销售区: [112, 140, 140, 140, 180, 140, 140, 180], |
| | | DDD销售区: [200, 165, 200, 200, 165, 165, 140, 140], |
| | | }; |
| | | |
| | | const series = typeOrder.map((t) => ({ |
| | | const series = typeOrder.map(t => ({ |
| | | name: t, |
| | | type: "line", |
| | | smooth: true, |
| | | symbolSize: 7, |
| | | symbolSize: getResponsiveValue(7), |
| | | showSymbol: true, |
| | | data: map[t] || [], |
| | | lineStyle: { width: 3, color: colorMap[t] }, |
| | | lineStyle: { width: getResponsiveValue(3), color: colorMap[t] }, |
| | | itemStyle: { color: colorMap[t] }, |
| | | areaStyle: { |
| | | opacity: 0.25, |
| | |
| | | |
| | | return { |
| | | backgroundColor: "transparent", |
| | | |
| | | legend: { |
| | | top: 10, |
| | | top: getResponsiveValue(10), |
| | | left: "center", |
| | | textStyle: { color: "#B8C8E0", fontSize: 11, padding: [0, 0, 0, 2] }, |
| | | itemWidth: 12, |
| | | itemHeight: 10, |
| | | itemGap: 18, |
| | | textStyle: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | padding: [0, 0, 0, getResponsiveValue(2)], |
| | | }, |
| | | itemWidth: getResponsiveValue(12), |
| | | itemHeight: getResponsiveValue(10), |
| | | itemGap: getResponsiveValue(18), |
| | | }, |
| | | tooltip: { |
| | | trigger: "axis", |
| | | backgroundColor: "rgba(0,0,0,0.55)", |
| | | borderColor: "rgba(64,158,255,0.25)", |
| | | borderWidth: 1, |
| | | textStyle: { color: "#B8C8E0" }, |
| | | borderWidth: getResponsiveValue(1), |
| | | textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | }, |
| | | grid: { |
| | | left: "10%", |
| | |
| | | data: periods, |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: 11, margin: 10 }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(10), |
| | | }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | name: "", |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: 11, margin: 8 }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(8), |
| | | }, |
| | | splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } }, |
| | | }, |
| | | series, |
| | |
| | | tooltip: { |
| | | trigger: "axis", |
| | | formatter: "{b}: {c} 立方米", |
| | | textStyle: { fontSize: getResponsiveValue(11) }, |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | data: periods, |
| | | axisLabel: { fontSize: getResponsiveValue(11) }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | name: "累计销量(立方米)", |
| | | axisLabel: { fontSize: getResponsiveValue(11) }, |
| | | }, |
| | | series: [ |
| | | { |
| | |
| | | color: "#E6A23C", |
| | | }, |
| | | lineStyle: { |
| | | width: 3, |
| | | width: getResponsiveValue(3), |
| | | }, |
| | | }, |
| | | ], |
| | |
| | | tooltip: { |
| | | trigger: "axis", |
| | | formatter: "{b}: {c} 万元", |
| | | textStyle: { fontSize: getResponsiveValue(11) }, |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | data: periods, |
| | | axisLabel: { fontSize: getResponsiveValue(11) }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | name: "累计销售金额(万元)", |
| | | axisLabel: { fontSize: getResponsiveValue(11) }, |
| | | }, |
| | | series: [ |
| | | { |
| | |
| | | const handleFilterChange = () => { |
| | | // 处理筛选条件变化 |
| | | updateCharts(); |
| | | }; |
| | | const baseWidth = ref(1650); |
| | | // 计算响应式值 |
| | | const getResponsiveValue = baseValue => { |
| | | return Math.round((baseValue * window.innerWidth) / baseWidth.value); |
| | | }; |
| | | |
| | | // 初始化图表 |
| | |
| | | |
| | | updateCharts(); |
| | | }; |
| | | |
| | | // 更新图表 |
| | | const updateCharts = () => { |
| | | // 更新销量趋势图表 |
| | | if (salesVolumeChartInstance) { |
| | | salesVolumeChartInstance.setOption(salesVolumeChartOption.value); |
| | | salesVolumeChartInstance.setOption( |
| | | JSON.parse(JSON.stringify(salesVolumeChartOption.value)) |
| | | ); |
| | | } |
| | | |
| | | // 更新销售金额趋势图表 |
| | |
| | | |
| | | // 监听窗口大小变化 |
| | | const handleResize = () => { |
| | | console.log("resize"); |
| | | // 先更新图表选项,重新计算响应式值 |
| | | updateCharts(); |
| | | // 然后调整图表大小 |
| | | if (salesVolumeChartInstance) { |
| | | salesVolumeChartInstance.resize(); |
| | | } |
| | |
| | | .sales-statistics-container { |
| | | position: relative; |
| | | width: 100%; |
| | | min-height: calc(100vh - 84px); |
| | | min-height: calc(100vh - 8.4vh); |
| | | overflow: hidden; |
| | | color: #B8C8E0; |
| | | color: #b8c8e0; |
| | | background: #041026; |
| | | } |
| | | |
| | |
| | | .bi-bg { |
| | | position: absolute; |
| | | inset: 0; |
| | | background-image: url("@/assets/BI/backImage@2x.png"); |
| | | /* background-image: url("@/assets/BI/backImage@2x.png"); */ |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | |
| | | .bi-topbar { |
| | | position: relative; |
| | | z-index: 2; |
| | | height: 58px; |
| | | height: 5.8vh; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | height: 58px; |
| | | height: 8vh; |
| | | width: 100%; |
| | | object-fit: cover; |
| | | z-index: 0; |
| | |
| | | position: relative; |
| | | z-index: 1; |
| | | width: 100%; |
| | | padding: 0 28px; |
| | | padding: 0 2.8vh; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | |
| | | position: absolute; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | font-size: 26px; |
| | | font-size: 2.6vh; |
| | | font-weight: 800; |
| | | letter-spacing: 1px; |
| | | background: linear-gradient(180deg, #ffffff 0%, #B8DFFF 100%); |
| | | letter-spacing: 0.1vh; |
| | | background: linear-gradient(180deg, #ffffff 0%, #b8dfff 100%); |
| | | -webkit-background-clip: text; |
| | | background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | color: transparent; |
| | | text-shadow: 0 0 26px rgba(0, 164, 237, 0.55); |
| | | text-shadow: 0 0 2.6vh rgba(0, 164, 237, 0.55); |
| | | } |
| | | |
| | | .bi-topbar-left { |
| | | position: absolute; |
| | | left: 10px; |
| | | left: 1vh; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | gap: 0.8vh; |
| | | color: rgba(208, 231, 255, 0.85); |
| | | font-size: 13px; |
| | | font-size: 1.3vh; |
| | | } |
| | | |
| | | .status-sun { |
| | | color: #ffd85e; |
| | | text-shadow: 0 0 10px rgba(255, 216, 94, 0.8); |
| | | font-size: 13px; |
| | | text-shadow: 0 0 1vh rgba(255, 216, 94, 0.8); |
| | | font-size: 1.3vh; |
| | | line-height: 1; |
| | | } |
| | | |
| | | .bi-topbar-meta { |
| | | position: absolute; |
| | | right: 52px; |
| | | top: 16px; |
| | | font-size: 12px; |
| | | right: 5.2vh; |
| | | /* top: 1.6vh; */ |
| | | font-size: 1.2vh; |
| | | font-weight: 500; |
| | | letter-spacing: 0.5px; |
| | | letter-spacing: 0.05vh; |
| | | color: rgba(208, 231, 255, 0.85); |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | gap: 1vh; |
| | | } |
| | | |
| | | .fullscreen-btn { |
| | | position: absolute; |
| | | right: 10px; |
| | | top: 12px; |
| | | bottom: -1vh; |
| | | transform: none; |
| | | border: 1px solid rgba(64, 158, 255, 0.45); |
| | | border: 0.1vh solid rgba(64, 158, 255, 0.45); |
| | | background: rgba(0, 164, 237, 0.14); |
| | | color: #d0e7ff; |
| | | width: 34px; |
| | | height: 34px; |
| | | border-radius: 6px; |
| | | width: 3.4vh; |
| | | height: 3.4vh; |
| | | border-radius: 0.6vh; |
| | | padding: 0; |
| | | cursor: pointer; |
| | | transition: all 0.2s ease; |
| | |
| | | |
| | | .fullscreen-btn:hover { |
| | | background: rgba(0, 164, 237, 0.24); |
| | | box-shadow: 0 0 12px rgba(0, 164, 237, 0.3); |
| | | box-shadow: 0 0 1.2vh rgba(0, 164, 237, 0.3); |
| | | } |
| | | |
| | | .bi-topbar-sep { |
| | |
| | | .bi-dashboard-grid { |
| | | position: relative; |
| | | z-index: 2; |
| | | height: calc(100vh - 84px - 58px); |
| | | min-height: 450px; |
| | | padding: 10px 18px 14px; |
| | | height: calc(100vh - 8.4vh - 5.8vh); |
| | | min-height: 45vh; |
| | | padding: 1vh 1.8vh 1.4vh; |
| | | display: grid; |
| | | grid-template-columns: 1fr 1.05fr 1fr; |
| | | grid-template-rows: 1fr 1fr; |
| | | gap: 12px; |
| | | gap: 1.2vh; |
| | | } |
| | | |
| | | .sales-statistics-container.is-fullscreen .bi-dashboard-grid { |
| | | height: calc(100vh - 58px); |
| | | height: calc(100vh - 5.8vh); |
| | | } |
| | | |
| | | .bi-panel { |
| | | background: rgba(3, 18, 46, 0.62); |
| | | border: 1px solid rgba(64, 158, 255, 0.35); |
| | | border-radius: 4px; |
| | | border: 0.1vh solid rgba(64, 158, 255, 0.35); |
| | | border-radius: 0.4vh; |
| | | overflow: hidden; |
| | | box-shadow: 0 0 22px rgba(0, 164, 237, 0.12); |
| | | box-shadow: 0 0 2.2vh rgba(0, 164, 237, 0.12); |
| | | display: flex; |
| | | flex-direction: column; |
| | | position: relative; |
| | | } |
| | | |
| | | .bi-panel-title { |
| | | height: 44px; |
| | | height: 4.4vh; |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 0 18px; |
| | | font-size: 15px; |
| | | padding: 0 1.8vh; |
| | | font-size: 1.5vh; |
| | | font-weight: 700; |
| | | color: #B8C8E0; |
| | | color: #b8c8e0; |
| | | background: linear-gradient( |
| | | 90deg, |
| | | rgba(0, 164, 237, 0.2), |
| | | rgba(0, 164, 237, 0.04) |
| | | ); |
| | | border-bottom: 1px solid rgba(64, 158, 255, 0.25); |
| | | border-bottom: 0.1vh solid rgba(64, 158, 255, 0.25); |
| | | } |
| | | |
| | | .panel-tabs { |
| | | position: absolute; |
| | | top: 8px; |
| | | right: 12px; |
| | | top: 0.8vh; |
| | | right: 1.2vh; |
| | | display: flex; |
| | | gap: 6px; |
| | | gap: 0.6vh; |
| | | z-index: 4; |
| | | } |
| | | |
| | | .tab-item { |
| | | font-size: 12px; |
| | | font-size: 1.2vh; |
| | | color: rgba(184, 200, 224, 0.75); |
| | | padding: 1px 5px; |
| | | border: 1px solid rgba(64, 158, 255, 0.25); |
| | | border-radius: 3px; |
| | | padding: 0.1vh 0.5vh; |
| | | border: 0.1vh solid rgba(64, 158, 255, 0.25); |
| | | border-radius: 0.3vh; |
| | | line-height: 1.4; |
| | | } |
| | | |
| | |
| | | |
| | | .bi-panel-body { |
| | | flex: 1; |
| | | padding: 8px 10px; |
| | | padding: 0.8vh 1vh; |
| | | } |
| | | |
| | | .echart-fill { |
| | |
| | | |
| | | .chart-filter-tabs { |
| | | display: flex; |
| | | gap: 6px; |
| | | margin: 0 0 5px 0; |
| | | gap: 0.6vh; |
| | | margin: 0 0 0.5vh 0; |
| | | } |
| | | |
| | | .cf-tab { |
| | | font-size: 11px; |
| | | font-size: 1.1vh; |
| | | color: rgba(184, 200, 224, 0.68); |
| | | background: rgba(18, 56, 106, 0.65); |
| | | border: 1px solid rgba(64, 158, 255, 0.25); |
| | | padding: 3px 9px; |
| | | border: 0.1vh solid rgba(64, 158, 255, 0.25); |
| | | padding: 0.3vh 0.9vh; |
| | | line-height: 1; |
| | | } |
| | | |
| | | .cf-tab.active { |
| | | color: #D9ECFF; |
| | | color: #d9ecff; |
| | | background: rgba(0, 108, 208, 0.85); |
| | | border-color: rgba(64, 158, 255, 0.65); |
| | | } |
| | |
| | | .chart-unit-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | font-size: 12px; |
| | | font-size: 1.2vh; |
| | | color: rgba(208, 231, 255, 0.88); |
| | | margin-bottom: 4px; |
| | | padding: 0 2px; |
| | | margin-bottom: 0.4vh; |
| | | padding: 0 0.2vh; |
| | | } |
| | | |
| | | .dot-legend::before { |
| | | content: ""; |
| | | display: inline-block; |
| | | width: 8px; |
| | | height: 8px; |
| | | background: #65A0FF; |
| | | margin-right: 6px; |
| | | width: 0.8vh; |
| | | height: 0.8vh; |
| | | background: #65a0ff; |
| | | margin-right: 0.6vh; |
| | | } |
| | | |
| | | .chart-mini-title { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | font-size: 18px; |
| | | color: #D9ECFF; |
| | | gap: 0.8vh; |
| | | font-size: 1.8vh; |
| | | color: #d9ecff; |
| | | font-weight: 700; |
| | | margin: 0 0 8px 0; |
| | | margin: 0 0 0.8vh 0; |
| | | line-height: 1; |
| | | } |
| | | |
| | | .diamond { |
| | | width: 10px; |
| | | height: 10px; |
| | | background: #1E8BFF; |
| | | width: 1vh; |
| | | height: 1vh; |
| | | background: #1e8bff; |
| | | transform: rotate(45deg); |
| | | display: inline-block; |
| | | } |
| | | |
| | | .chart-unit-single { |
| | | justify-content: flex-start; |
| | | margin-bottom: 2px; |
| | | margin-bottom: 0.2vh; |
| | | } |
| | | |
| | | .bi-panel-top-left .echart-fill, |
| | | .bi-panel-top-right .echart-fill { |
| | | height: calc(100% - 44px); |
| | | height: calc(100% - 4.4vh); |
| | | } |
| | | |
| | | .bi-panel-bottom-left .echart-fill, |
| | | .bi-panel-bottom-right .echart-fill { |
| | | height: calc(100% - 28px); |
| | | height: calc(100% - 2.8vh); |
| | | } |
| | | |
| | | .bi-panel-bottom-center .echart-fill { |
| | | height: calc(100% - 44px); |
| | | height: calc(100% - 4.4vh); |
| | | } |
| | | |
| | | .bi-panel-top-left { |
| | |
| | | grid-column: 2; |
| | | grid-row: 1 / span 2; |
| | | position: absolute; |
| | | left:25%; |
| | | background: url("@/assets/BI/imageSS@2x.png") no-repeat bottom center; |
| | | background-size: 100% 30%; |
| | | left: 25%; |
| | | top: 25%; |
| | | transform: translate(-50%, -50%); |
| | | width: 400px; |
| | | height: 275px; |
| | | width: 60vh; |
| | | height: 40.5vh; |
| | | z-index: 3; |
| | | pointer-events: none; |
| | | } |
| | | .center-ring-box { |
| | | position: absolute; |
| | | /* inset: 0; */ |
| | | height: 100%; |
| | | width: 100%; |
| | | /* background-color: #fff; */ |
| | | background: url("@/assets/BI/imageSStop.png") no-repeat center center; |
| | | background-size: 80% 90%; |
| | | } |
| | | |
| | | .center-ring-bg { |
| | |
| | | position: absolute; |
| | | left: 50%; |
| | | top: 56%; |
| | | width: 370px; |
| | | height: 146px; |
| | | width: 37vh; |
| | | height: 14.6vh; |
| | | transform: translate(-50%, -50%) rotate(-18deg); |
| | | border: 2px solid rgba(40, 186, 255, 0.45); |
| | | border: 0.2vh solid rgba(40, 186, 255, 0.45); |
| | | border-radius: 50%; |
| | | filter: drop-shadow(0 0 8px rgba(0, 164, 237, 0.35)); |
| | | filter: drop-shadow(0 0 0.8vh rgba(0, 164, 237, 0.35)); |
| | | opacity: 0.7; |
| | | } |
| | | |
| | | .center-ring-content::after { |
| | | width: 360px; |
| | | height: 150px; |
| | | width: 36vh; |
| | | height: 15vh; |
| | | transform: translate(-50%, -50%) rotate(26deg); |
| | | border-color: rgba(80, 220, 255, 0.35); |
| | | opacity: 0.55; |
| | |
| | | top: 50%; |
| | | left: 50%; |
| | | transform: translate(-50%, -50%); |
| | | font-size: 36px; |
| | | font-size: 3.6vh; |
| | | line-height: 1.05; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | color: #EAF6FF; |
| | | text-shadow: 0 0 22px rgba(0, 164, 237, 0.55); |
| | | color: #eaf6ff; |
| | | text-shadow: 0 0 2.2vh rgba(0, 164, 237, 0.55); |
| | | z-index: 2; |
| | | } |
| | | |
| | |
| | | position: absolute; |
| | | left: 50%; |
| | | top: 50%; |
| | | width: 155px; |
| | | height: 155px; |
| | | width: 15.5vh; |
| | | height: 15.5vh; |
| | | transform: translate(-50%, -50%); |
| | | background: radial-gradient(circle, rgba(43, 199, 255, 0.26) 0%, rgba(8, 28, 61, 0.86) 70%); |
| | | border: 2px solid rgba(39, 198, 255, 0.46); |
| | | background: radial-gradient( |
| | | circle, |
| | | rgba(43, 199, 255, 0.26) 0%, |
| | | rgba(8, 28, 61, 0.86) 70% |
| | | ); |
| | | border: 0.2vh solid rgba(39, 198, 255, 0.46); |
| | | border-radius: 50%; |
| | | box-shadow: 0 0 20px rgba(0, 164, 237, 0.45), inset 0 0 26px rgba(0, 164, 237, 0.2); |
| | | box-shadow: 0 0 2vh rgba(0, 164, 237, 0.45), |
| | | inset 0 0 2.6vh rgba(0, 164, 237, 0.2); |
| | | z-index: -1; |
| | | } |
| | | |
| | | .center-metric { |
| | | position: absolute; |
| | | width: 155px; |
| | | width: 15.5vh; |
| | | z-index: 3; |
| | | text-align: center; |
| | | height: 120px; |
| | | height: 12vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .center-metric::before { |
| | | content: ""; |
| | | position: absolute; |
| | | left: 50%; |
| | | top: 50%; |
| | | width: 104px; |
| | | height: 104px; |
| | | transform: translate(-50%, -50%); |
| | | border-radius: 50%; |
| | | border: 2px solid rgba(71, 223, 255, 0.4); |
| | | background: radial-gradient(circle, rgba(37, 177, 255, 0.25) 0%, rgba(8, 33, 69, 0.55) 70%); |
| | | box-shadow: 0 0 18px rgba(0, 164, 237, 0.35), inset 0 0 18px rgba(0, 164, 237, 0.2); |
| | | z-index: -1; |
| | | } |
| | | |
| | | .center-metric-label { |
| | | font-size: 12px; |
| | | font-size: 1.2vh; |
| | | font-weight: 500; |
| | | color: rgba(234, 246, 255, 0.9); |
| | | margin-top: 0; |
| | | } |
| | | |
| | | .center-metric-value { |
| | | font-size: 34px; |
| | | font-size: 3.4vh; |
| | | font-weight: 800; |
| | | color: #EAF6FF; |
| | | text-shadow: 0 0 8px rgba(0, 229, 255, 0.22); |
| | | line-height: 1.0; |
| | | color: #eaf6ff; |
| | | text-shadow: 0 0 0.8vh rgba(0, 229, 255, 0.22); |
| | | line-height: 1; |
| | | } |
| | | |
| | | .center-metric-unit { |
| | | margin-top: 0; |
| | | font-size: 12px; |
| | | font-size: 1.2vh; |
| | | color: rgba(208, 231, 255, 0.85); |
| | | } |
| | | |
| | | .m1 { |
| | | top: -6px; |
| | | left: -26px; |
| | | top: 2.5vh; |
| | | left: 2.3vw; |
| | | text-align: left; |
| | | } |
| | | |
| | | .m2 { |
| | | top: -6px; |
| | | right: -26px; |
| | | top: 4.1vh; |
| | | right: 4.3vw; |
| | | text-align: right; |
| | | } |
| | | |
| | | .m3 { |
| | | bottom: 66px; |
| | | left: -30px; |
| | | bottom: 7.9vh; |
| | | left: 4vh; |
| | | text-align: left; |
| | | } |
| | | |
| | | .m4 { |
| | | bottom: 66px; |
| | | right: -30px; |
| | | bottom: 7vh; |
| | | right: 5.4vh; |
| | | text-align: right; |
| | | } |
| | | |
| | | @media (max-width: 1100px) { |
| | | .bi-topbar-content { |
| | | padding: 0 14px; |
| | | padding: 0 1.4vh; |
| | | } |
| | | .center-ring { |
| | | left: 45.2%; |
| | | width: 330px; |
| | | height: 245px; |
| | | top: 24px; |
| | | width: 33vh; |
| | | height: 24.5vh; |
| | | top: 2.4vh; |
| | | } |
| | | .center-ring-title { |
| | | top: 50%; |
| | | font-size: 28px; |
| | | font-size: 2.8vh; |
| | | transform: translate(-50%, -50%); |
| | | } |
| | | .center-metric { |
| | | height: 105px; |
| | | height: 10.5vh; |
| | | } |
| | | .m1 { |
| | | top: 52px; |
| | | left: 42px; |
| | | top: 5.2vh; |
| | | left: 4.2vh; |
| | | } |
| | | .m2 { |
| | | top: 54px; |
| | | right: 42px; |
| | | top: 5.4vh; |
| | | right: 4.2vh; |
| | | } |
| | | .m3 { |
| | | bottom: 62px; |
| | | left: 48px; |
| | | bottom: 6.2vh; |
| | | left: 4.8vh; |
| | | } |
| | | .m4 { |
| | | bottom: 68px; |
| | | right: 44px; |
| | | bottom: 6.8vh; |
| | | right: 4.4vh; |
| | | } |
| | | } |
| | | </style> |