Vue保姆级项目教程:十万字零基础开发信贷管理系统!

本教程详细讲解了如何使用Vue.js构建一个信贷管理系统,包括项目搭建、登录页面、首页、贷款申请、审批、合同管理和权限管理等功能。内容涵盖vue-router、elementui、axios的使用,以及接口联调和数据管理。教程覆盖了前端开发的多个关键环节,适合初学者学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目简介与搭建过程

项目简介

需求背景

信贷管理系统是一种用于银行、金融机构或其他借贷组织用于管理信贷流程的软件系统。它可以帮助机构管理贷款申请、贷款审批、合同管理等相关流程,提高信贷业务的效率和准确性。

需求描述

本需求文档旨在定义信贷管理系统的功能和特性,以满足机构对于信贷业务管理的需求。
信贷管理系统项目基于vue2实现,鉴于vue2的语法已经停止维护,后期会考虑使用vue3重写本项目

搭建过程

新建项目命令

vue create credit-management-system

项目配置语言选择

项目配置.png

项目启动

npm run serve

登录页面初始化及其vue-router路由编写

配置路由

  1. 先把app.vue的默认代码删除,留下一个router-view路由出口
    App.vue
<template>
  <div id="app">
    <router-view/>
  </div>
</template>

  1. 打开router文件夹下的index.js,删除掉默认的路由配置
Vue.use(VueRouter)

const routes = [

]

const router = new VueRouter({
  routes
})

export default router

  1. 在main.js里引入公共样式文件,导入和使用elementui组件

    引入elementui组件
cnpm i element-ui -S

导入使用

import App from './App.vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(ElementUI)
  1. 先在router文件夹下index.js添加一个登录页面的路由和重定向
    组件是使用的懒加载,可以减少页面加载时间
const routes = [
    {
    path:'/',
    redirect:'/login'
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('../views/Login.vue')
  },
]

LoginView.vue写css之后报错不能解析sass-loader
在命令行执行如下命令

npm install sass-loader -D
cnpm install node-sass -D

引入公共样式normalize.css文件之后出现错误
错误信息:

error2.png
解决方案:ctrl+shift+p,在setting.json中添加如下
“javascript.validate.enable”: false

编写登录页面

第一步

<div class="login-box">
    <div class="login-input-box center">
      <h1>信贷管理系统</h1>
    
    </div>
  </div>

第二步

先定义表单内容放到–上面的h1标签下面

<el-form :model="ruleForm" :rules="rules" status-icon ref="ruleForm" class="demo-ruleForm">
    
        <el-form-item prop="username">
          <el-input prefix-icon="el-icon-user-solid" v-model="ruleForm.username"></el-input>
        </el-form-item>
    
        <el-form-item prop="pass">
          <el-input prefix-icon="el-icon-s-order" type="password" v-model="ruleForm.pass" autocomplete="off"></el-input>
        </el-form-item>

        <el-button type="primary" @click="submitForm">提交</el-button>
      </el-form>

第三步

1.data中定义一个ruleForm,接收用户名和密码

2.再定义一个rules,限制输入格式

3.在methods中添加一个submitForm表单提交方法和密码限制的validatePass方法

data中:

ruleForm: {
   
            username: "",
            pass: ""
          }
rules: {
   
        pass: [
          {
   
            validator: this.validatePass,
            trigger: "blur"
          }
        ],
        username: [{
    required: true, trigger: "blur", message: "请输入用户名" }]
      }

methods中:

validatePass(rule, value, callback) {
   
      if (value === "") {
   
        callback(new Error("请输入密码"));
      } else if (value.length < 6) {
   
        callback(new Error("密码不能小于6位数"));
      } else {
   
        callback();
      }
    },
 submitForm(){
   
 this.$refs.ruleForm.validate(valid => {
   
        if (valid) {
   
          // 如果验证通过,
         //调用login方法,传入登录信息,下面会定义
         this.login(this.ruleForm)
        } else {
   
         
          return false;
        }
      });
  }

4.创建login登录方法

async login(form){
   
    //成功后跳转到首页
     this.$router.replace("/home");
}

5.样式的引入

在main.js中引入样式

 import '@/assets/normalize.css';

6.在登录界面中引入下面样式

!!!注意语言是scss

<style lang="scss" scoped>
.login-input-box {
   
  width: 650px;
  height: 320px;
  background: #fff;
  text-align: center;
  padding: 40px 40px 12px 12px;
}

.login-box {
   
  height: 100%;
  background: url(../assets/bg2.jpg);
  background-size: cover;
}

.el-button {
   
  width: 600px;
}

.el-input {
   
  width: 600px;
  margin-bottom: 16px;
}

::v-deep .el-input__inner {
   
  background: #e5e5e5;
}
</style>

编写首页

添加路由规则

打开router文件夹下的index.js

其中的Layout为布局页面

//为routes添加
{
    path: '/',
    redirect:'/home',
        //下面这两个页面按照层级自行创建
    component:()=>  import('@/layout/layout.vue'),
    children:[
      {
      meta:{
       title:'首页'
        },
        path:'/home',
        component:()=> import('@/views/home.vue')
      }
    ]
  }

layout布局和编写首页及其vue-router路由跳转

layout布局包括侧边栏,导航栏和内容部分

 <div>
    <el-container>
     <el-aside width="240px">
        <el-menu   class="el-menu-vertical-demo" background-color="#545c64"
            text-color="#fff" active-text-color="#ffd04b">
            <!--//没有二级导航的 -->
             <el-menu-item index="1">
                <span slot="title"> 首页</span>
             </el-menu-item>
        
    	 <!--	//有二级导航的 -->
            <el-submenu index="2">
                    <template slot="title">
                    <span>贷款管理</span>
                    </template>
                  <el-menu-item index="2-1">
                     贷款申请
                  </el-menu-item>
            </el-submenu>   
        </el-menu>
    </el-aside>
        <el-container>
            <el-header>
               <!--//左侧面包屑-->
               <div class="left">
                   首页
                </div>
         		<!--//右侧用户名-->
                <div class="right">
                   <!--// //下拉菜单-->
                   <el-dropdown >
                   
                    <span class="el-dropdown-link"> admin </span>
                   
                    <el-dropdown-menu slot="dropdown">
                         <el-dropdown-item >退出登录</el-dropdown-item>
                    </el-dropdown-menu>
                   
                  </el-dropdown>
                </div>
            </el-header>
            <el-main>
                <!-- //放置一个路由出口 -->
                <router-view />
            </el-main>
        </el-container>
    </el-container>
  </div>

侧边栏包含二级菜单,导航栏最右侧有一个退出登录选择,内容包括了数字滚动和echarts图表

数字滚动组件vue-count-to

官网:https://www.npmjs.com/package/vue-count-to
安装插件的命令如下

npm i -S vue-count-to@1.0.13

引入后插入页面使用,在使用命令安装过程中出现如下报错信息

error3.png
解决方案:

根据提示检查网络情况,更换手机热点(我开发过程中更换热点仍然报错,应该不是网络原因了)
修改npm的网络设置 npm config list

1.png
图中设置用到的命令如下

npm config set proxy null
npm config set https-proxy null
npm config set registry https://registry.npmjs.org/

最初查阅文档之类的设置了很多次,最后有点懵懵哒,npm init了

稍过一会,再次下载就ok了(也许是设置原因或者最初网络不佳,不是非常确定)

最后一次成功使用的命令是

cnpm i -S vue-count-to@1.0.13 

( npm是node官方的包管理器。 cnpm是个中国版的npm,是淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm)

2.png

首先设置3个栅格布局,其中属性作用,查看element-ui官网的layout布局

 <div class="home">
    <el-row :gutter="10">
            <el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24" >
            <div>1</div>
            </el-col>
            <el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24" >
            <div>2</div>
            </el-col>
            <el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24" >
            <div>3</div>
        </el-col>
    </el-row>
</div>

把栅格布局的内容使用数组遍历来显示

<el-row :gutter="10">
        <el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24" v-for="(item, index) in list"          :key="index">
          
          <div class="dashboard-item" :style="{ background: item.color }">
            <p>{
  { item.title }}</p>
            
          </div>
        </el-col>
</el-row>

data中定义一个数组

 data(){
        return {
            list: [
                { val: 13594, title: '最高可借金额', color: '#67ca3a', },
                { val: 9833, title: '回报率', color: '#ff6600' },
                { val: 8888, title: '业绩领跑', color: '#f56c6c' },
                { val: 6666, title: '安稳底薪战队', color: '#409eff' }
             ]
        }
    }

echarts图表

介绍echart

官网https://echarts.apache.org/zh/index.html

下载echarts并使用

  1. 下载
cnpm i -S echarts@4.9.0
  1. HomeViews页面引入
import echarts from 'echarts';

编写第一个图表

  1. 定义图表位置
<template>
    <div class="home">
     <el-row :gutter="10">
          <el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24" v-for="(item, index) in             list"  :key="index">
              
            <div class="dashboard-item" :style="{ background: item.color }">
              <p>{
  { item.title }}</p>
              <CountTo :startVal="0" :endVal="item.val" :duration="3000" />
            </div>
          </el-col>
        </el-row>
        
		<!-- 所有图表位置,一共3个 -->
    <div class="echarts-box">
        <!-- 第一个图表位置-->
      <div class="chart1"></div>

    </div>


    </div>
  </template>
  1. 配置图表

添加一个initCharts方法

 initCharts() {
     //初始化图表实例,为什么要添加到this上面,因为后面要检测页面大小改变,更新图表大小
      this.chart1 = echarts.init(document.querySelector('.chart1'));
     //图表配置
     let option1 = {
        title: {
   
        },
        tooltip: {
          trigger: 'axis'
        },
        legend: {
          data: ['Email', 'Union Ads', 'Video Ads', 'Direct', 'Search Engine']
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '3%',
          containLabel: true
        },
        toolbox: {
          feature: {
            saveAsImage: {}
          }
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
        },
        yAxis: {
          type: 'value'
        },
        series: [
          {
            name: 'Email',
            type: 'line',
            stack: 'Total',
            data: [120, 132, 101, 134, 90, 230, 210]
          },
          {
            name: 'Union Ads',
            type: 'line',
            stack: 'Total',
            data: [220, 182, 191, 234, 290, 330, 310]
          },
          {
            name: 'Video Ads',
            type: 'line',
            stack: 'Total',
            data: [150, 232, 201, 154, 190, 330, 410]
          },
          {
            name: 'Direct',
            type: 'line',
            stack: 'Total',
            data: [320, 332, 301, 334, 390, 330, 320]
          },
          {
            name: 'Search Engine',
            type: 'line',
            stack: 'Total',
            data: [820, 932, 901, 934, 1290, 1330, 1320]
          }
        ]
      }
     
     //应用配置生成图表
      this.chart1.setOption(option1)
 }
  1. 在mounted生命周期里执行initCharts方法
mounted() {
    this.initCharts()
 }
  1. 图表没有显示

需要设置容器大小

 .chart1 {
   
    width: 100%;
    height: 400px;
  }

编写第二个图表

	<!-- 放在第一个图表下面     --> 
<div class="chart2"></div>
  1. 在initCharts方法中编写第二个图表数据
     this.chart2 = echarts.init(document.querySelector('.chart2'));
		//下面都是图表的配置,顺序不能错
    
      let posList = [
        'left',
        'right',
        'top',
        'bottom',
        'inside',
        'insideTop',
        'insideLeft',
        'insideRight',
        'insideBottom',
        'insideTopLeft',
        'insideTopRight',
        'insideBottomLeft',
        'insideBottomRight'
      ];
      let app = {
   };

      app.configParameters = {
   
        rotate: {
   
          min: -90,
          max: 90
        },
        align: {
   
          options: {
   
            left: 'left',
            center: 'center',
            right: 'right'
          }
        },
        verticalAlign: {
   
          options: {
   
            top: 'top',
            middle: 'middle',
            bottom: 'bottom'
          }
        },
        position: {
   
          options: posList.reduce(function (map, pos) {
   
            map[pos] = pos;
            return map;
          }, {
   })
        },
        distance: {
   
          min: 0,
          max: 100
        }
      };
      app.config = {
   
        rotate: 90,
        align: 'left',
        verticalAlign: 'middle',
        position: 'insideBottom',
        distance: 15,
        onChange: function () {
   
          const labelOption = {
   
            rotate: app.config.rotate,
            align: app.config.align,
            verticalAlign: app.config.verticalAlign,
            position: app.config.position,
            distance: app.config.distance
          };
          this.chart2.setOption({
   
            series: [
              {
   
                label: labelOption
              },
              {
   
                label: labelOption
              },
              {
   
                label: labelOption
              },
              {
   
                label: labelOption
              }
            ]
          });
        }
      };
      const labelOption = {
   
        show: true,
        position: app.config.position,
        distance: app.config.distance,
        align: app.config.align,
        verticalAlign: app.config.verticalAlign,
        rotate: app.config.rotate,
        formatter: '{c}  {name|{a}}',
        fontSize: 16,
        rich: {
   
          name: {
   }
        }
      };
      let option2 = {
   
        tooltip: {
   
          trigger: 'axis',
          axisPointer: {
   
            type: 'shadow'
          }
        },
        legend: {
   
          data: ['Forest', 'Steppe', 'Desert', 'Wetland']
        },
        toolbox: {
   
          show: true,
          orient: 'vertical',
          left: 'right',
          top: 'center',
          feature: {
   
            mark: {
    show: true },
            dataView: {
    show: true, readOnly: false },
            magicType: {
    show: true, type: ['line', 'bar', 'stack'] },
            restore: {
    show: true },
            saveAsImage: {
    show: true }
          }
        },
        xAxis: [
          {
   
            type: 'category',
            axisTick: {
    show: false },
            data: ['2012', '2013', '2014', '2015', '2016']
          }
        ],
        yAxis: [
          {
   
            type: 'value'
          }
        ],
        series: [
          {
   
            name: 'Forest',
            type: 'bar',
            barGap: 0,
            label: labelOption,
            emphasis: {
   
              focus: 'series'
            },
            data: [320, 332, 301, 334, 390]
          },
          {
   
            name: 'Steppe',
            type: 'bar',
            label: labelOption,
            emphasis: {
   
              focus: 'series'
            },
            data: [220, 182, 191, 234, 290]
          },
          {
   
            name: 'Desert',
            type: 'bar',
            label: labelOption,
            emphasis: {
   
              focus: 'series'
            },
            data: [150, 232, 201, 154, 190]
          },
          {
   
            name: 'Wetland',
            type: 'bar',
            label: labelOption,
            emphasis: {
   
              focus: 'series'
            },
            data: [98, 77, 101, 99, 40]
          }
        ]
      };
      
      this.chart2.setOption(option2);
  1. 设置第二个图表的容器大小
.chart2 {
    height: 400px;
    width: 50%;
  }

编写第三个图表

      <!--放到第二个图表下面 -->
<div class="chart3"></div>
  1. 配置第三个图表信息
      this.chart3 = echarts.init(document.querySelector('.chart3'));
    let option3  = {
   
        angleAxis: {
   },
        radiusAxis: {
   
          type: 'category',
          data: ['Mon', 'Tue', 'Wed', 'Thu'],
          z: 10
        },
        polar: {
   },
        series: [
          {
   
            type: 'bar',
            data: [1, 2, 3, 4],
            coordinateSystem: 'polar',
            name: 'A',
            stack: 'a',
            emphasis: {
   
              focus: 'series'
            }
          },
          {
   
            type: 'bar',
            data: [2, 4, 6, 8],
            coordinateSystem: 'polar',
            name: 'B',
            stack: 'a',
            emphasis: {
   
              focus: 'series'
            }
          },
          {
   
            type: 'bar',
            data: [1, 2, 3, 4],
            coordinateSystem: 'polar',
            name: 'C'
目录 第1章 1.1 背景概括 …………………………………………………… 5 1.2 可行性分析……………………………………………………… 7 (1) 经济可行性………………………………………………… 7 (2)操作可行性………………………………………………… 8 (3)技术可行性………………………………………………… (4)系统特点……………………………………………………… 8 第2章 需求分析………………………………………………………… 9 4.1 功能……………………………………………… 11 4.2 目标 4.3 业务流程设计……………………………………………… 11 (1) 存款管理……………………………………………………… 9 (2) 贷款管理…………………………………………………… 10 4.4 业务流程重组 4.5 数据流程图………………………………………………… 13 第3章 总体设计………………………………………………………… 11 第6章 详细设计………………………………………………………… 16 6.1 模块设计 ……………………………………………………… 16 6.2 代码设计……………………………………………………… 20 6.3 输入输出设计 ……………………………………………… 20 结束语 ……………………………………………………………………… 21 致谢 …………………………………………………………………………… 22 参考文献……………………………………………………………………… 23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隐藏用户y

虽然不是很有才华,但是渴望打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值