前后端分离CRUD+代码管理工具-svn

一、课程介绍
前后端分离技术概述(掌握)
后端crud接口完整实现(掌握)
前端crud实现(掌握)
Idea集成svn插件(掌握)
Idea中svn的基本操作(掌握)
项目仓库搭建(重要)

什么是前后端分离

** 前后端分离是一种架构模式,前后端项目分开开发,测试,部署.
并行开发:前后端并行开发,测试,再联调.
后端先行:后端先开发好接口,前端使用真是数据,省去写mock过程. 采纳**
后台controller层crud

package cn.itsource.crm.web.controller;

import cn.itsource.AjaxResult;
import cn.itsource.crm.domain.Department;
import cn.itsource.crm.service.IDepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Controller
@RequestMapping("/department")
@CrossOrigin
public class DepartmentController {

    @Autowired
    private IDepartmentService departmentService;

    /*@RequestMapping("/list")*/
    @RequestMapping(method = RequestMethod.PATCH)
    @ResponseBody
    @CrossOrigin
    public List list(){
        return  departmentService.findAll();
    }

    //json格式过来 @RequestBody 接收json数据
    @ResponseBody
    @RequestMapping(value="/save",method = RequestMethod.PUT)
    @CrossOrigin
    public AjaxResult save(@RequestBody Department department){
        try {
            departmentService.save(department);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setMsg("操作失败").setSuccess(false);
        }
        return  AjaxResult.me();
    }

    @ResponseBody
    @RequestMapping(value="/update",method = RequestMethod.PUT)
    public AjaxResult update(@RequestBody Department department){
        try {
            departmentService.update(department);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setMsg("操作失败").setSuccess(false);
        }
        return  AjaxResult.me();
    }

    //   /employee/id=1   /employee/1
    //  编译的问题
    @RequestMapping(value="{id}",method = RequestMethod.DELETE)
    @ResponseBody
    public AjaxResult delete(@PathVariable("id") Long id){
        System.out.println("---------------------------------------");
        try {

            departmentService.delete(id);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setMsg("操作失败").setSuccess(false);
        }
        return  AjaxResult.me();
    }

    @RequestMapping(value="{id}",method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult findOne(@PathVariable("id") Long id){
        System.out.println("---------------------------------------");
        try {
            Department department = departmentService.loadById(id);
            System.out.println(department);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setMsg("操作失败").setSuccess(false);
        }
        return  AjaxResult.me();
    }


}

前端crud

运行前端项目
npm install 安装依赖前端js库
npm run dev 运行前端项目
npm run build 打包

main.js

import babelpolyfill from 'babel-polyfill'
import Vue from 'vue'
import App from './App'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'
//import './assets/theme/theme-green/index.css'
import VueRouter from 'vue-router'
import store from './vuex/store'
import Vuex from 'vuex'
//import NProgress from 'nprogress'
//import 'nprogress/nprogress.css'
import routes from './routes'
/*import Mock from './mock'
Mock.bootstrap();*/
import 'font-awesome/css/font-awesome.min.css'
//引入axios组件
import axios from 'axios';
//设置axios请求基本路径  每次发送请求前面都要添加该路径 http://localhost/department
axios.defaults.baseURL='http://localhost';
Vue.prototype.$http=axios;

Vue.use(ElementUI)
Vue.use(VueRouter)
Vue.use(Vuex)

//NProgress.configure({ showSpinner: false });

const router = new VueRouter({
    routes
})

//请求的时候 路由的 http://localhost:8080/home 登陆拦截
/*router.beforeEach((to, from, next) => {
  //NProgress.start();
  if (to.path == '/login') {
    //前端的session
    sessionStorage.removeItem('user');
  }
  //获取前端session里面的user信息
  let user = JSON.parse(sessionStorage.getItem('user'));
  //user false
  if (!user && to.path != '/login') {
    next({ path: '/login' })
  } else {
    next()
  }
})*/

//router.afterEach(transition => {
//NProgress.done();
//});

new Vue({
    //el: '#app',
    //template: '<App/>',
    router,
    store,
    //components: { App }
    render: h => h(App)
}).$mount('#app')


routes.js

import Login from './views/Login.vue'
import NotFound from './views/404.vue'
import Home from './views/Home.vue'
import Main from './views/Main.vue'
import Table from './views/nav1/Table.vue'
import Form from './views/nav1/Form.vue'
import user from './views/nav1/user.vue'
import Page4 from './views/nav2/Page4.vue'
import Page5 from './views/nav2/Page5.vue'
import Page6 from './views/nav3/Page6.vue'
import echarts from './views/charts/echarts.vue'
import Department from './views/itsource/Department.vue'

let routes = [
    {
        path: '/login',
        component: Login,
        name: '',
        hidden: true
    },
    {
        path: '/404',
        component: NotFound,
        name: '',
        hidden: true
    },
    {
        path: '/',
        component: Home,
        name: '你的位置',
        iconCls: 'fa fa-bar-chart',
        children: [
            { path: '/echarts', component: echarts, name: '主页' }
        ]
    },
    //{ path: '/main', component: Main },
    /*{
        path: '/',
        component: Home,
        name: '导航一',
        iconCls: 'el-icon-message',//图标样式class
        children: [
            { path: '/main', component: Main, name: '主页', hidden: true },
            { path: '/table', component: Table, name: 'Table' },
            { path: '/form', component: Form, name: 'Form' },
            { path: '/user', component: user, name: '列表' },
        ]
    },*/
    {
        path: '/',
        component: Home,
        name: '组织机构',
        iconCls: 'el-icon-message',//图标样式class
        children: [
            { path: '/department', component: Department, name: '部门管理' }

        ]
    },
    /*{
        path: '/',
        component: Home,
        name: '导航二',
        iconCls: 'fa fa-id-card-o',
        children: [
            { path: '/page4', component: Page4, name: '页面4' },
            { path: '/page5', component: Page5, name: '页面5' }
        ]
    },
    {
        path: '/',
        component: Home,
        name: '',
        iconCls: 'fa fa-address-card',
        leaf: true,//只有一个节点
        children: [
            { path: '/page6', component: Page6, name: '导航三' }
        ]
    },*/
    {
        path: '*',
        hidden: true,
        redirect: { path: '/404' }
    }
];

export default routes;

<template>
	<section>
		<!--工具条-->
		<el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
			<el-form :inline="true" :model="filters">
				<el-form-item>
					<el-input v-model="filters.name" placeholder="姓名"></el-input>
				</el-form-item>
				<el-form-item>
					<el-button type="primary" v-on:click="getDepartments">查询</el-button>
				</el-form-item>
				<el-form-item>
					<el-button type="primary" @click="handleAdd">添加</el-button>
				</el-form-item>
			</el-form>
		</el-col>

		<!--列表-->
		<el-table :data="departments" highlight-current-row v-loading="listLoading" @selection-change="selsChange" style="width: 100%;">
			<el-table-column type="selection" width="55">
			</el-table-column>
			<el-table-column type="index" width="60">
			</el-table-column>
            <!--<el-table-column prop="id" label="id" width="120" sortable>
            </el-table-column>-->
			<el-table-column prop="name" label="部门名称" sortable>
			</el-table-column>

			<el-table-column label="操作" width="150">
				<template scope="scope">
					<el-button size="small" @click="handleEdit(scope.$index, scope.row)">修改</el-button>
					<el-button type="danger" size="small" @click="handleDel(scope.$index, scope.row)">删除</el-button>
				</template>
			</el-table-column>
		</el-table>

		<!--工具条-->
		<el-col :span="24" class="toolbar">
			<el-pagination layout="prev, pager, next" @current-change="handleCurrentChange" :page-size="20" :total="total" style="float:right;">
			</el-pagination>
		</el-col>

		<!--编辑界面-->
		<el-dialog title="编辑" v-model="departmentFormVisible" :close-on-click-modal="false">
			<el-form :model="department" label-width="80px" :rules="departmentFormRules" ref="departmentForm">
				<el-form-item label="部门名称" prop="name">
					<el-input v-model="department.name" auto-complete="off"></el-input>
				</el-form-item>

			</el-form>
			<div slot="footer" class="dialog-footer">
				<el-button @click.native="departmentFormVisible = false">取消</el-button>
                <!-- native支持原生的js注册事件方法 onclick = xxx() elementui/vue method写的方法-->
				<el-button type="primary" @click="editSubmit" :loading="editLoading">提交</el-button>
			</div>
		</el-dialog>


	</section>
</template>

<script>

	export default {
		data() {
			return {
				filters: {
					name: ''
				},
				departments: [],
				total: 0,
				page: 1,
				listLoading: false,
				sels: [],//列表选中列

				departmentFormVisible: false,//编辑界面是否显示
				editLoading: false,
				departmentFormRules: {
					name: [
					    //部门名称失去焦点的时候,触发验证规则
						{ required: true, message: '请输入部门名称', trigger: 'blur' }
					]
				},
				//编辑界面数据
                department: {
					id: 0,
					name: ''
				}
			}
		},
		methods: {
			//性别显示转换
			formatSex: function (row, column) {
				return row.sex == 1 ? '男' : row.sex == 0 ? '女' : '未知';
			},
			handleCurrentChange(val) {
				this.page = val;
				this.getDepartments();
			},
			//获取用户列表
			getDepartments() {
			    //参数
				let para = {
					page: this.page,
					name: this.filters.name
				};
				//刷新效果
				this.listLoading = true;
                //发送请求 axios请求 -- 全部axios http://localhost/department
                this.$http.patch('/department',para).then(res=>{
			//	getUserListPage(para).then((res) => {
                    console.log(res);
					this.total = 100;
					this.departments = res.data;
					this.listLoading = false;
					//NProgress.done();
				});
			},
			//删除
			handleDel: function (index, row) {
				this.$confirm('确认删除该记录吗?', '提示', {
					type: 'warning'
				}).then(() => {
				    //开启 加载中
					this.listLoading = true;
					//获取删除的id
					this.$http.delete('/department/'+row.id).then((res) => {
                        //{'success':true/false,'msg':'xxxx'}
						this.listLoading = false;
						if(res.data.success){
                            this.$message({
                                message: '删除成功',
                                type: 'success'
                            });
                        }else{
                            this.$message({
                                message: '删除失败',
                                type: 'error'
                            });
                        }

						//查询数据
						this.getDepartments();
					});


				}).catch(() => {

				});
			},
			//显示编辑界面 弹出编辑框
			handleEdit: function (index, row) {
			    //打开对话框
				this.departmentFormVisible = true;
				//回显作用 拷贝row到新的{}对象
				this.department = Object.assign({}, row);
			},
			//显示新增界面
			handleAdd: function () {
			    //控制是否弹出对话框
				this.departmentFormVisible=true;
				//清空表单数据
				this.department = {
					name: ''

				};
			},
			//新增 修改 保存
			editSubmit: function () {
			    //必须验证通过之后,才执行下面的代码
				this.$refs.departmentForm.validate((valid) => {
					if (valid) {
					    //询问你 是否要提交
						this.$confirm('确认提交吗?', '提示', {}).then(() => {
						    //显示加载 圈
							this.editLoading = true;
							//备份 表单里面数据 备分一份给para变量
							let para = Object.assign({}, this.department);
					        //发送ajax请求
							//editUser(para).then((res) => {
                            let url = '/department/save';
                            if(this.department.id){
                                console.log(this.department.id);
                                url='/department/update';
                            }
                            this.$http.put(url,para).then(res=>{
                                //关闭滚动圈
								this.editLoading = false;

								this.$message({
									message: '提交成功',
									type: 'success'
								});
								//重置表单信息 为null
								this.$refs['departmentForm'].resetFields();
								//关闭对话框
								this.departmentFormVisible = false;
								//重心查询数据
								this.getDepartments();
							});
						});
					}
				});
			},
			//新增
			addSubmit: function () {
				this.$refs.addForm.validate((valid) => {
					if (valid) {
						this.$confirm('确认提交吗?', '提示', {}).then(() => {
							this.addLoading = true;
							//NProgress.start();
							let para = Object.assign({}, this.addForm);
							para.birth = (!para.birth || para.birth == '') ? '' : util.formatDate.format(new Date(para.birth), 'yyyy-MM-dd');
							addUser(para).then((res) => {
								this.addLoading = false;
								//NProgress.done();
								this.$message({
									message: '提交成功',
									type: 'success'
								});
								this.$refs['addForm'].resetFields();
								this.addFormVisible = false;
								this.getDepartments();
							});
						});
					}
				});
			},
			selsChange: function (sels) {
				this.sels = sels;
			},
			//批量删除
			batchRemove: function () {
				var ids = this.sels.map(item => item.id).toString();
				this.$confirm('确认删除选中记录吗?', '提示', {
					type: 'warning'
				}).then(() => {
					this.listLoading = true;
					//NProgress.start();
					let para = { ids: ids };
					batchRemoveUser(para).then((res) => {
						this.listLoading = false;
						//NProgress.done();
						this.$message({
							message: '删除成功',
							type: 'success'
						});
						this.getDepartments();
					});
				}).catch(() => {

				});
			}
		},
		mounted() {
			this.getDepartments();
		}
	}

</script>

<style scoped>

</style>

解决跨域问题

什么是跨域
跨域是值跨域名.域名:记忆网络电脑ip很难记,就给它取了一个名字来记忆,这个名字就要域名,域名最终要被转换为ip.

跨域解决方案
目前比较常用的跨域解决方案有3种:

  • Jsonp
    最早的解决方案,利用script标签可以跨域的原理实现。
    限制:

    • 需要服务的支持
    • 只能发起GET请求
  • nginx反向代理(部署)
    思路是:利用nginx反向代理把跨域为不跨域,支持各种请求方式
    缺点:需要在nginx进行额外配置,语义不清晰

  • CORS(都可以使用-采纳)
    规范化的跨域请求解决方案,安全可靠。
    优势:

    • 在服务端进行控制是否允许跨域,可自定义规则
    • 支持各种请求方式
      缺点:
    • 会产生额外的请求,要做询问

我们这里会采用cors的跨域方案。注意spring版本 修改 4.2.5
<spring.version>4.2.5.RELEASE</spring.version>

Idea集成svn插件

在这里插入图片描述
检出
在这里插入图片描述
跟新代码
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值