# 模块生成

# 案例概述

在前面章节《模板介绍》中我们详细的说明了获取数据源的方式以及封装了生成每个模块文件的具体方法,绑定数据源进行模板标签替换后生成对应的模块文件并移入指定的目录中,实现的原理是获取数据表的列详细信息,包装成一个有效数据源的数组绑定到模板并进行替换,下面我们将以示例模块讲述具体的实现流程:

# 代码生成

登录后台管理系统后,打开系统管理=>系统工具=>代码生成管理模块,此时我们所看到的便是框架所集成的代码生成器模块,点击代码生成菜单,呈现出来的是当前数据库中的所有数据表,我们可以选择所需要生成模块的数据表点击一键生成模块确定后便可自动调用代码生成程序生成当前数据表所对应的模块,如下图所示:

  • 选择数据表

    mixureSecure

# 模块生成

上一步已经选择所需生成模块的数据表,这一步就可以生成模块文件了,点击同意生成确认框之后,程序会自动创建所有模块文件,包括:控制器文件模型文件服务类文件数据列表文件编辑表单文件模块JS文件,文件会按照设置路径存放值指定的目录,我们已数据表think_test为例生成模块文件,数据表脚本如下:

CREATE TABLE `think_demo`  (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '唯一性标识',
  `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '职级名称',
  `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像',
  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '状态:1正常 2停用',
  `type` int(10) UNSIGNED NULL DEFAULT 1 COMMENT '类型:1京东 2淘宝 3拼多多 4唯品会',
  `is_vip` tinyint(1) UNSIGNED NULL DEFAULT 2 COMMENT '是否VIP:1是 2否',
  `sort` smallint(5) UNSIGNED NULL DEFAULT 125 COMMENT '显示顺序',
  `create_user` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '添加人',
  `create_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '添加时间',
  `update_user` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '更新人',
  `update_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '更新时间',
  `mark` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '有效标识',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `name`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '演示管理表' ROW_FORMAT = Dynamic;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

生成的模块文件如下:

  • 控制器文件(Demo.php)
<?php 
// +----------------------------------------------------------------------
// | RXThinkCMF框架 [ RXThinkCMF ]
// +----------------------------------------------------------------------
// | 版权所有 2017~2020 南京RXThinkCMF研发中心
// +----------------------------------------------------------------------
// | 官方网站: http://www.rxthink.cn
// +----------------------------------------------------------------------
// | Author: 牧羊人 <1175401194@qq.com>
// +----------------------------------------------------------------------

namespace app\admin\controller;


use app\admin\service\DemoService;
use app\common\controller\Backend;

/**
 * 演示管理-控制器
 * @author 牧羊人
 * @since: 2020/07/17
 * Class Demo
 * @package app\admin\controller
 */
class Demo extends Backend
{
    /**
     * 初始化方法
     * @author 牧羊人
     * @since: 2020/07/17
     */
    public function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
        $this->model = new \app\admin\model\Demo();
        $this->service = new DemoService();
    }
	
	                	
	/**
	 * 设置状态	 
	 * @return mixed
	 * @since 2020/07/17	 
	 * @author 牧羊人	 
	 */
	public function setStatus()
	{
		if (IS_POST) {
			$result = $this->service->setStatus();
			return $result;
		}
	}
	        	
	/**
	 * 设置是否VIP	 
	 * @return mixed
	 * @since 2020/07/17	 
	 * @author 牧羊人	 
	 */
	public function setIsVip()
	{
		if (IS_POST) {
			$result = $this->service->setIsVip();
			return $result;
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  • 模型文件(Demo.php)
<?php 
// +----------------------------------------------------------------------
// | RXThinkCMF框架 [ RXThinkCMF ]
// +----------------------------------------------------------------------
// | 版权所有 2017~2020 南京RXThinkCMF研发中心
// +----------------------------------------------------------------------
// | 官方网站: http://www.rxthink.cn
// +----------------------------------------------------------------------
// | Author: 牧羊人 <1175401194@qq.com>
// +----------------------------------------------------------------------

namespace app\admin\model;


use app\common\model\BaseModel;

/**
 * 演示-模型
 * @author 牧羊人
 * @since: 2020/07/17
 * Class Demo
 * @package app\admin\model
 */
class Demo extends BaseModel
{
    // 设置数据表名
    protected $name = "demo";

    /**
     * 获取缓存信息
     * @param int $id 记录ID
     * @return \app\common\model\数据信息|mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @author 牧羊人
     * @since: 2020/07/17
     */
    public function getInfo($id)
    {
        $info = parent::getInfo($id); // TODO: Change the autogenerated stub
        if ($info) {
                                        
            // 头像
            $info['avatar'] = get_image_url($info['avatar']);
                                                                                                                            
        }
        return $info;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  • 服务类文件(DemoService.php)
<?php 
// +----------------------------------------------------------------------
// | RXThinkCMF框架 [ RXThinkCMF ]
// +----------------------------------------------------------------------
// | 版权所有 2017~2020 南京RXThinkCMF研发中心
// +----------------------------------------------------------------------
// | 官方网站: http://www.rxthink.cn
// +----------------------------------------------------------------------
// | Author: 牧羊人 <1175401194@qq.com>
// +----------------------------------------------------------------------

namespace app\admin\service;


use app\admin\model\Demo;
use app\common\service\BaseService;

/**
 * 演示管理-服务类
 * @author 牧羊人
 * @since: 2020/07/17
 * Class DemoService
 * @package app\admin\service
 */
class DemoService extends BaseService
{
    /**
     * 构造函数
     * LevelService constructor.
     */
    public function __construct()
    {
        $this->model = new Demo();
    }
	
	/**
     * 获取数据列表
     * @return array
     * @since 2020/07/17
     * @author 牧羊人
     */
    public function getList()
    {
        $param = request()->param();

        // 查询条件
        $map = [];
		
	
	    // 职级名称
        $name = isset($param['name']) ? trim($param['name']) : '';
        if ($name) {
            $map[] = ['name', 'like', "%{$name}%"];
        }
		
	    // 状态
        $status = isset($param['status']) ? (int)$param['status'] : 0;
        if ($status) {
            $map[] = ['status', '=', $status];
        }
		
	    // 类型
        $type = isset($param['type']) ? (int)$param['type'] : 0;
        if ($type) {
            $map[] = ['type', '=', $type];
        }
		
	    // 是否VIP
        $is_vip = isset($param['is_vip']) ? (int)$param['is_vip'] : 0;
        if ($is_vip) {
            $map[] = ['is_vip', '=', $is_vip];
        }
	
        return parent::getList($map); // TODO: Change the autogenerated stub
    }

	/**
     * 添加或编辑
     * @return array
     * @since 2020/07/17
     * @author 牧羊人
     */
    public function edit()
    {
        // 参数
        $data = request()->param();
	                                
		// 头像处理
        $avatar = trim($data['avatar']);
        if (strpos($avatar, "temp")) {
            $data['avatar'] = save_image($avatar, 'demo');
        } else {
            $data['avatar'] = str_replace(IMG_URL, "", $data['avatar']);
        }
                                                                                                                                
        return parent::edit($data); // TODO: Change the autogenerated stub
    }

                	
	/**
     * 设置状态     
	 * @return array
     * @throws \think\db\exception\BindParamException
     * @throws \think\exception\PDOException
     * @since 2020/07/17     
	 * @author 牧羊人     
	 */
    public function setStatus()
    {
		// 参数
        $data = request()->param();
        if (!$data['id']) {
            return message('记录ID不能为空', false);
        }
		if (!$data['status']) {
            return message('记录状态不能为空', false);
        }
        $error = '';
        $rowId = $this->model->edit($data, $error);
        if (!$rowId) {
            return message($error, false);
        }
        return message();
    }
	        	
	/**
     * 设置是否VIP     
	 * @return array
     * @throws \think\db\exception\BindParamException
     * @throws \think\exception\PDOException
     * @since 2020/07/17     
	 * @author 牧羊人     
	 */
    public function setIsVip()
    {
		// 参数
        $data = request()->param();
        if (!$data['id']) {
            return message('记录ID不能为空', false);
        }
		if (!$data['is_vip']) {
            return message('记录是否VIP不能为空', false);
        }
        $error = '';
        $rowId = $this->model->edit($data, $error);
        if (!$rowId) {
            return message($error, false);
        }
        return message();
    }
	                        
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  • 数据列表页文件(index.html)

<!-- 引入基类模板 -->
{extend name='public/base' /}

<!-- 主体部分 -->
{block name='content'}

    <!-- 功能操作区一 -->
    <form class="layui-form toolbar">
        <div class="layui-form-item">
                    
            <!-- 职级名称 -->
            <div class="layui-inline">
                <label class="layui-form-label w-auto">职级名称:</label>
                <div class="layui-input-inline">
                    <input type="text" name="name" placeholder="请输入职级名称" autocomplete="off" class="layui-input">
                </div>
            </div>
                                
            <!-- 状态 -->
            <div class="layui-inline">
                <label class="layui-form-label w-auto">状态:</label>
                <div class="layui-input-inline">
                    {common:select param="status|0|状态|name|id" data="1=正常,2=停用" value="0"}
                </div>
            </div>
                                
            <!-- 类型 -->
            <div class="layui-inline">
                <label class="layui-form-label w-auto">类型:</label>
                <div class="layui-input-inline">
                    {common:select param="type|0|类型|name|id" data="1=京东,2=淘宝,3=拼多多,4=唯品会" value="0"}
                </div>
            </div>
                                
            <!-- 是否VIP -->
            <div class="layui-inline">
                <label class="layui-form-label w-auto">是否VIP:</label>
                <div class="layui-input-inline">
                    {common:select param="is_vip|0|是否VIP|name|id" data="1=是,2=否" value="0"}
                </div>
            </div>
                    
            <div class="layui-inline">
                <div class="layui-input-inline" style="width: auto;">
                    {widget:query name="查询"}
                    {widget:add name="添加演示"}
                    {widget:dall name="批量删除"}
                </div>
            </div>
        </div>
    </form>

    <!-- TABLE渲染区 -->
    <table class="layui-hide" id="tableList" lay-filter="tableList"></table>

    <!-- 操作功能区二 -->
    <script type="text/html" id="toolBar">
        {widget:edit name="编辑"}
        {widget:delete name="删除"}
    </script>

    <!-- 状态 -->
    <script type="text/html" id="statusTpl">
        <input type="checkbox" name="status" value="{literal}{{ d.id }}{/literal}" lay-skin="switch" lay-text="正常|停用" lay-filter="status" {literal}{{ d.status == 1 ? 'checked' : '' }}{/literal} >
    </script>

    <!-- 是否VIP -->
    <script type="text/html" id="is_vipTpl">
        <input type="checkbox" name="is_vip" value="{literal}{{ d.id }}{/literal}" lay-skin="switch" lay-text="是|否" lay-filter="is_vip" {literal}{{ d.is_vip == 1 ? 'checked' : '' }}{/literal} >
    </script>

{/block}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  • 编辑表单文件
<form class="layui-form model-form" action="">
    <input name="id" id="id" type="hidden" value="{$info.id|default=0}">
        
    <div class="layui-form-item">
        <label class="layui-form-label">头像:</label>
        {upload:image name="avatar|头像|90x90|建议上传尺寸450x450|450x450" value="isset($info['avatar']) ? $info['avatar'] : ''"}
    </div>
            
    <div class="layui-form-item">
        <div class="layui-inline">
            <label class="layui-form-label">职级名称:</label>
            <div class="layui-input-inline">
            
                <input name="name" value="{$info['name']|default=''}" lay-verify="required" autocomplete="off" placeholder="请输入职级名称" class="layui-input" type="text">
            
            </div>
        </div>
        <div class="layui-inline">
            <label class="layui-form-label">状态:</label>
            <div class="layui-input-inline">
                            
                {common:switch name="status" title="正常|停用" value="isset($info['status']) ? $info['status'] : 1"}
                        
            </div>
        </div>
        
    </div>
            
    <div class="layui-form-item">
        <div class="layui-inline">
            <label class="layui-form-label">类型:</label>
            <div class="layui-input-inline">
                            
                {common:select param="type|1|类型|name|id" data="1=京东,2=淘宝,3=拼多多,4=唯品会" value="isset($info['type']) ? $info['type'] : 1"}
                            
            </div>
        </div>
        <div class="layui-inline">
            <label class="layui-form-label">是否VIP:</label>
            <div class="layui-input-inline">
                            
                {common:switch name="is_vip" title="是|否" value="isset($info['is_vip']) ? $info['is_vip'] : 2"}
                        
            </div>
        </div>
        
    </div>
            
    <div class="layui-form-item">
        <div class="layui-inline">
            <label class="layui-form-label">显示顺序:</label>
            <div class="layui-input-inline">
            
                <input name="sort" value="{$info['sort']|default=0}" lay-verify="required|number" autocomplete="off" placeholder="请输入显示顺序" class="layui-input" type="text">
            
            </div>
        </div>
        
    </div>
        
    {widget:submit name="submit|立即保存,close|关闭"}
</form>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  • 模块JS文件
/**
 * 演示管理
 * @author 牧羊人
 * @since 2020/07/17
 */
layui.use(['function'], function () {
    //声明变量
    var func = layui.function
        , $ = layui.$;

    if (A == 'index') {
        //【TABLE列数组】
        var cols = [
            {type: 'checkbox', fixed: 'left'}
            , {field: 'id', width: 80, title: 'ID', align: 'center', sort: true, fixed: 'left'}
            , {field: 'name', width: 100, title: '职级名称', align: 'center'}
            , {field: 'avatar', width: 60, title: '头像', align: 'center', templet: function (d) {
                var avatar = "";
                if (d.avatar) {
                    avatar = '<a href="' + d.avatar + '" target="_blank"><img src="' + d.avatar + '" height="26" /></a>';
                }
                return avatar;
                }
            }
            , {field: 'status', width: 100, title: '状态', align: 'center', templet: '#statusTpl'}
            , {field: 'type', width: 100, title: '类型', align: 'center'}
            , {field: 'is_vip', width: 100, title: '是否VIP', align: 'center', templet: '#is_vipTpl'}
            , {field: 'sort', width: 100, title: '显示顺序', align: 'center'}
            , {field: 'update_user', width: 100, title: '更新人', align: 'center'}
            , {field: 'create_user_name', width: 100, title: '创建人', align: 'center'}
            , {field: 'create_time', width: 180, title: '创建时间', align: 'center', sort: true}
            , {field: 'update_time', width: 180, title: '更新时间', align: 'center', sort: true}
            , {fixed: 'right', width: 150, title: '功能操作', align: 'center', toolbar: '#toolBar'}
        ];

        //【渲染TABLE】
        func.tableIns(cols, "tableList");

        //【设置弹框】
        func.setWin("演示");

                
        //【设置状态】
        func.formSwitch('status', null, function (data, res) {
            console.log("开关回调成功");
        });

            
        //【设置是否VIP】
        func.formSwitch('is_vip', null, function (data, res) {
            console.log("开关回调成功");
        });

                            
    }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

# 运行效果

以上便是生成的模块文件的内容,代码生成器在生成模块的同时,我们也同时创建了当前模块对应的菜单和权限节点,菜单默认是放入系统工具导航下面,如果变更层级请至菜单管理中修改,这里的前提是我们要赋予当前生成模块的菜单角色权限,如下图所示:

  • 菜单权限设置

打开角色管理菜单,选择管理员角色,点击角色权限,弹出的便是权限菜单列表,把我们刚生成的模块菜单进行勾选,提交即可;

mixureSecure

  • 模板预览

设置好菜单权限后,我们刷新当前系统,在左侧的菜单系统工具中卞可以看到模块菜单,如下图所示:

mixureSecure