From 8a1fa3fb8bdedaa944a588ed74bd996214de3292 Mon Sep 17 00:00:00 2001 From: yiqiu Date: Thu, 20 Nov 2025 23:37:31 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=85=8D=E7=BD=AE=E6=8F=92?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/addon/theme_configurator/README.md | 30 ++ .../theme_configurator/ThemeConfigurator.php | 80 ++++ plugins/addon/theme_configurator/auth.php | 15 + .../controller/ThemeController.php | 58 +++ .../controller/clientarea/ThemeController.php | 61 +++ .../addon/theme_configurator/lang/zh-cn.php | 10 + .../model/ThemeConfigModel.php | 93 ++++ plugins/addon/theme_configurator/route.php | 30 ++ plugins/addon/theme_configurator/sidebar.php | 17 + .../theme_configurator/sidebar_clientarea.php | 9 + .../template/admin/index.php | 82 ++++ .../template/admin/lang/index.js | 15 + .../template/clientarea/lang/index.js | 15 + plugins_dev.md | 408 ++++++++++++++++++ 14 files changed, 923 insertions(+) create mode 100644 plugins/addon/theme_configurator/README.md create mode 100644 plugins/addon/theme_configurator/ThemeConfigurator.php create mode 100644 plugins/addon/theme_configurator/auth.php create mode 100644 plugins/addon/theme_configurator/controller/ThemeController.php create mode 100644 plugins/addon/theme_configurator/controller/clientarea/ThemeController.php create mode 100644 plugins/addon/theme_configurator/lang/zh-cn.php create mode 100644 plugins/addon/theme_configurator/model/ThemeConfigModel.php create mode 100644 plugins/addon/theme_configurator/route.php create mode 100644 plugins/addon/theme_configurator/sidebar.php create mode 100644 plugins/addon/theme_configurator/sidebar_clientarea.php create mode 100644 plugins/addon/theme_configurator/template/admin/index.php create mode 100644 plugins/addon/theme_configurator/template/admin/lang/index.js create mode 100644 plugins/addon/theme_configurator/template/clientarea/lang/index.js create mode 100644 plugins_dev.md diff --git a/plugins/addon/theme_configurator/README.md b/plugins/addon/theme_configurator/README.md new file mode 100644 index 0000000..31b9c9f --- /dev/null +++ b/plugins/addon/theme_configurator/README.md @@ -0,0 +1,30 @@ +# Theme Configurator 插件 + +此插件演示如何通过后台插件的方式为 BlackFruit-UI 主题提供可配置能力,支持设置导航、页脚、站点信息、SEO、首页轮播以及右侧浮窗,并提供 `/console/v1/theme/config` 接口与前端联动。 + +## 功能 +- 后台界面(`template/admin/index.php`)以 JSON 的形式集中维护所有主题参数; +- 接口 `GET/POST /{DIR_ADMIN}/v1/theme/config` 提供配置读取与保存; +- 前台接口 `GET /console/v1/theme/config` 输出与 `/console/v1/common` 相同结构的数据,BlackFruit-UI 可以直接接入; +- 插件安装时创建 `addon_theme_configurator` 表并写入默认配置。 + +## 目录 +``` +plugins/addon/theme_configurator +├── ThemeConfigurator.php # 插件主文件 +├── controller/ +│ ├── ThemeController.php # 后台 API +│ └── clientarea/ThemeController.php # 前台 API +├── model/ThemeConfigModel.php # 主题配置模型 +├── template/admin/index.php # 后台可视化页面 +├── route.php # 自定义路由定义 +├── sidebar*.php # 前后台导航 +├── auth.php # 权限配置 +└── lang/zh-cn.php # 多语言 +``` + +## 使用步骤 +1. 将目录复制到业务系统的 `public/plugins/addon` 下; +2. 在后台启用插件,安装脚本会自动创建 `addon_theme_configurator` 表; +3. 进入“插件 > 主题配置”页,按 JSON 结构维护导航、SEO、轮播、侧边栏等; +4. 前端 BlackFruit-UI 请求 `/console/v1/theme/config` 以获取运行时配置。若需要兼容现有 `/console/v1/common`,可在 Nginx 或网关层做转发。 diff --git a/plugins/addon/theme_configurator/ThemeConfigurator.php b/plugins/addon/theme_configurator/ThemeConfigurator.php new file mode 100644 index 0000000..5d0f1ca --- /dev/null +++ b/plugins/addon/theme_configurator/ThemeConfigurator.php @@ -0,0 +1,80 @@ + 'ThemeConfigurator', + 'title' => '主题可视化配置', + 'description' => '通过插件管理 BlackFruit-UI 导航、页脚、SEO、轮播与侧边栏等主题参数', + 'author' => 'yiqiu', + 'version' => '1.0.0', + ]; + + /** @var bool 标记不需要默认插件导航 */ + public $noNav = false; + + /** + * 安装插件 - 初始化存储表以及默认配置 + */ + public function install() + { + try { + Db::execute( + "CREATE TABLE IF NOT EXISTS `addon_theme_configurator`( + `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `config` longtext NOT NULL, + `update_time` int(11) DEFAULT 0, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;" + ); + } catch (\Throwable $throwable) { + return [ + 'status' => 400, + 'msg' => $throwable->getMessage(), + ]; + } + + (new ThemeConfigModel())->initConfig(); + + return [ + 'status' => 200, + 'msg' => lang_plugins('theme_configurator_install_success'), + ]; + } + + /** + * 卸载插件 - 移除存储表 + */ + public function uninstall() + { + try { + Db::execute("DROP TABLE IF EXISTS `addon_theme_configurator`;"); + } catch (\Throwable $throwable) { + return [ + 'status' => 400, + 'msg' => $throwable->getMessage(), + ]; + } + + return [ + 'status' => 200, + 'msg' => lang_plugins('theme_configurator_uninstall_success'), + ]; + } + + /** + * 供其他业务调用,快速获取主题配置 + */ + public function getThemeConfig() + { + return (new ThemeConfigModel())->getConfig(); + } +} diff --git a/plugins/addon/theme_configurator/auth.php b/plugins/addon/theme_configurator/auth.php new file mode 100644 index 0000000..e6a0bdd --- /dev/null +++ b/plugins/addon/theme_configurator/auth.php @@ -0,0 +1,15 @@ + 'auth_plugin_addon_theme_configurator', + 'url' => 'theme_config', + 'child' => [ + [ + 'title' => 'auth_plugin_addon_theme_configurator_save', + 'url' => '', + 'auth_rule' => 'ThemeController::save', + 'auth_rule_title' => 'auth_plugin_addon_theme_configurator_save', + ], + ], + ], +]; diff --git a/plugins/addon/theme_configurator/controller/ThemeController.php b/plugins/addon/theme_configurator/controller/ThemeController.php new file mode 100644 index 0000000..8c9f4c1 --- /dev/null +++ b/plugins/addon/theme_configurator/controller/ThemeController.php @@ -0,0 +1,58 @@ +model = new ThemeConfigModel(); + } + + /** + * 获取配置 + */ + public function config(): Response + { + return json([ + 'status' => 200, + 'msg' => lang_plugins('theme_configurator_success'), + 'data' => $this->model->getConfig(), + ]); + } + + /** + * 保存配置 + */ + public function save(): Response + { + $param = $this->request->param(); + $payload = [ + 'seo' => $param['seo'] ?? [], + 'header_nav' => $param['header_nav'] ?? [], + 'footer_nav' => $param['footer_nav'] ?? [], + 'site_config' => $param['site_config'] ?? [], + 'friendly_link' => $param['friendly_link'] ?? [], + 'banner' => $param['banner'] ?? [], + 'side' => $param['side'] ?? [], + ]; + + $config = $this->model->saveConfig($payload); + + return json([ + 'status' => 200, + 'msg' => lang_plugins('theme_configurator_save_success'), + 'data' => $config, + ]); + } +} diff --git a/plugins/addon/theme_configurator/controller/clientarea/ThemeController.php b/plugins/addon/theme_configurator/controller/clientarea/ThemeController.php new file mode 100644 index 0000000..fe97856 --- /dev/null +++ b/plugins/addon/theme_configurator/controller/clientarea/ThemeController.php @@ -0,0 +1,61 @@ +model = new ThemeConfigModel(); + } + + /** + * 返回给 BlackFruit-UI 的 /console/v1/common 同结构数据 + */ + public function config(): Response + { + $config = $this->model->getConfig(); + + $data = [ + 'enterprise_name' => $config['site_config']['enterprise_name'] ?? '', + 'enterprise_telephone' => $config['site_config']['enterprise_telephone'] ?? '', + 'enterprise_mailbox' => $config['site_config']['enterprise_mailbox'] ?? '', + 'enterprise_qrcode' => $config['site_config']['enterprise_qrcode'] ?? '', + 'official_website_logo' => $config['site_config']['official_website_logo'] ?? '', + 'icp_info' => $config['site_config']['icp_info'] ?? '', + 'icp_info_link' => $config['site_config']['icp_info_link'] ?? '', + 'public_security_network_preparation' => $config['site_config']['public_security_network_preparation'] ?? '', + 'public_security_network_preparation_link' => $config['site_config']['public_security_network_preparation_link'] ?? '', + 'telecom_appreciation' => $config['site_config']['telecom_appreciation'] ?? '', + 'copyright_info' => $config['site_config']['copyright_info'] ?? '', + 'terms_service_url' => $config['site_config']['terms_service_url'] ?? '', + 'terms_privacy_url' => $config['site_config']['terms_privacy_url'] ?? '', + 'cloud_product_link' => $config['site_config']['cloud_product_link'] ?? '', + 'dcim_product_link' => $config['site_config']['dcim_product_link'] ?? '', + 'honor' => $config['site_config']['honor'] ?? [], + 'partner' => $config['site_config']['partner'] ?? [], + 'friendly_link' => $config['friendly_link'] ?? [], + 'banner' => $config['banner'] ?? [], + 'header_nav' => $config['header_nav'] ?? [], + 'footer_nav' => $config['footer_nav'] ?? [], + 'side_floating_window' => $config['side'] ?? [], + 'feedback_type' => $config['site_config']['feedback_type'] ?? [], + ]; + + return json([ + 'status' => 200, + 'msg' => lang_plugins('theme_configurator_success'), + 'data' => $data, + ]); + } +} diff --git a/plugins/addon/theme_configurator/lang/zh-cn.php b/plugins/addon/theme_configurator/lang/zh-cn.php new file mode 100644 index 0000000..b480169 --- /dev/null +++ b/plugins/addon/theme_configurator/lang/zh-cn.php @@ -0,0 +1,10 @@ + '请求成功', + 'theme_configurator_save_success' => '主题配置保存成功', + 'theme_configurator_install_success' => '主题配置插件安装成功', + 'theme_configurator_uninstall_success' => '主题配置插件卸载成功', + 'nav_plugin_addon_theme_configurator' => '主题配置', + 'auth_plugin_addon_theme_configurator' => '主题控制', + 'auth_plugin_addon_theme_configurator_save' => '保存主题配置', +]; diff --git a/plugins/addon/theme_configurator/model/ThemeConfigModel.php b/plugins/addon/theme_configurator/model/ThemeConfigModel.php new file mode 100644 index 0000000..8afb156 --- /dev/null +++ b/plugins/addon/theme_configurator/model/ThemeConfigModel.php @@ -0,0 +1,93 @@ +table)->order('id', 'asc')->find(); + if (!$row) { + return $this->defaultConfig(); + } + + $config = json_decode($row['config'], true); + return is_array($config) ? $config : $this->defaultConfig(); + } + + /** + * 保存配置 + */ + public function saveConfig(array $config): array + { + $payload = [ + 'config' => json_encode($config, JSON_UNESCAPED_UNICODE), + 'update_time' => time(), + ]; + + $exists = Db::name($this->table)->order('id', 'asc')->find(); + if ($exists) { + Db::name($this->table)->where('id', $exists['id'])->update($payload); + } else { + Db::name($this->table)->insert($payload); + } + + return $config; + } + + /** + * 安装时写入默认配置 + */ + public function initConfig(): void + { + $exists = Db::name($this->table)->order('id', 'asc')->find(); + if (!$exists) { + $this->saveConfig($this->defaultConfig()); + } + } + + /** + * 默认结构 + */ + protected function defaultConfig(): array + { + return [ + 'seo' => [ + 'title' => 'BlackFruit-UI', + 'keywords' => '云服务器,主题云,BlackFruit', + 'description' => 'BlackFruit-UI 默认站点说明', + ], + 'header_nav' => [], + 'footer_nav' => [], + 'site_config' => [ + 'enterprise_name' => '主题云', + 'enterprise_telephone' => '400-000-0000', + 'enterprise_mailbox' => 'support@example.com', + 'enterprise_qrcode' => '/upload/qrcode.png', + 'official_website_logo' => '/upload/logo.png', + 'icp_info' => '京ICP备示例号', + 'icp_info_link' => 'https://beian.miit.gov.cn/#/Integrated/index', + 'public_security_network_preparation' => '京公网安备示例号', + 'public_security_network_preparation_link' => 'https://beian.mps.gov.cn/#/query/webSearch', + 'telecom_appreciation' => '增值电信业务经营许可证', + 'copyright_info' => '© ' . date('Y') . ' 主题云', + 'terms_service_url' => '/agreement/service.html', + 'terms_privacy_url' => '/agreement/privacy.html', + 'cloud_product_link' => '/cart/goods.htm?id=1', + 'dcim_product_link' => '/cart/goods.htm?id=2', + ], + 'friendly_link' => [], + 'banner' => [], + 'side' => [], + ]; + } +} diff --git a/plugins/addon/theme_configurator/route.php b/plugins/addon/theme_configurator/route.php new file mode 100644 index 0000000..c34f425 --- /dev/null +++ b/plugins/addon/theme_configurator/route.php @@ -0,0 +1,30 @@ +append([ + '_plugin' => 'theme_configurator', + '_controller' => 'theme', + '_action' => 'config', + ]); +})->middleware(\app\http\middleware\ParamFilter::class); + +// 后台配置接口 +Route::group(DIR_ADMIN . '/v1', function () { + Route::get('theme/config', "\\addon\\theme_configurator\\controller\\ThemeController@config") + ->append([ + '_plugin' => 'theme_configurator', + '_controller' => 'theme', + '_action' => 'config', + ]) + ->middleware(\app\http\middleware\CheckAdmin::class); + Route::post('theme/config', "\\addon\\theme_configurator\\controller\\ThemeController@save") + ->append([ + '_plugin' => 'theme_configurator', + '_controller' => 'theme', + '_action' => 'save', + ]) + ->middleware(\app\http\middleware\CheckAdmin::class); +})->middleware(\app\http\middleware\ParamFilter::class); diff --git a/plugins/addon/theme_configurator/sidebar.php b/plugins/addon/theme_configurator/sidebar.php new file mode 100644 index 0000000..9798ba4 --- /dev/null +++ b/plugins/addon/theme_configurator/sidebar.php @@ -0,0 +1,17 @@ + 'nav_plugin_addon_theme_configurator', + 'url' => '', + 'icon' => 'dashboard', + 'in' => '', + 'child' => [ + [ + 'name' => 'nav_plugin_addon_theme_configurator', + 'url' => 'index', + 'in' => '', + 'icon' => 'setting', + ], + ], + ], +]; diff --git a/plugins/addon/theme_configurator/sidebar_clientarea.php b/plugins/addon/theme_configurator/sidebar_clientarea.php new file mode 100644 index 0000000..f2e392c --- /dev/null +++ b/plugins/addon/theme_configurator/sidebar_clientarea.php @@ -0,0 +1,9 @@ + 'nav_plugin_addon_theme_configurator', + 'url' => 'theme_configurator', + 'icon' => 'setting', + 'child' => [], + ], +]; diff --git a/plugins/addon/theme_configurator/template/admin/index.php b/plugins/addon/theme_configurator/template/admin/index.php new file mode 100644 index 0000000..3bb840f --- /dev/null +++ b/plugins/addon/theme_configurator/template/admin/index.php @@ -0,0 +1,82 @@ + + + + + + 主题配置 + + + + +
+

主题配置 JSON

+

此页面演示如何通过插件快速调整 BlackFruit-UI 的导航、页脚、SEO、轮播、侧边栏以及企业信息。直接编辑下方 JSON 提交即可。

+ + +
+ + + + + diff --git a/plugins/addon/theme_configurator/template/admin/lang/index.js b/plugins/addon/theme_configurator/template/admin/lang/index.js new file mode 100644 index 0000000..49cd5d9 --- /dev/null +++ b/plugins/addon/theme_configurator/template/admin/lang/index.js @@ -0,0 +1,15 @@ +(function () { + const module_lang = { + "zh-cn": { + save: "保存配置", + }, + "zh-hk": { + save: "保存配置", + }, + "en-us": { + save: "Save", + }, + }; + const DEFAULT_LANG = localStorage.getItem("backLang") || "zh-cn"; + window.theme_configurator_lang = module_lang[DEFAULT_LANG]; +})(); diff --git a/plugins/addon/theme_configurator/template/clientarea/lang/index.js b/plugins/addon/theme_configurator/template/clientarea/lang/index.js new file mode 100644 index 0000000..88dd0f4 --- /dev/null +++ b/plugins/addon/theme_configurator/template/clientarea/lang/index.js @@ -0,0 +1,15 @@ +(function () { + const module_lang = { + "zh-cn": { + success: "请求成功", + }, + "zh-hk": { + success: "请求成功", + }, + "en-us": { + success: "Success", + }, + }; + const DEFAULT_LANG = localStorage.getItem("lang") || "zh-cn"; + window.theme_configurator_client_lang = module_lang[DEFAULT_LANG]; +})(); diff --git a/plugins_dev.md b/plugins_dev.md new file mode 100644 index 0000000..78fbef0 --- /dev/null +++ b/plugins_dev.md @@ -0,0 +1,408 @@ +阅读须知:此文件是插件制作方法,和BlackFruit-UI项目是互相辅助的关系,BlackFruit-UI需要配置的地方都会在插件中体现,也就是一个业务管理系统的主题和后台插件控制主题的关系。所以以下内容的路径不是指的BlackFruit-UI的位置,是业务管理系统的,和本项目无关。 + +一、位置 + +插件放在\public\plugins\addon\目录下 + + + +二、目录结构 + +\plugins\addon\idcsmart_ticket + +|--- controller(控制器目录,后台控制器直接放此目录下) + +|--- clientarea(前台控制器放此目录下) + +|--- lang(语言目录) + +|--- zh-cn.php(中文语言文件) + +|--- template(模板) + +|--- admin(后台模板目录) + +|--- clientarea(前台模板目录) + +|--- IdcsmartTicket.php(插件主文件) + +|--- route.php(自定义路由文件) + +|--- sidebar.php(后台插件导航文件) + + + +三、开发流程 + +以工单插件为例: + +1、创建工单插件目录\public\plugins\addon\idcsmart_ticket\; + +①目录名以小写字母+下划线形式,必须以字母开头,如idcsmart_ticket; + + + +2、创建入口文件:IdcsmartTicket.php: + +①命名空间namespace addon\idcsmart_ticket(控制器下命名空间对应相应目录即可,其它同理); + +②以目录名大驼峰+.php,创建在插件根目录下,如idcsmart_ticket\IdcsmartTicket.php; + +③文件中需要定义info属性,示例: + +# 插件基本信息 +public $info = array( + 'name' => 'IdcsmartTicket', //插件英文名,作为插件唯一标识,改成你的插件英文就行了 + 'title' => '智简魔方工单插件', //插件名称 + 'description' => '智简魔方工单插件', //插件描述 + 'author' => 'idcsmart', //开发者 + 'version' => '1.0', // 版本号 +); + +④必须实现install()安装以及uninstall()卸载方法 + +⑤可实现钩子方法,如要实现订单创建后钩子after_order_create,则可在此文件中创建 + +public function afterOrderCreate($param)公共方法; + +⑥系统会在订单创建后的位置放置⑤中的钩子,放置方式: + +hook(‘after_order_create’,[‘id’=>$orderId]) ; + +⑦如果定义变量noNav,表示不需要默认导航(具体参考7,插件后台导航) + +public $noNav; + + + +3、创建插件后台控制器 idcsmart_ticket\controller\TicketController.php + +①命名空间addon\idcsmart_ticket\controller; + +②继承后台基类控制器PluginAdminBaseController,增加了权限控制,允许使用一些通用方法; + +③get_admin_id()可获取后台管理员登录ID; + +④实现接口,如public function ticketList(),系统默认访问此接口的url为: + +网站地址/admin/addon?_plugin=idcsmart_ticket&_controller=ticket&_action=ticket_list,说明:系统默认地址默认登录,若需要免登录访问,需要自定义路由(见后面自定义路由); + +⑤系统提供了生成④中默认访问地址的方法: + +idcsmart_addon_url($url,$vars=[],$is_admin=false) + +参数说明: + +url: 格式:插件名://控制器名/方法,如 IdcsmartTicket://Ticket/ticketList + +vars: 参数,默认为空数组 + +Is_admin: 是否后台,默认为false + + + +4、创建插件前台控制器idcsmart_ticket\controller\clientarea\TicketController + +.php + +①命名空间addon\idcsmart_ticket\controller\clientarea; + +②继承前台基类控制器PluginBaseController,允许使用一些通用方法; + +③get_client_id()可获取前台客户登录ID; + +④实现接口,如public function ticketList(),系统默认访问此接口的url为: + +网站地址/console/addon?_plugin=idcsmart_ticket&_controller=ticket&_action=ticket_list或者: + +网站地址/console/addon?_plugin=1&_controller=ticket&_action=ticket_list,1表示插件ID; + +说明:系统默认地址默认登录,若需要免登录访问,需要自定义路由(见后面自定义路由); + +⑤系统提供了生成④中默认访问地址的方法: + +idcsmart_addon_url($url,$vars=[],$is_admin=false) + +参数说明: + +url: 格式:插件名://控制器名/方法,如 IdcsmartTicket://Ticket/ticketList + +vars: 参数,默认为空数组 + +Is_admin: 是否后台,默认为false + + + +5、插件提供两种路由: + +①、系统默认url带参数,参考4 + +②、自定义路由,插件根目录下定义route.php,示例: + +前台路由: + +Route::group('console/v1',function (){ + +Route::get('ticket',"\\addon\\idcsmart_ticket\\controller\\clientarea\\TicketController@ticketList")->append(['_plugin'=>'idcsmart_ticket','_controller'=>'ticket','_action'=>'ticket_list']);# 带上默认参数,可以使用继承控制器app\admin\controller\PluginBaseController的一些通用方法,也可以不追加这些参数(_plugin插件名称C风格,_controller控制器名称C风格,_action方法名称C风格) + +})->middleware(\app\http\middleware\ParamFilter::class) + +->middleware(\app\http\middleware\CheckHome::class);#前台需要登录就使用此中间件 + +后台路由: + +Route::group(DIR_ADMIN . '/v1',function (){ + +Route::get('ticket',"\\addon\idcsmart_ticket\controller\TicketController@ticketList")->append(['_plugin'=>'idcsmart_ticket','_controller'=>'ticket','_action'=>'ticket_list']);})->middleware(\app\http\middleware\ParamFilter::class)-> + +middleware(\app\http\middleware\CheckAdmin::class);#后台需要登录就使用此中间件 + + + +6、插件多语言 + +①创建语言文件lang/zh-cn.php,返回如下格式的数组: + +return [ + 'success_message' => '请求成功', + 'ticket_title_require' => '请输入工单标题', + +'ticket_log_client_create_ticket' => '{client}新建工单:{ticket_id}', +] + + + +②使用lang_plugins('语言标识',$param=[])实现多语言,$param为语言文件中参数,格式['{client}'=>'wyh'],如: + +lang_plugins('ticket_log_client_create_ticket',['{client}'=>'wyh','{ticket_id}'=>1]); + +③前端多语言文件 + + 前台语言文件:在template/clientarea/lang/目录下index.js文件; + + 后台语言文件:在template/admin/lang目录下 + +(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_ticket工单插件 + + + +7、插件后台导航 + +①导航默认会创建在插件导航之下,默认链接:plugin/插件名/index.html,对应template/admin/index.php文件,同时需要在lang/下的语言文件创建如下格式的语言,nav_plugin_addon_插件名: + +'nav_plugin_addon_idcsmart_ticket' => '工单', + + + +②自定义导航,若是一级导航,会增加在插件导航之上,管理导航之下,在插件根目录下创建sidebar.php,示例: + +/* + * 自定义后台导航菜单(仅支持一二级),注意系统会在插件导航下默认创建url为"plugin/插件名称/index.html"的导航,因此需要在template/admin/目录下创建index.php文件作为插件入口 + */ +return [ + [ # 一级导航 + 'name' => 'nav_plugin_addon_ticket', # 导航名称,不要与系统冲突(参考idcsmart_nav表中name字段),同时需要在lang/目录下定义语言 + 'url' => '', # 为空表示一级导航,不需要链接 + 'icon' => 'tools', # 图标,获取图标:https://tdesign.tencent.com/vue/components/icon + 'in' => '', # 一级导航,此值为空 + 'child' => [ # 二级导航 + [ + 'name' => 'nav_plugin_addon_ticket_list', # 导航名称 + 'url' => 'ticket', # 链接格式,会自动加上.html + 'in' => 'nav_user_management', # 可定义导航在某个一级导航之下,默认会放置在此一级导航最后的位置(获取方式:idcsmart_nav表中的parent_id==0的name字段) + 'icon' => '', # 图标,获取图标:https://tdesign.tencent.com/vue/components/icon + ], + [ + 'name' => 'nav_plugin_addon_ticket_internal_list', # 导航名称 + 'url' => 'ticket_internal', # 链接格式,会自动加上.html + 'in' => '', # 可定义导航在某个一级导航之下,默认会放置在此一级导航最后的位置 + 'icon' => '', # 图标,获取图标:https://tdesign.tencent.com/vue/components/icon + ], + ] + ], +]; + + + +8、插件前台导航 + +①导航默认会创建在插件导航之下,默认链接:plugin/插件名/index.html; + +②自定义导航,会增加在插件导航之上,管理导航之下,在插件根目录下创建sidebar_clientarea.php,示例: + +/* + * 自定义前台导航菜单(仅支持一二级) + */ +return [ + [ + 'name' => 'nav_plugin_addon_ticket', # 链接名称,同时需要在lang/目录下定义语言 + 'url' => '', # 链接格式,会自动加上.html + 'icon' => '', # 图标 + 'child' => [ # 二级菜单 + [ + 'name' => 'nav_plugin_addon_ticket_list', + 'url' => 'ticket', + 'icon' => '', # 图标 + ], + ] + ], +]; + + + + + +9、插件后台权限管理 + +在插件根目录下创建auth.php,示例如下(注意定义语言): + + 'auth_plugin_addon_ticket_list', # y用户工单 + 'url' => 'ticket', + 'child' => [ # 操作权限 + [ + 'title' => 'auth_plugin_addon_ticket_view', # 工单查看 + 'url' => '', + 'auth_rule' => 'TicketController::ticketList', # 工单列表具体控制器方法 + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_list' # 具体权限名称 + ], + [ + 'title' => 'auth_plugin_addon_ticket_receive', + 'url' => '', + 'auth_rule' => 'TicketController::receive', + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_receive' # 具体权限名称 + ], + [ + 'title' => 'auth_plugin_addon_ticket_resolved', + 'url' => '', + 'auth_rule' => 'TicketController::resolved', + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_resolved' # 具体权限名称 + ], + ] + ], + [ + 'title' => 'auth_plugin_addon_ticket_detail', # 工单详情 + 'url' => 'ticket_detail', + 'child' => [ + [ + 'title' => 'auth_plugin_addon_ticket_view', + 'url' => '', + 'auth_rule' => 'TicketController::index', + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_index' # 具体权限名称 + ], + [ + 'title' => 'auth_plugin_addon_ticket_reply', + 'url' => '', + 'auth_rule' => 'TicketController::reply', + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_reply' # 具体权限名称 + ], + [ + 'title' => 'auth_plugin_addon_ticket_download', + 'url' => '', + 'auth_rule' => 'TicketController::download', + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_download' # 具体权限名称 + ], + ] + ], + [ + 'title' => 'auth_plugin_addon_ticket_internal_list', # 内部工单 + 'url' => 'ticket_internal', + 'child' => [ + [ + 'title' => 'auth_plugin_addon_ticket_view', + 'url' => '', + 'auth_rule' => 'TicketInternalController::ticketInternalList', + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_internal_list' # 具体权限名称 + ], + [ + 'title' => 'auth_plugin_addon_ticket_view', + 'url' => '', + 'auth_rule' => 'TicketInternalController::index', + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_internal_index' # 具体权限名称 + ], + [ + 'title' => 'auth_plugin_addon_ticket_add', + 'url' => '', + 'auth_rule' => 'TicketInternalController::create', + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_internal_create' # 具体权限名称 + ], + [ + 'title' => 'auth_plugin_addon_ticket_receive', + 'url' => '', + 'auth_rule' => 'TicketInternalController::receive', + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_internal_receive' # 具体权限名称 + ], + [ + 'title' => 'auth_plugin_addon_ticket_resolved', + 'url' => '', + 'auth_rule' => 'TicketInternalController::resolved', + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_internal_resolved' # 具体权限名称 + ], + [ + 'title' => 'auth_plugin_addon_ticket_reply', + 'url' => '', + 'auth_rule' => 'TicketInternalController::reply', + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_internal_reply' # 具体权限名称 + ], + [ + 'title' => 'auth_plugin_addon_ticket_forward', + 'url' => '', + 'auth_rule' => 'TicketInternalController::forward', + 'auth_rule_title' => 'auth_rule_plugin_addon_ticket_internal_forward' # 具体权限名称 + ], + ] + ], +]; + + + +10、插件接口内部调用 + +使用plugin_api($addon,$controller,$action,$param=[])函数可内部调用插件API,需要开发者提供插件API开发文档,具体格式参考系统API文档 + + * @param string addon - 插件 require + + * @param string controller - 控制器前缀 require + + * @param string action - 方法 require + + * @param array param - 传入的参数 \ No newline at end of file