### 快速入門: 一個簡單的商品管理模塊
#### 安裝注意事項
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 類型請檢查數據庫版本是否滿足要求*
最后將 相關數據庫配置修改成你當前使用的配置
安裝成功:

**賬號: 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) 中第二條*
#### 使用代碼生成器生成管理模塊
使用賬號密碼登陸后默認的首頁如圖所示:

點擊右側菜單中的 代碼生成:

代碼生成器的界面如圖:

我們選擇剛剛創建的商品分類表 (product_category), 系統讀取表的信息, 并生成一個待填寫的表單:

將表單按如同所示填寫完成 并 提交:

提示 `success` 后, 重新選擇商品表, 并按下圖填寫 提交:


*代碼生成器的說明請查看 [代碼生成器說明](代碼生成器說明.md)*
#### 添加角色權限
系統實現了 RBAC 的權限管理, 所以要讓用戶能夠訪問對應的頁面, 需要給用戶或者角色對應的權限才行
這里我們給管理員角色訪問之前創建的兩個模塊的權限
點擊右側菜單 選擇 角色和權限 => 權限管理 => 角色權限管理

點擊右上角添加按鈕:

角色選擇 `管理員` 并勾選 `/admin/product/` 開頭 和 `/admin/product_category` 開頭的所有權限 并提交
如圖:

#### 創建菜單欄目
這個時候我們已經可以正常訪問相應的管理頁面了, 但是菜單上還沒有對應的入口, 所以我們需要創建兩個菜單欄目
點擊權限和菜單 => 菜單管理
點擊添加按鈕:

按下圖填寫:

*菜單排序默認 50, 數值越大, 在右側菜單欄的排序越考上*
*菜單類名用于給菜單添加圖標, 內置 `layui` 圖標, 詳情參考: [layui-icon](https://www.layui.com/doc/element/icon.html)*
*菜單權限是連接對應的頁面*
提交后右側菜單欄中就已經有了商品分類管理:

類似的我們再繼續把 商品管理 也添加上:

分別查看 商品分類管理 和 商品管理, 頁面如同所示:


這樣商品分類和商品管理兩個模塊就完成了
#### 進一步完善
上一步結束后, 雖然基礎的功能都已經完成, 但是還不夠完善, 比如說 添加和編輯頁面的商品分類需要手動填寫對應 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,修改時間',
];
}
```
可以看到, 上述所說的問題已經解決了