模块开发
目录结构
public/plugins/server/demo_module
|--- controller(控制器目录)
|----- home(前台控制器)
|----- admin(后台控制器)
|--- lang(语言)
|----- zh-cn.php(中文简体)
|----- en-us.php(English)
|----- zh-hk.php(中文繁体)
|--- model(模型目录)
|--- template(前端代码目录)
|--- validate(验证目录)
|--- DemoModule.php(模块主文件)
|--- route.php(路由)
|--- hooks.php(钩子)钩子
由hooks.php实现
例如, 实现after_host_delete钩子
add_hook('after_host_delete', function($param){
// 具体处理逻辑
});注意:模块钩子一开始就会引入,需要在钩子里面自行增加判断,防止超出模块处理范围
具体使用可以参考mf_dcim模块
多语言
需要在lang目录下提前预设语言,为了防止模块语言不冲突,尽量把模块标识作为语言文件
使用时使用 lang_plugins('语言标识',$param=[]) 实现多语言,该方法定义在系统app/common.php下
具体使用可以参考mf_dcim模块
前端多语言
前台多语言文件:在template/clientarea/lang/index.js
后台多语言文件:在template/admin/lang/index.js
(function () {
const module_lang = {
"zh-cn": {
add: "添加",
},
"zh-hk": {
add: "添加",
},
"en-us": {
add: "Add",
},
};
const DEFAULT_LANG = localStorage.getItem("backLang") || "zh-cn";
window.module_lang = module_lang[DEFAULT_LANG];
})();具体参考idcsmart_common模块
路由
注意:方法只有登录验证,其他鉴权需要开发者自己处理
具体使用可以参考mf_dcim模块
系统方法和参数
方法在模块主文件里实现,主文件类名和文件名一致
模块基础信息 metaData
模块必须实现该方法
示例代码
public function metaData(){
return ['display_name'=>'DCIM(自定义配置)', 'version'=>'1.0.4'];
}
参数
无
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
display_name | string | 模块名称 |
version | string | 版本号 |
第一次使用模块创建该接口后 afterCreateFirstServer
按需实现该方法,通常该方法用于添加模块需要的数据表
模块表名建议idcsmart_module_+模块目录+具体,如idcsmart_module_mf_dcim_model_config_option_link
示例代码
public function afterCreateFirstServer(){
$sql = [
"CREATE TABLE `idcsmart_module_mf_dcim_model_config_option_link` (
`model_config_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'dcim型号配置id',
`option_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '可选配optionID',
`option_rel_type` tinyint(7) unsigned NOT NULL DEFAULT '0' COMMENT 'option表的rel_type',
KEY `idx_model_config_id` (`model_config_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='型号配置可选配置表';",
];
foreach($sql as $v){
Db::execute($v);
}
}
参数
无
返回值
无
删除最后一个使用该模块的接口 afterDeleteLastServer
按需实现该方法,通常该方法用于删除模块添加的数据表
示例代码
public function afterDeleteLastServer(){
$sql = [
'drop table `idcsmart_module_mf_dcim_model_config_option_link`;',
];
foreach($sql as $v){
Db::execute($v);
}
}
参数
无
返回值
无
测试连接 testConnect
建议实现该方法,通常使用该方法来测试和三方接口的连接状态是否可用
使用位置: 后台-商品管理-接口管理页面 接口名称前面的状态
示例代码
public function testConnect($param){
$res = [
'status' => 200,
'msg' => '连接成功',
];
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.server | ServerModel | — | 当前接口ServerModel,可直接获取相关接口参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
status | int | 状态(200=成功,400=失败) |
msg | string | 信息 |
产品模块开通 createAccount
建议实现该方法,当产品自动开通或者在产品内页开通会调用该方法
注意: 如果未实现该方法,开通时默认会成功
示例代码
public function createAccount($param){
$res = [
'status' => 200,
'msg' => '开通成功',
];
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.host | HostModel | — | 当前产品HostModel,可获取产品相关参数 |
param.client | ClientModel | — | 当前产品所属用户ClientModel,可获取产品所属用户相关参数 |
param.product | ProductModel | — | 当前产品所属商品ProductModel,可获取产品对应商品相关参数 |
param.server | ServerModel | — | 当前产品关联接口ServerModel,可获取关联接口相关参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
status | int | 状态(200=成功,400=失败) |
msg | string | 信息 |
产品模块暂停 suspendAccount
建议实现该方法,当产品到期或其他原因暂停或者在产品内页暂停会调用该方法
注意: 如果未实现该方法,暂停时默认会成功
示例代码
public function suspendAccount($param){
$res = [
'status' => 200,
'msg' => '暂停成功',
];
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.host | HostModel | — | 当前产品HostModel,可获取产品相关参数 |
param.client | ClientModel | — | 当前产品所属用户ClientModel,可获取产品所属用户相关参数 |
param.product | ProductModel | — | 当前产品所属商品ProductModel,可获取产品对应商品相关参数 |
param.server | ServerModel | — | 当前产品关联接口ServerModel,可获取关联接口相关参数 |
param.suspend_type | string | — | 暂停类型(overdue=到期暂停,overtraffic=超流暂停,certification_not_complete=实名未完成,other=其他,downstream=下游暂停) |
param.suspend_reason | string | — | 暂停原因 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
status | int | 状态(200=成功,400=失败) |
msg | string | 信息 |
产品模块解除暂停 unsuspendAccount
建议实现该方法,当产品解除暂停会调用该方法
注意: 如果未实现该方法,解除暂停时默认会成功
示例代码
public function unsuspendAccount($param){
$res = [
'status' => 200,
'msg' => '解除暂停成功',
];
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.host | HostModel | — | 当前产品HostModel,可获取产品相关参数 |
param.client | ClientModel | — | 当前产品所属用户ClientModel,可获取产品所属用户相关参数 |
param.product | ProductModel | — | 当前产品所属商品ProductModel,可获取产品对应商品相关参数 |
param.server | ServerModel | — | 当前产品关联接口ServerModel,可获取关联接口相关参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
status | int | 状态(200=成功,400=失败) |
msg | string | 信息 |
产品模块删除 terminateAccount
建议实现该方法,当产品模块删除时会调用该方法
注意: 如果未实现该方法,删除时默认会成功
示例代码
public function terminateAccount($param){
$res = [
'status' => 200,
'msg' => '删除成功',
];
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.host | HostModel | — | 当前产品HostModel,可获取产品相关参数 |
param.client | ClientModel | — | 当前产品所属用户ClientModel,可获取产品所属用户相关参数 |
param.product | ProductModel | — | 当前产品所属商品ProductModel,可获取产品对应商品相关参数 |
param.server | ServerModel | — | 当前产品关联接口ServerModel,可获取关联接口相关参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
status | int | 状态(200=成功,400=失败) |
msg | string | 信息 |
产品续费后调用 renew
建议实现该方法,当产品续费后会调用该方法
示例代码
public function renew($param){
// 续费逻辑
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.host | HostModel | — | 当前产品HostModel,可获取产品相关参数 |
param.client | ClientModel | — | 当前产品所属用户ClientModel,可获取产品所属用户相关参数 |
param.product | ProductModel | — | 当前产品所属商品ProductModel,可获取产品对应商品相关参数 |
param.server | ServerModel | — | 当前产品关联接口ServerModel,可获取关联接口相关参数 |
返回值
无
升降级配置项后调用 changePackage
按需实现该方法,当产品升降级配置项后会调用该方法
示例代码
public function changePackage($param){
// 具体逻辑
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.host | HostModel | — | 当前产品HostModel,可获取产品相关参数 |
param.client | ClientModel | — | 当前产品所属用户ClientModel,可获取产品所属用户相关参数 |
param.product | ProductModel | — | 当前产品所属商品ProductModel,可获取产品对应商品相关参数 |
param.server | ServerModel | — | 当前产品关联接口ServerModel,可获取关联接口相关参数 |
返回值
无
升降级商品后调用 changeProduct
按需实现该方法,当产品升降级商品后会调用该方法
示例代码
public function changeProduct($param){
// 具体逻辑
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.host | HostModel | — | 当前产品HostModel,可获取产品相关参数 |
param.client | ClientModel | — | 当前产品所属用户ClientModel,可获取产品所属用户相关参数 |
param.product | ProductModel | — | 当前产品所属商品ProductModel,可获取产品对应商品相关参数 |
param.server | ServerModel | — | 当前产品关联接口ServerModel,可获取关联接口相关参数 |
param.custom | array | — | 升降级参数 |
返回值
无
购物车价格计算 cartCalculatePrice
必须实现该方法,当商品计算价格或结算时会调用该方法
示例代码
public function cartCalculatePrice($param){
$res = [
'status' => 200,
'msg' => '请求成功',
'data' => [
'price' => 1.1,
'renew_price' => 1.1,
'billing_cycle' => '月',
'duration' => 30*24*3600,
'description' => 'CPU:2核,内存:4G通用型云主机',
'base_price' => 1.1
]
];
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.product | ProductModel | — | 当前商品ProductModel,可获商品相关参数 |
param.custom | array | — | 模块自定义参数 |
param.qty | int | — | 商品数量 |
param.scene | string | — | 场景(cal_price=计算价格,buy=结算) |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
status | int | 状态(200=成功,400=失败) |
msg | string | 信息 |
data.price | float | 价格 |
data.renew_price | float | 续费价格 |
data.billing_cycle | string | 周期名称 |
data.duration | int | 周期时长(秒) |
data.description | string | 订单子项描述 |
data.base_price | float | 基础价格 |
后台商品接口配置输出 serverConfigOption
建议实现该方法
位置: 后台-商品管理-商品内页-接口管理,关联接口或接口分组后下方输出
示例代码
public function serverConfigOption($param){
$res = [
'template'=>'template/admin/mf_dcim.html',
'vars' => []
];
// $res = "<p>我是输出</p>";
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.product | ProductModel | — | 当前商品ProductModel,可获取商品相关参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
返回值 | string | 要输出的内容 |
返回值 | array | 使用下列字段 |
template | string | 模板地址,从模块根目录开始算 |
vars | array | 替换模板变量,注意不要和系统变量冲突,使用thinkphp自带模板语法 |
前台导航产品列表 hostList
必须实现该方法
示例代码
public function hostList($param){
$res = [
'template'=>'template/clientarea/product_list.html',
'vars' => []
];
// $res = "<p>我是输出</p>";
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.product_id | array | — | 当前导航关联的所有商品ID |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
返回值 | string | 要输出的内容 |
返回值 | array | 使用下列字段 |
template | string | 模板地址,从模块根目录开始算 |
vars | array | 替换模板变量,注意不要和系统变量冲突,使用thinkphp自带模板语法 |
前台产品内页输出 clientArea
必须实现该方法
示例代码
public function clientArea($param){
$res = [
'template'=>'template/clientarea/product_detail.html',
'vars' => []
];
// $res = "<p>我是输出</p>";
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.host | HostModel | — | 当前产品HostModel,可获取产品相关参数 |
param.client | ClientModel | — | 当前产品所属用户ClientModel,可获取产品所属用户相关参数 |
param.product | ProductModel | — | 当前产品所属商品ProductModel,可获取产品对应商品相关参数 |
param.server | ServerModel | — | 当前产品关联接口ServerModel,可获取关联接口相关参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
返回值 | string | 要输出的内容 |
返回值 | array | 使用下列字段 |
template | string | 模板地址,从模块根目录开始算 |
vars | array | 替换模板变量,注意不要和系统变量冲突,使用thinkphp自带模板语法 |
后台产品内页输出 adminArea
按需实现该方法
位置: 后台-用户管理-用户列表-用户详情-产品信息最底部输出
示例代码
public function adminArea($param){
$res = [
'template'=>'template/admin/product_detail.html',
'vars' => []
];
// $res = "<p>我是输出</p>";
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.host | HostModel | — | 当前产品HostModel,可获取产品相关参数 |
param.client | ClientModel | — | 当前产品所属用户ClientModel,可获取产品所属用户相关参数 |
param.product | ProductModel | — | 当前产品所属商品ProductModel,可获取产品对应商品相关参数 |
param.server | ServerModel | — | 当前产品关联接口ServerModel,可获取关联接口相关参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
返回值 | string | 要输出的内容 |
返回值 | array | 使用下列字段 |
template | string | 模板地址,从模块根目录开始算 |
vars | array | 替换模板变量,注意不要和系统变量冲突,使用thinkphp自带模板语法 |
前台商品购买页面输出 clientProductConfigOption
必须实现该方法,否则将不能购买该商品
位置: 前台-订购产品-具体商品购买
示例代码
public function clientProductConfigOption($param){
$res = [
'template'=>'template/clientarea/goods.html',
'vars' => []
];
// $res = "<p>我是输出</p>";
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.product | ProductModel | — | 当前商品ProductModel,可获取商品相关参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
返回值 | string | 要输出的内容 |
返回值 | array | 使用下列字段 |
template | string | 模板地址,从模块根目录开始算 |
vars | array | 替换模板变量,注意不要和系统变量冲突,使用thinkphp自带模板语法 |
结算之后调用 afterSettle
建议实现该方法,一般用于保存模块配置和产品关联关系。该方法不负责远端开通,远端资源应在 createAccount() 中创建。
示例代码
public function afterSettle($param){
// 具体逻辑
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.product | ProductModel | — | 当前商品ProductModel,可获取商品相关参数 |
param.host_id | int | — | 创建的产品ID |
param.custom | array | — | 模块自定义参数 |
param.customfields | array | — | 其他自定义参数 |
返回值
无
获取当前产品所有周期价格 durationPrice
建议实现该方法, 一般用于给续费提供周期价格
示例代码
public function durationPrice($param){
$res = [
'status' => 200,
'msg' => '请求成功',
'data' => [
[
'duration' => 30*24*3600,
'billing_cycle' => '月',
'price' => 1.1,
]
]
];
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.host | HostModel | — | 当前产品HostModel,可获取产品相关参数 |
param.client | ClientModel | — | 当前产品所属用户ClientModel,可获取产品所属用户相关参数 |
param.product | ProductModel | — | 当前产品所属商品ProductModel,可获取产品对应商品相关参数 |
param.server | ServerModel | — | 当前产品关联接口ServerModel,可获取关联接口相关参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
status | int | 状态(200=成功,400=失败) |
msg | string | 信息 |
data[].price | float | 价格 |
data[].billing_cycle | string | 周期名称 |
data[].duration | int | 周期时长(秒) |
获取商品起售周期价格 getPriceCycle
建议实现该方法
显示位置:
后台-商品管理-商品管理-商品内页基础信息-商品起售价格
前台-订购商品列表周期价格
示例代码
public function getPriceCycle($param){
$res = [
'price' => 1.1,
'cycle' => '月',
];
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.product | ProductModel | — | 当前商品ProductModel,可获取商品相关参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
price | float | 商品起售价格 |
cycle | string | 周期 |
下载上游资源 downloadResource
按需实现该方法
如果需要实现上下游,需要使用该方法, 并且需要实现对应的reserver模块,同时把reserver模块打包在该模块中
示例代码
public function downloadResource($param){
$res = [
'status' => 200,
'msg' => '获取成功',
'data' => [
'module' => 'mf_dcim',
'url' => request()->domain() . '/plugins/server/mf_dcim/data/abc.zip',
'version'=> '1.0.1',
]
];
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.product | ProductModel | — | 当前商品ProductModel,可获取商品相关参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
status | int | 状态(200=成功,400=失败) |
msg | string | 信息 |
data.module | string | 对应reserver模块名称 |
data.url | string | 对应reserver模块zip包 |
version | string | 当前模块版本号 |
产品内页模块配置信息输出 adminField
按需实现该方法
位置:用户管理-用户列表-用户内页-产品信息-产品内页配置信息
示例代码
public function adminField($param){
$res = [
[
'name' => '基础配置',
'field' => [
[
'name' => '数据中心',
'key' => 'data_center',
'value' => '中国-香港',
'disable' => true,
]
]
]
];
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.host | HostModel | — | 当前产品HostModel,可获取产品相关参数 |
param.client | ClientModel | — | 当前产品所属用户ClientModel,可获取产品所属用户相关参数 |
param.product | ProductModel | — | 当前产品所属商品ProductModel,可获取产品对应商品相关参数 |
param.server | ServerModel | — | 当前产品关联接口ServerModel,可获取关联接口相关参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
[].name | string | 配置小标题 |
[].field[].name | string | 名称 |
[].field[].key | string | 标识(不要重复) |
[].field[].value | string | 当前值 |
[].field[].disable | bool | 状态(false=可修改,true=不可修改) |
产品保存后 hostUpdate
按需实现该方法,该方法建议和adminField方法一起使用
示例代码
public function hostUpdate($param){
// 实现配置变更逻辑
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.host | HostModel | — | 当前产品HostModel,可获取产品相关参数 |
param.client | ClientModel | — | 当前产品所属用户ClientModel,可获取产品所属用户相关参数 |
param.product | ProductModel | — | 当前产品所属商品ProductModel,可获取产品对应商品相关参数 |
param.server | ServerModel | — | 当前产品关联接口ServerModel,可获取关联接口相关参数 |
param.module_admin_field | array | — | 模块自定义配置信息(键是配置标识,值是填写的内容) |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
status | int | 状态(200=成功,400=失败) |
msg | string | 提示信息 |
获取商品所有配置项 allConfigOption
不推荐使用该方法,需要返回商品的所有配置
示例代码
public function allConfigOption($param){
$res = [
'status' => 200,
'msg' => '获取成功',
'data' => [
[
'name' => '内存',
'field' => 'memory',
'type' => 'dropdown',
'option'=> [
[
'name' => '2G',
'value'=> '2',
]
]
]
]
];
return $res;
}
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
param.product | ProductModel | — | 当前商品ProductModel,可获取商品相关参数 |
返回值
| 字段 | 类型 | 说明 |
|---|---|---|
status | int | 状态(200=成功,400=失败) |
msg | string | 信息 |
data[].name | string | 配置项名称 |
data[].field | string | 订购时对应配置的键 |
data[].type | string | 类型(dropdown=下拉),只支持下拉 |
data[].option[].name | string | 选项名称 |
data[].option[].value | int / string | 对应选项值 |