fix: 客户分析页面样式调整

This commit is contained in:
lzhizhao 2025-10-01 22:12:12 +08:00
parent 5127607c14
commit 077750fffd
1 changed files with 245 additions and 138 deletions

View File

@ -21,26 +21,6 @@
</el-option>
</el-select>
</el-form-item>
<el-form-item label="统计类型">
<el-select
style="margin-right: 20px"
v-model="formInline.elementType"
placeholder="请选择统计类型"
>
<el-option
v-for="item in [
{ value: '1', label: '浏览数量' },
{ value: '2', label: '浏览人数' },
{ value: '3', label: '新客数量' },
{ value: '4', label: '支付订单人数' },
]"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="getList" type="primary">查询</el-button>
<el-button @click="batchExport" type="success">导出</el-button>
@ -49,104 +29,108 @@
</div>
<div class="stat-list">
<div class="stat-item">
<i style="font-size: 22px" class="el-icon-camera-solid"></i>
<div class="stat-icon-wrapper icon-1">
<i class="el-icon-view"></i>
</div>
<div class="stat-right">
<div class="stat-title">展现量 </div>
<div class="stat-title">展现量 ()</div>
<div class="stat-value">
<span style="font-size: 20px">{{
analysis.viewCount ? analysis.viewCount : "0"
}}</span>
<span class="value-main">{{ analysis.viewCount || "0" }}</span>
<span
v-if="analysis.viewCountRatio < '0%'"
style="font-size: 16px; margin: 0 5px; color: green"
></span
class="value-ratio"
v-if="analysis.viewCountRatio"
:class="getRatioClass(analysis.viewCountRatio)"
>
<span style="font-size: 16px; margin: 0 5px; color: red" v-else
></span
>
<span style="font-size: 16px">{{ analysis.viewCountRatio }}</span>
<i :class="getRatioIcon(analysis.viewCountRatio)"></i>
{{ analysis.viewCountRatio }}
</span>
</div>
</div>
</div>
<div class="stat-item">
<i style="font-size: 22px" class="el-icon-user-solid"></i>
<div class="stat-icon-wrapper icon-2">
<i class="el-icon-user"></i>
</div>
<div class="stat-right">
<div class="stat-title">浏览人数 </div>
<div class="stat-title">浏览人数 ()</div>
<div class="stat-value">
<span style="font-size: 20px">{{ analysis.peopleCount }}</span>
<span class="value-main">{{ analysis.peopleCount || "0" }}</span>
<span
v-if="analysis.peopleCountRatio < '0%'"
style="font-size: 16px; margin: 0 5px; color: green"
></span
class="value-ratio"
v-if="analysis.peopleCountRatio"
:class="getRatioClass(analysis.peopleCountRatio)"
>
<span style="font-size: 16px; margin: 0 5px; color: red" v-else
></span
>
<span style="font-size: 16px">{{ analysis.peopleCountRatio }}</span>
<i :class="getRatioIcon(analysis.peopleCountRatio)"></i>
{{ analysis.peopleCountRatio }}
</span>
</div>
</div>
</div>
<div class="stat-item">
<i style="font-size: 22px" class="el-icon-user-solid"></i>
<div class="stat-icon-wrapper icon-3">
<i class="el-icon-star-off"></i>
</div>
<div class="stat-right">
<div class="stat-title">新客数量 </div>
<div class="stat-title">新客数量 ()</div>
<div class="stat-value">
<span style="font-size: 20px">{{
analysis.newPeopleCount ? analysis.newPeopleCount : "0"
<span class="value-main">{{
analysis.newPeopleCount || "0"
}}</span>
<span
v-if="analysis.newPeopleCountRatio < '0%'"
style="font-size: 16px; margin: 0 5px; color: green"
></span
class="value-ratio"
v-if="analysis.newPeopleCountRatio"
:class="getRatioClass(analysis.newPeopleCountRatio)"
>
<span style="font-size: 16px; margin: 0 5px; color: red" v-else
></span
>
<span style="font-size: 16px">{{
analysis.newPeopleCountRatio
<i :class="getRatioIcon(analysis.newPeopleCountRatio)"></i>
{{ analysis.newPeopleCountRatio }}
</span>
</div>
</div>
</div>
<div class="stat-item">
<div class="stat-icon-wrapper icon-4">
<i class="el-icon-s-custom"></i>
</div>
<div class="stat-right">
<div class="stat-title">支付订单人数 ()</div>
<div class="stat-value">
<span class="value-main">{{ analysis.payCount || "0" }}</span>
</div>
</div>
</div>
<div class="stat-item">
<div class="stat-icon-wrapper icon-5">
<i class="el-icon-s-order"></i>
</div>
<div class="stat-right">
<div class="stat-title">支付订单转化率 (%)</div>
<div class="stat-value">
<span class="value-main">{{
analysis.payConversion || "0"
}}</span>
</div>
</div>
</div>
<div class="stat-item">
<i style="font-size: 22px" class="el-icon-user-solid"></i>
<div class="stat-right">
<div class="stat-title">支付订单人数 </div>
<div style="font-size: 20px" class="stat-value">
{{ analysis.payCount ? analysis.payCount : "0" }}
</div>
<div class="stat-icon-wrapper icon-6">
<i class="el-icon-refresh"></i>
</div>
</div>
<div class="stat-item">
<i style="font-size: 22px" class="el-icon-s-order"></i>
<div class="stat-right">
<div class="stat-title">支付订单转化率 %</div>
<div style="font-size: 20px" class="stat-value">
{{ analysis.payConversion ? analysis.payConversion : "0" }}
</div>
</div>
</div>
<div class="stat-item">
<i style="font-size: 22px" class="el-icon-s-order"></i>
<div class="stat-right">
<div class="stat-title">客户复购率 %</div>
<div style="font-size: 20px" class="stat-value">
{{ analysis.repurchaseRate ? analysis.repurchaseRate : "0" }}
<div class="stat-title">客户复购率 (%)</div>
<div class="stat-value">
<span class="value-main">{{
analysis.repurchaseRate || "0"
}}</span>
</div>
</div>
</div>
</div>
<el-row class="echarts-line">
<div
id="echarts-LineChart"
style="
width: 100%;
height: calc(100vh - 500px);
margin-top: 20px;
border: 1px solid #ccc;
"
/>
</el-row>
<div class="echarts-grid">
<div class="echarts-item" id="echarts-LineChart-1"></div>
<div class="echarts-item" id="echarts-LineChart-2"></div>
<div class="echarts-item" id="echarts-LineChart-3"></div>
<div class="echarts-item" id="echarts-LineChart-4"></div>
</div>
</div>
</template>
@ -162,94 +146,136 @@ export default {
value: "",
formInline: {
dateType: "1",
elementType: "1",
},
analysis: {},
trend: [],
charts: [], // ECharts
};
},
mounted() {
this.getList();
},
beforeDestroy() {
// ECharts
this.charts.forEach((chart) => {
chart.dispose();
});
},
methods: {
getList() {
console.log("1213");
this.$api.dataCenter
.customerAnalysis({ dateType: this.formInline.dateType })
.then((res) => {
this.analysis = res.data.data;
});
this.$api.dataCenter.customerTrend(this.formInline).then((res) => {
this.trend = res.data.data;
this.init(res.data.data);
const elementTypes = ["1", "2", "3", "4"];
const chartPromises = elementTypes.map((type) =>
this.$api.dataCenter.customerTrend({ ...this.formInline, elementType: type })
);
Promise.all(chartPromises).then((responses) => {
const chartData = responses.map((res) => res.data.data);
this.init(chartData);
});
},
init(data) {
init(allData) {
//
this.charts.forEach((chart) => {
chart.dispose();
});
this.charts = [];
const titles = ["浏览数量", "浏览人数", "新客数量", "支付订单人数"];
const colors = ["#5470C6", "#91CC75", "#FAC858", "#EE6666"];
this.$nextTick(() => {
// 线
const myChat = echarts.init(
document.getElementById("echarts-LineChart")
);
myChat.setOption(this.LineChart(data));
window.addEventListener("resize", () => {
myChat.resize();
allData.forEach((data, index) => {
const chartDom = document.getElementById(
`echarts-LineChart-${index + 1}`
);
if (chartDom) {
const myChart = echarts.init(chartDom);
const options = this.LineChart(
data,
titles[index],
colors[index]
);
myChart.setOption(options);
this.charts.push(myChart);
}
});
window.addEventListener("resize", this.resizeCharts);
});
},
LineChart(data) {
resizeCharts() {
this.charts.forEach((chart) => {
chart.resize();
});
},
LineChart(data, title, color) {
return {
title: {
text: "数据趋势分析",
text: title + "趋势",
left: "left",
},
tooltip: {
trigger: "axis",
},
legend: {
data: [this.elementTypeName(this.formInline.elementType)],
data: [title],
top: "top",
right: "10",
},
grid: {
left: "3%",
right: "4%",
bottom: "3%",
top: "20%",
containLabel: true,
},
toolbox: {
feature: {
saveAsImage: {},
},
feature: {},
},
xAxis: {
type: "category",
boundaryGap: false,
data: data.map((item) => {
return item.countDate;
}),
data: data.map((item) => item.countDate),
},
yAxis: {
type: "value",
},
series: [
{
name: this.elementTypeName(this.formInline.elementType),
name: title,
type: "line",
stack: "Total",
data: data.map((item) => {
return item.value;
}),
smooth: true,
stack: "Total", //
data: data.map((item) => item.value),
itemStyle: {
color: color,
},
lineStyle: {
color: color,
},
areaStyle: {
color: color,
opacity: 0.3,
},
},
],
};
},
elementTypeName(row) {
if (row == "1") {
return "浏览数量";
} else if (row == "2") {
return "浏览人数";
} else if (row == "3") {
return "新客数量";
} else if (row == "4") {
return "支付订单人数";
}
getRatioClass(ratio) {
if (!ratio || typeof ratio !== "string") return "";
return ratio.startsWith("-") ? "is-down" : "is-up";
},
getRatioIcon(ratio) {
if (!ratio || typeof ratio !== "string") return "";
return ratio.startsWith("-")
? "el-icon-bottom-right"
: "el-icon-top-right";
},
async batchExport() {
let trendData = this.trend.map((item) => {
@ -297,32 +323,113 @@ export default {
<style lang="scss" scoped>
.stat-list {
display: flex;
align-items: center;
/* justify-content: space-between; */
flex-wrap: wrap;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
margin-top: 20px;
padding: 10px;
border: 1px solid #ccc;
}
.stat-item {
width: 25%;
margin: 30px 30px;
display: flex;
align-items: center;
padding: 20px;
background-color: #f8f9fa;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
&:hover {
transform: translateY(-5px);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1);
}
}
.stat-icon {
background: rgb(99 152 252);
.stat-icon-wrapper {
display: flex;
align-items: center;
justify-content: center;
width: 60px;
height: 60px;
border-radius: 3px;
border-radius: 50%;
color: #fff;
font-size: 28px;
flex-shrink: 0;
&.icon-1 {
background: linear-gradient(45deg, #4facfe, #00f2fe);
}
&.icon-2 {
background: linear-gradient(45deg, #43e97b, #38f9d7);
}
&.icon-3 {
background: linear-gradient(45deg, #fa709a, #fee140);
}
&.icon-4 {
background: linear-gradient(45deg, #84fab0, #8fd3f4);
}
&.icon-5 {
background: linear-gradient(45deg, #a18cd1, #fbc2eb);
}
&.icon-6 {
background: linear-gradient(45deg, #ff9a9e, #fecfef);
}
}
.stat-right {
margin-left: 12px;
font-size: 18px;
margin-left: 20px;
overflow: hidden;
}
.stat-title {
color: #969696;
margin-bottom: 10px;
color: #6c757d;
font-size: 14px;
margin-bottom: 8px;
white-space: nowrap;
}
.stat-value {
display: flex;
align-items: baseline;
font-weight: bold;
.value-main {
font-size: 26px;
color: #343a40;
margin-right: 8px;
}
.value-ratio {
font-size: 14px;
display: flex;
align-items: center;
&.is-up {
color: #dc3545;
}
&.is-down {
color: #28a745;
}
i {
margin-right: 4px;
font-weight: bold;
}
}
}
.echarts-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
margin-top: 30px;
}
.echarts-item {
height: 400px;
padding: 20px;
border: 1px solid #e9ecef;
border-radius: 8px;
background-color: #fff;
}
</style>