至尊智能家居项目开发全过程

【至尊智能家居】

主要内容

  1. 项目开发过程简介
  2. 项目功能分析
  3. 数据建模&UML 建模
  4. 基础环境搭建

在这里插入图片描述

一、 项目开发过程简介

1 项目的核心是什么?

项目不是简单的 CRUD。不是数据的增删改查。一个项目的实质是业务的实现。不同 的行业、环境、项目,会有不同的业务需求,根据具体的业务需求,完成对应的应用开发, 称为项目开发。

数据的变化是项目的底层支撑,非常重要。但是数据的操作基本是固定的。只要有一定 的开发经验,对数据的 CRUD 操作,就没有太大的问题。

业务实现是项目的精华核心。每个业务,都和行业、环境、情景、时间有关,任何一个 条件的变化,都会导致业务的实现变化。对于程序员来说,积累项目经验,就是积累业务经 验。如:银行、电信、电商、交友社区等不同的行业,登录业务差别的非常大。银行要求必 须有足够的安全,网银需要有 U 盾、电话银行必须绑定手机号、ATM 必须使用卡片或手机预约、柜台必须持有个人有效证件。电信只要手机号是对的就行。电商要求身份和凭证有效, 在支付的时候需要提供额外的支付凭证。交友平台只看身份和凭证,甚至可以游客访问,可 以游客交流,可以三方登录等。

2 项目的开发过程有哪些?
2.1 需求过程

由销售、售前、架构、项目经理、项目组长、开发代表、测试经理、测试组长、测试代 表等参与完成。

确认一个项目都要做什么功能实现的环节。

如:Ting 域主持人管理平台中需求如下:

用户登录: 用户登录、菜单查询

成员管理: 主持人管理-新增主持人、修改主持人信息、修改主持人权限、修改主持人 帐号状态、删除主持人、分页查询、多条件分页查询;婚庆公司管理-新增婚庆公司、修改 公司信息、修改公司状态、分页查询、多条件分页查询、删除公司;新人管理-分页查询、 多条件分页查询。

2.2 分析过程

参与人员:架构、项目经理、项目组长、开发代表(可能是全体开发人员)

就是分析实现一个具体的功能,需要如何去做。需要什么数据、需要如何操作数据、需 要如何管理事务、需要如何控制逻辑、需要根据什么确定返回结果等。

需要明确一个需求,在实现的过程中,都经过哪些接口、类型、方法的处理;传入参数 是什么,有什么标准;输出参数是什么,有什么标准;异常处理应该如何实现,是自定义异常还是使用 JDK 提供的异常;控制器返回结果的时候,是返回 AJAX 异步处理结果 (ResponseBody)还是一个视图结果,当发生异常的时候,要进入哪一个错误提示页面等。

2.3 开发过程

用代码技术实现需求的过程。

二、 项目功能分析

1 模块划分

所谓的模块,就是当前工程中,可以绑定开发的多个功能。如:用户管理模块包含新增 用户、修改用户、删除用户、查询用户等。

1.1 用户登录模块

用户登录。 传入参数:用户名(身份)、密码(凭证)、记住我(rememberMe) 输出参数:显示主页面(返回视图地址)、实现权限查询、身份数据记录(session 记 录)

1.1.1 用例图

在这里插入图片描述

1.1.2 时序图

在这里插入图片描述

1.1.3 类图

在这里插入图片描述

1.2 系统公告管理(CMS 系统)

Content Manager(Management) System 内容管理系统。用户管理平台编辑内容。

客户平台可以查看内容。类似百度中的新闻。

在这里插入图片描述

1.2.1 公告类别管理

新增公告类别:输入-公告类别名称和公告类别描述;输出-显示分页查询公告类别页面

删除公告类别:输入-公告类别的主键;输出-显示分页查询公告类别页面

修改公告类别:输入-公告类别的主键;输出-显示修改公告类别详情表单页面;二次输 入-修改后的公告类别数据;输出-分页查询公告类别页面

分页查询公告类别:输入-页码和每页显示数据数量; 输出-显示逻辑

1.2.2 公告管理

新增公告;修改公告;删除公告;分页查询公告;名称模糊分页查询。

三、 数据建模

一般都是 DBA 数据库管理员进行设计的。就是数据库的库表设计。

用户数据如下:
在这里插入图片描述

四、 基础环境搭建

使用一个脚手架实现快速的开发。 使用的脚手架是若依开发平台。是一个使用 SpringBoot+Shiro 实现的一个后台统一 管理模板。在若依脚手架中,提供了若干统一管理能力。如:用户管理、权限管理、菜单管 理、角色管理等。

1 创建数据库

在这里插入图片描述

2 导入数据脚本

在软件目录中,有 02 若依子目录,其中有连个 sql 脚本。ry_20191122.sql、quartz.sql。 依次执行连个数据库脚本,初始化表格内容。

3 创建工程

创建一个 Maven 工程,根据已有的工程进行导入创建。已有工程命名为 Ting。工程 所在位置在软件目录/02 若依/Ting

4 启动

启动 com.ruoyi.RuoYiApplication。

访问 http://localhost/。

默认提供的超级管理员 帐户:
用户名-admin;
密码-admin123

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

主要内容

  1. CMS 内容管理实现

在这里插入图片描述

一、 CMS 内容管理实现

1 登录页面视图修改
1.1 找到登录页面

在这里插入图片描述

1.2 修改内容

在这里插入图片描述

2 主页面视图修改
2.1 找到主页面视图

在这里插入图片描述

2.2 修改内容

修改 32 行显示内容:
在这里插入图片描述
注释 78~168 行视图代码

在这里插入图片描述
注释 184~185 行视图代码

在这里插入图片描述

3 修改工作台首页选项卡内容
3.1 找到首页视图

在这里插入图片描述

3.2 修改内容

注释全部显示内容,添加自定义内容。
在这里插入图片描述

4 菜单管理操作

添加需要的权限。并提供对应角色和用户。

4.1 进入菜单管理页面

在这里插入图片描述

4.2 新增需要的菜单
4.2.1 点击新增按钮

在这里插入图片描述

4.2.2 编辑目录内容

在这里插入图片描述

4.2.3 为目录添加菜单

在这里插入图片描述

4.2.4 编辑菜单内容

在这里插入图片描述

4.2.5 为菜单添加按钮权限

在这里插入图片描述

4.2.6 编辑按钮内容

在这里插入图片描述

5 角色管理操作
5.1 进入角色管理页面

在这里插入图片描述

5.2 新增需要的角色
5.2.1 点击新增按钮

在这里插入图片描述

5.2.2 编辑角色内容

在这里插入图片描述

6 用户管理操作
6.1 进入用户管理页面

在这里插入图片描述

6.2 新增需要的用户
6.2.1 点击新增按钮

在这里插入图片描述

6.2.2 编辑用户内容

在这里插入图片描述

7 CMS 分类管理
7.1 公告分类分页查询
7.1.1 视图开发

创建 html 视图文件:src/main/resources/templates/cms/type/type.html

在这里插入图片描述

具体内容如下:

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <th:block th:include="include :: header('公告类型列表')" />
</head>
<body class="gray-bg">
<div class="container-div">
    <div class="row">
        <div class="col-sm-12 search-collapse">
            <form id="post-form">
                <div class="select-list">
                    <ul>
                        <li>
                            类型名称:<input type="text" name="typeName"/>
                        </li>
                        <li>
                            <a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
                            <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
                        </li>
                    </ul>
                </div>
            </form>
        </div>

        <div class="btn-group-sm" id="toolbar" role="group">
            <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="cms:type:add">
                <i class="fa fa-plus"></i> 新增
            </a>
            <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="cms:type:edit">
                <i class="fa fa-edit"></i> 修改
            </a>
            <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="cms:type:remove">
                <i class="fa fa-remove"></i> 删除
            </a>
        </div>

        <div class="col-sm-12 select-table table-striped">
            <table id="bootstrap-table"></table>
        </div>
    </div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
    // @permission.hasPermi('cms:type:edit')  调用作用域中的Shiro提供的内置对象,做权限校验。
    var editFlag = [[${@permission.hasPermi('cms:type:edit')}]];
    var removeFlag = [[${@permission.hasPermi('cms:type:remove')}]];
    var datas = [[${@dict.getType('sys_normal_disable')}]];
    var prefix = ctx + "cms/type";

    $(function() {
        var options = {
            url: prefix + "/list", // 查询路径地址。就是分页查询
            createUrl: prefix + "/add", // 新增路径地址、 显示新增页面和提交新增数据同地址。不同请求方式。 get请求显示新增视图, post请求提交新增数据
            updateUrl: prefix + "/edit/{id}", // 修改路径地址。 根据主键查询,或提交修改内容
            removeUrl: prefix + "/remove", // 删除路径地址。
            // exportUrl: prefix + "/export", // 到处表格路径地址
            sortName: "typeSort", // 定义短名称
            modalName: "公告类型",
            columns: [{
                    checkbox: true // 复选框
                },
                {
                    field: 'typeId',
                    title: '公告类型编号',
                    sortable: true
                },
                {
                    field: 'typeName',  // 提供要显示的数据的属性名称。
                    title: '公告类型名称',
                    sortable: true
                },
                {
                    field: 'remark',
                    title: '公告类型描述',
                    sortable: true
                },
                {
                    field: 'typeSort',
                    title: '显示顺序',
                    sortable: true
                },
                {
                    field: 'status',
                    title: '状态',
                    align: 'center',
                    formatter: function(value, row, index) {
                        return $.table.selectDictLabel(datas, value);
                    }
                },
                {
                    title: '操作',
                    align: 'center',
                    formatter: function(value, row, index) {
                        var actions = [];
                        actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" οnclick="$.operate.edit(\'' + row.typeId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" οnclick="$.operate.remove(\'' + row.typeId + '\')"><i class="fa fa-remove"></i>删除</a>');
                        return actions.join('');
                    }
                }]
        };
        $.table.init(options);
    });
</script>
</body>
</html>
7.1.1.1视图中的注意点

th:include - 导入其他 html 内容。下述’图 1’内容代表导入一个命名为 include.html 的视图中的 header 部分内容,且在导入的同时,传入参数’公告类型列表’。'图 2’是 include.html 文件内容片段
在这里插入图片描述
搜索函数和表单重置:'图 3’内容是 type.html 中的代码片段,用于触发条件分页查询 和表单重置。其中的 . t a b l e 和 .table 和 .table.form 都是若依脚手架提供的 JavaScript 函数。函数定义 在 src/main/resources/static/ruoyi/js/ry-ui.js 文件中。'图 4’和’图 5’为 ry-ui.js 代码片 段截图。
在这里插入图片描述

7.1.2 常量接口
package com.ruoyi.project.cms.type.commons;

public interface CMSTypeConst {
    // 返回视图的前缀。相当于src/resources/templates/目录名称
    String PREFIX = "cms/type";
    // 所有公告类型相关控制器的访问路径前缀。
    String PATH_PREFIX = "/cms/type";

    // 公告类型名称唯一
    String TYPE_NAME_UNIQUE = "0";
    // 公告类型名称不唯一
    String TYPE_NAME_NOT_UNIQUE = "1";
}

7.1.3 实体类型
package com.ruoyi.project.cms.type.domain;

import com.ruoyi.framework.web.domain.BaseEntity;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

public class CMSType extends BaseEntity {
    private static final long serialVersionUID = 1L;

    private Long typeId;
    private String typeName;
    private String typeSort;
    private String status;

    public Long getTypeId() {
        return typeId;
    }

    public void setTypeId(Long typeId) {
        this.typeId = typeId;
    }

    @NotBlank(message = "公告类型名称不能为空")
    @Size(min = 0, max = 50, message = "公告类型名称长度不能超过50个字符")
    public String getTypeName() {
        return typeName;
    }

    public void setTypeName(String typeName) {
        this.typeName = typeName;
    }

    @NotBlank(message = "显示顺序不能为空")
    public String getTypeSort() {
        return typeSort;
    }

    public void setTypeSort(String typeSort) {
        this.typeSort = typeSort;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

7.1.4 控制器开发
package com.ruoyi.project.cms.type.controller;

import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.cms.type.commons.CMSTypeConst;
import com.ruoyi.project.cms.type.domain.CMSType;
import com.ruoyi.project.cms.type.service.ICMSTypeService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 老金
 *
 * @version 1.0
 *
 * 分页查询公告类型控制器
 */
@Controller
@RequestMapping(CMSTypeConst.PATH_PREFIX)
public class CMSTypeController extends BaseController {

    @Autowired
    private ICMSTypeService typeService;

    @RequiresPermissions("cms:type:view")
    @GetMapping
    public String view(){
        return CMSTypeConst.PREFIX + "/type";
    }

    @RequiresPermissions("cms:type:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(CMSType type){

        // 分页处理
        startPage();

        // 查询, 通过服务代码,调用Mapper逻辑,查询数据库中的数据。
        List<CMSType> list = typeService.selectCMSTypeList(type);

        return getDataTable(list);
    }

}

7.1.5 服务接口开发
package com.ruoyi.project.cms.type.service;

import com.ruoyi.project.cms.type.domain.CMSType;

import java.util.List;

/**
 * @author 老金
 * @version 1.0
 * 公告类型管理服务接口 - 处理分页查询公告类型
 */
public interface ICMSTypeService {
    /**
     * 查询公告类型信息集合 - 分页查询,使用PageHelper插件实现分页。
     *
     * @param type 公告类型信息 - 查询条件
     * @return 公告类型信息集合
     */
    public List<CMSType> selectCMSTypeList(CMSType type);
}

7.1.6 服务实现开发
package com.ruoyi.project.cms.type.service;

import com.ruoyi.project.cms.type.domain.CMSType;
import com.ruoyi.project.cms.type.mapper.CMSTypeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author 老金
 * @version 1.0
 * 公告类型管理服务实现 - 处理分页查询公告类型
 */
@Service
public class CMSTypeServiceImpl implements ICMSTypeService {

    // 公告类型数据访问接口
    @Autowired
    private CMSTypeMapper typeMapper;

    @Override
    public List<CMSType> selectCMSTypeList(CMSType type) {
        return typeMapper.selectCMSTypeList(type);
    }
}

7.1.7 数据访问接口开发
package com.ruoyi.project.cms.type.mapper;

import com.ruoyi.project.cms.type.domain.CMSType;

import java.util.List;

/**
 * @author 老金
 * @version 1.0
 * 公告类型数据访问接口 - 专门处理查询公告类型数据
 */
public interface CMSTypeMapper {
    /**
     * 查询公告类型数据集合
     *
     * @param type 公告类型信息
     * @return 公告类型数据集合
     */
    List<CMSType> selectCMSTypeList(CMSType type);
}

7.1.8 SQL 映射文件

在 src/main/resources/mybatis/cms 目录中编写 XML 文件:CMSTypeMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.project.cms.type.mapper.CMSTypeMapper">
    <!-- 查询结果resultSet和实体类型CMSType之间的映射关系 -->
    <resultMap type="CMSType" id="CMSTypeResult">
        <id     property="typeId"        column="type_id"       />
        <result property="typeName"      column="type_name"     />
        <result property="typeSort"      column="type_sort"     />
        <result property="status"        column="status"        />
        <result property="createBy"      column="create_by"     />
        <result property="createTime"    column="create_time"   />
        <result property="updateBy"      column="update_by"     />
        <result property="updateTime"    column="update_time"   />
        <result property="remark"        column="remark"        />
    </resultMap>

    <!-- 条件查询 -->
    <select id="selectCMSTypeList" parameterType="CMSType" resultMap="CMSTypeResult">
        select type_id, type_name, type_sort, status, create_by, create_time, update_by, update_time, remark
        from cms_type
        <where>
            <if test="typeName != null and typeName != ''">
            <!-- concat是MySQL数据库中的函数,用来实现字符串拼接。
                 concat(string...)
             -->
                AND type_name like concat('%', #{typeName}, '%')
            </if>
        </where>
    </select>
</mapper>
7.1.9 实现结果

在这里插入图片描述

7.2 新增公告分类
7.2.1 视图开发

创建 html 视图文件:src/main/resources/templates/cms/type/add.html

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
    <th:block th:include="include :: header('新增公告类型')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
    <form class="form-horizontal m" id="form-post-add">
        <div class="form-group">
            <label class="col-sm-3 control-label">公告类型名称:</label>
            <div class="col-sm-8">
                <input class="form-control" type="text" name="typeName" id="typeName" required>
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-3 control-label">显示顺序:</label>
            <div class="col-sm-8">
                <input class="form-control" type="text" name="typeSort" id="typeSort" required>
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-3 control-label">状态:</label>
            <div class="col-sm-8">
                <div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
                    <input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:checked="${dict.default}">
                    <label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
                </div>
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-3 control-label">备注:</label>
            <div class="col-sm-8">
                <textarea id="remark" name="remark" class="form-control"></textarea>
            </div>
        </div>
    </form>
</div>
<th:block th:include="include :: footer" />
<script type="text/javascript">
    var prefix = ctx + "cms/type";

    $("#form-post-add").validate({
        onkeyup: false,
        rules:{
            typeName:{
                remote: {
                    url: prefix + "/checkTypeNameUnique",
                    type: "post",
                    dataType: "json",
                    data: {
                        "typeName" : function() {
                            return $.common.trim($("#typeName").val());
                        }
                    },
                    dataFilter: function(data, type) {
                        return $.validate.unique(data);
                    }
                }
            },
            typeSort:{
                digits:true
            },
        },
        messages: {
            "typeName": {
                remote: "公告类型名称已经存在"
            }
        },
        focusCleanup: true
    });

    function submitHandler() { // 提交新增公告类型请求。
        if ($.validate.form()) {
            $.operate.save(prefix + "/add", $('#form-post-add').serialize());
        }
    }
</script>
</body>
</html>

7.2.2 控制器开发
package com.ruoyi.project.cms.type.controller;

import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.cms.type.commons.CMSTypeConst;
import com.ruoyi.project.cms.type.domain.CMSType;
import com.ruoyi.project.cms.type.service.ICMSTypeAddService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author 老金
 *
 * @version 1.0
 *
 * 新增公告类型控制器
 */
@Controller
@RequestMapping(CMSTypeConst.PATH_PREFIX)
public class CMSTypeAddController extends BaseController {

    @Autowired
    private ICMSTypeAddService icmsTypeAddService;

    /**
     * 新增公告类型到数据库, 要求必须有权限cms:type:add才可访问当前方法。
     * 注解Validated - 用于校验请求参数。需要配合实体类型中get/set方法上定义的注解实现校验。
     * @param type 要新增的公告类型
     * @return
     */
    @RequiresPermissions("cms:type:add")
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult add(@Validated CMSType type){
        if(CMSTypeConst.TYPE_NAME_NOT_UNIQUE.equals(icmsTypeAddService.checkTypeNameUnique(type))){
            // 公告类型名称不可用。
            return error("新增公告类型'" + type.getTypeName() + "'失败,公告类型名称已存在");
        }

        // 调用服务逻辑,新增数据到数据库。
        // toAjax是父类型BaseController中定义的方法。 根据新增行数判断是否成功。新增数据行数大于0,成功。反之失败。
        return toAjax(icmsTypeAddService.addCMSType(type));
    }

    /**
     * 新增公告类型页面跳转
     */
    @GetMapping("/add")
    public String toAdd(){
        return CMSTypeConst.PREFIX + "/add";
    }

    /**
     * 检查公告类型名称是否唯一
     * @return
     *   字符串0 - 唯一数据,可以使用
     *   字符串1 - 非唯一数据,不可使用
     */
    @PostMapping("/checkTypeNameUnique")
    @ResponseBody
    public String checkTypeNameUnique(CMSType type){
        return icmsTypeAddService.checkTypeNameUnique(type);
    }

}

7.2.3 服务接口开发
package com.ruoyi.project.cms.type.service;

import com.ruoyi.project.cms.type.domain.CMSType;

/**
 * @author 老金
 *
 * @version 1.0
 *
 * 公告类型服务接口 - 处理新增相关业务
 */
public interface ICMSTypeAddService {
    /**
     * 判断公告类型名称是否唯一
     * @param type 查询参数
     * @return 0 - 唯一可用。 1 - 不唯一不可用。
     */
    String checkTypeNameUnique(CMSType type);

    /**
     * 新增数据到数据库
     * @param type
     * @return
     */
    int addCMSType(CMSType type);
}

7.2.4 服务实现开发
package com.ruoyi.project.cms.type.service;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.project.cms.type.commons.CMSTypeConst;
import com.ruoyi.project.cms.type.domain.CMSType;
import com.ruoyi.project.cms.type.mapper.CMSTypeAddMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author 老金
 * @version 1.0
 * 新增公告类型服务实现
 */
@Service
public class CMSTypeAddServiceImpl implements ICMSTypeAddService {

    @Autowired
    private CMSTypeAddMapper typeAddMapper;

    @Override
    public String checkTypeNameUnique(CMSType type) {
        // 当前可能是在修改公告类型,也可能在新增公告类型。 如果是修改,则需要判定主键。
        Long typeId = StringUtils.isNull(type.getTypeId()) ? -1L : type.getTypeId();
        CMSType info = typeAddMapper.checkTypeNameUnique(type.getTypeName());
        if (StringUtils.isNotNull(info) && info.getTypeId().longValue() != typeId.longValue())
        {
            return CMSTypeConst.TYPE_NAME_NOT_UNIQUE;
        }
        return CMSTypeConst.TYPE_NAME_UNIQUE;
    }

    @Override
    public int addCMSType(CMSType type) {
        // 将当前登录用户的登录名,赋值到createBy属性中。
        type.setCreateBy(ShiroUtils.getLoginName());

        return typeAddMapper.insertCMSType(type);
    }
}

7.2.5 数据访问接口开发
package com.ruoyi.project.cms.type.mapper;

import com.ruoyi.project.cms.type.domain.CMSType;

/**
 * 新增公告类型数据访问接口
 */
public interface CMSTypeAddMapper {
    /**
     * 根据公告类型名称查询公告类型对象
     * @param typeName 查询条件
     * @return
     */
    CMSType checkTypeNameUnique(String typeName);

    /**
     * 新增公告类型
     * @param type 要新增的数据
     * @return
     */
    int insertCMSType(CMSType type);
}

7.2.6 SQL 映射文件

在 src/main/resources/mybatis/cms 目 录 中 编 写 XML 文 件 : CMSTypeAddMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.project.cms.type.mapper.CMSTypeAddMapper">

    <!--新增公告类型-->
    <insert id="insertCMSType" parameterType="CMSType" useGeneratedKeys="true" keyProperty="typeId">
        insert into cms_type(
        <if test="typeId != null and typeId != 0">type_id,</if>
        <if test="typeName != null and typeName != ''">type_name,</if>
        <if test="typeSort != null and typeSort != ''">type_sort,</if>
        <if test="status != null and status != ''">status,</if>
        <if test="remark != null and remark != ''">remark,</if>
        <if test="createBy != null and createBy != ''">create_by,</if>
        create_time
        ) values (
        <if test="typeId != null and typeId != 0">#{typeId},</if>
        <if test="typeName != null and typeName != ''">#{typeName},</if>
        <if test="typeSort != null and typeSort != ''">#{typeSort},</if>
        <if test="status != null and status != ''">#{status},</if>
        <if test="remark != null and remark != ''">#{remark},</if>
        <if test="createBy != null and createBy != ''">#{createBy},</if>
        sysdate()
        )
    </insert>

    <!-- 根据公告类型名称查询公告类型对象 -->
    <select id="checkTypeNameUnique" parameterType="String"
            resultMap="com.ruoyi.project.cms.type.mapper.CMSTypeMapper.CMSTypeResult">
        select type_id, type_name, type_sort, status, create_by, create_time, update_by, update_time, remark
        from cms_type
        where type_name = #{typeName}
    </select>

</mapper>
7.2.7 实现结果

'图 6’为新增公告类型“名称重复”情况发生时的提示视图;'图 7’为正常新增公告类 型数据视图。
在这里插入图片描述
在这里插入图片描述

7.3 修改公告分类
7.3.1 视图开发

创建 html 视图文件:src/main/resources/templates/cms/type/edit.html
在这里插入图片描述

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
    <th:block th:include="include :: header('修改公告类型')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
    <form class="form-horizontal m" id="form-post-edit" th:object="${type}">
        <input id="typeId" name="typeId" type="hidden" th:field="*{typeId}"/>
        <div class="form-group">
            <label class="col-sm-3 control-label">公告类型名称:</label>
            <div class="col-sm-8">
                <input class="form-control" type="text" name="typeName" id="typeName" th:field="*{typeName}" required>
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-3 control-label">显示顺序:</label>
            <div class="col-sm-8">
                <input class="form-control" type="text" name="typeSort" id="typeSort" th:field="*{typeSort}" required>
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-3 control-label">状态:</label>
            <div class="col-sm-8">
                <div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
                    <input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:field="*{status}">
                    <label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
                </div>
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-3 control-label">备注:</label>
            <div class="col-sm-8">
                <textarea id="remark" name="remark" class="form-control">[[*{remark}]]</textarea>
            </div>
        </div>
    </form>
</div>
<th:block th:include="include :: footer" />
<script type="text/javascript">
    var prefix = ctx + "cms/type";

    $("#form-post-edit").validate({
        onkeyup: false,
        rules:{
            typeName:{
                remote: {
                    url: prefix + "/checkTypeNameUnique",
                    type: "post",
                    dataType: "json",
                    data: {
                        "typeId": function() {
                            return $("input[name='typeId']").val();
                        },
                        "typeName" : function() {
                            return $.common.trim($("#typeName").val());
                        }
                    },
                    dataFilter: function(data, type) {
                        return $.validate.unique(data);
                    }
                }
            },
            typeSort:{
                digits:true
            },
        },
        messages: {
            "typeName": {
                remote: "公告类型名称已经存在"
            }
        },
        focusCleanup: true
    });

    function submitHandler() {
        if ($.validate.form()) {
            $.operate.save(prefix + "/edit", $('#form-post-edit').serialize());
        }
    }
</script>
</body>
</html>

7.3.2 控制器开发
package com.ruoyi.project.cms.type.controller;

import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.cms.type.commons.CMSTypeConst;
import com.ruoyi.project.cms.type.domain.CMSType;
import com.ruoyi.project.cms.type.service.ICMSTypeAddService;
import com.ruoyi.project.cms.type.service.ICMSTypeEditService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@Controller
@RequestMapping(CMSTypeConst.PATH_PREFIX)
public class CMSTypeEditController extends BaseController {
    @Autowired
    private ICMSTypeEditService editService;
    @Autowired
    private ICMSTypeAddService addService;

    /**
     * 修改公告类型数据。就是要根据主键更新其他字段。
     * @param type
     * @return
     */
    @RequiresPermissions("cms:type:edit")
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult edit(@Validated CMSType type){
        // 判断公告类型的名称是否可用。
        if(CMSTypeConst.TYPE_NAME_NOT_UNIQUE.equals(addService.checkTypeNameUnique(type))){
            // 公告类型名称不可用
            return error();
        }

        // 更新数据。并返回结果。更新行数大于0,代表更新成功。反之失败。
        return toAjax(editService.editCMSType(type));
    }

    /**
     * 根据主键查询公告类型
     * @param id 公告类型主键
     * @return 视图
     */
    @GetMapping("/edit/{id}")
    public String toEdit(@PathVariable("id") Long id, Model model){
        CMSType type = editService.selectCMSTypeByPK(id);
        model.addAttribute("type", type);
        return CMSTypeConst.PREFIX + "/edit";
    }
}

7.3.3 服务接口开发
package com.ruoyi.project.cms.type.service;

import com.ruoyi.project.cms.type.domain.CMSType;

/**
 * @author  老金
 * @version 1.0
 * 修改公告类型服务接口
 */
public interface ICMSTypeEditService {
    /**
     * 根据主键查询公告类型
     * @param id
     * @return
     */
    CMSType selectCMSTypeByPK(Long id);

    /**
     * 根据主键更新公告类型。
     * @param type
     * @return
     */
    int editCMSType(CMSType type);
}

7.3.4 服务实现开发
package com.ruoyi.project.cms.type.service;

import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.project.cms.type.domain.CMSType;
import com.ruoyi.project.cms.type.mapper.CMSTypeEditMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author 老金
 * @version 1.0
 * 修改公告类型服务实现
 */
@Service
public class CMSTypeEditServiceImpl implements ICMSTypeEditService {
    @Autowired
    private CMSTypeEditMapper editMapper;
    @Override
    public CMSType selectCMSTypeByPK(Long id) {
        return editMapper.selectByPK(id);
    }

    @Override
    public int editCMSType(CMSType type) {
        // 设置更新者名称
        type.setUpdateBy(ShiroUtils.getLoginName());
        return editMapper.updateCMSType(type);
    }
}

7.3.5 数据访问接口开发
package com.ruoyi.project.cms.type.mapper;

import com.ruoyi.project.cms.type.domain.CMSType;

/**
 * @author 老金
 * @version 1.0
 * 修改公告类型数据访问接口
 */
public interface CMSTypeEditMapper {
    /**
     * 主键查询公告类型
     * @param id
     * @return
     */
    CMSType selectByPK(Long id);

    /**
     * 根据主键更新公告类型
     * @param type
     * @return
     */
    int updateCMSType(CMSType type);
}

7.3.6 SQL 映射文件

在 src/main/resources/mybatis/cms 目 录 中 编 写 XML 文 件 : CMSTypeEditMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.project.cms.type.mapper.CMSTypeEditMapper">
    <!-- 根据主键更新公告类型 -->
    <update id="updateCMSType" parameterType="CMSType">
        update cms_type
        <set>
            <if test="typeName != null and typeName != ''">type_name = #{typeName},</if>
            <if test="typeSort != null and typeSort != ''">type_sort = #{typeSort},</if>
            <if test="status != null and status != ''">status = #{status},</if>
            <if test="remark != null">remark = #{remark},</if>
            <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
            update_time = sysdate()
        </set>
        where type_id = #{typeId}
    </update>
    <!-- 主键查询公告类型 -->
    <select id="selectByPK" parameterType="long"
            resultMap="com.ruoyi.project.cms.type.mapper.CMSTypeMapper.CMSTypeResult">
        select type_id, type_name, type_sort, status, create_by, create_time, update_by, update_time, remark
        from cms_type
        where type_id = #{id}
    </select>
</mapper>
7.3.7 实现结果

'图 8’和’图 9’为两种进入编辑公告类型的方式。
在这里插入图片描述
在这里插入图片描述
'图 10’为修改公告类型“公告名称重复”情况发生时的提示视图。
在这里插入图片描述
'图 11’是正常修改公告类型数据视图。
在这里插入图片描述

7.4 删除公告分类
7.4.1 控制器开发
package com.ruoyi.project.cms.type.controller;

import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.cms.type.commons.CMSTypeConst;
import com.ruoyi.project.cms.type.service.ICMSTypeRemoveService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author 老金
 * @version 1.0
 * 删除公告类型控制器
 */
@Controller
@RequestMapping(CMSTypeConst.PATH_PREFIX)
public class CMSTypeRemoveController extends BaseController {
    @Autowired
    private ICMSTypeRemoveService removeService;

    /**
     * 删除公告类型
     * @param ids 要删除的公告类型的主键,多个主键使用逗号分隔
     * @return
     */
    @PostMapping("/remove")
    @RequiresPermissions("cms:type:remove")
    @ResponseBody
    public AjaxResult remove(String ids){
        try{
            return toAjax(removeService.removeCMSTypeByIds(ids));
        }catch(Exception e){
            return error(e.getMessage());
        }
    }
}

7.4.2 服务接口开发
package com.ruoyi.project.cms.type.service;

/**
 * @author 老金
 * @version 1.0
 * 删除公告类型服务接口
 */

public interface ICMSTypeRemoveService {
    /**
     * 根据主键删除公告类型。
     * @param ids 要删除的公告类型主键。如果是批量删除,多个主键之间使用逗号分隔。
     * @return
     */
    int removeCMSTypeByIds(String ids);
}

7.4.3 服务实现开发
package com.ruoyi.project.cms.type.service;

import com.ruoyi.common.utils.text.Convert;
import com.ruoyi.project.cms.type.mapper.CMSTypeRemoveMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author 老金
 * @version 1.0
 * 删除公告类型服务实现
 */
@Service
public class CMSTypeRemoveServiceImpl implements ICMSTypeRemoveService {
    @Autowired
    private CMSTypeRemoveMapper removeMapper;

    /**
     * 删除公告类型
     * @param ids 要删除的公告类型主键。如果是批量删除,多个主键之间使用逗号分隔。
     * @return
     */
    @Override
    public int removeCMSTypeByIds(String ids) {
        Long[] typeIds = Convert.toLongArray(ids);

        return removeMapper.deleteCMSTypeByIds(typeIds);
    }
}

7.4.4 数据访问接口开发
package com.ruoyi.project.cms.type.mapper;

import org.apache.ibatis.annotations.Param;

/**
 * @author 老金
 * @version 1.0
 * 删除公告类型数据访问接口
 */
public interface CMSTypeRemoveMapper {
    /**
     * 主键删除公告类型。 此方法支持批量删除
     * @param typeIds
     * @return
     */
    int deleteCMSTypeByIds(@Param("ids") Long[] typeIds);
}

7.4.5 SQL 映射文件

在 src/main/resources/mybatis/cms 目 录 中 编 写 XML 文 件 : CMSTypeRemoveMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.project.cms.type.mapper.CMSTypeRemoveMapper">
    <delete id="deleteCMSTypeByIds" parameterType="Long">
        delete from cms_type where type_id in
        <foreach collection="ids" item="typeId" open="(" separator="," close=")">
            #{typeId}
        </foreach>
    </delete>
</mapper>
7.4.6 实现结果

'图 12’为删除单一公告类型方式。

在这里插入图片描述
'图 13’为删除单一公告类型确认框提示。
在这里插入图片描述
'图 14’为批量删除公告类型方式。

在这里插入图片描述
'图 15’为批量删除公告类型确认框提示。
在这里插入图片描述
项目练习源码:https://gitee.com/cutelili/Ting

zookeeper

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
系统集成项目管理师的十五至尊图是指系统集成项目管理师考试中的十五个重要知识点,分别是: 1. 项目管理概论:介绍项目管理的定义、特点、项目生命周期、项目管理过程组等基本概念和知识点。 2. 项目整体管理:包括项目启动、规划、执行、监控和收尾等过程。 3. 项目范围管理:涵盖项目范围规划、需求收集、范围定义、范围确认和范围控制等过程。 4. 项目进度管理:包括进度计划制定、进度控制、时间估算和网络图技术等知识点。 5. 项目成本管理:介绍成本管理的基本概念、成本估算方法、成本控制等知识点。 6. 项目质量管理:包括质量计划、质量保证、质量控制等过程。 7. 项目资源管理:包括人力资源规划、团队建设、项目组织、通信管理等内容。 8. 项目风险管理:涵盖风险管理的概念、风险识别、风险评估、风险应对等过程。 9. 项目采购管理:介绍项目采购管理的基本概念、采购规划、采购执行和采购控制等知识点。 10. 项目沟通管理:包括沟通管理的基本概念、沟通计划、沟通执行和沟通监控等过程。 11. 项目干系人管理:包括干系人识别、干系人参与和干系人管理等内容。 12. 项目信息管理:包括信息收集、信息分类、信息分析和信息传递等知识点。 13. 项目环境管理:包括政治、经济、社会、技术、环境等方面的影响因素。 14. 项目法律法规和职业道德:介绍项目管理中的法律法规和职业道德等知识点。 15. 项目实战:通过案例分析、项目管理工具和技术等方式,深入了解项目管理实践。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值