feat(largeScreen): 大屏展示功能开发
- 新增 RevenueContractCard 组件,用于展示收入、支出等合同数据 - 实现 bottomboxconpoent 组件的通用化,支持自定义标题、数值等 - 在 centerPage 中集成 RevenueContractCard 组件,展示大屏数据 - 更新 rightPage 组件,添加实际数据请求和展示 - 优化 optionList 中的图表配置,提高图表可读性
This commit is contained in:
22
src/api/largeScreen/index.js
Normal file
22
src/api/largeScreen/index.js
Normal file
@ -0,0 +1,22 @@
|
||||
import request from '@/utils/request';
|
||||
// 合同金额
|
||||
export const totalAmount = () => {
|
||||
return request({
|
||||
url: '/money/big/screen/totalAmount',
|
||||
method: 'get',
|
||||
});
|
||||
};
|
||||
// 资金KPI
|
||||
export const monthMoney = () => {
|
||||
return request({
|
||||
url: '/money/big/screen/monthMoney',
|
||||
method: 'get',
|
||||
});
|
||||
};
|
||||
// 现金流
|
||||
export const monthCash = () => {
|
||||
return request({
|
||||
url: '/money/big/screen/monthCash',
|
||||
method: 'get',
|
||||
});
|
||||
};
|
@ -5,25 +5,18 @@
|
||||
|
||||
<!-- 数值区域 -->
|
||||
<div class="stat-card__value-container">
|
||||
<span class="stat-card__value">{{ formattedValue }}</span>
|
||||
<span class="stat-card__value">{{ props.value }}</span>
|
||||
<span class="stat-card__unit">{{ unit }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 底部信息区域 -->
|
||||
<div class="stat-card__footer">
|
||||
<div class="stat-card__footer" v-if="showIcon">
|
||||
<div class="stat-card__trend">
|
||||
<img
|
||||
class="stat-card__trend-icon"
|
||||
:src="'/src/assets/large/' + trendIcon+'.png'"
|
||||
:alt="trendDirection === 'up' ? '上升' : '下降'"
|
||||
>
|
||||
<img class="stat-card__trend-icon" :src="'/src/assets/large/' + trendIcon + '.png'"
|
||||
:alt="trendDirection === 'up' ? '上升' : '下降'">
|
||||
<span class="stat-card__trend-text">{{ trendText }}</span>
|
||||
</div>
|
||||
<img
|
||||
class="stat-card__badge"
|
||||
:src="'/src/assets/large/'+badgeIcon+'.png'"
|
||||
alt="徽章图标"
|
||||
>
|
||||
<img class="stat-card__badge" :src="'/src/assets/large/' + badgeIcon + '.png'" alt="徽章图标">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -78,6 +71,10 @@ const props = defineProps({
|
||||
customStyles: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
showIcon: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
@ -103,10 +100,12 @@ const trendText = computed(() => {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
padding: 35px 10px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid rgba(29, 214, 255, 0.1);
|
||||
border-radius: 4px; // 增加轻微圆角,提升视觉效果
|
||||
text-align: center;
|
||||
|
||||
|
||||
&__title {
|
||||
font-size: 14px;
|
||||
@ -115,8 +114,10 @@ const trendText = computed(() => {
|
||||
}
|
||||
|
||||
&__value-container {
|
||||
display: flex;
|
||||
// display: flex;
|
||||
align-items: baseline;
|
||||
// align-items: center;
|
||||
// flex-direction: column;
|
||||
}
|
||||
|
||||
&__value {
|
||||
|
@ -1,45 +1,65 @@
|
||||
<template>
|
||||
<div class="bottom_box">
|
||||
<div class="bottom_box_title">收入合同</div>
|
||||
<div>
|
||||
<span class="bottom_box_number">205,805.17</span>
|
||||
<span>万元</span>
|
||||
</div>
|
||||
<div class="bottom_box_bottom">
|
||||
<el-progress :percentage="50" color="rgba(255, 147, 42, 1)" />
|
||||
</div>
|
||||
<div class="bottom_box_text">
|
||||
成本率
|
||||
</div>
|
||||
<div class="bottom_box">
|
||||
<div class="bottom_box_title">{{ title }}</div>
|
||||
<div>
|
||||
<span class="bottom_box_number">{{ value }}</span>
|
||||
<span>{{ unit }}</span>
|
||||
</div>
|
||||
<div class="bottom_box_bottom">
|
||||
<el-progress :percentage="50" color="rgba(255, 147, 42, 1)" />
|
||||
</div>
|
||||
<div class="bottom_box_text">
|
||||
{{ period }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '收入合同'
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
default: 205805.17
|
||||
},
|
||||
unit: {
|
||||
type: String,
|
||||
default: '万元'
|
||||
},
|
||||
growthRate: {
|
||||
type: Number,
|
||||
default: 3.2
|
||||
},
|
||||
period: {
|
||||
type: String,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.bottom_box {
|
||||
width: 225px;
|
||||
height: 147px;
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
width: 225px;
|
||||
height: 147px;
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
|
||||
.bottom_box_title,
|
||||
.bottom_box_text {
|
||||
color: rgba(143, 171, 191, 1);
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.bottom_box_number {
|
||||
font-size: 24px;
|
||||
color: #fff;
|
||||
line-height: 30px;
|
||||
}
|
||||
.bottom_box_title,
|
||||
.bottom_box_text {
|
||||
color: rgba(143, 171, 191, 1);
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.bottom_box_number {
|
||||
font-size: 24px;
|
||||
color: #fff;
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -16,14 +16,19 @@
|
||||
<img class="top_img" src="@/assets/large/top1.png" alt=""></img>
|
||||
</div>
|
||||
</div> -->
|
||||
<RevenueContractCard title="收入合同" :value="156234.89" :growthRate="-1.5" trendDirection="up" trendIcon="up"
|
||||
<!-- <RevenueContractCard title="收入合同" :value="156234.89" :growthRate="-1.5" trendDirection="up" trendIcon="up"
|
||||
badgeIcon="top1" period="较上月" />
|
||||
<RevenueContractCard title="支出合同" :value="156234.89" :growthRate="-1.5" trendDirection="up" trendIcon="up"
|
||||
badgeIcon="top2" period="较上月" />
|
||||
<RevenueContractCard title="合同利润" :value="156234.89" :growthRate="-1.5" trendDirection="up" trendIcon="down"
|
||||
badgeIcon="top3" period="较上月" />
|
||||
<RevenueContractCard title="工程变更" :value="156234.89" :growthRate="-1.5" trendDirection="up" trendIcon="up"
|
||||
badgeIcon="top4" period="较上月" />
|
||||
badgeIcon="top4" period="较上月" /> -->
|
||||
<RevenueContractCard title="收入合同" :value="bigDataObj.incomeTotalAmount" />
|
||||
<RevenueContractCard title="支出合同" :value="bigDataObj.expensesTotalAmount" />
|
||||
|
||||
<RevenueContractCard title="合同利润" :value="bigDataObj.profitAmount" />
|
||||
<RevenueContractCard title="工程变更" :value="bigDataObj.changeAmount" unit="%" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="centerPage_map">
|
||||
@ -44,7 +49,7 @@
|
||||
成本率
|
||||
</div>
|
||||
</div> -->
|
||||
<bottomboxconpoent> </bottomboxconpoent>
|
||||
<bottomboxconpoent title="材料成本" unit="万元" :value="1"> </bottomboxconpoent>
|
||||
<bottomboxconpoent> </bottomboxconpoent>
|
||||
<bottomboxconpoent> </bottomboxconpoent>
|
||||
<bottomboxconpoent> </bottomboxconpoent>
|
||||
@ -59,7 +64,16 @@ import * as echarts from 'echarts';
|
||||
import china from '@/assets/china.json';
|
||||
import RevenueContractCard from './RevenueContractCard.vue';
|
||||
import bottomboxconpoent from './bottomboxconpoent.vue';
|
||||
const data = ref<any>({});
|
||||
import { totalAmount } from "@/api/largeScreen/index.js"
|
||||
const bigDataObj = ref<any>({});
|
||||
|
||||
const getTotalAmount = async () => {
|
||||
const { data: { incomeTotalAmount, expensesTotalAmount, profitAmount, changeAmount } } = await totalAmount()
|
||||
bigDataObj.value.incomeTotalAmount = incomeTotalAmount || 0;
|
||||
bigDataObj.value.expensesTotalAmount = expensesTotalAmount || 0;
|
||||
bigDataObj.value.profitAmount = profitAmount || 0;
|
||||
bigDataObj.value.changeAmount = changeAmount || 0;
|
||||
}
|
||||
|
||||
// 地图容器引用
|
||||
const mapRef = ref<HTMLDivElement | null>(null);
|
||||
@ -181,6 +195,7 @@ const initEcharts = () => {
|
||||
|
||||
// 组件挂载时初始化
|
||||
onMounted(() => {
|
||||
getTotalAmount()
|
||||
// 确保DOM渲染完成
|
||||
nextTick(() => {
|
||||
initEcharts();
|
||||
|
@ -862,7 +862,7 @@ export const getBarOptions = (data: any) => {
|
||||
// 收支合同分析
|
||||
export const getBarOptions2 = (data: any) => {
|
||||
const option = {
|
||||
color:['#FF932A', '#678FE6', '#1DD6FF', '#00E396'],
|
||||
color: ['#FF932A', '#678FE6', '#1DD6FF', '#00E396'],
|
||||
title: {
|
||||
text: '数量(个)',
|
||||
subtext: '16',
|
||||
@ -872,7 +872,7 @@ export const getBarOptions2 = (data: any) => {
|
||||
color: '#9DADB7',
|
||||
fontSize: 16
|
||||
},
|
||||
subtextStyle:{
|
||||
subtextStyle: {
|
||||
color: '#707070',
|
||||
fontSize: 32,
|
||||
fontWeight: 'bold'
|
||||
@ -907,7 +907,7 @@ export const getBarOptions2 = (data: any) => {
|
||||
show: false
|
||||
},
|
||||
data: [
|
||||
{ value: 3, name: '100万一下' },
|
||||
{ value: 3, name: '100万以下' },
|
||||
{ value: 4, name: '100-500万' },
|
||||
{ value: 5, name: '500-1000万' },
|
||||
{ value: 4, name: '1000万以上' },
|
||||
|
@ -45,38 +45,48 @@ import TitleComponent from './TitleComponent.vue';
|
||||
import EchartBox from '@/components/EchartBox/index.vue';
|
||||
import { getLineOption, getBarOptions } from './optionList';
|
||||
import ProgressComponent from './ProgressComponent.vue';
|
||||
import { monthMoney, monthCash } from '@/api/largeScreen';
|
||||
|
||||
const lineOption = ref();
|
||||
const barOption = ref();
|
||||
|
||||
const getCapitalData = (data?: any) => {
|
||||
const getCapitalData = async () => {
|
||||
const { data } = await monthMoney()
|
||||
const month = data.map((item: any) => item.month);
|
||||
const income = data.map((item: any) => item.incomeAmount);
|
||||
const expenses = data.map((item: any) => item.expensesAmount);
|
||||
const profit = data.map((item: any) => item.profitAmount);
|
||||
// const xData = data.map((item) => item.time);
|
||||
// const yData = data.map((item) => item.content);
|
||||
const lineData = {
|
||||
xLabel: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
||||
xLabel: month,
|
||||
line1: [
|
||||
[100, 200, 150, 300, 250, 350, 400, 350, 450, 500, 400, 550],
|
||||
[220, 250, 230, 280, 270, 300, 350, 320, 380, 400, 450, 500],
|
||||
[300, 350, 320, 380, 400, 450, 500, 480, 520, 550, 600, 650]
|
||||
income,
|
||||
expenses,
|
||||
profit
|
||||
]
|
||||
|
||||
// line2: ['20', '50', '12', '65', '30', '60']
|
||||
};
|
||||
lineOption.value = getLineOption(lineData);
|
||||
};
|
||||
const getTurnoverList = (data?: any) => {
|
||||
const getTurnoverList = async () => {
|
||||
// const xData = data.map((item) => item.time);
|
||||
// const yData = data.map((item) => {
|
||||
// // 先将content转换为数字,再调用toFixed
|
||||
// const num = Number(item.content);
|
||||
// return isNaN(num) ? 0 : Number(num.toFixed(2));
|
||||
// });
|
||||
|
||||
const { data } = await monthCash()
|
||||
const month = data.map((item: any) => item.month);
|
||||
const income = data.map((item: any) => item.incomeAmount);
|
||||
const expenses = data.map((item: any) => item.expensesAmount);
|
||||
// const profit = data.map((item: any) => item.profitAmount);
|
||||
const barData = {
|
||||
name: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
||||
name: month,
|
||||
value: [
|
||||
[2, 5, 15, 30, 25, 35, 40, 35, 45, 50, 40, 55],
|
||||
[4, 3, 6, 11, 15, 22, 30, 14, 48, 22, 25, 60]
|
||||
income,
|
||||
expenses
|
||||
]
|
||||
};
|
||||
barOption.value = getBarOptions(barData);
|
||||
|
Reference in New Issue
Block a user