项目开发记录:销售管理系统+数据可视化分析 开发笔记

销售管理系统+数据可视化分析 开发笔记

项目描述:

一个基于SpringBoot+Vue搭建的简单的管理系统,对于管理的数据可以根据自身的情况进行动态的调整,可以是管理图书销售、零食销售等,在本项目中以 水果销售为例。

项目原型是B站UP主的一个简单的视频教程,并由个人对其做出调整和补充

项目地址:

https://gitee.com/geng_kun_yuan/SaleSystemAndDataAnalysis

一、前端技术

1、插件使用

安装

npm install axios
npm i element-ui -S
npm install echarts --save

引入:element-ui、axios、echarts —> main.js

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);

import axios from 'axios';
Vue.prototype.$axios = axios;

import echarts from 'echarts'
Vue.prototype.$echarts = echarts

2、编辑页面

知识点:

页面加载时发送请求获取返回的数据渲染页面

点击事件+数据的传递

表单校验,获取表单数据

<template>
    <el-form ref="form" :rules="rules" :model="fruit" label-width="80px" style="width: 600px">
        <el-form-item label="ID">
            <el-input v-model="fruit.id" readonly></el-input>
        </el-form-item>
        <el-form-item label="名称" prop="name">
            <el-input v-model="fruit.name"></el-input>
        </el-form-item>
        <el-form-item label="统计" prop="sale">
            <el-input v-model.number="fruit.sale"></el-input>
        </el-form-item>
        <el-form-item label="图片" prop="icon">
            <el-input v-model="fruit.icon"></el-input>
        </el-form-item>
        <el-form-item>
            <el-button type="primary" @click="onSubmit('form')">立即修改</el-button>
            <el-button>取消</el-button>
        </el-form-item>
    </el-form>
</template>

<script>
    export default {
        name: "Edit",
        data() {
            return {
                fruit: {
                    name: '',
                    sale: '',
                    icon: ''
                },
                rules:{
                    name:[
                        { required: true, message: '请输入水果名称', trigger: 'blur' }
                    ],
                    sale:[
                        { required: true, message: '请输入销量', trigger: 'blur' },
                        { type: 'number', message: '销量必须为数字值'}
                    ],
                    icon:[
                        { required: true, message: '请输入图片链接', trigger: 'blur' }
                    ]
                }
            }
        },
        created() {
            let id = this.$route.query.id
            let _this = this
            this.$axios.get('http://localhost:8081/fruit/find/'+id).then(function (response) {
                _this.fruit = response.data
            })
        },
        methods: {
            onSubmit(formName) {
                this.$refs[formName].validate((valid) => {
                    if (valid) {
                        let _this = this
                        this.$axios.put('http://localhost:8081/fruit/update',this.fruit).then(function (response) {
                            if(response.data){
                                _this.$alert(_this.fruit.name+'修改成功!', '修改数据', {
                                    confirmButtonText: '确定',
                                    callback: action => {
                                        //跳转到/table
                                        _this.$router.push('/table')
                                    }
                                });
                            }
                        })
                    }
                });
            }
        }
    }
</script>

<style scoped>

</style>

3、主页面

知识点:

点击删除按钮时,弹出提示框,并对于不同的选择做出不同的操作

            fruitDelete(object) {

                let _this = this
                this.$confirm('是否确定要删除' + object.name + '?', '删除数据', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    this.$axios.delete('http://localhost:8081/fruit/delete/' + object.id).then(function (response) {
                        if (response.data) {
                            _this.$alert(object.name + '删除成功!', '删除数据', {
                                confirmButtonText: '确定',
                                callback: action => {
                                    //跳转到/table
                                    location.reload()
                                }
                            });
                        }
                    })
                }).catch(() => {

                });
            }
        },

4、柱状图

知识点:

数据的获取以及对页面数据的渲染

<template>
  <div id="myChart" :style="{width: '800px', height: '600px'}"></div>
</template>
<script>
  export default {
    name: 'Bar',
    mounted(){
      let _this = this
      this.$axios.get('http://localhost:8081/fruit/barVO').then(function (response) {
        // 基于准备好的dom,初始化echarts实例
        let myChart = _this.$echarts.init(document.getElementById('myChart'))
        // 绘制图表
        myChart.setOption({
          title: {
            text: 'XX统计',
            left: 'center',
            top: 20,
            textStyle: {
              color: '#555555'
            }
          },
          tooltip: {},
          xAxis: {
            data: response.data.names
          },
          yAxis: {},
          series: [{
            name: '统计',
            type: 'bar',
            data: response.data.values
          }]
        });
      })

    }
  }
</script>

二、后端技术

1、跨域问题

package com.lut.configuration;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CrosConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    }

}

2、代码生成器

package com.lut;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

public class GenerateTest {
    public static void main(String[] args) {
        //创建generator对象
        AutoGenerator autoGenerator = new AutoGenerator();
        //数据源
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL);
        dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSourceConfig.setUsername("root");
        dataSourceConfig.setPassword("88888888");
        dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/test");
        autoGenerator.setDataSource(dataSourceConfig);
        //全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java");
        globalConfig.setAuthor("admin");
        globalConfig.setOpen(false);
        globalConfig.setServiceName("%sService");
        autoGenerator.setGlobalConfig(globalConfig);
        //包信息
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent("com.lut.fruit_java");
        packageConfig.setEntity("entity");
        packageConfig.setMapper("mapper");
        packageConfig.setService("service");
        packageConfig.setServiceImpl("service.impl");
        packageConfig.setController("controller");
        autoGenerator.setPackageInfo(packageConfig);
        //策略配置
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setInclude("fruit");
        strategyConfig.setNaming(NamingStrategy.underline_to_camel);
        strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
        strategyConfig.setEntityLombokModel(true);
        autoGenerator.setStrategy(strategyConfig);
        //运行
        autoGenerator.execute();
    }
}

3、配置文件

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 88888888
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:com/southwind/mapper/xml/*.xml
server:
  port: 8081

4、数据的封装

对于图表数据(柱状图 和 饼状图)要加载的数据类型进行封装

@Data
public class BarVO {
    private List<String> names;
    private List<DataVO> values;
}
@Data
public class DataVO {
    private Integer value;
    private Map<String,String> itemStyle;
}
@Data
public class PieVO {
    private Integer value;
    private Map<String,String> itemStyle;
    private String name;
}
    @GetMapping("/barVO")
    public BarVO barVO() {
        return this.fruitService.barVOList();
    }

    @GetMapping("/pieVO")
    public List<PieVO> pieVO() {
        return this.fruitService.pieVOList();
    }
/**
 * <p>
 *  服务实现类
 * </p>
 */
@Service
public class FruitServiceImpl extends ServiceImpl<FruitMapper, Fruit> implements FruitService {

    @Autowired
    private FruitMapper fruitMapper;

    @Override
    public BarVO barVOList() {
        BarVO barVO = new BarVO();
        List<String> names = new ArrayList<>();
        List<DataVO> values = new ArrayList<>();
        //先查出数据
        List<Fruit> fruits = this.fruitMapper.selectList(null);
        for (Fruit fruit : fruits) {
            names.add(fruit.getName());
            DataVO dataVO = new DataVO();
            dataVO.setValue(fruit.getSale());
            dataVO.setItemStyle(DataUtil.createItemStyle(fruit.getSale()));
            values.add(dataVO);
        }
        barVO.setNames(names);
        barVO.setValues(values);
        //转换VO
        return barVO;
    }

    @Override
    public List<PieVO> pieVOList() {
        List<PieVO> pieVOList = new ArrayList<>();
        List<Fruit> fruits = this.fruitMapper.selectList(null);
        for (Fruit fruit : fruits) {
            PieVO pieVO = new PieVO();
            pieVO.setValue(fruit.getSale());
            pieVO.setName(fruit.getName());
            pieVO.setItemStyle(DataUtil.createItemStyle(fruit.getSale()));
            pieVOList.add(pieVO);
        }
        return pieVOList;
    }
}

三、BUG处理

BUG1:axios is not defined

[Vue warn]: Error in created hook: “ReferenceError: axios is not defined”


正确安装

正确安装 axios

axios已经是安装好的状态

在main.js下

import VueAxios from 'vue-axios';
import axios from 'axios';

使用的npm 例子的代码如下:

created(){
    const  _this = this
    axios.get('http://localhost:8081/book/findall').then(function (resp) {
        _this.books = resp.data;
      })
  }
}

请求时浏览器出现以下错误

webpack-internal:///./node_modules/vue/dist/vue.esm.js:629 [Vue warn]: Error in created hook: "ReferenceError: axios is not defined"
found in
--->  at src/components/Book.vue
    at src/App.vue
     
     warn @ webpack-internal:///./node_modules/vue/dist/vue.esm.js:629

解决办法

在main.js下 改成

import VueAxios from 'vue-axios';
import axios from 'axios';
Vue.prototype.$axios = axios;

例子的代码改成

created(){
    const  _this = this
    this.$axios.get('http://localhost:8081/book/findall').then(function (resp) {
        _this.books = resp.data;
      })
  }
}

改好之后 运行 问题得到解决

BUG2:中文变成??

在于数据库交互时,写入数据库的中文会变成 ???

查看配置数据库配置文件

spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8

解决方法:在后面加上useUnicode=true&characterEncoding=UTF-8即可

spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值