前因:需要展示年/月收益,月收益为0时后端不返回,仅返回有数据的日期
解决方案:获取月份的天数,进行填补数据,渲染时匹配渲染
<template>
<div class="calendar-box">
<div class="cumulative-income">
<div class="incom-item">
<span class="label"
>{{
mode == "year"
? `${dafaultTime}年`
: `${moment(dafaultTime).format("M")}月`
}}收益</span
>
<span :class="colorFun(sumInfo.sumProfit)">
{{ sumInfo.sumProfit > 0 ? "+" : "" }}{{ sumInfo.sumProfit }}
</span>
</div>
<div class="incom-item">
<span class="label">收益率</span>
<span :class="colorFun(sumInfo.sumProfitPercentage)">
{{ sumInfo.sumProfitPercentage > 0 ? "+" : ""
}}{{ sumInfo.sumProfitPercentage }}%
</span>
</div>
</div>
<a-calendar
:class="mode === 'year' ? 'calendar-year' : ''"
:disabledDate="disabledDate"
@panelChange="handleDateSelect"
:mode="mode"
>
<!--自定义- 月-天 -->
<template slot="dateFullCellRender" slot-scope="value" class="events">
<div
class="month-box"
:class="bgFun(item.profitToday)"
v-for="(item, index) in data"
:key="index"
>
<div
class="data-item"
v-if="
item.tradeDate ==
`${value.year()}-${value.month() + 1 < 10 ? '0' : ''}${
value.month() + 1
}-${value.date() < 10 ? '0' : ''}${value.date()}`
"
>
<div class="data-title">{{ value.date() }}</div>
<div :class="colorFun(item.profitToday)">
<div>
{{ item.profitToday > 0 ? "+" : "" }}{{ item.profitToday }}
</div>
<div>
{{ item.percentageProfitToday > 0 ? "+" : ""
}}{{ item.percentageProfitToday }}%
</div>
</div>
</div>
</div>
</template>
<!-- 自定义年-月 -->
<template slot="monthFullCellRender" slot-scope="value">
<div
:class="bgFun(item.profitToday)"
v-for="item in data"
:key="item.tradeDate"
>
<div
v-if="moment(item.tradeDate).format('M') == `${value.month() + 1}`"
class="data-item"
>
<div class="data-title">{{ value.month() + 1 }}月</div>
<div :class="colorFun(item.profitToday)">
<div>
{{ item.profitToday > 0 ? "+" : "" }}{{ item.profitToday }}
</div>
<div>
{{ item.percentageProfitToday > 0 ? "+" : ""
}}{{ item.percentageProfitToday }}%
</div>
</div>
</div>
</div>
</template>
</a-calendar>
<div class="echarts-box" v-if="isShowEcharts">
<histogram-echarts :data="data" :mode="mode"></histogram-echarts>
</div>
</div>
</template>
<script>
import moment from "moment";
// 接口文件
import customerProfitLossApi from "@/services/customerProfitLoss";
const { getEarningsCalendar } = customerProfitLossApi;
// 柱状图-不用管
import histogramEcharts from "./histogramEcharts.vue";
export default {
components: { histogramEcharts },
props: {
marke: {
type: String,
required: false,
},
checkInfo: {
type: Object,
required: false,
},
},
data() {
return {
moment,
dafaultTime: moment().format("YYYY-MM"),
mode: "month",
data: [],
sumInfo: {
sumProfit: 0,
sumProfitPercentage: 0,
},
isShowEcharts: false,
};
},
created() {
this.getEarningsCalendar();
},
methods: {
colorFun(value) {
let num = Number(value);
if (num > 0) return "rise";
if (num < 0) return "fall";
if (num === 0) return "";
},
bgFun(value) {
let num = Number(value);
if (num > 0) return "rise-bg";
if (num < 0) return "fall-bg";
if (num === 0) return "com-bg";
},
// 补数据
suppData(date) {
let indexNum = 0;
const days = moment(date, "YYYY-MM").daysInMonth();
const valuableArr = [];
if (this.mode === "year") {
indexNum = 12;
} else {
indexNum = days;
}
for (let index = 0; index < indexNum; index += 1) {
valuableArr.push(`${date}-${index + 1}`);
}
// 返回的数据的-日期
const dataArr = [];
const noDate = [];
this.data.forEach((item) => {
dataArr.push(item.tradeDate);
});
valuableArr.forEach((item) => {
if (this.mode === "year") {
item = moment(item).format("YYYY-MM");
} else {
item = moment(item).format("YYYY-MM-DD");
}
// 柱状图是否显示
if (dataArr && dataArr.length > 0) {
this.isShowEcharts = true;
} else {
this.isShowEcharts = false;
}
if (dataArr.indexOf(item) === -1) {
// 补到存数据的数组
this.data.push({
tradeDate: item,
percentageProfitToday: '0.00',
profitToday: '0.00',
});
noDate.push(item);
}
});
this.data.sort(this.dataFilter("tradeDate", true));
},
dataFilter(property, type) {
return function (a, b) {
let value1 = a[property];
let value2 = b[property];
if (type) {
// 升序
return Date.parse(value1) - Date.parse(value2);
} else {
// 降序
return Date.parse(value2) - Date.parse(value1);
}
};
},
disabledDate(current) {
return (
(current && current < moment(this.dafaultTime).startOf("month")) ||
current > moment(this.dafaultTime).endOf("month")
);
},
handleDateSelect(date, mode) {
this.mode = mode;
if (mode === "month") {
this.getEarningsCalendar(moment(date).format("YYYY-MM"));
} else {
this.getEarningsCalendar(moment(date).format("YYYY"));
}
},
getEarningsCalendar(date) {
this.dafaultTime = date || this.dafaultTime;
this.data = [];
let params = {
exchangeType: this.marke,
fundAccount: this.checkInfo.fundAccount,
tradeDate: this.dafaultTime, // 日期(举例,月份为2022-06,年份为2022)
type: this.mode === "year" ? 1 : 0, // 查询类型(0:月,1:年)
};
// 后端接口
getEarningsCalendar(params).then((res) => {
if (res.data.data) {
this.sumInfo = {
sumProfit: res.data.data.sumProfit,
sumProfitPercentage: res.data.data.sumProfitPercentage,
};
this.data = res.data.data.vos || [];
this.suppData(this.dafaultTime);
}
});
},
},
};
</script>
<style scoped lang="less">
.calendar-box {
background-color: #fff;
.month-box {
text-align: center;
margin: 2px 2px;
font-size: 11px;
}
.events {
list-style: none;
margin: 0;
padding: 0;
}
.events .ant-badge-status {
overflow: hidden;
white-space: nowrap;
width: 100%;
text-overflow: ellipsis;
font-size: 12px;
}
.notes-month {
text-align: center;
font-size: 28px;
}
.notes-month section {
font-size: 28px;
}
.data-item {
padding: 4px;
.data-title {
font-size: 14px;
font-weight: bold;
}
}
.cumulative-income {
background-color: #fff;
display: flex;
line-height: 30px;
padding: 10px 20px;
font-size: 15px;
border-bottom: 1px solid #f0f0f0;
margin-bottom: 10px;
.incom-item {
flex: 1;
font-weight: 600;
.label {
margin-right: 15px;
}
}
}
.echarts-box {
padding: 0 20px;
}
}
::v-deep .ant-fullcalendar-fullscreen {
// width: 680px;
margin: auto;
background: #fff;
}
::v-deep .ant-fullcalendar-date {
border-top: 0;
text-align: center;
}
::v-deep .ant-fullcalendar-value {
text-align: center;
color: #000;
font-weight: 600;
}
::v-deep .ant-fullcalendar-column-header-inner {
text-align: center;
font-weight: 600;
}
::v-deep .ant-fullcalendar-content {
height: 46px;
}
::v-deep .ant-fullcalendar-month {
height: auto;
}
.calendar-year {
// width: 600px;
// margin: 0 auto;
}
::v-deep .ant-fullcalendar-month-panel-cell {
text-align: center;
padding: 4px;
}
.rise {
color: #f44345;
}
.fall {
color: #16ba71;
}
.rise-bg {
background-color: rgba(244, 67, 69, 0.1);
}
.fall-bg {
background-color: rgba(22, 186, 113, 0.1);
}
.com-bg {
background-color: rgba(246, 246, 249, 0.4);
}
</style>