【愚公系列】《循序渐进Vue.js 3.x前端开发实践》072-商业项目:电商后台管理系统实战(财务管理与数据统计功能模块开发)

举报
愚公搬代码 发表于 2025/03/30 17:36:09 2025/03/30
【摘要】 标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度博客之星TOP2,2023年度博客之星TOP2,2022年华为云十佳博主,2023年华为云十佳博主,2024年华为云十佳...
标题 详情
作者简介 愚公搬代码
头衔 华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。
近期荣誉 2022年度博客之星TOP2,2023年度博客之星TOP2,2022年华为云十佳博主,2023年华为云十佳博主,2024年华为云十佳博主等。
博客内容 .NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
欢迎 👍点赞、✍评论、⭐收藏

🚀前言

在电商行业中,财务管理与数据统计功能模块是确保企业健康运营的关键组成部分。它不仅涉及到销售收入、成本支出、利润分析等财务数据的实时监控,还关系到各类数据的统计与分析,为商家的决策提供有力支持。一个高效的财务管理与数据统计模块,能够帮助企业准确把握经营状况,优化资源配置,提升整体竞争力。

本文将深入探讨电商后台管理系统中财务管理与数据统计功能模块的开发实践。我们将从功能需求分析入手,逐步构建包括收入管理、支出管理、财务报表生成、数据可视化等功能。

🚀一、财务管理与数据统计功能模块开发

订单管理、商品管理和店长管理是电商后台管理系统中最为重要的功能模块。财务明细模块主要用来统计收入与支出,将数据使用列表进行展示即可。基础管理模块中提供了整体的数据统计功能,可以使用开源的图表模块来实现。

🔎1.交易明细与财务对账单

🦋1.1 Router.js

根据前面的工程代码,补充如下:

import TradeInfo from '../components/financial/TradeInfo.vue'
import TradeList from '../components/financial/TradeList.vue'
import DataCom from '../components/financial/DataCom.vue'
{
    path:'tradeinfo',
    component:TradeInfo,
    name:'TradeInfo'
},
{
    path:'tradelist',
    component:TradeList,
    name:'TradeList'
},
{
    path:'data',
    component:DataCom,
    name:'DataCom'
}

🦋1.2 Moke.js

根据前面的工程代码,补充如下:

getTradeInfo() {
    let array = [];
    for (let i = 0; i < mockjs.Random.integer(5,10); i ++) {
        array.push(mockjs.mock({
            'name':mockjs.Random.csentence(),
            'id':mockjs.Random.string(11),
            'user':mockjs.Random.cname(),
            'payType':mockjs.Random.boolean() ? '网络支付' : '线下支付',
            'time':mockjs.Random.datetime('yyyy-MM-dd A HH:mm:ss'),
        }))
    }
    return array;
},
getTradeList() {
    let array = [];
    for (let i = 0; i < mockjs.Random.integer(5,10); i ++) {
        array.push(mockjs.mock({
            'info':mockjs.Random.csentence(),
            'income':mockjs.Random.integer(0,5000) + '元',
            'expend':mockjs.Random.integer(0,5000) + '元',
            'time':mockjs.Random.datetime('yyyy-MM-dd A HH:mm:ss'),
        }))
    }
    return array;
},
getChartsData() {
    let array = [];
    for (let i = 0; i < 6; i ++) {
        array.push(mockjs.Random.integer(0,100))
    }
    return array;
},
getTradeData() {
    return mockjs.mock({
        'allTra':mockjs.Random.integer(10000,50000),
        'speTra':mockjs.Random.integer(0,5000),
        'norTra':mockjs.Random.integer(0,5000),
        'userCount':mockjs.Random.integer(0,1000),
        'managerCount':mockjs.Random.integer(0,100),
        'time':mockjs.Random.datetime('yyyy-MM-dd A HH:mm:ss'),
    })
}

🦋1.3 页面代码

☀️1.3.1 TradeList.vue

<script setup>
import Mock from '../../mock/Mock'
import { ElMessage } from 'element-plus'
import { ref, onMounted } from 'vue'
const tradeList = ref([])

onMounted(() => {
    tradeList.value = Mock.getTradeList()
})

function handleClick() {
    tradeList.value = Mock.getTradeList()
}

</script>
<template>
    <div class="content-container" direction="vertical">
        <div>
            <el-tabs type="card" @tab-click="handleClick">
                <el-tab-pane label="日汇总"></el-tab-pane>
                <el-tab-pane label="月汇总"></el-tab-pane>
            </el-tabs>
        </div>
        <div>
            <el-table
            :data="tradeList"
            tooltip-effect="dark"
            style="width: 100%">
                <el-table-column
                label="日期"
                width="300"
                prop="time">
                </el-table-column>
                <el-table-column
                label="收入"
                width="300"
                prop="income">
                </el-table-column>
                <el-table-column
                label="支出"
                width="300"
                prop="expend">
                </el-table-column>
                <el-table-column
                label="备注"
                width="300"
                prop="info">
                </el-table-column>
            </el-table>
        </div>
    </div>
</template>

在这里插入图片描述

☀️1.3.2 TradeInfo.vue

<script setup>
import Mock from '../../mock/Mock'
import Tools from '../../tools/Tools'
import { ElMessage } from 'element-plus'
import { ref, onMounted } from 'vue'

const queryParams = ref({
    proName:"",
    userName:"",
    phone:"",
    type:"",
    id:"",
    payTime:""
})
const tradeList = ref([])

onMounted(() => {
    tradeList.value = Mock.getTradeInfo();
})

function search() {
    ElMessage({
        type:'success',
        message:'请求参数:' + JSON.stringify(queryParams.value)
    });
    tradeList.value = Mock.getTradeInfo();
}
function clear() {
    queryParams.value = {
        proName:"",
        userName:"",
        phone:"",
        type:"",
        id:"",
        payTime:""
    };
    tradeList.value = Mock.getTradeInfo();
}
function exportData() {
    Tools.exportJson('交易明细.json', JSON.stringify(tradeList.value));
}
</script>

<template>
    <div class="content-container" direction="vertical">
        <div>
            <el-container class="content-row">
                <div class="input-tip">
                    商品名称:
                </div>
                <div class="input-field">
                    <el-input v-model="queryParams.proName"></el-input>
                </div>
                <div class="input-tip">
                    用户名称:
                </div>
                <div class="input-field">
                    <el-input v-model="queryParams.userName"></el-input>
                </div>
                <div class="input-tip">
                    手机号码:
                </div>
                <div class="input-field">
                    <el-input v-model="queryParams.phone"></el-input>
                </div>                
            </el-container>
            <el-container class="content-row">
                <div class="input-tip">
                    订单类型:
                </div>
                <div class="input-field">
                    <el-input v-model="queryParams.type"></el-input>
                </div>
                <div class="input-tip">
                    平台单号:
                </div>
                <div class="input-field">
                    <el-input v-model="queryParams.id"></el-input>
                </div>
                <div class="input-tip">
                    支付时间:
                </div>
                <div class="input-field">
                    <el-date-picker
                    type="daterange"
                    range-separator="至"
                    start-placeholder="开始日期"
                    end-placeholder="结束日期"
                    v-model="queryParams.payTime">
                    </el-date-picker>
                </div>             
            </el-container>
            <el-container class="content-row">
                <el-button type="primary" @click="search">搜索</el-button>
                <el-button type="primary" @click="clear">清空搜索条件</el-button>
                <el-button type="primary" @click="exportData">导出</el-button>
            </el-container>
        </div>
        <div>
            <el-table
            :data="tradeList"
            tooltip-effect="dark"
            style="width: 100%">
                <el-table-column
                label="名称"
                width="400"
                prop="name">
                </el-table-column>
                <el-table-column
                label="单号"
                width="150"
                prop="id">
                </el-table-column>
                <el-table-column
                label="用户"
                width="100"
                prop="user">
                </el-table-column>
                <el-table-column
                label="支付方式"
                width="100"
                prop="payType">
                </el-table-column>
                <el-table-column
                label="时间"
                width="300"
                prop="time">
                </el-table-column>
            </el-table>
        </div>
    </div>
</template>

在这里插入图片描述

🔎2.数据统计模块开发

数据统计模块是这个电商后台管理系统中的最后一个功能模块。该模块需要使用图表绘制工具,而ECharts模块可以方便地实现这一功能。以下是详细的步骤:

🦋2.1 安装ECharts

首先,在项目工程的根目录下执行以下命令来安装ECharts:

npm install echarts --save

🦋2.2 创建Charts.vue组件

安装完成后,在工程中的financial文件夹下新建一个名为Charts.vue的文件,编写如下代码:

<script setup>
import * as echarts from 'echarts';
import { onMounted, watch, getCurrentInstance } from 'vue'

const props = defineProps(['xData','data'])
// 用来获取当前组件实例
const instance = getCurrentInstance()
watch(props, ()=>{
    refresh()
}) 

onMounted(() => {
    refresh()
})

function refresh() {
    let chart = echarts.init(instance.proxy.$refs.chart);
    chart.clear()
    chart.setOption({
        xAxis:{
            data:props.xData
        },
        yAxis: {
            type: 'value'
        },
        series:{
            type:'line',
            data:props.data
        }
    });
}
</script>
<template>
    <div ref="chart"></div>
</template>

🦋2.3 创建DataCom.vue组件

再在financial文件夹下新建一个名为DataCom.vue的文件,进行常规的路由配置后,在其中编写如下代码:

<script setup>
import Charts from './Charts.vue'
import Mock from '../../mock/Mock'
import { ref, onMounted } from 'vue'

const xData = ["8月1日","8月2日","8月3日","8月4日","8月5日","8月6日"]
const chartsData = ref([])
const name = "销量"
const type = ref("总交易额")
const data = ref({})

onMounted(() => {
    chartsData.value = Mock.getChartsData()
    data.value = Mock.getTradeData()
})

function changeType() {
    chartsData.value = Mock.getChartsData()
}

</script>

<template>
    <div class="content-container" direction="vertical">
        <el-container class="content-row">
            <div class="info">总交易额:{{data.allTra}}</div>
            <div class="info">秒杀交易额:{{data.speTra}}</div>
            <div class="info">普通商品交易额:{{data.norTra}}</div>
            <div class="info">累计用户数:{{data.userCount}}</div>
            <div class="info">分销总用户数:{{data.managerCount}}</div>
        </el-container>
        <el-container class="content-row">
            <el-radio-group @change="changeType" v-model="type">
                <el-radio-button label="总交易额" value="总交易额"></el-radio-button>
                <el-radio-button label="商品交易额" value="商品交易额"></el-radio-button>
                <el-radio-button label="新用户销量" value="新用户销量"></el-radio-button>
                <el-radio-button label="方可转化率" value="方可转化率"></el-radio-button>
                <el-radio-button label="下单转化率" value="下单转化率"></el-radio-button>
                <el-radio-button label="付款转化率" value="付款转化率"></el-radio-button>
                <el-radio-button label="流水" value="流水"></el-radio-button>
            </el-radio-group>
        </el-container>
        <charts id="charts" :xData="xData" :data="chartsData"></charts>
        <div class="realTime">
            <div class="info">
                实时数据-更新时间:{{data.time}}
            </div>
            <el-container class="content-row">
                <div class="block">
                    <div class="title">付款金额:10000</div>
                    <div class="subTitle">当日:1900</div>
                    <div class="subTitle">昨日:1020</div>
                </div>
                <div class="block">
                    <div class="title">支付订单数:1000</div>
                    <div class="subTitle">当日:100</div>
                    <div class="subTitle">昨日:130</div>
                </div>
                <div class="block">
                    <div class="title">付款人数:503</div>
                    <div class="subTitle">当日:102</div>
                    <div class="subTitle">昨日:300</div>
                </div>
                <div class="block">
                    <div class="title">付款转换率:70</div>
                    <div class="subTitle">当日:50</div>
                    <div class="subTitle">昨日:70</div>
                </div>
            </el-container>
            <el-container class="content-row">
                <div class="block">
                    <div class="title">访客数:105310</div>
                    <div class="subTitle">当日:10310</div>
                    <div class="subTitle">昨日:20032</div>
                </div>
                <div class="block">
                    <div class="title">访问次数:1022440</div>
                    <div class="subTitle">当日:101230</div>
                    <div class="subTitle">昨日:1022120</div>
                </div>
                <div class="block">
                    <div class="title">新增用户:500</div>
                    <div class="subTitle">当日:300</div>
                    <div class="subTitle">昨日:200</div>
                </div>
                <div class="block">
                    <div class="title">累计用户:1542200</div>
                    <div class="subTitle">当日:154220</div>
                    <div class="subTitle">昨日:154200</div>
                </div>
            </el-container>
        </div>
    </div>
</template>

<style scoped>
  #charts {
    width: 1200px;
    height: 400px;
  }
  .info {
    margin: 15px 40px;
    font-size: 20px;
    color:#777777;
  }
  .realTime {
    border: #777777 solid 1px;
    width: 1200px;
    height: 300px;
  }
  .block {
      margin: auto;
      width:300px;
      padding: 10px 30px;
  }
  .title {
      font-size: 20px;
      color:#777777;
      margin-bottom: 5px;
  }
  .subTitle {
      font-size: 18px;
      color: #777777;
      margin-top: 3px;
  }
</style>

🦋2.4 运行效果

运行代码,效果如图所示。
在这里插入图片描述

至此,我们已经使用Vue完成了一个完整的电商后台管理系统。此项目虽然略微复杂,但是可以帮助读者积累一些宝贵的实践经验。如果你在动手实现的过程中遇到问题,也可以从如下地址找到完整的项目代码:

项目代码地址

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。