品优购项目记录:day03

本文详细介绍如何使用AngularJS进行分层开发,包括服务层、控制器的定义与使用,通过实例讲解规格管理和模板管理的实现过程。

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

今日目标:

        (1)理解和运用 angular js 的 service

        (2)理解好运用控制器继承

        (3)掌握代码生成器的使用

        (4)实现规格管理

        (5)实现模板管理

目录

1、前段分层开发

2、规格管理

2.1 规格列表显示,后端代码与JS代码使用生成器生成,只需修改页面

2.2 新增规格

2.3 修改规格

2.4 删除规格

3、模板管理

3.1 模板列表和规格列表几乎一样,参考规格列表

3.2 品牌下拉列表(select2组件)

3.3 品牌下拉列表从后端获取数据集

3.4 规格下拉列表和品牌下拉列表做法一致,参考品牌下拉列表

3.5 增加和删除扩展属性表格行

3.6 点击保存,保存模板信息

3.7 修改模板信息

3.8 删除模板,只需要为复选框绑定单击事件,并给删除按钮绑定单击事件

3.9 优化模板列表显示


 

1、前段分层开发

 

1.1 JS 代码改造

// 自定义模块,引入分页模块
var app = angular.module('pinyougou', ['pagination']);

//自定义服务
app.service('brandService', function ($http) {

    // 分页查询品牌列表
    this.findByPage = function (page, size) {
        return $http.get('../brand/findByPage.do?page=' + page + '&size=' + size);
    };

    // 新增品牌
    this.add = function (entity) {
        return $http.post('../brand/add.do', entity);
    };

    // 按id查询品牌
    this.findOne = function (id) {
        return $http.get('../brand/findOne.do?id=' + id);
    };

    // 修改品牌
    this.update = function (entity) {
        return $http.post('../brand/update.do', entity);
    };

    // 删除品牌
    this.dele = function (ids) {
        return $http.get('../brand/delete.do?ids=' + ids);
    }

    this.search = function (page,size,queryParam) {
        return $http.post('../brand/search.do?page=' + page + '&size=' + size, queryParam);
    }


});


//自定义控制器
app.controller('brandController', function ($scope, brandService) {

    //分页控件配置
    $scope.paginationConf = {
        //当前页
        currentPage: 1,
        //总记录数
        totalItems: 10,
        //每页记录数
        itemsPerPage: 10,
        //可以选择的每页记录数
        perPageOptions: [10, 20, 30, 40, 50],
        //选择每页记录数事件
        onChange: function () {
            $scope.reloadList();
        }
    };
    //重新加载
    $scope.reloadList = function () {
        $scope.search($scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage);
    };

    /*
        分页查询品牌列表
     */
    $scope.findByPage = function (page, size) {
        brandService.findByPage(page, size).success(
            function (rtn) {
                //显示当前页的数据
                $scope.list = rtn.rows;
                //修改总记录数
                $scope.paginationConf.totalItems = rtn.total;
            }
        );
    };

    /*
        新增品牌、修改品牌
     */
    $scope.save = function () {
        var object = null;
        if ($scope.entity.id != null) {
            object = brandService.update($scope.entity);
        } else {
            object = brandService.add($scope.entity);
        }
        object.success(
            function (rtn) {
                alert(rtn.message);
                if (rtn.success) {
                    //重新加载数据
                    $scope.reloadList();
                }
            }
        );
    };

    /*
        加载要修改的品牌到编辑品牌表单
     */
    $scope.findOne = function (id) {
        brandService.findOne(id).success(
            function (rtn) {
                $scope.entity = rtn;
            }
        );
    };

    //记录被勾选的id值
    $scope.selectIds = [];

    /*
        更新被勾选的id值
     */
    $scope.updateSelection = function ($event, id) {
        if ($event.target.checked) {//选中状态
            //将id值加入selectIds
            $scope.selectIds.push(id);
        } else {//取消选中
            //获取id值的下标
            var index = $scope.selectIds.indexOf(id);
            //移除id
            $scope.selectIds.splice(index, 1);
        }
    };

    /*
        删除操作
     */
    $scope.dele = function () {
        brandService.dele($scope.selectIds).success(
            function (rtn) {
                alert(rtn.message);
                if (rtn.success) {
                    //重新加载数据
                    $scope.reloadList();
                }
            }
        );
    };

    /*
        条件查询
     */
    //初始化queryParam
    $scope.queryParam = {};
    $scope.search = function (page, size) {
        brandService.search(page, size, $scope.queryParam).success(
            function (rtn) {
                //显示当前页的数据
                $scope.list = rtn.rows;
                //修改总记录数
                $scope.paginationConf.totalItems = rtn.total;
            }
        );
    };


});

 

 

 

1.2 将改造后的 JS 分层,即将放入不同的 JS 文件中

(1)base_pagination.js

// 自定义模块,引入分页模块
var app = angular.module('pinyougou', ['pagination']);

(2)brandService.js

//自定义服务
app.service('brandService', function ($http) {

    // 分页查询品牌列表
    this.findByPage = function (page, size) {
        return $http.get('../brand/findByPage.do?page=' + page + '&size=' + size);
    };

    // 新增品牌
    this.add = function (entity) {
        return $http.post('../brand/add.do', entity);
    };

    // 按id查询品牌
    this.findOne = function (id) {
        return $http.get('../brand/findOne.do?id=' + id);
    };

    // 修改品牌
    this.update = function (entity) {
        return $http.post('../brand/update.do', entity);
    };

    // 删除品牌
    this.dele = function (ids) {
        return $http.get('../brand/delete.do?ids=' + ids);
    }

    this.search = function (page,size,queryParam) {
        return $http.post('../brand/search.do?page=' + page + '&size=' + size, queryParam);
    }

});

 

(3)brandController.js

//自定义控制器
app.controller('brandController', function ($scope, brandService) {

    //分页控件配置
    $scope.paginationConf = {
        //当前页
        currentPage: 1,
        //总记录数
        totalItems: 10,
        //每页记录数
        itemsPerPage: 10,
        //可以选择的每页记录数
        perPageOptions: [10, 20, 30, 40, 50],
        //选择每页记录数事件
        onChange: function () {
            $scope.reloadList();
        }
    };
    //重新加载
    $scope.reloadList = function () {
        $scope.search($scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage);
    };

    /*
        分页查询品牌列表
     */
    $scope.findByPage = function (page, size) {
        brandService.findByPage(page, size).success(
            function (rtn) {
                //显示当前页的数据
                $scope.list = rtn.rows;
                //修改总记录数
                $scope.paginationConf.totalItems = rtn.total;
            }
        );
    };

    /*
        新增品牌、修改品牌
     */
    $scope.save = function () {
        var object = null;
        if ($scope.entity.id != null) {
            object = brandService.update($scope.entity);
        } else {
            object = brandService.add($scope.entity);
        }
        object.success(
            function (rtn) {
                alert(rtn.message);
                if (rtn.success) {
                    //重新加载数据
                    $scope.reloadList();
                }
            }
        );
    };

    /*
        加载要修改的品牌到编辑品牌表单
     */
    $scope.findOne = function (id) {
        brandService.findOne(id).success(
            function (rtn) {
                $scope.entity = rtn;
            }
        );
    };

    //记录被勾选的id值
    $scope.selectIds = [];

    /*
        更新被勾选的id值
     */
    $scope.updateSelection = function ($event, id) {
        if ($event.target.checked) {//选中状态
            //将id值加入selectIds
            $scope.selectIds.push(id);
        } else {//取消选中
            //获取id值的下标
            var index = $scope.selectIds.indexOf(id);
            //移除id
            $scope.selectIds.splice(index, 1);
        }
    };

    /*
        删除操作
     */
    $scope.dele = function () {
        brandService.dele($scope.selectIds).success(
            function (rtn) {
                alert(rtn.message);
                if (rtn.success) {
                    //重新加载数据
                    $scope.reloadList();
                }
            }
        );
    };

    /*
        条件查询
     */
    //初始化queryParam
    $scope.queryParam = {};
    $scope.search = function (page, size) {
        brandService.search(page, size, $scope.queryParam).success(
            function (rtn) {
                //显示当前页的数据
                $scope.list = rtn.rows;
                //修改总记录数
                $scope.paginationConf.totalItems = rtn.total;
            }
        );
    };


});

 

(4)在品牌管理页面中引入这些 JS

 

 

1.3 控制器继承

(1)抽取出控制器中公共代码到baseController.js中

app.controller('baseController',function ($scope) {
    //分页控件配置
    $scope.paginationConf = {
        //当前页
        currentPage: 1,
        //总记录数
        totalItems: 10,
        //每页记录数
        itemsPerPage: 10,
        //可以选择的每页记录数
        perPageOptions: [10, 20, 30, 40, 50],
        //选择每页记录数事件
        onChange: function () {
            $scope.reloadList();
        }
    };
//重新加载
    $scope.reloadList = function () {
        $scope.search($scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage);
    };

//记录被勾选的id值
    $scope.selectIds = [];

    /*
        更新被勾选的id值
     */
    $scope.updateSelection = function ($event, id) {
        if ($event.target.checked) {//选中状态
            //将id值加入selectIds
            $scope.selectIds.push(id);
        } else {//取消选中
            //获取id值的下标
            var index = $scope.selectIds.indexOf(id);
            //移除id
            $scope.selectIds.splice(index, 1);
        }
    };
});

 

(2)使用 brandController 继承 baseController

    // 继承baseController
    $controller('baseController', {$scope: $scope});

注意:要使用继承,必须先将$controller 服务注入到brandController,并且要在引入brandController.js之前引入baseController.js

 

 

 

2、规格管理

 

 

2.1 规格列表显示,后端代码与JS代码使用生成器生成,只需修改页面

(1)引入 JS 文件

 

(2)引入 angular JS

 

(3)循环获取值

 

 

2.2 新增规格

 

需求1:点击新增规格选项,在表格中新增一行

(1)点击新建按钮时,初始化绑定的变量

 

(2)编写 JS 代码(specificationController.js)

    //新增规格选项
    $scope.addTableRow = function () {
		$scope.entity.specificationOptionList.push({});
    }

 

(3)为新增规格选项按钮绑定事件

 

 

需求2:点击删除按钮,删除当前表格行

(1)编写 JS 代码(specificationController.js)

    //删除规格选项
	$scope.deleTableRow = function (index) {
		$scope.entity.specificationOptionList.splice(index,1);
    }

 

(2)为删除按钮绑定事件,index参数可以使用 $index 直接获取

 

需求3:点击保存按钮,提交到后端进行保存

(1)后端代码

    a、pinyougou-dao,修改TbSpecificationMapper.xml中的insert映射,加入代码,为了在插入规格后获取其ID,用于后续操作

    <selectKey resultType="java.lang.Long" order="AFTER" keyProperty="id">
      SELECT LAST_INSERT_ID() AS id
    </selectKey>

    b、创建一个实体类,用于接受前端传过来的参数

package com.pinyougou.pojogroup;

import com.pinyougou.pojo.TbSpecification;
import com.pinyougou.pojo.TbSpecificationOption;

import java.util.List;

/**
 * 规格和规格选项组合实体类
 * Author xushuai
 * Description
 */
public class Specification {

    /** 品牌规格 */
    private TbSpecification specification;
    /** 规格选项 */
    private List<TbSpecificationOption> specificationOptionList;

    public TbSpecification getSpecification() {
        return specification;
    }

    public void setSpecification(TbSpecification specification) {
        this.specification = specification;
    }

    public List<TbSpecificationOption> getSpecificationOptionList() {
        return specificationOptionList;
    }

    public void setSpecificationOptionList(List<TbSpecificationOption> specificationOptionList) {
        this.specificationOptionList = specificationOptionList;
    }
}

 

     c、服务层接口(sellergoods-interface),重载add方法

    /**
     * 新增
     *
     * @param specification 规格组合实体
     */
    void add(Specification specification);

 

     d、服务层实现(sellergoods-service),新增实现

 

    @Override
    public void add(Specification specification) {
        //从组合实体中获取规格对象
        TbSpecification tbSpecification = specification.getSpecification();
        //执行保存
        specificationMapper.insert(tbSpecification);

        //从组合试题中获取规格选项
        List<TbSpecificationOption> tbSpecificationOptionList = specification.getSpecificationOptionList();
        //循环保存
        for (TbSpecificationOption option : tbSpecificationOptionList) {
            //设置规格id
            option.setSpecId(tbSpecification.getId());
            //保存规格选项
            specificationOptionMapper.insert(option);
        }
    }

 

     d、控制层(manager-web)

 

	/**
	 * 增加
	 * @param specification
	 * @return
	 */
	@RequestMapping("/add")
	public Result add(@RequestBody Specification specification){
		try {
			specificationService.add(specification);
			return new Result(true, "增加成功");
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false, "增加失败");
		}
	}

 

 

 

(2)后端代码

        a、为规格名称绑定变量

 

        b、为保存按钮添加事件

	//保存 
	$scope.save=function(){				
		var serviceObject;//服务层对象  				
		if($scope.entity.specification.id!=null){//如果有ID
			serviceObject=specificationService.update( $scope.entity ); //修改  
		}else{
			serviceObject=specificationService.add( $scope.entity  );//增加 
		}				
		serviceObject.success(
			function(response){
				if(response.success){
					//重新查询 
		        	$scope.reloadList();//重新加载
				}else{
					alert(response.message);
				}
			}		
		);				
	}

 

 

2.3 修改规格

(1)后端代码

    a、服务层接口(sellergoods-interface)

    /**
     * 根据ID获取实体
     *
     * @param id
     * @return
     */
    Specification findOne(Long id);

 

        b、服务层实现(sellergoods-service)

 

    /**
     * 根据ID获取实体
     *
     * @param id
     * @return
     */
    @Override
    public Specification findOne(Long id) {
        //查询规格
        TbSpecification tbSpecification = specificationMapper.selectByPrimaryKey(id);
        //封装规格选项查询条件
        TbSpecificationOptionExample specificationOptionExample = new TbSpecificationOptionExample();
        specificationOptionExample.createCriteria().andSpecIdEqualTo(id);
        //查询规格选项
        List<TbSpecificationOption> tbSpecificationOptions = specificationOptionMapper.selectByExample(specificationOptionExample);

        //创建规格组合实体类
        Specification specification = new Specification();
        specification.setSpecification(tbSpecification);
        specification.setSpecificationOptionList(tbSpecificationOptions);

        return specification;
    }

 

        c、控制层

 

	/**
	 * 获取实体
	 * @param id
	 * @return
	 */
	@RequestMapping("/findOne")
	public Specification findOne(Long id){
		return specificationService.findOne(id);		
	}

 

(2)前端无需修改

 


 

 

2.4 删除规格

(1)后端代码,只需要修改服务层实现中的delete方法

    /**
     * 批量删除
     */
    @Override
    public void delete(Long[] ids) {
        for (Long id : ids) {
            //删除规格数据
            specificationMapper.deleteByPrimaryKey(id);

            //删除规格选项数据
            TbSpecificationOptionExample specificationOptionExample = new TbSpecificationOptionExample();
            specificationOptionExample.createCriteria().andSpecIdEqualTo(id);
            //删除规格选项
            specificationOptionMapper.deleteByExample(specificationOptionExample);
        }
    }

 

 

 

(2)前端

        a、为复选框加入单击事件

        b、为删除按钮绑定事件

 

 

 

 

 

 

3、模板管理

 

 

 

3.1 模板列表和规格列表几乎一样,参考规格列表

 

 

3.2 品牌下拉列表(select2组件)

(1)引入select2的js和css文件

    <link rel="stylesheet" href="../plugins/select2/select2.css" />
    <link rel="stylesheet" href="../plugins/select2/select2-bootstrap.css" />
    <script src="../plugins/select2/select2.min.js" type="text/javascript"></script>
    <script type="text/javascript" src="../js/angular-select2.js">  </script>

注意:angular-select2.js 必须放在自定义模块的js文件后面引入,因为angular-select2中会使用到app

 

(2)在controller中新增变量,即下拉菜单中的数据

 

(3)在页面中添加select2组件

 

(4)效果

 

 

3.3 品牌下拉列表从后端获取数据集

(1)新增mapper映射(TbBrandMapper.xml)

  <!-- 查询品牌列表,并封装为Map返回 -->
  <select id="selectOptionList" resultType="java.util.Map">
    select id,name as text
    from tb_brand
  </select>

 

(2)BrandMapper接口,新增对应方法

    List<Map> selectOptionList();

 

(3)服务层接口(BrandService)

    /**
     * 返回品牌下拉列表数据
     *
     * @return java.util.List<java.util.Map>
     */
    List<Map> selectOptionList();

 

(4)服务层实现(BrandServiceImpl)

	@Override
	public List<Map> selectOptionList() {
		return brandMapper.selectOptionList();
	}

 

(5)控制层(BrandController)

    /**
     * 获取品牌下拉列表需要的品牌列表数据格式
     *
     * @return java.util.List<java.util.Map>
     */
    @RequestMapping("/selectOptionList")
    public List<Map> selectOptionList() {
        return brandService.selectOptionList();
    }

 

(6)在前端 brandService.js 中,添加方法

    // 获取品牌下拉列表需要的数据集
    this.selectOptionList = function () {
        return $http.get('../brand/selectOptionList.do');
    }

 

(7)在 typeTemplateController.js 中注入 brandService 服务

注意:需要在页面引入 brandService.js 文件

 

(8)在 typeTemplateController.js 中定义加载品牌列表数据的方法

	//获取品牌列表下拉列表需要的数据集
	$scope.findBrandList = function () {
		brandService.selectOptionList().success(
		    function (rtn) {
                        $scope.brandList = {data:rtn};
                    }    
		);
        }

 

(9)在 angular js 初始化调用指令,调用该方法

 

(10)测试

 

 

3.4 规格下拉列表和品牌下拉列表做法一致,参考品牌下拉列表

 

 

3.5 增加和删除扩展属性表格行

 

(1)在点击新建按钮时,初始化扩展属性的数组

 

(2)编写新增行方法

    //新增扩展属性行
    $scope.addTableRow = function () {
		$scope.entity.customAttributeItems.push({});
    }

 

(3)为新增扩展属性按钮绑定单击事件

 

(4)绑定扩展属性数组到表格行

 

(5)编写删除行方法

    //删除扩展属性行
	$scope.deleTableRow = function (index) {
		$scope.entity.customAttributeItems.splice(index,1);
	}

 

(6)为删除按钮绑定单击事件

 

 

 

3.6 点击保存,保存模板信息

(1)为商品类型绑定变量

 

(2)为保存按钮绑定单击事件

 

 

3.7 修改模板信息

(1)为修改按钮绑定单击事件

 

(2)修改 findOne 方法

效果:

 

 

3.8 删除模板,只需要为复选框绑定单击事件,并给删除按钮绑定单击事件

 

 

3.9 优化模板列表显示

 

我们需要将信息以更友好的方式展现出来,如下图形式

 

(1)提交一个转换方法到baseController.js中

    /*
        json数据转换方法
     */
    $scope.jsonToString = function (jsonString, key) {
        //将jsonString转换为json对象
        var json = JSON.parse(jsonString);

        //存放转换后的值
        var value = '';

        //遍历json进行转换
        for(var i = 0; i < json.length; i++) {
            if(i>0) {
                value += ',';
            }
            value += json[i][key];
        }

        return value;
    }

 

(2)在页面调用这个方法

 

(3)效果

 

 

 

 

 

 

1.2. 结构化一下 1.3. 图形化一下 1.3.1. 运营商后台 1.3.2. 商家后台 1.3.3. 网页前台 参考京东 2. 技术选型 前端:angularJS + Bootstrap 后台:SSM( springmvc+spring+mybatis) 数据库:mysql,使用mycat读写分离 开发模式:SOA 服务中间件:dubbox,需要和zookeeper配合使用 注册中心:zookeeper 消息中间件:Activemq,使用spring-jms 负载均衡:nginx 搜索:solr集群(solrCloud),配合zookeeper搭建, 使用spring-data-solor 缓存:redis集群,使用spring-data-redis 图片存储:fastDFS集群 网页静态化:freemarker 单点登录:cas 权限管理:SpringSecurity, 跨域:cros 支付:微信扫描 短信验证:阿里大于 密码加密:BCrypt 富文本:KindEditor 事务:声明式事务 任务调度:spring task 所有的技术,都可能涉及到为什么用?怎么用?用的过程中有什么问题? 3. 框架搭建 3.1. 前端 理解baseControler.js、base.js、base_pagination.js,以及每一个xxxController.js里面都公共的做了些什么。 baseControler.js 分页配置 列表刷新 处理checkBox勾选 xxxControler.js 自动生成增删改查 base_pagination.js 带分页 base.js 不带分页 3.2. dao 使用了mybatis逆向工程 4. 模块开发 逐个模块开发就好 4.1. 学会评估模块难不难 一个模块难不难从几方面考虑。 涉及几张表? 1,2张表的操作还是没有什么难度的。 涉及哪些功能? 增删改查,批量删除。 前端展示? 分页列表、树形、面包屑、三级联动、内容格式化。 4.2. 举几个简单模块的例子 4.2.1. 牌管理 单表 分页、新增、删除、修改 4.2.2. 规格管理 2张表 分页、新增、删除、修改、显示化(显示列表内容的一部分) 4.2.3. 模板管理 2张表 分页、新增、删除、修改、显示化(显示列表内容的一部分) 4.2.4. 分类管理 单表 4.2.5. 商家审核 单表 4.3. 举一个复杂模块 4.3.1. 商新增 需要插入3张表,tb_goods、tb_goods_desc、tb_item 前端:三级联动、富文本、图片上传、动态生成内容 4.3.2. 商修改 需要从3张表获取数据,然后进行回显。 4.4. 典型模块设计 4.4.1. 管理后台 商新增、商修改 4.4.2. 前台页面 搜索模块实现 物车模块实现 支付模块实现 秒杀模块实现 5. 开发过程中问题&化 1.1. 登录 单点登录怎么实现 session怎么共享 1.2. 缓存 哪些场景需要用到redis redis存储格式的选择 怎么提高redis缓存利用率 缓存如何同步 1.3. 图片上传 图片怎么存储 图片怎么上传 1.4. 搜索 ​ 怎么实现 数据量大、 并发量高的搜索 怎么分词 1.5. 消息通知 ​ 哪些情况用到activeMq 1.6. 化 seo怎么化 怎么加快访问速度 1.7. 秒杀 ​ 怎么处理高并发 ​ 秒杀过程中怎么控制库存
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值