ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
### 快速入门: 一个简单的商品管理模块 #### 安装注意事项 1. 环境需求 php >= 7.1, mysql >= 5.7, composer, ext-gd, ext-dom 等 #### 安装 1. 从 git 获取最新代码 2. cd 到项目目录使用 composer 安装依赖 3. 将 `db.sql` 导入到数据库 4. 修改 `application\database.php` 文件中相关的数据库配置 #### 安装示例 从 git 拉取最新代码: ```bash git clone http://47.94.83.94:8082/r/framework.git myDemo ``` 安装依赖: ```bash cd myDemo composer install ``` *如果提示缺少拓展, 或php版本错误请检查相应拓展是否安装, 或者php版本是否满足要求* 导入 数据库文件 使用命令行 ```bash # 使用 mysql 客户端 mysql -u root create database shop; use shop; source db.sql ``` 或使用其它第三方的数据库管理工具 *如果提示语法错误, 或不支持 datetime 类型请检查数据库版本是否满足要求* 最后将 相关数据库配置修改成你当前使用的配置 安装成功: ![](https://box.kancloud.cn/38151a3dde3c81f5250179dc51748cdf_2998x1704.png) **账号: admin** **密码: 111111** #### 数据库结构 商品分类表 ```sql CREATE TABLE `product_category` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` 商品表 ```sql CREATE TABLE `product` ( `id` int(11) NOT NULL AUTO_INCREMENT, `cid` int(11) NOT NULL COMMENT '商品分类', `name` varchar(255) NOT NULL COMMENT '商品名称', `price` decimal(10,2) NOT NULL COMMENT '价格', `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态 1 上架 2 下架', `thumb` varchar(255) NOT NULL COMMENT '商品封面', `banners` varchar(255) DEFAULT NULL COMMENT '商品 banner', `information` text COMMENT '详情', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加时间', `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '最后一次修改时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` *商品表中表示状态的 status 字段并没有使用 0 或者 NULL 作为判断条件, 具体请参考[数据库建议规范](数据库规范建议.md) 中第二条* #### 使用代码生成器生成管理模块 使用账号密码登陆后默认的首页如图所示: ![首页](https://box.kancloud.cn/af522415b199c367ca3af7273f116eda_2999x1709.png) 点击右侧菜单中的 代码生成: ![代码生成](https://box.kancloud.cn/5b8d22c6b5c35dafa8965b4be0e70173_479x116.png) 代码生成器的界面如图: ![未选择](https://box.kancloud.cn/b635970ef737ec3ce59eb26cc2562f09_2996x1717.png) 我们选择刚刚创建的商品分类表 (product_category), 系统读取表的信息, 并生成一个待填写的表单: ![product_category](https://box.kancloud.cn/ceb26712d64b91894951d66296e0ed5e_2996x1720.png) 将表单按如同所示填写完成 并 提交: ![product_category](https://box.kancloud.cn/d2e10bb5535a7903d0d5b962e79f81e0_2501x1553.png) 提示 `success` 后, 重新选择商品表, 并按下图填写 提交: ![product](https://box.kancloud.cn/da725a8395db7d54d8966a9292c70454_2493x1548.png) ![product](https://box.kancloud.cn/cc75a90488d045a5facba1cbcdd31427_2477x1022.png) *代码生成器的说明请查看 [代码生成器说明](代码生成器说明.md)* #### 添加角色权限 系统实现了 RBAC 的权限管理, 所以要让用户能够访问对应的页面, 需要给用户或者角色对应的权限才行 这里我们给管理员角色访问之前创建的两个模块的权限 点击右侧菜单 选择 角色和权限 => 权限管理 => 角色权限管理 ![menu](https://box.kancloud.cn/b8ebede3c3969e964232edada58bb816_499x862.png) 点击右上角添加按钮: ![role](https://box.kancloud.cn/669f5c6906da70536cfdba70dbcdb6ec_2998x1703.png) 角色选择 `管理员` 并勾选 `/admin/product/` 开头 和 `/admin/product_category` 开头的所有权限 并提交 如图: ![role](https://box.kancloud.cn/3dd505f14e9095b352b8d5586beb5019_2989x1718.png) #### 创建菜单栏目 这个时候我们已经可以正常访问相应的管理页面了, 但是菜单上还没有对应的入口, 所以我们需要创建两个菜单栏目 点击权限和菜单 => 菜单管理 点击添加按钮: ![menu](https://box.kancloud.cn/f328e5693a5005bc173e7c7f34f374e7_2991x1716.png) 按下图填写: ![menu](https://box.kancloud.cn/cae87379e28f3e06a136cefdc8e8d835_2994x1722.png) *菜单排序默认 50, 数值越大, 在右侧菜单栏的排序越考上* *菜单类名用于给菜单添加图标, 内置 `layui` 图标, 详情参考: [layui-icon](https://www.layui.com/doc/element/icon.html)* *菜单权限是连接对应的页面* 提交后右侧菜单栏中就已经有了商品分类管理: ![menu](https://box.kancloud.cn/19c416b6c7c3e90a62d4eb0c934e57a6_481x719.png) 类似的我们再继续把 商品管理 也添加上: ![menu](https://box.kancloud.cn/9f0d8af2e872f34ebeae285f22eed4a2_2504x1555.png) 分别查看 商品分类管理 和 商品管理, 页面如同所示: ![商品分类管理](https://box.kancloud.cn/e113cedee8d6f69babcfcb0693432075_3000x1712.png) ![商品管理](https://box.kancloud.cn/8cca25d56ccdd03b3496c368a0086fda_2991x1709.png) 这样商品分类和商品管理两个模块就完成了 #### 进一步完善 上一步结束后, 虽然基础的功能都已经完成, 但是还不够完善, 比如说 添加和编辑页面的商品分类需要手动填写对应 id, 商品详情还是普通的 input 表单, 搜索的时候 状态 也需要手动填写状态代码, 表格中显示的商品分类 和 状态都是数字等等, 接下来我们来完善这些问题 用 编辑器打开 项目, 可以看到 `application\admin` 目录下有一个 `viewModel` 目录, 里面有刚刚由代码生成器生成的 Product.php, ProductCategory.php 这两个类文件都继承了 app\common\ViewModel 类, 我们把它叫做 `视图模型` 它的功能就是通过自身的属性和方法, 来生成对应的视图 (参考 [视图模型](视图模型.md)) 我们需要修改的是 `application\admin\viewModel\Product.php` , 使用编辑器打开这个文件 文件内容如下: ```php <?php /** * 由代码生成工具自动生成 * Date: 2019-03-16 * Time: 15:30:07 */ namespace app\admin\viewModel; use app\common\ViewModel; class Product extends ViewModel { public $fieldsName = [ 'id' => 'ID', 'cid' => '商品分类', 'name' => '商品名称', 'price' => '商品价格', 'status' => '状态', 'thumb' => '商品封面', 'banners' => '商品banner', 'information' => '商品详情', 'create_time' => '添加时间', 'update_time' => '修改时间', ]; public $indexFields = [ 'id' => 'text', 'cid' => 'text', 'name' => 'text', 'price' => 'text', 'status' => 'text', 'thumb' => 'img', 'create_time' => 'text', 'update_time' => 'text', ]; public $updateFields = [ 'cid' => ['text', 'require'], 'name' => ['text', 'require'], 'price' => ['text', 'require'], 'status' => ['text', 'require'], 'thumb' => ['image', 'require'], 'banners' => ['image', null], 'information' => ['text', null], ]; public $addFields = [ 'cid' => ['text', 'require'], 'name' => ['text', 'require'], 'price' => ['text', 'require'], 'status' => ['text', 'require'], 'thumb' => ['image', 'require'], 'banners' => ['image', null], 'information' => ['text', null], ]; public $search = [ 'name' => ['text', 'like'], 'create_time' => ['datetime', ], 'cid' => ['text', ], 'status' => ['text', ], ]; public $exportFields = [ 'id,ID', 'cid,商品分类', 'name,商品名称', 'price,商品价格', 'status,状态', 'thumb,商品封面', 'banners,商品banner', 'information,商品详情', 'create_time,添加时间', 'update_time,修改时间', ]; public $importFields = [ 'id,ID', 'cid,商品分类', 'name,商品名称', 'price,商品价格', 'status,状态', 'thumb,商品封面', 'banners,商品banner', 'information,商品详情', 'create_time,添加时间', 'update_time,修改时间', ]; } ``` 属性说明: `$fieldsName` 对应字段的展示名, 是一个键值对数组, 数组的键为相应的字段, 数组的值 可以是 数组和 字符串是对应字段的展示名(字符串)或参数(数组) `$indexFields` 表格中展示的字段 和 相应的参数, 是一个键值对数组, 键为字段名, 值为相应参数 (使用的表格组件和参数) `$updateFields` 和 `$addFields` 分别是编辑页面 和 添加页面的表单字段和参数, `$addFields` 可以省略, 如果省略的话则直接使用 `$updateFields` 的规则 `$search` 搜索字段的规则, 是一个键值对数组 其它属性和方法参考 [视图模型](视图模型.md) 修改后的代码如下, 修改对应的作用看注释: ```php <?php /** * 由代码生成工具自动生成 * Date: 2019-03-16 * Time: 15:30:07 */ namespace app\admin\viewModel; use app\common\ViewModel; class Product extends ViewModel { // 定义表的别名 $1 表示 数组的第一个, $2 表示第二个 以此类推, $0 为当前视图模型对应的表名 public $variables = ['product_category']; // 定义关联 public $join = [ ['$1', '$1.id=$0.cid', 'left'] ]; public $fieldsName = [ 'id' => 'ID', 'cid' => '商品分类', 'name' => '商品名称', 'price' => '商品价格', 'status' => '状态', 'thumb' => '商品封面', 'banners' => '商品banner', 'information' => '商品详情', 'create_time' => '添加时间', 'update_time' => '修改时间', // 添加 product_category.name 字段的展示名 '$1.name' => '商品分类', // 'c_name' => '商品分类' ]; public $indexFields = [ 'id' => 'text', // 表格中的商品分类显示 product_category.name 字段, // 由于 product_category.name 与 product.name 字段冲突, 会导致商品名称 和 商品分类显示的内容完全一样, 这里我们给他定义一个别名 // 'alias' => 'c_name', 同时 fieldsName 中也需要添加 c_name 的显示名, 不然会报错: 未定义数组索引: product.c_name '$1.name' => ['text', 'alias' => 'c_name'], 'name' => 'text', 'price' => 'text', // 状态使用 表格组件中的 Convert 组件 'status' => ['convert', [1 => '上架', 2 => '下架']], 'thumb' => 'img', 'create_time' => 'text', 'update_time' => 'text', ]; public $updateFields = [ // 使用表单组件中的 selector 组件, 使用 product_category 表中的数据 'cid' => ['selector', 'require', null, [ 'table' => 'product_category', 'field' => 'name', 'value' => 'id' ]], 'name' => ['text', 'require'], 'price' => ['text', 'require'], // 使用表单组件中的 selector 组件, 使用固定数据 'status' => ['selector', 'require', null, [ 'list' => [ [1, '上架'], [2, '下架'] ], 'field' => 1, 'value' => 0 ]], 'thumb' => ['image', 'require'], 'banners' => ['image', null], // 使用表单组件 中的 Html 富文本组件 'information' => ['html', null], ]; // $addFields 与 $updateFields 完全相同, 可以去掉 // public $addFields = [ // 'cid' => ['text', 'require'], // 'name' => ['text', 'require'], // 'price' => ['text', 'require'], // 'status' => ['text', 'require'], // 'thumb' => ['image', 'require'], // 'banners' => ['image', null], // 'information' => ['text', null], // ]; public $search = [ 'name' => ['text', 'like'], 'create_time' => ['datetime', ], // 使用搜索组件中的 selector 组件, 使用 product_category 表中的数据 'cid' => ['selector', null, [ 'table' => 'product_category', 'field' => 'name', 'value' => 'id' ]], // 使用搜索组件中的 selector 组件, 使用固定数据 'status' => ['selector', null, [ 'list' => [ [1, '上架'], [2, '下架'] ], 'field' => 1, 'value' => 0 ]], ]; public $exportFields = [ 'id,ID', 'cid,商品分类', 'name,商品名称', 'price,商品价格', 'status,状态', 'thumb,商品封面', 'banners,商品banner', 'information,商品详情', 'create_time,添加时间', 'update_time,修改时间', ]; public $importFields = [ 'id,ID', 'cid,商品分类', 'name,商品名称', 'price,商品价格', 'status,状态', 'thumb,商品封面', 'banners,商品banner', 'information,商品详情', 'create_time,添加时间', 'update_time,修改时间', ]; } ``` 可以看到, 上述所说的问题已经解决了