作者 黄超

2023.05.23 kevin xs

正在显示 57 个修改的文件 包含 4707 行增加0 行删除

要显示太多修改。

为保证性能只显示 57 of 57+ 个文件。

  1 +{
  2 + "directory": "public/assets/libs",
  3 + "ignoredDependencies": [
  4 + "es6-promise",
  5 + "file-saver",
  6 + "html2canvas",
  7 + "jspdf",
  8 + "jspdf-autotable",
  9 + "pdfmake"
  10 + ]
  11 +}
  1 +[app]
  2 +debug = false
  3 +trace = false
  4 +
  5 +[database]
  6 +hostname = 127.0.0.1
  7 +database = fastadmin
  8 +username = root
  9 +password = root
  10 +hostport = 3306
  11 +prefix = fa_
  1 +/nbproject/
  2 +/runtime/*
  3 +/public/uploads/*
  4 +.idea
  5 +composer.lock
  6 +*.log
  7 +*.css.map
  8 +!.gitkeep
  9 +.env
  10 +/application/database.php
  11 +.svn
  12 +.vscode
  13 +node_modules
  14 +public/.htaccess
  15 +public/.user.ini
  16 +public/nginx.htaccess
  17 +.htaccess
  18 +public/.well-known/
  19 +public/ccc.txt
  20 +public/kevin_face_check.log
  1 +Apache License
  2 +Version 2.0, January 2004
  3 +http://www.apache.org/licenses/
  4 +
  5 +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
  6 +
  7 +1. Definitions.
  8 +
  9 +"License" shall mean the terms and conditions for use, reproduction, and
  10 +distribution as defined by Sections 1 through 9 of this document.
  11 +
  12 +"Licensor" shall mean the copyright owner or entity authorized by the copyright
  13 +owner that is granting the License.
  14 +
  15 +"Legal Entity" shall mean the union of the acting entity and all other entities
  16 +that control, are controlled by, or are under common control with that entity.
  17 +For the purposes of this definition, "control" means (i) the power, direct or
  18 +indirect, to cause the direction or management of such entity, whether by
  19 +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
  20 +outstanding shares, or (iii) beneficial ownership of such entity.
  21 +
  22 +"You" (or "Your") shall mean an individual or Legal Entity exercising
  23 +permissions granted by this License.
  24 +
  25 +"Source" form shall mean the preferred form for making modifications, including
  26 +but not limited to software source code, documentation source, and configuration
  27 +files.
  28 +
  29 +"Object" form shall mean any form resulting from mechanical transformation or
  30 +translation of a Source form, including but not limited to compiled object code,
  31 +generated documentation, and conversions to other media types.
  32 +
  33 +"Work" shall mean the work of authorship, whether in Source or Object form, made
  34 +available under the License, as indicated by a copyright notice that is included
  35 +in or attached to the work (an example is provided in the Appendix below).
  36 +
  37 +"Derivative Works" shall mean any work, whether in Source or Object form, that
  38 +is based on (or derived from) the Work and for which the editorial revisions,
  39 +annotations, elaborations, or other modifications represent, as a whole, an
  40 +original work of authorship. For the purposes of this License, Derivative Works
  41 +shall not include works that remain separable from, or merely link (or bind by
  42 +name) to the interfaces of, the Work and Derivative Works thereof.
  43 +
  44 +"Contribution" shall mean any work of authorship, including the original version
  45 +of the Work and any modifications or additions to that Work or Derivative Works
  46 +thereof, that is intentionally submitted to Licensor for inclusion in the Work
  47 +by the copyright owner or by an individual or Legal Entity authorized to submit
  48 +on behalf of the copyright owner. For the purposes of this definition,
  49 +"submitted" means any form of electronic, verbal, or written communication sent
  50 +to the Licensor or its representatives, including but not limited to
  51 +communication on electronic mailing lists, source code control systems, and
  52 +issue tracking systems that are managed by, or on behalf of, the Licensor for
  53 +the purpose of discussing and improving the Work, but excluding communication
  54 +that is conspicuously marked or otherwise designated in writing by the copyright
  55 +owner as "Not a Contribution."
  56 +
  57 +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
  58 +of whom a Contribution has been received by Licensor and subsequently
  59 +incorporated within the Work.
  60 +
  61 +2. Grant of Copyright License.
  62 +
  63 +Subject to the terms and conditions of this License, each Contributor hereby
  64 +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
  65 +irrevocable copyright license to reproduce, prepare Derivative Works of,
  66 +publicly display, publicly perform, sublicense, and distribute the Work and such
  67 +Derivative Works in Source or Object form.
  68 +
  69 +3. Grant of Patent License.
  70 +
  71 +Subject to the terms and conditions of this License, each Contributor hereby
  72 +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
  73 +irrevocable (except as stated in this section) patent license to make, have
  74 +made, use, offer to sell, sell, import, and otherwise transfer the Work, where
  75 +such license applies only to those patent claims licensable by such Contributor
  76 +that are necessarily infringed by their Contribution(s) alone or by combination
  77 +of their Contribution(s) with the Work to which such Contribution(s) was
  78 +submitted. If You institute patent litigation against any entity (including a
  79 +cross-claim or counterclaim in a lawsuit) alleging that the Work or a
  80 +Contribution incorporated within the Work constitutes direct or contributory
  81 +patent infringement, then any patent licenses granted to You under this License
  82 +for that Work shall terminate as of the date such litigation is filed.
  83 +
  84 +4. Redistribution.
  85 +
  86 +You may reproduce and distribute copies of the Work or Derivative Works thereof
  87 +in any medium, with or without modifications, and in Source or Object form,
  88 +provided that You meet the following conditions:
  89 +
  90 +You must give any other recipients of the Work or Derivative Works a copy of
  91 +this License; and
  92 +You must cause any modified files to carry prominent notices stating that You
  93 +changed the files; and
  94 +You must retain, in the Source form of any Derivative Works that You distribute,
  95 +all copyright, patent, trademark, and attribution notices from the Source form
  96 +of the Work, excluding those notices that do not pertain to any part of the
  97 +Derivative Works; and
  98 +If the Work includes a "NOTICE" text file as part of its distribution, then any
  99 +Derivative Works that You distribute must include a readable copy of the
  100 +attribution notices contained within such NOTICE file, excluding those notices
  101 +that do not pertain to any part of the Derivative Works, in at least one of the
  102 +following places: within a NOTICE text file distributed as part of the
  103 +Derivative Works; within the Source form or documentation, if provided along
  104 +with the Derivative Works; or, within a display generated by the Derivative
  105 +Works, if and wherever such third-party notices normally appear. The contents of
  106 +the NOTICE file are for informational purposes only and do not modify the
  107 +License. You may add Your own attribution notices within Derivative Works that
  108 +You distribute, alongside or as an addendum to the NOTICE text from the Work,
  109 +provided that such additional attribution notices cannot be construed as
  110 +modifying the License.
  111 +You may add Your own copyright statement to Your modifications and may provide
  112 +additional or different license terms and conditions for use, reproduction, or
  113 +distribution of Your modifications, or for any such Derivative Works as a whole,
  114 +provided Your use, reproduction, and distribution of the Work otherwise complies
  115 +with the conditions stated in this License.
  116 +
  117 +5. Submission of Contributions.
  118 +
  119 +Unless You explicitly state otherwise, any Contribution intentionally submitted
  120 +for inclusion in the Work by You to the Licensor shall be under the terms and
  121 +conditions of this License, without any additional terms or conditions.
  122 +Notwithstanding the above, nothing herein shall supersede or modify the terms of
  123 +any separate license agreement you may have executed with Licensor regarding
  124 +such Contributions.
  125 +
  126 +6. Trademarks.
  127 +
  128 +This License does not grant permission to use the trade names, trademarks,
  129 +service marks, or product names of the Licensor, except as required for
  130 +reasonable and customary use in describing the origin of the Work and
  131 +reproducing the content of the NOTICE file.
  132 +
  133 +7. Disclaimer of Warranty.
  134 +
  135 +Unless required by applicable law or agreed to in writing, Licensor provides the
  136 +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
  137 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
  138 +including, without limitation, any warranties or conditions of TITLE,
  139 +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
  140 +solely responsible for determining the appropriateness of using or
  141 +redistributing the Work and assume any risks associated with Your exercise of
  142 +permissions under this License.
  143 +
  144 +8. Limitation of Liability.
  145 +
  146 +In no event and under no legal theory, whether in tort (including negligence),
  147 +contract, or otherwise, unless required by applicable law (such as deliberate
  148 +and grossly negligent acts) or agreed to in writing, shall any Contributor be
  149 +liable to You for damages, including any direct, indirect, special, incidental,
  150 +or consequential damages of any character arising as a result of this License or
  151 +out of the use or inability to use the Work (including but not limited to
  152 +damages for loss of goodwill, work stoppage, computer failure or malfunction, or
  153 +any and all other commercial damages or losses), even if such Contributor has
  154 +been advised of the possibility of such damages.
  155 +
  156 +9. Accepting Warranty or Additional Liability.
  157 +
  158 +While redistributing the Work or Derivative Works thereof, You may choose to
  159 +offer, and charge a fee for, acceptance of support, warranty, indemnity, or
  160 +other liability obligations and/or rights consistent with this License. However,
  161 +in accepting such obligations, You may act only on Your own behalf and on Your
  162 +sole responsibility, not on behalf of any other Contributor, and only if You
  163 +agree to indemnify, defend, and hold each Contributor harmless for any liability
  164 +incurred by, or claims asserted against, such Contributor by reason of your
  165 +accepting any such warranty or additional liability.
  166 +
  167 +END OF TERMS AND CONDITIONS
  168 +
  169 +APPENDIX: How to apply the Apache License to your work
  170 +
  171 +To apply the Apache License to your work, attach the following boilerplate
  172 +notice, with the fields enclosed by brackets "{}" replaced with your own
  173 +identifying information. (Don't include the brackets!) The text should be
  174 +enclosed in the appropriate comment syntax for the file format. We also
  175 +recommend that a file or class name and description of purpose be included on
  176 +the same "printed page" as the copyright notice for easier identification within
  177 +third-party archives.
  178 +
  179 + Copyright 2017 Karson
  180 +
  181 + Licensed under the Apache License, Version 2.0 (the "License");
  182 + you may not use this file except in compliance with the License.
  183 + You may obtain a copy of the License at
  184 +
  185 + http://www.apache.org/licenses/LICENSE-2.0
  186 +
  187 + Unless required by applicable law or agreed to in writing, software
  188 + distributed under the License is distributed on an "AS IS" BASIS,
  189 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  190 + See the License for the specific language governing permissions and
  191 + limitations under the License.
  1 +FastAdmin是一款基于ThinkPHP+Bootstrap的极速后台开发框架。
  2 +
  3 +
  4 +## 主要特性
  5 +
  6 +* 基于`Auth`验证的权限管理系统
  7 + * 支持无限级父子级权限继承,父级的管理员可任意增删改子级管理员及权限设置
  8 + * 支持单管理员多角色
  9 + * 支持管理子级数据或个人数据
  10 +* 强大的一键生成功能
  11 + * 一键生成CRUD,包括控制器、模型、视图、JS、语言包、菜单、回收站等
  12 + * 一键压缩打包JS和CSS文件,一键CDN静态资源部署
  13 + * 一键生成控制器菜单和规则
  14 + * 一键生成API接口文档
  15 +* 完善的前端功能组件开发
  16 + * 基于`AdminLTE`二次开发
  17 + * 基于`Bootstrap`开发,自适应手机、平板、PC
  18 + * 基于`RequireJS`进行JS模块管理,按需加载
  19 + * 基于`Less`进行样式开发
  20 +* 强大的插件扩展功能,在线安装卸载升级插件
  21 +* 通用的会员模块和API模块
  22 +* 共用同一账号体系的Web端会员中心权限验证和API接口会员权限验证
  23 +* 二级域名部署支持,同时域名支持绑定到应用插件
  24 +* 多语言支持,服务端及客户端支持
  25 +* 支持大文件分片上传、剪切板粘贴上传、拖拽上传,进度条显示,图片上传前压缩
  26 +* 支持表格固定列、固定表头、跨页选择、Excel导出、模板渲染等功能
  27 +* 强大的第三方应用模块支持([CMS](https://www.fastadmin.net/store/cms.html)[博客](https://www.fastadmin.net/store/blog.html)[知识付费问答](https://www.fastadmin.net/store/ask.html)[在线投票系统](https://www.fastadmin.net/store/vote.html)[B2C商城](https://www.fastadmin.net/store/shopro.html)[B2B2C商城](https://www.fastadmin.net/store/wanlshop.html))
  28 +* 支持CMS、博客、知识付费问答无缝整合[Xunsearch全文搜索](https://www.fastadmin.net/store/xunsearch.html)
  29 +* 第三方小程序支持([CMS小程序](https://www.fastadmin.net/store/cms.html)[预订小程序](https://www.fastadmin.net/store/ball.html)[问答小程序](https://www.fastadmin.net/store/ask.html)[点餐小程序](https://www.fastadmin.net/store/unidrink.html)[B2C小程序](https://www.fastadmin.net/store/shopro.html)[B2B2C小程序](https://www.fastadmin.net/store/wanlshop.html)[博客小程序](https://www.fastadmin.net/store/blog.html))
  30 +* 整合第三方短信接口(阿里云、腾讯云短信)
  31 +* 无缝整合第三方云存储(七牛云、阿里云OSS、又拍云)功能,支持云储存分片上传
  32 +* 第三方富文本编辑器支持(Summernote、Kindeditor、百度编辑器)
  33 +* 第三方登录(QQ、微信、微博)整合
  34 +* 第三方支付(微信、支付宝)无缝整合,微信支持PC端扫码支付
  35 +* 丰富的插件应用市场
  36 +
  37 +## 安装使用
  38 +
  39 +https://doc.fastadmin.net
  40 +
  41 +## 在线演示
  42 +
  43 +https://demo.fastadmin.net
  44 +
  45 +用户名:admin
  46 +
  47 +密 码:123456
  48 +
  49 +提 示:演示站数据无法进行修改,请下载源码安装体验全部功能
  50 +
  51 +## 界面截图
  52 +![控制台](https://images.gitee.com/uploads/images/2020/0929/202947_8db2d281_10933.gif "控制台")
  53 +
  54 +## 问题反馈
  55 +
  56 +在使用中有任何问题,请使用以下联系方式联系我们
  57 +
  58 +交流社区: https://ask.fastadmin.net
  59 +
  60 +QQ 1 群(满)、QQ 2 群(满)、QQ 3 群(满)、QQ 4 群(满)、QQ 5 群(满)、QQ 6 群(满)、[QQ 7 群](https://www.fastadmin.net/goto/qun)
  61 +
  62 +Github: https://github.com/karsonzhang/fastadmin
  63 +
  64 +Gitee: https://gitee.com/karson/fastadmin
  65 +
  66 +## 特别鸣谢
  67 +
  68 +感谢以下的项目,排名不分先后
  69 +
  70 +ThinkPHP:http://www.thinkphp.cn
  71 +
  72 +AdminLTE:https://adminlte.io
  73 +
  74 +Bootstrap:http://getbootstrap.com
  75 +
  76 +jQuery:http://jquery.com
  77 +
  78 +Bootstrap-table:https://github.com/wenzhixin/bootstrap-table
  79 +
  80 +Nice-validator: https://validator.niceue.com
  81 +
  82 +SelectPage: https://github.com/TerryZ/SelectPage
  83 +
  84 +Layer: https://layuion.com/layer/
  85 +
  86 +DropzoneJS: https://www.dropzonejs.com
  87 +
  88 +
  89 +## 版权信息
  90 +
  91 +FastAdmin遵循Apache2开源协议发布,并提供免费使用。
  92 +
  93 +本项目包含的第三方源码和二进制文件之版权信息另行标注。
  94 +
  95 +版权所有Copyright © 2017-2022 by FastAdmin (https://www.fastadmin.net)
  96 +
  97 +All rights reserved。
  1 +{"files":[],"license":"regular","licenseto":"15629","licensekey":"38jTdqf4pm6XoSwz mqjMxWqQU9Je1XcOZtI6Yg==","domains":["cardverification.com"],"licensecodes":[],"validations":["867a7ee97b89c3a1f31235c70da23ecf"]}
  1 +<?php
  2 +
  3 +namespace addons\address;
  4 +
  5 +use think\Addons;
  6 +
  7 +/**
  8 + * 地址选择
  9 + * @author [MiniLing] <[laozheyouxiang@163.com]>
  10 + */
  11 +class Address extends Addons
  12 +{
  13 +
  14 + /**
  15 + * 插件安装方法
  16 + * @return bool
  17 + */
  18 + public function install()
  19 + {
  20 + return true;
  21 + }
  22 +
  23 + /**
  24 + * 插件卸载方法
  25 + * @return bool
  26 + */
  27 + public function uninstall()
  28 + {
  29 + return true;
  30 + }
  31 +
  32 +}
  1 +require([], function () {
  2 + //绑定data-toggle=addresspicker属性点击事件
  3 +
  4 + $(document).on('click', "[data-toggle='addresspicker']", function () {
  5 + var that = this;
  6 + var callback = $(that).data('callback');
  7 + var input_id = $(that).data("input-id") ? $(that).data("input-id") : "";
  8 + var lat_id = $(that).data("lat-id") ? $(that).data("lat-id") : "";
  9 + var lng_id = $(that).data("lng-id") ? $(that).data("lng-id") : "";
  10 + var lat = lat_id ? $("#" + lat_id).val() : '';
  11 + var lng = lng_id ? $("#" + lng_id).val() : '';
  12 + var url = "/addons/address/index/select";
  13 + url += (lat && lng) ? '?lat=' + lat + '&lng=' + lng : '';
  14 + Fast.api.open(url, '位置选择', {
  15 + callback: function (res) {
  16 + input_id && $("#" + input_id).val(res.address).trigger("change");
  17 + lat_id && $("#" + lat_id).val(res.lat).trigger("change");
  18 + lng_id && $("#" + lng_id).val(res.lng).trigger("change");
  19 + try {
  20 + //执行回调函数
  21 + if (typeof callback === 'function') {
  22 + callback.call(that, res);
  23 + }
  24 + } catch (e) {
  25 +
  26 + }
  27 + }
  28 + });
  29 + });
  30 +});
  1 +<?php
  2 +
  3 +return [
  4 + [
  5 + 'name' => 'maptype',
  6 + 'title' => '默认地图类型',
  7 + 'type' => 'radio',
  8 + 'content' => [
  9 + 'baidu' => '百度地图',
  10 + 'amap' => '高德地图',
  11 + 'tencent' => '腾讯地图',
  12 + ],
  13 + 'value' => 'tencent',
  14 + 'rule' => 'required',
  15 + 'msg' => '',
  16 + 'tip' => '',
  17 + 'ok' => '',
  18 + 'extend' => '',
  19 + ],
  20 + [
  21 + 'name' => 'zoom',
  22 + 'title' => '默认缩放级别',
  23 + 'type' => 'string',
  24 + 'content' => [],
  25 + 'value' => '11',
  26 + 'rule' => 'required',
  27 + 'msg' => '',
  28 + 'tip' => '',
  29 + 'ok' => '',
  30 + 'extend' => '',
  31 + ],
  32 + [
  33 + 'name' => 'lat',
  34 + 'title' => '默认Lat',
  35 + 'type' => 'string',
  36 + 'content' => [],
  37 + 'value' => '39.919990',
  38 + 'rule' => 'required',
  39 + 'msg' => '',
  40 + 'tip' => '',
  41 + 'ok' => '',
  42 + 'extend' => '',
  43 + ],
  44 + [
  45 + 'name' => 'lng',
  46 + 'title' => '默认Lng',
  47 + 'type' => 'string',
  48 + 'content' => [],
  49 + 'value' => '116.456270',
  50 + 'rule' => 'required',
  51 + 'msg' => '',
  52 + 'tip' => '',
  53 + 'ok' => '',
  54 + 'extend' => '',
  55 + ],
  56 + [
  57 + 'name' => 'baidukey',
  58 + 'title' => '百度地图KEY',
  59 + 'type' => 'string',
  60 + 'content' => [],
  61 + 'value' => '',
  62 + 'rule' => '',
  63 + 'msg' => '',
  64 + 'tip' => '',
  65 + 'ok' => '',
  66 + 'extend' => '',
  67 + ],
  68 + [
  69 + 'name' => 'amapkey',
  70 + 'title' => '高德地图KEY',
  71 + 'type' => 'string',
  72 + 'content' => [],
  73 + 'value' => '',
  74 + 'rule' => '',
  75 + 'msg' => '',
  76 + 'tip' => '',
  77 + 'ok' => '',
  78 + 'extend' => '',
  79 + ],
  80 + [
  81 + 'name' => 'amapsecurityjscode',
  82 + 'title' => '高德地图安全密钥',
  83 + 'type' => 'string',
  84 + 'content' => [],
  85 + 'value' => '',
  86 + 'rule' => '',
  87 + 'msg' => '',
  88 + 'tip' => '',
  89 + 'ok' => '',
  90 + 'extend' => '',
  91 + ],
  92 + [
  93 + 'name' => 'tencentkey',
  94 + 'title' => '腾讯地图KEY',
  95 + 'type' => 'string',
  96 + 'content' => [],
  97 + 'value' => 'D4KBZ-6YNCZ-5QKXK-ZMP65-TEC7V-DTBGT',
  98 + 'rule' => '',
  99 + 'msg' => '',
  100 + 'tip' => '',
  101 + 'ok' => '',
  102 + 'extend' => '',
  103 + ],
  104 + [
  105 + 'name' => '__tips__',
  106 + 'title' => '温馨提示',
  107 + 'type' => '',
  108 + 'content' => [],
  109 + 'value' => '请先申请对应地图的Key,配置后再使用',
  110 + 'rule' => '',
  111 + 'msg' => '',
  112 + 'tip' => '',
  113 + 'ok' => '',
  114 + 'extend' => 'alert-danger-light',
  115 + ],
  116 +];
  1 +<?php
  2 +
  3 +namespace addons\address\controller;
  4 +
  5 +use think\addons\Controller;
  6 +use think\Config;
  7 +use think\Hook;
  8 +
  9 +class Index extends Controller
  10 +{
  11 +
  12 + // 首页
  13 + public function index()
  14 + {
  15 + // 语言检测
  16 + $lang = $this->request->langset();
  17 + $lang = preg_match("/^([a-zA-Z\-_]{2,10})\$/i", $lang) ? $lang : 'zh-cn';
  18 +
  19 + $site = Config::get("site");
  20 +
  21 + // 配置信息
  22 + $config = [
  23 + 'site' => array_intersect_key($site, array_flip(['name', 'cdnurl', 'version', 'timezone', 'languages'])),
  24 + 'upload' => null,
  25 + 'modulename' => 'addons',
  26 + 'controllername' => 'index',
  27 + 'actionname' => 'index',
  28 + 'jsname' => 'addons/address',
  29 + 'moduleurl' => '',
  30 + 'language' => $lang
  31 + ];
  32 + $config = array_merge($config, Config::get("view_replace_str"));
  33 +
  34 + // 配置信息后
  35 + Hook::listen("config_init", $config);
  36 + // 加载当前控制器语言包
  37 + $this->view->assign('site', $site);
  38 + $this->view->assign('config', $config);
  39 +
  40 + return $this->view->fetch();
  41 + }
  42 +
  43 + // 选择地址
  44 + public function select()
  45 + {
  46 + $config = get_addon_config('address');
  47 + $lng = $this->request->get('lng');
  48 + $lat = $this->request->get('lat');
  49 + $lng = $lng ? $lng : $config['lng'];
  50 + $lat = $lat ? $lat : $config['lat'];
  51 + $this->view->assign('lng', $lng);
  52 + $this->view->assign('lat', $lat);
  53 + $maptype = $config['maptype'];
  54 + if (!isset($config[$maptype . 'key']) || !$config[$maptype . 'key']) {
  55 + $this->error("请在配置中配置对应类型地图的密钥");
  56 + }
  57 + return $this->view->fetch('index/' . $maptype);
  58 + }
  59 +
  60 +}
  1 +name = address
  2 +title = 地址位置选择插件
  3 +intro = 地图位置选择插件,可返回地址和经纬度
  4 +author = FastAdmin
  5 +website = https://www.fastadmin.net
  6 +version = 1.0.10
  7 +state = 1
  8 +url = /addons/address
  9 +license = regular
  10 +licenseto = 15629
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  5 + <title>地址选择器</title>
  6 + <link rel="stylesheet" href="__CDN__/assets/css/frontend.min.css"/>
  7 + <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>
  8 + <style type="text/css">
  9 + body {
  10 + margin: 0;
  11 + padding: 0;
  12 + }
  13 +
  14 + #container {
  15 + position: absolute;
  16 + left: 0;
  17 + top: 0;
  18 + right: 0;
  19 + bottom: 0;
  20 + }
  21 +
  22 + .confirm {
  23 + position: absolute;
  24 + bottom: 30px;
  25 + right: 4%;
  26 + z-index: 99;
  27 + height: 50px;
  28 + width: 50px;
  29 + line-height: 50px;
  30 + font-size: 15px;
  31 + text-align: center;
  32 + background-color: white;
  33 + background: #1ABC9C;
  34 + color: white;
  35 + border: none;
  36 + cursor: pointer;
  37 + border-radius: 50%;
  38 + }
  39 +
  40 + .search {
  41 + position: absolute;
  42 + width: 400px;
  43 + top: 0;
  44 + left: 50%;
  45 + padding: 5px;
  46 + margin-left: -200px;
  47 + }
  48 +
  49 + .amap-marker-label {
  50 + border: 0;
  51 + background-color: transparent;
  52 + }
  53 +
  54 + .info {
  55 + padding: .75rem 1.25rem;
  56 + margin-bottom: 1rem;
  57 + border-radius: .25rem;
  58 + position: fixed;
  59 + top: 2rem;
  60 + background-color: white;
  61 + width: auto;
  62 + min-width: 22rem;
  63 + border-width: 0;
  64 + left: 1.8rem;
  65 + box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
  66 + }
  67 + </style>
  68 +</head>
  69 +<body>
  70 +<div class="search">
  71 + <div class="input-group">
  72 + <input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/>
  73 + <span class="input-group-btn">
  74 + <button type="submit" name="search" id="search-btn" class="btn btn-success">
  75 + <i class="fa fa-search"></i>
  76 + </button>
  77 + </span>
  78 + </div>
  79 +</div>
  80 +<div class="confirm">确定</div>
  81 +<div id="container"></div>
  82 +<script type="text/javascript">
  83 + window._AMapSecurityConfig = {
  84 + securityJsCode: "{$config.amapsecurityjscode|default=''}",
  85 + }
  86 +</script>
  87 +<script type="text/javascript" src="//webapi.amap.com/maps?v=1.4.11&key={$config.amapkey|default=''}&plugin=AMap.ToolBar,AMap.Autocomplete,AMap.PlaceSearch,AMap.Geocoder"></script>
  88 +<!-- UI组件库 1.0 -->
  89 +<script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
  90 +<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>
  91 +<script type="text/javascript">
  92 + $(function () {
  93 + var as, address, map, lat, lng, geocoder;
  94 + var init = function () {
  95 + AMapUI.loadUI(['misc/PositionPicker', 'misc/PoiPicker'], function (PositionPicker, PoiPicker) {
  96 + //加载PositionPicker,loadUI的路径参数为模块名中 'ui/' 之后的部分
  97 + map = new AMap.Map('container', {
  98 + zoom: parseInt('{$config.zoom}')
  99 + });
  100 + geocoder = new AMap.Geocoder({
  101 + radius: 1000 //范围,默认:500
  102 + });
  103 + var positionPicker = new PositionPicker({
  104 + mode: 'dragMarker',//设定为拖拽地图模式,可选'dragMap'、'dragMarker',默认为'dragMap'
  105 + map: map//依赖地图对象
  106 + });
  107 + //输入提示
  108 + var autoOptions = {
  109 + input: "place"
  110 + };
  111 +
  112 + var relocation = function (lnglat) {
  113 + lng = lnglat.lng;
  114 + lat = lnglat.lat;
  115 + map.panTo([lng, lat]);
  116 + positionPicker.start(lnglat);
  117 + geocoder.getAddress(lng + ',' + lat, function (status, result) {
  118 + if (status === 'complete' && result.regeocode) {
  119 + var address = result.regeocode.formattedAddress;
  120 + var label = '<div class="info">地址:' + address + '<br>经度:' + lng + '<br>纬度:' + lat + '</div>';
  121 + positionPicker.marker.setLabel({
  122 + content: label //显示内容
  123 + });
  124 + } else {
  125 + console.log(JSON.stringify(result));
  126 + }
  127 + });
  128 + };
  129 + var auto = new AMap.Autocomplete(autoOptions);
  130 +
  131 + //构造地点查询类
  132 + var placeSearch = new AMap.PlaceSearch({
  133 + map: map
  134 + });
  135 + //注册监听,当选中某条记录时会触发
  136 + AMap.event.addListener(auto, "select", function (e) {
  137 + placeSearch.setCity(e.poi.adcode);
  138 + placeSearch.search(e.poi.name); //关键字查询查询
  139 + });
  140 + AMap.event.addListener(map, 'click', function (e) {
  141 + relocation(e.lnglat);
  142 + });
  143 +
  144 + //加载工具条
  145 + var tool = new AMap.ToolBar();
  146 + map.addControl(tool);
  147 +
  148 + var poiPicker = new PoiPicker({
  149 + input: 'place',
  150 + placeSearchOptions: {
  151 + map: map,
  152 + pageSize: 6 //关联搜索分页
  153 + }
  154 + });
  155 + poiPicker.on('poiPicked', function (poiResult) {
  156 + poiPicker.hideSearchResults();
  157 + $('.poi .nearpoi').text(poiResult.item.name);
  158 + $('.address .info').text(poiResult.item.address);
  159 + $('#address').val(poiResult.item.address);
  160 + $("#place").val(poiResult.item.name);
  161 +
  162 + relocation(poiResult.item.location);
  163 + });
  164 +
  165 + positionPicker.on('success', function (positionResult) {
  166 + as = positionResult.position;
  167 + address = positionResult.address;
  168 + lat = as.lat;
  169 + lng = as.lng;
  170 + });
  171 + positionPicker.on('fail', function (positionResult) {
  172 + address = '';
  173 + });
  174 + positionPicker.start();
  175 +
  176 + var defaultLng = {$lng}, defaultLat = {$lat};
  177 + if (defaultLng && defaultLat) {
  178 + relocation(new AMap.LngLat(Number(defaultLng), Number(defaultLat)));
  179 + }
  180 + });
  181 + };
  182 +
  183 + //点击确定后执行回调赋值
  184 + var close = function (data) {
  185 + var index = parent.Layer.getFrameIndex(window.name);
  186 + var callback = parent.$("#layui-layer" + index).data("callback");
  187 + //再执行关闭
  188 + parent.Layer.close(index);
  189 + //再调用回传函数
  190 + if (typeof callback === 'function') {
  191 + callback.call(undefined, data);
  192 + }
  193 + };
  194 +
  195 + var getParam = function (name, url) {
  196 + url = url || location.href;
  197 + return url.match(new RegExp('[?&]' + name + '=([^?&]+)', 'i')) ? decodeURIComponent(RegExp.$1) : '';
  198 + };
  199 +
  200 + //点击搜索按钮
  201 + $(document).on('click', '.confirm', function () {
  202 + var zoom = map.getZoom();
  203 + var data = {lat: lat, lng: lng, zoom: zoom, address: address};
  204 + close(data);
  205 + });
  206 + init();
  207 + });
  208 +</script>
  209 +</body>
  210 +</html>
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  5 + <title>地址选择器</title>
  6 + <link rel="stylesheet" href="__CDN__/assets/css/frontend.min.css"/>
  7 + <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>
  8 + <style type="text/css">
  9 + body {
  10 + margin: 0;
  11 + padding: 0;
  12 + }
  13 +
  14 + #container {
  15 + position: absolute;
  16 + left: 0;
  17 + top: 0;
  18 + right: 0;
  19 + bottom: 0;
  20 + }
  21 +
  22 + .confirm {
  23 + position: absolute;
  24 + bottom: 30px;
  25 + right: 4%;
  26 + z-index: 99;
  27 + height: 50px;
  28 + width: 50px;
  29 + line-height: 50px;
  30 + font-size: 15px;
  31 + text-align: center;
  32 + background-color: white;
  33 + background: #1ABC9C;
  34 + color: white;
  35 + border: none;
  36 + cursor: pointer;
  37 + border-radius: 50%;
  38 + }
  39 +
  40 + .search {
  41 + position: absolute;
  42 + width: 400px;
  43 + top: 0;
  44 + left: 50%;
  45 + padding: 5px;
  46 + margin-left: -200px;
  47 + }
  48 +
  49 + label.BMapLabel {
  50 + max-width: inherit;
  51 + padding: .75rem 1.25rem;
  52 + margin-bottom: 1rem;
  53 + background-color: white;
  54 + width: auto;
  55 + min-width: 22rem;
  56 + border: none;
  57 + box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
  58 + }
  59 +
  60 + </style>
  61 +</head>
  62 +<body>
  63 +<div class="search">
  64 + <div class="input-group">
  65 + <input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/>
  66 + <div id="searchResultPanel" style="border:1px solid #C0C0C0;width:150px;height:auto; display:none;"></div>
  67 + <span class="input-group-btn">
  68 + <button type="button" name="search" id="address" class="btn btn-success">
  69 + <i class="fa fa-search"></i>
  70 + </button>
  71 + </span>
  72 + </div>
  73 +</div>
  74 +<div class="confirm">确定</div>
  75 +<div id="container"></div>
  76 +<script type="text/javascript" src="//api.map.baidu.com/api?v=2.0&ak={$config.baidukey|default=''}"></script>
  77 +<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>
  78 +<script type="text/javascript">
  79 + $(function () {
  80 + // 百度地图API功能
  81 + function G(id) {
  82 + return document.getElementById(id);
  83 + }
  84 +
  85 + var map, marker, searchService, address = null, lng, lat;
  86 +
  87 + var init = function () {
  88 + map = new BMap.Map("container"); // 创建地图实例
  89 + var point = new BMap.Point({$lng}, {$lat}); // 创建点坐标
  90 + map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
  91 + map.centerAndZoom(point, parseInt("{$config.zoom}")); // 初始化地图,设置中心点坐标和地图级别
  92 +
  93 + var size = new BMap.Size(10, 20);
  94 + map.addControl(new BMap.CityListControl({
  95 + anchor: BMAP_ANCHOR_TOP_LEFT,
  96 + offset: size,
  97 + }));
  98 +
  99 + var geoc = new BMap.Geocoder();
  100 +
  101 + var addpoint = function (point) {
  102 + //通过点击百度地图,可以获取到对应的point, 由point的lng、lat属性就可以获取对应的经度纬度
  103 + var pt = point;
  104 + geoc.getLocation(pt, function (rs) {
  105 + //对象可以获取到详细的地址信息
  106 + address = rs.address;
  107 + deletePoint();
  108 + var mk = new BMap.Marker(pt);
  109 + map.addOverlay(mk);
  110 + map.panTo(pt);
  111 + var label = new BMap.Label('<div class="info">地址:' + address + '<br>经度:' + pt.lng + '<br>纬度:' + pt.lat + '</div>', {offset: new BMap.Size(16, 20)});
  112 + label.setStyle({
  113 + border: 'none',
  114 + padding: '.75rem 1.25rem'
  115 + });
  116 + mk.setLabel(label);
  117 + //将对应的HTML元素设置值
  118 + lng = pt.lng;
  119 + lat = pt.lat;
  120 + });
  121 + };
  122 +
  123 + if ("{$lng}" != '' && "{$lat}" != '') {
  124 + addpoint(point);
  125 + }
  126 +
  127 + ac = new BMap.Autocomplete({"input": "place", "location": map}); //建立一个自动完成的对象
  128 + ac.addEventListener("onhighlight", function (e) { //鼠标放在下拉列表上的事件
  129 + var str = "";
  130 + var _value = e.fromitem.value;
  131 + var value = "";
  132 + if (e.fromitem.index > -1) {
  133 + value = _value.province + _value.city + _value.district + _value.street + _value.business;
  134 + }
  135 + str = "FromItem<br />index = " + e.fromitem.index + "<br />value = " + value;
  136 +
  137 + value = "";
  138 + if (e.toitem.index > -1) {
  139 + _value = e.toitem.value;
  140 + value = _value.province + _value.city + _value.district + _value.street + _value.business;
  141 + }
  142 + str += "<br />ToItem<br />index = " + e.toitem.index + "<br />value = " + value;
  143 + G("searchResultPanel").innerHTML = str;
  144 + });
  145 + ac.addEventListener("onconfirm", function (e) { //鼠标点击下拉列表后的事件
  146 + var _value = e.item.value;
  147 + myValue = _value.province + _value.city + _value.district + _value.street + _value.business;
  148 + G("searchResultPanel").innerHTML = "onconfirm<br />index = " + e.item.index + "<br />myValue = " + myValue;
  149 + setPlace();
  150 + });
  151 +
  152 + function setPlace() {
  153 + map.clearOverlays(); //清除地图上所有覆盖物
  154 + function myFun() {
  155 + var result = local.getResults().getPoi(0);
  156 + var pp = result.point; //获取第一个智能搜索的结果
  157 + map.centerAndZoom(pp, 18);
  158 + map.addOverlay(new BMap.Marker(pp)); //添加标注
  159 + lng = pp.lng;
  160 + lat = pp.lat;
  161 + address = result.address;
  162 + }
  163 +
  164 + var local = new BMap.LocalSearch(map, { //智能搜索
  165 + onSearchComplete: myFun
  166 + });
  167 + local.search(myValue);
  168 + }
  169 +
  170 + map.addEventListener("click", function (e) {
  171 + //通过点击百度地图,可以获取到对应的point, 由point的lng、lat属性就可以获取对应的经度纬度
  172 + var pt = e.point;
  173 + addpoint(e.point);
  174 + });
  175 +
  176 + /**
  177 + * 清除覆盖物
  178 + */
  179 + function deletePoint() {
  180 + var allOverlay = map.getOverlays();
  181 + for (var i = 0; i < allOverlay.length; i++) {
  182 + map.removeOverlay(allOverlay[i]);
  183 + }
  184 + }
  185 + };
  186 +
  187 + var close = function (data) {
  188 + var index = parent.Layer.getFrameIndex(window.name);
  189 + var callback = parent.$("#layui-layer" + index).data("callback");
  190 + //再执行关闭
  191 + parent.Layer.close(index);
  192 + //再调用回传函数
  193 + if (typeof callback === 'function') {
  194 + callback.call(undefined, data);
  195 + }
  196 + };
  197 +
  198 + //点击确定后执行回调赋值
  199 + $(document).on('click', '.confirm', function () {
  200 + var zoom = map.getZoom();
  201 + var data = {lat: lat, lng: lng, zoom: zoom, address: address};
  202 + close(data);
  203 + });
  204 +
  205 + init();
  206 + });
  207 +</script>
  208 +</body>
  209 +</html>
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
  5 + <title>地图位置(经纬度)选择插件</title>
  6 + <link rel="stylesheet" href="__CDN__/assets/css/frontend.min.css"/>
  7 + <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>
  8 +</head>
  9 +<body>
  10 +<div class="container">
  11 +
  12 + <div class="bs-docs-section clearfix">
  13 + <div class="row">
  14 + <div class="col-lg-12">
  15 + <div class="page-header">
  16 + <h2>地图位置(经纬度)选择示例</h2>
  17 + </div>
  18 +
  19 + <div class="bs-component">
  20 + <form action="" method="post" role="form">
  21 + <div class="form-group">
  22 + <label for=""></label>
  23 + <input type="text" class="form-control" name="" id="address" placeholder="地址">
  24 + </div>
  25 + <div class="form-group">
  26 + <label for=""></label>
  27 + <input type="text" class="form-control" name="" id="lng" placeholder="经度">
  28 + </div>
  29 + <div class="form-group">
  30 + <label for=""></label>
  31 + <input type="text" class="form-control" name="" id="lat" placeholder="纬度">
  32 + </div>
  33 +
  34 + <button type="button" class="btn btn-primary" data-toggle='addresspicker' data-input-id="address" data-lng-id="lng" data-lat-id="lat">点击选择</button>
  35 + </form>
  36 + </div>
  37 +
  38 + <div class="page-header">
  39 + <h2 id="code">调用代码</h2>
  40 + </div>
  41 + <div class="bs-component">
  42 + <textarea class="form-control" rows="17">
  43 + <form action="" method="post" role="form">
  44 + <div class="form-group">
  45 + <label for=""></label>
  46 + <input type="text" class="form-control" name="" id="address" placeholder="地址">
  47 + </div>
  48 + <div class="form-group">
  49 + <label for=""></label>
  50 + <input type="text" class="form-control" name="" id="lng" placeholder="经度">
  51 + </div>
  52 + <div class="form-group">
  53 + <label for=""></label>
  54 + <input type="text" class="form-control" name="" id="lat" placeholder="纬度">
  55 + </div>
  56 +
  57 + <button type="button" class="btn btn-primary" data-toggle='addresspicker' data-input-id="address" data-lng-id="lng" data-lat-id="lat">点击选择地址获取经纬度</button>
  58 + </form>
  59 + </textarea>
  60 + </div>
  61 + <div class="page-header">
  62 + <h2>参数说明</h2>
  63 + </div>
  64 +
  65 + <div class="bs-component">
  66 + <table class="table table-condensed table-hover">
  67 + <thead>
  68 + <tr>
  69 + <th>参数</th>
  70 + <th>释义</th>
  71 + </tr>
  72 + </thead>
  73 + <tbody>
  74 + <tr>
  75 + <td>data-input-id</td>
  76 + <td>填充地址的文本框ID</td>
  77 + </tr>
  78 + <tr>
  79 + <td>data-lng-id</td>
  80 + <td>填充经度的文本框ID</td>
  81 + </tr>
  82 + <tr>
  83 + <td>data-lat-id</td>
  84 + <td>填充纬度的文本框ID</td>
  85 + </tr>
  86 + </tbody>
  87 + </table>
  88 + </div>
  89 +
  90 + </div>
  91 + </div>
  92 + </div>
  93 +
  94 +</div>
  95 +<!--@formatter:off-->
  96 +<script type="text/javascript">
  97 + var require = {
  98 + config: {$config|json_encode}
  99 + };
  100 +</script>
  101 +<!--@formatter:on-->
  102 +
  103 +<script>
  104 + require.callback = function () {
  105 + define('addons/address', ['jquery', 'bootstrap', 'frontend', 'template'], function ($, undefined, Frontend, Template) {
  106 + var Controller = {
  107 + index: function () {
  108 + }
  109 + };
  110 + return Controller;
  111 + });
  112 + define('lang', function () {
  113 + return [];
  114 + });
  115 + }
  116 +</script>
  117 +
  118 +<script src="__CDN__/assets/js/require.min.js" data-main="__CDN__/assets/js/require-frontend.min.js?v={$site.version}"></script>
  119 +</body>
  120 +</html>
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  5 + <title>地址选择器</title>
  6 + <link rel="stylesheet" href="__CDN__/assets/css/frontend.min.css"/>
  7 + <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>
  8 + <style type="text/css">
  9 + body {
  10 + margin: 0;
  11 + padding: 0;
  12 + }
  13 +
  14 + #container {
  15 + position: absolute;
  16 + left: 0;
  17 + top: 0;
  18 + right: 0;
  19 + bottom: 0;
  20 + }
  21 +
  22 + .confirm {
  23 + position: absolute;
  24 + bottom: 30px;
  25 + right: 4%;
  26 + z-index: 99;
  27 + height: 50px;
  28 + width: 50px;
  29 + line-height: 50px;
  30 + font-size: 15px;
  31 + text-align: center;
  32 + background-color: white;
  33 + background: #1ABC9C;
  34 + color: white;
  35 + border: none;
  36 + cursor: pointer;
  37 + border-radius: 50%;
  38 + }
  39 +
  40 + .search {
  41 + position: absolute;
  42 + width: 400px;
  43 + top: 0;
  44 + left: 50%;
  45 + padding: 5px;
  46 + margin-left: -200px;
  47 + }
  48 + </style>
  49 +</head>
  50 +<body>
  51 +<div class="search">
  52 + <div class="input-group">
  53 + <input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/>
  54 + <span class="input-group-btn">
  55 + <button type="submit" name="search" id="search-btn" class="btn btn-success">
  56 + <i class="fa fa-search"></i>
  57 + </button>
  58 + </span>
  59 + </div>
  60 +</div>
  61 +<div class="confirm">确定</div>
  62 +<div id="container"></div>
  63 +
  64 +<script charset="utf-8" src="//map.qq.com/api/js?v=2.exp&libraries=place&key={$config.tencentkey|default=''}"></script>
  65 +<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>
  66 +
  67 +<script type="text/javascript">
  68 + $(function () {
  69 + var map, marker, geocoder, infoWin, searchService, address = null;
  70 + var init = function () {
  71 + var center = new qq.maps.LatLng({$lat}, {$lng});
  72 + map = new qq.maps.Map(document.getElementById('container'), {
  73 + center: center,
  74 + zoom: parseInt("{$config.zoom}")
  75 + });
  76 + //初始化marker
  77 + initmarker(center);
  78 +
  79 + //实例化信息窗口
  80 + infoWin = new qq.maps.InfoWindow({
  81 + map: map
  82 + });
  83 + geocoder = new qq.maps.Geocoder({
  84 + complete: function (result) {
  85 + infoWin.open();
  86 + address = result.detail.addressComponents.province +
  87 + result.detail.addressComponents.city +
  88 + result.detail.addressComponents.district;
  89 + if (result.detail.addressComponents.streetNumber == '') {
  90 + address += result.detail.addressComponents.street;
  91 + } else {
  92 + address += result.detail.addressComponents.streetNumber;
  93 + }
  94 + infoWin.setContent(address);
  95 + infoWin.setPosition(result.detail.location);
  96 + }
  97 + });
  98 + //显示当前marker的位置信息窗口
  99 + geocoder.getAddress(center);
  100 +
  101 + var latlngBounds = new qq.maps.LatLngBounds();
  102 + //查询poi类信息
  103 + searchService = new qq.maps.SearchService({
  104 + complete: function (results) {
  105 + console.log(results);
  106 + if (typeof results.detail.pois === 'undefined') {
  107 + alert("未搜索到相关信息");
  108 + return;
  109 + }
  110 + var pois = results.detail.pois;
  111 + for (var i = 0, l = pois.length; i < l; i++) {
  112 + var poi = pois[i];
  113 + latlngBounds.extend(poi.latLng);
  114 + initmarker(poi.latLng);
  115 + //显示当前marker的位置信息窗口
  116 + geocoder.getAddress(poi.latLng);
  117 + }
  118 + map.fitBounds(latlngBounds);
  119 + }
  120 + });
  121 + //实例化自动完成
  122 + var ap = new qq.maps.place.Autocomplete(document.getElementById('place'));
  123 + //添加监听事件
  124 + qq.maps.event.addListener(ap, "confirm", function (res) {
  125 + searchKeyword.call(this, res.value);
  126 + });
  127 + qq.maps.event.addListener(
  128 + map,
  129 + 'click',
  130 + function (event) {
  131 + try {
  132 + infoWin.setContent('<div style="text-align:center;white-space:nowrap;margin:10px;">加载中</div>');
  133 + var latLng = event.latLng,
  134 + lat = latLng.getLat().toFixed(5),
  135 + lng = latLng.getLng().toFixed(5);
  136 + var location = new qq.maps.LatLng(lat, lng);
  137 + //调用获取位置方法
  138 + geocoder.getAddress(location);
  139 + infoWin.setPosition(location);
  140 + marker.setPosition(location);
  141 + } catch (e) {
  142 + console.log(e);
  143 + }
  144 + }
  145 + );
  146 + };
  147 +
  148 + //实例化marker和监听拖拽结束事件
  149 + var initmarker = function (latLng) {
  150 + marker = new qq.maps.Marker({
  151 + map: map,
  152 + position: latLng,
  153 + draggable: true,
  154 + title: '拖动图标选择位置'
  155 + });
  156 + //监听拖拽结束
  157 + qq.maps.event.addListener(marker, 'dragend', function (event) {
  158 + var latLng = event.latLng,
  159 + lat = latLng.getLat().toFixed(5),
  160 + lng = latLng.getLng().toFixed(5);
  161 + var location = new qq.maps.LatLng(lat, lng);
  162 + //调用获取位置方法
  163 + geocoder.getAddress(location);
  164 + });
  165 + };
  166 +
  167 + var close = function (data) {
  168 + var index = parent.Layer.getFrameIndex(window.name);
  169 + var callback = parent.$("#layui-layer" + index).data("callback");
  170 + //再执行关闭
  171 + parent.Layer.close(index);
  172 + //再调用回传函数
  173 + if (typeof callback === 'function') {
  174 + callback.call(undefined, data);
  175 + }
  176 + };
  177 +
  178 + //执行搜索方法
  179 + var searchKeyword = function () {
  180 + searchService.clear();//先清除
  181 + marker.setMap(null);
  182 + infoWin.close();
  183 + var keyword = $("#place").val();
  184 + // searchService.setLocation("北京");//设置默认检索范围(默认为全国),类型可以是坐标或指定的城市名称。
  185 + searchService.setPageIndex(0);//设置检索的特定页数。
  186 + searchService.setPageCapacity(1);//设置每页返回的结果数量。
  187 + searchService.search(this.place.address + " " + keyword);//开始查询
  188 + };
  189 +
  190 + //点击确定后执行回调赋值
  191 + $(document).on('click', '.confirm', function () {
  192 + var as = marker.getPosition();
  193 + var x = as.getLat().toFixed(5);
  194 + var y = as.getLng().toFixed(5);
  195 + var zoom = map.getZoom();
  196 + var data = {lat: x, lng: y, zoom: zoom, address: address};
  197 + close(data);
  198 + });
  199 +
  200 + //点击搜索按钮
  201 + $(document).on('click', '#search-btn', function () {
  202 + if ($("#place").val() == '')
  203 + return;
  204 + searchKeyword();
  205 + });
  206 +
  207 + init();
  208 + });
  209 +</script>
  210 +</body>
  211 +</html>
  1 +{"files":["application\\admin\\controller\\Command.php","application\\admin\\lang\\zh-cn\\command.php","application\\admin\\model\\Command.php","application\\admin\\validate\\Command.php","application\\admin\\view\\command\\add.html","application\\admin\\view\\command\\detail.html","application\\admin\\view\\command\\index.html","public\\assets\\js\\backend\\command.js"],"license":"regular","licenseto":"15629","licensekey":"auhpc1Bb4L3oPUDX +Bfufan9+OW8F9NrTKgVdw==","domains":["cardverification.com"],"licensecodes":[],"validations":["867a7ee97b89c3a1f31235c70da23ecf"],"menus":["command","command\/index","command\/add","command\/detail","command\/command","command\/execute","command\/del","command\/multi"]}
  1 +<?php
  2 +
  3 +namespace addons\command;
  4 +
  5 +use app\common\library\Menu;
  6 +use think\Addons;
  7 +
  8 +/**
  9 + * 在线命令插件
  10 + */
  11 +class Command extends Addons
  12 +{
  13 +
  14 + /**
  15 + * 插件安装方法
  16 + * @return bool
  17 + */
  18 + public function install()
  19 + {
  20 + $menu = [
  21 + [
  22 + 'name' => 'command',
  23 + 'title' => '在线命令管理',
  24 + 'icon' => 'fa fa-terminal',
  25 + 'sublist' => [
  26 + ['name' => 'command/index', 'title' => '查看'],
  27 + ['name' => 'command/add', 'title' => '添加'],
  28 + ['name' => 'command/detail', 'title' => '详情'],
  29 + ['name' => 'command/command', 'title' => '生成并执行命令'],
  30 + ['name' => 'command/execute', 'title' => '再次执行命令'],
  31 + ['name' => 'command/del', 'title' => '删除'],
  32 + ['name' => 'command/multi', 'title' => '批量更新'],
  33 + ]
  34 + ]
  35 + ];
  36 + Menu::create($menu);
  37 + return true;
  38 + }
  39 +
  40 + /**
  41 + * 插件卸载方法
  42 + * @return bool
  43 + */
  44 + public function uninstall()
  45 + {
  46 + Menu::delete('command');
  47 + return true;
  48 + }
  49 +
  50 + /**
  51 + * 插件启用方法
  52 + * @return bool
  53 + */
  54 + public function enable()
  55 + {
  56 + Menu::enable('command');
  57 + return true;
  58 + }
  59 +
  60 + /**
  61 + * 插件禁用方法
  62 + * @return bool
  63 + */
  64 + public function disable()
  65 + {
  66 + Menu::disable('command');
  67 + return true;
  68 + }
  69 +
  70 +}
  1 +<?php
  2 +
  3 +return [
  4 +];
  1 +<?php
  2 +
  3 +namespace addons\command\controller;
  4 +
  5 +use think\addons\Controller;
  6 +
  7 +class Index extends Controller
  8 +{
  9 +
  10 + public function index()
  11 + {
  12 + $this->error("当前插件暂无前台页面");
  13 + }
  14 +
  15 +}
  1 +name = command
  2 +title = 在线命令
  3 +intro = 可在线执行一键生成CRUD、一键生成菜单等相关命令
  4 +author = FastAdmin
  5 +website = https://www.fastadmin.net
  6 +version = 1.1.1
  7 +state = 1
  8 +url = /addons/command
  9 +license = regular
  10 +licenseto = 15629
  1 +CREATE TABLE IF NOT EXISTS `__PREFIX__command` (
  2 + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',
  3 + `type` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '类型',
  4 + `params` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '参数',
  5 + `command` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '命令',
  6 + `content` text COMMENT '返回结果',
  7 + `executetime` bigint(16) UNSIGNED DEFAULT NULL COMMENT '执行时间',
  8 + `createtime` bigint(16) UNSIGNED DEFAULT NULL COMMENT '创建时间',
  9 + `updatetime` bigint(16) UNSIGNED DEFAULT NULL COMMENT '更新时间',
  10 + `status` enum('successed','failured') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'failured' COMMENT '状态',
  11 + PRIMARY KEY (`id`) USING BTREE
  12 +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '在线命令表';
  1 +<?php
  2 +
  3 +namespace addons\command\library;
  4 +
  5 +/**
  6 + * Class Output
  7 + */
  8 +class Output extends \think\console\Output
  9 +{
  10 +
  11 + protected $message = [];
  12 +
  13 + public function __construct($driver = 'console')
  14 + {
  15 + parent::__construct($driver);
  16 + }
  17 +
  18 + protected function block($style, $message)
  19 + {
  20 + $this->message[] = $message;
  21 + }
  22 +
  23 + public function getMessage()
  24 + {
  25 + return $this->message;
  26 + }
  27 +
  28 +}
  1 +{"files":["application\\admin\\controller\\example\\Bootstraptable.php","application\\admin\\controller\\example\\Colorbadge.php","application\\admin\\controller\\example\\Controllerjump.php","application\\admin\\controller\\example\\Customform.php","application\\admin\\controller\\example\\Customsearch.php","application\\admin\\controller\\example\\Cxselect.php","application\\admin\\controller\\example\\Echarts.php","application\\admin\\controller\\example\\Multitable.php","application\\admin\\controller\\example\\Relationmodel.php","application\\admin\\controller\\example\\Tablelink.php","application\\admin\\controller\\example\\Tabletemplate.php","application\\admin\\model\\Area.php","application\\admin\\view\\example\\bootstraptable\\detail.html","application\\admin\\view\\example\\bootstraptable\\edit.html","application\\admin\\view\\example\\bootstraptable\\index.html","application\\admin\\view\\example\\colorbadge\\index.html","application\\admin\\view\\example\\controllerjump\\index.html","application\\admin\\view\\example\\customform\\index.html","application\\admin\\view\\example\\customsearch\\index.html","application\\admin\\view\\example\\cxselect\\index.html","application\\admin\\view\\example\\echarts\\index.html","application\\admin\\view\\example\\multitable\\index.html","application\\admin\\view\\example\\relationmodel\\index.html","application\\admin\\view\\example\\tablelink\\index.html","application\\admin\\view\\example\\tabletemplate\\index.html","public\\assets\\js\\backend\\example\\bootstraptable.js","public\\assets\\js\\backend\\example\\colorbadge.js","public\\assets\\js\\backend\\example\\controllerjump.js","public\\assets\\js\\backend\\example\\customform.js","public\\assets\\js\\backend\\example\\customsearch.js","public\\assets\\js\\backend\\example\\cxselect.js","public\\assets\\js\\backend\\example\\echarts.js","public\\assets\\js\\backend\\example\\multitable.js","public\\assets\\js\\backend\\example\\relationmodel.js","public\\assets\\js\\backend\\example\\tablelink.js","public\\assets\\js\\backend\\example\\tabletemplate.js","public\\assets\\addons\\example\\css\\common.css","public\\assets\\addons\\example\\img\\200x200.png","public\\assets\\addons\\example\\img\\plus.png","public\\assets\\addons\\example\\js\\async.js"],"license":"regular","licenseto":"15629","licensekey":"tPF5COLi1AuI7ScR 5YrH\/jKQmS3gnZuosjc0sw==","domains":["cardverification.com"],"licensecodes":[],"validations":["867a7ee97b89c3a1f31235c70da23ecf"],"menus":["example","example\/bootstraptable","example\/bootstraptable\/index","example\/bootstraptable\/detail","example\/bootstraptable\/change","example\/bootstraptable\/del","example\/bootstraptable\/multi","example\/customsearch","example\/customsearch\/index","example\/customsearch\/del","example\/customsearch\/multi","example\/customform","example\/customform\/index","example\/tablelink","example\/tablelink\/index","example\/colorbadge","example\/colorbadge\/index","example\/colorbadge\/del","example\/colorbadge\/multi","example\/controllerjump","example\/controllerjump\/index","example\/controllerjump\/del","example\/controllerjump\/multi","example\/cxselect","example\/cxselect\/index","example\/cxselect\/del","example\/cxselect\/multi","example\/multitable","example\/multitable\/index","example\/multitable\/del","example\/multitable\/multi","example\/relationmodel","example\/relationmodel\/index","example\/relationmodel\/del","example\/relationmodel\/multi","example\/tabletemplate","example\/tabletemplate\/index","example\/tabletemplate\/detail","example\/tabletemplate\/del","example\/tabletemplate\/multi","example\/echarts","example\/echarts\/index"]}
  1 +<?php
  2 +
  3 +namespace addons\example;
  4 +
  5 +use app\common\library\Menu;
  6 +use think\Addons;
  7 +
  8 +/**
  9 + * Example
  10 + */
  11 +class Example extends Addons
  12 +{
  13 +
  14 + /**
  15 + * 插件安装方法
  16 + * @return bool
  17 + */
  18 + public function install()
  19 + {
  20 + $menu = [
  21 + [
  22 + 'name' => 'example',
  23 + 'title' => '开发示例管理',
  24 + 'icon' => 'fa fa-magic',
  25 + 'sublist' => [
  26 + [
  27 + 'name' => 'example/bootstraptable',
  28 + 'title' => '表格完整示例',
  29 + 'icon' => 'fa fa-table',
  30 + 'sublist' => [
  31 + ['name' => 'example/bootstraptable/index', 'title' => '查看'],
  32 + ['name' => 'example/bootstraptable/detail', 'title' => '详情'],
  33 + ['name' => 'example/bootstraptable/change', 'title' => '变更'],
  34 + ['name' => 'example/bootstraptable/del', 'title' => '删除'],
  35 + ['name' => 'example/bootstraptable/multi', 'title' => '批量更新'],
  36 + ]
  37 + ],
  38 + [
  39 + 'name' => 'example/customsearch',
  40 + 'title' => '自定义搜索',
  41 + 'icon' => 'fa fa-table',
  42 + 'sublist' => [
  43 + ['name' => 'example/customsearch/index', 'title' => '查看'],
  44 + ['name' => 'example/customsearch/del', 'title' => '删除'],
  45 + ['name' => 'example/customsearch/multi', 'title' => '批量更新'],
  46 + ]
  47 + ],
  48 + [
  49 + 'name' => 'example/customform',
  50 + 'title' => '自定义表单示例',
  51 + 'icon' => 'fa fa-edit',
  52 + 'sublist' => [
  53 + ['name' => 'example/customform/index', 'title' => '查看'],
  54 + ]
  55 + ],
  56 + [
  57 + 'name' => 'example/tablelink',
  58 + 'title' => '表格联动示例',
  59 + 'icon' => 'fa fa-table',
  60 + 'remark' => '点击左侧日志列表,右侧的表格数据会显示指定管理员的日志列表',
  61 + 'sublist' => [
  62 + ['name' => 'example/tablelink/index', 'title' => '查看'],
  63 + ]
  64 + ],
  65 + [
  66 + 'name' => 'example/colorbadge',
  67 + 'title' => '彩色角标',
  68 + 'icon' => 'fa fa-table',
  69 + 'remark' => '左侧彩色的角标会根据当前数据量的大小进行更新',
  70 + 'sublist' => [
  71 + ['name' => 'example/colorbadge/index', 'title' => '查看'],
  72 + ['name' => 'example/colorbadge/del', 'title' => '删除'],
  73 + ['name' => 'example/colorbadge/multi', 'title' => '批量更新'],
  74 + ]
  75 + ],
  76 + [
  77 + 'name' => 'example/controllerjump',
  78 + 'title' => '控制器间跳转',
  79 + 'icon' => 'fa fa-table',
  80 + 'remark' => '点击IP地址可以跳转到新的选项卡中查看指定IP的数据',
  81 + 'sublist' => [
  82 + ['name' => 'example/controllerjump/index', 'title' => '查看'],
  83 + ['name' => 'example/controllerjump/del', 'title' => '删除'],
  84 + ['name' => 'example/controllerjump/multi', 'title' => '批量更新'],
  85 + ]
  86 + ],
  87 + [
  88 + 'name' => 'example/cxselect',
  89 + 'title' => '多级联动',
  90 + 'icon' => 'fa fa-table',
  91 + 'remark' => '基于jquery.cxselect实现的多级联动',
  92 + 'sublist' => [
  93 + ['name' => 'example/cxselect/index', 'title' => '查看'],
  94 + ['name' => 'example/cxselect/del', 'title' => '删除'],
  95 + ['name' => 'example/cxselect/multi', 'title' => '批量更新'],
  96 + ]
  97 + ],
  98 + [
  99 + 'name' => 'example/multitable',
  100 + 'title' => '多表格示例',
  101 + 'icon' => 'fa fa-table',
  102 + 'remark' => '展示在一个页面显示多个Bootstrap-table表格',
  103 + 'sublist' => [
  104 + ['name' => 'example/multitable/index', 'title' => '查看'],
  105 + ['name' => 'example/multitable/del', 'title' => '删除'],
  106 + ['name' => 'example/multitable/multi', 'title' => '批量更新'],
  107 + ]
  108 + ],
  109 + [
  110 + 'name' => 'example/relationmodel',
  111 + 'title' => '关联模型示例',
  112 + 'icon' => 'fa fa-table',
  113 + 'remark' => '列表中的头像、用户名和昵称字段均从关联表中取出',
  114 + 'sublist' => [
  115 + ['name' => 'example/relationmodel/index', 'title' => '查看'],
  116 + ['name' => 'example/relationmodel/del', 'title' => '删除'],
  117 + ['name' => 'example/relationmodel/multi', 'title' => '批量更新'],
  118 + ]
  119 + ],
  120 + [
  121 + 'name' => 'example/tabletemplate',
  122 + 'title' => '表格模板示例',
  123 + 'icon' => 'fa fa-table',
  124 + 'remark' => '',
  125 + 'sublist' => [
  126 + ['name' => 'example/tabletemplate/index', 'title' => '查看'],
  127 + ['name' => 'example/tabletemplate/detail', 'title' => '详情'],
  128 + ['name' => 'example/tabletemplate/del', 'title' => '删除'],
  129 + ['name' => 'example/tabletemplate/multi', 'title' => '批量更新'],
  130 + ]
  131 + ],
  132 + [
  133 + 'name' => 'example/echarts',
  134 + 'title' => '统计图表示例',
  135 + 'icon' => 'fa fa-bar-chart',
  136 + 'sublist' => [
  137 + ['name' => 'example/echarts/index', 'title' => '查看'],
  138 + ]
  139 + ],
  140 + ]
  141 + ]
  142 + ];
  143 + Menu::create($menu);
  144 + return true;
  145 + }
  146 +
  147 + /**
  148 + * 插件卸载方法
  149 + * @return bool
  150 + */
  151 + public function uninstall()
  152 + {
  153 + Menu::delete('example');
  154 + return true;
  155 + }
  156 +
  157 + /**
  158 + * 插件启用方法
  159 + */
  160 + public function enable()
  161 + {
  162 + Menu::enable('example');
  163 + }
  164 +
  165 + /**
  166 + * 插件禁用方法
  167 + */
  168 + public function disable()
  169 + {
  170 + Menu::disable('example');
  171 + }
  172 +
  173 +}
  1 +<?php
  2 +
  3 +return [
  4 + [
  5 + 'name' => 'condition1',
  6 + 'title' => '条件1',
  7 + 'type' => 'radio',
  8 + 'group' => '选项组一',
  9 + 'content' => [
  10 + 'value1' => '值1',
  11 + 'value2' => '值2',
  12 + ],
  13 + 'value' => 'value2',
  14 + 'rule' => 'required',
  15 + 'msg' => '',
  16 + 'tip' => '',
  17 + 'ok' => '',
  18 + 'extend' => '',
  19 + ],
  20 + [
  21 + 'name' => 'condition2',
  22 + 'title' => '条件2',
  23 + 'type' => 'checkbox',
  24 + 'group' => '选项组一',
  25 + 'visible' => 'condition1=value1',
  26 + 'content' => [
  27 + 'value1' => '值1',
  28 + 'value2' => '值2',
  29 + 'value3' => '值3',
  30 + ],
  31 + 'value' => 'value1,value2',
  32 + 'rule' => 'required',
  33 + 'msg' => '',
  34 + 'tip' => '',
  35 + 'ok' => '',
  36 + 'extend' => '',
  37 + ],
  38 + [
  39 + 'name' => 'condition3',
  40 + 'title' => '条件3',
  41 + 'type' => 'select',
  42 + 'group' => '选项组一',
  43 + 'visible' => 'condition1=value2',
  44 + 'content' => [
  45 + 'value1' => '值1',
  46 + 'value2' => '值2',
  47 + ],
  48 + 'value' => 'value1',
  49 + 'rule' => 'required',
  50 + 'msg' => '',
  51 + 'tip' => '',
  52 + 'ok' => '',
  53 + 'extend' => '',
  54 + ],
  55 + [
  56 + 'name' => 'condition4',
  57 + 'title' => '条件4',
  58 + 'type' => 'selects',
  59 + 'group' => '选项组一',
  60 + 'content' => [
  61 + 'value1' => '值1',
  62 + 'value2' => '值2',
  63 + 'value3' => '值3',
  64 + ],
  65 + 'value' => 'value1,value2',
  66 + 'rule' => 'required',
  67 + 'msg' => '',
  68 + 'tip' => '',
  69 + 'ok' => '',
  70 + 'extend' => '',
  71 + ],
  72 + [
  73 + 'name' => 'title',
  74 + 'title' => '标题',
  75 + 'type' => 'string',
  76 + 'group' => '选项组一',
  77 + 'visible' => 'condition3=value1',
  78 + 'content' => [],
  79 + 'value' => '3x',
  80 + 'rule' => 'required',
  81 + 'msg' => '',
  82 + 'tip' => '',
  83 + 'ok' => '',
  84 + 'extend' => '',
  85 + ],
  86 + [
  87 + 'name' => 'domain',
  88 + 'title' => '绑定二级域名前缀',
  89 + 'type' => 'string',
  90 + 'group' => '选项组二',
  91 + 'content' => [],
  92 + 'value' => '',
  93 + 'rule' => 'required',
  94 + 'msg' => '',
  95 + 'tip' => '',
  96 + 'ok' => '',
  97 + 'extend' => '',
  98 + ],
  99 + [
  100 + 'name' => 'rewrite',
  101 + 'title' => '伪静态',
  102 + 'type' => 'array',
  103 + 'group' => '选项组二',
  104 + 'content' => [],
  105 + 'value' => [
  106 + 'index/index' => '/example$',
  107 + 'demo/index' => '/example/d/[:name]',
  108 + 'demo/demo1' => '/example/d1/[:name]',
  109 + 'demo/demo2' => '/example/d2/[:name]',
  110 + ],
  111 + 'rule' => 'required',
  112 + 'msg' => '',
  113 + 'tip' => '',
  114 + 'ok' => '',
  115 + 'extend' => '',
  116 + ],
  117 + [
  118 + 'name' => '__tips__',
  119 + 'title' => '温馨提示',
  120 + 'type' => 'string',
  121 + 'content' => [
  122 + ],
  123 + 'value' => '这里是提示的文本内容',
  124 + 'rule' => '',
  125 + 'msg' => '',
  126 + 'tip' => '',
  127 + 'ok' => '',
  128 + 'extend' => '',
  129 + ],
  130 +];
  1 +<?php
  2 +
  3 +namespace addons\example\controller;
  4 +
  5 +use think\addons\Controller;
  6 +
  7 +/**
  8 + * 测试控制器
  9 + */
  10 +class Demo extends Controller
  11 +{
  12 +
  13 + protected $layout = 'default';
  14 + protected $noNeedLogin = ['index', 'demo1'];
  15 + protected $noNeedRight = ['*'];
  16 +
  17 + public function index()
  18 + {
  19 + return $this->view->fetch();
  20 + }
  21 +
  22 + public function demo1()
  23 + {
  24 + return $this->view->fetch();
  25 + }
  26 +
  27 + public function demo2()
  28 + {
  29 + return $this->view->fetch();
  30 + }
  31 +
  32 +}
  1 +<?php
  2 +
  3 +namespace addons\example\controller;
  4 +
  5 +use think\addons\Controller;
  6 +
  7 +class Index extends Controller
  8 +{
  9 +
  10 + protected $layout = 'default';
  11 +
  12 + public function index()
  13 + {
  14 + return $this->view->fetch();
  15 + }
  16 +
  17 +}
  1 +name = example
  2 +title = 开发示例
  3 +intro = FastAdmin多个开发示例
  4 +author = FastAdmin
  5 +website = https://www.fastadmin.net
  6 +version = 1.1.2
  7 +state = 1
  8 +url = /addons/example
  9 +license = regular
  10 +licenseto = 15629
此 diff 太大无法显示。
  1 +<!-- Page Content -->
  2 + <div class="container">
  3 +
  4 + <!-- Page Heading/Breadcrumbs -->
  5 + <div class="row">
  6 + <div class="col-lg-12">
  7 + <h1 class="page-header">无需登录页面
  8 + <small>开发者示例</small>
  9 + </h1>
  10 + <ol class="breadcrumb">
  11 + <li><a href="{:addon_url('example/index/index')}">插件首页</a>
  12 + </li>
  13 + <li class="active">无需登录页面</li>
  14 + </ol>
  15 + </div>
  16 + </div>
  17 + <!-- /.row -->
  18 +
  19 + <!-- Content Row -->
  20 + <div class="row">
  21 + <div class="col-lg-12">
  22 + <p class="well">当前登录页面无需登录即可查看,当前请求的name值为:{$Request.param.name|htmlentities}</p>
  23 + {if $user}
  24 + <p class="well text-danger">但是如果你登录后可以浏览到这段隐藏的信息</p>
  25 + {/if}
  26 + </div>
  27 + </div>
  28 + <!-- /.row -->
  29 +
  30 + <hr>
  31 +
  32 + </div>
  33 + <!-- /.container -->
  1 +<!-- Page Content -->
  2 +<div class="container">
  3 +
  4 + <!-- Page Heading/Breadcrumbs -->
  5 + <div class="row">
  6 + <div class="col-lg-12">
  7 + <h1 class="page-header">需登录页面
  8 + <small>开发者示例</small>
  9 + </h1>
  10 + <ol class="breadcrumb">
  11 + <li><a href="{:addon_url('example/index/index')}">插件首页</a>
  12 + </li>
  13 + <li class="active">需登录页面</li>
  14 + </ol>
  15 + </div>
  16 + </div>
  17 + <!-- /.row -->
  18 +
  19 + <!-- Content Row -->
  20 + <div class="row">
  21 + <div class="col-lg-12">
  22 + <p class="well">当前登录页面需要登录后才可以查看,你可以退出后再访问此页面,会提醒登录,当前请求的name值为:{$Request.param.name|htmlentities}</p>
  23 + <p class="well">你好!{$user.nickname|htmlentities},<a href="{:url('index/user/logout')}">注销登录</a></p>
  24 + </div>
  25 + </div>
  26 + <!-- /.row -->
  27 +
  28 + <hr>
  29 +
  30 +</div>
  31 +<!-- /.container -->
  1 +<!-- Page Content -->
  2 + <div class="container">
  3 +
  4 + <!-- Page Heading/Breadcrumbs -->
  5 + <div class="row">
  6 + <div class="col-lg-12">
  7 + <h1 class="page-header">使用模板标签和变量
  8 + <small>开发者示例</small>
  9 + </h1>
  10 + <ol class="breadcrumb">
  11 + <li><a href="{:addon_url('example/index/index')}">插件首页</a>
  12 + </li>
  13 + <li class="active">使用模板标签和变量</li>
  14 + </ol>
  15 + </div>
  16 + </div>
  17 + <!-- /.row -->
  18 +
  19 + <!-- Content Row -->
  20 + <div class="row">
  21 + <div class="col-lg-12">
  22 + <p class="well">当前请求的name值为:{$Request.param.name|htmlentities}</p>
  23 + {literal}
  24 + <pre>
  25 +在插件视图中可以使用所有ThinkPHP5内支持的模板标签和变量,如
  26 +
  27 +{$Think.server.script_name} // 输出$_SERVER['SCRIPT_NAME']变量
  28 +{$Think.session.user_id} // 输出$_SESSION['user_id']变量
  29 +{$Think.get.pageNumber} // 输出$_GET['pageNumber']变量
  30 +{$Think.cookie.name} // 输出$_COOKIE['name']变量
  31 +
  32 +// 调用Request对象的get方法 传入参数为id
  33 +{$Request.get.id}
  34 +// 调用Request对象的param方法 传入参数为name
  35 +{$Request.param.name}
  36 +// 调用Request对象的param方法 传入参数为user.nickname
  37 +{$Request.param.user.nickname}
  38 +// 调用Request对象的root方法
  39 +{$Request.root}
  40 +// 调用Request对象的root方法,并且传入参数true
  41 +{$Request.root.true}
  42 +// 调用Request对象的path方法
  43 +{$Request.path}
  44 +// 调用Request对象的module方法
  45 +{$Request.module}
  46 +// 调用Request对象的controller方法
  47 +{$Request.controller}
  48 +// 调用Request对象的action方法
  49 +{$Request.action}
  50 +// 调用Request对象的ext方法
  51 +{$Request.ext}
  52 +// 调用Request对象的host方法
  53 +{$Request.host}
  54 +// 调用Request对象的ip方法
  55 +{$Request.ip}
  56 +// 调用Request对象的header方法
  57 +{$Request.header.accept-encoding}
  58 + </pre>
  59 + {/literal}
  60 + </div>
  61 + </div>
  62 + <!-- /.row -->
  63 +
  64 + <hr>
  65 +
  66 + </div>
  67 + <!-- /.container -->
  1 +<!-- Header Carousel -->
  2 +<header id="myCarousel" class="carousel slide">
  3 + <!-- Indicators -->
  4 + <ol class="carousel-indicators">
  5 + <li data-target="#myCarousel" data-slide-to="0" class="active"></li>
  6 + </ol>
  7 +
  8 + <!-- Wrapper for slides -->
  9 + <div class="carousel-inner">
  10 + <div class="item active">
  11 + <a href="javascript:">
  12 + <div class="fill" style="background-image:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzOTMiIGhlaWdodD0iMjI2Ij48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJyZ2IoNjMsIDE0MywgODUpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iI2RkZCIgZmlsbC1vcGFjaXR5PSIwLjE0MTMzMzMzMzMzMzMzIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAtMzcuODMzMzMzMzMzMzMzKSByb3RhdGUoMTgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjZGRkIiBmaWxsLW9wYWNpdHk9IjAuMTQxMzMzMzMzMzMzMzMiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDE4OS4xNjY2NjY2NjY2Nykgcm90YXRlKDE4MCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iIzIyMiIgZmlsbC1vcGFjaXR5PSIwLjA2MzMzMzMzMzMzMzMzMyIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjUuNTI5MjU1NTUzMDIzLCAtMzcuODMzMzMzMzMzMzMzKSByb3RhdGUoMCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iIzIyMiIgZmlsbC1vcGFjaXR5PSIwLjA2MzMzMzMzMzMzMzMzMyIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjUuNTI5MjU1NTUzMDIzLCAxODkuMTY2NjY2NjY2NjcpIHJvdGF0ZSgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjMjIyIiBmaWxsLW9wYWNpdHk9IjAuMDgwNjY2NjY2NjY2NjY3IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMzEuMDU4NTExMTA2MDUsIC0zNy44MzMzMzMzMzMzMzMpIHJvdGF0ZSgxODAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiMyMjIiIGZpbGwtb3BhY2l0eT0iMC4wODA2NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEzMS4wNTg1MTExMDYwNSwgMTg5LjE2NjY2NjY2NjY3KSByb3RhdGUoMTgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjMjIyIiBmaWxsLW9wYWNpdHk9IjAuMDQ2IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxOTYuNTg3NzY2NjU5MDcsIC0zNy44MzMzMzMzMzMzMzMpIHJvdGF0ZSgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjMjIyIiBmaWxsLW9wYWNpdHk9IjAuMDQ2IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxOTYuNTg3NzY2NjU5MDcsIDE4OS4xNjY2NjY2NjY2Nykgcm90YXRlKDAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4wODkzMzMzMzMzMzMzMzMiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI2Mi4xMTcwMjIyMTIwOSwgLTM3LjgzMzMzMzMzMzMzMykgcm90YXRlKDE4MCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iI2RkZCIgZmlsbC1vcGFjaXR5PSIwLjA4OTMzMzMzMzMzMzMzMyIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjYyLjExNzAyMjIxMjA5LCAxODkuMTY2NjY2NjY2NjcpIHJvdGF0ZSgxODAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4xNDEzMzMzMzMzMzMzMyIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzI3LjY0NjI3Nzc2NTExLCAtMzcuODMzMzMzMzMzMzMzKSByb3RhdGUoMCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iI2RkZCIgZmlsbC1vcGFjaXR5PSIwLjE0MTMzMzMzMzMzMzMzIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzMjcuNjQ2Mjc3NzY1MTEsIDE4OS4xNjY2NjY2NjY2Nykgcm90YXRlKDAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4wMiIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkgcm90YXRlKDAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiMyMjIiIGZpbGwtb3BhY2l0eT0iMC4wMjg2NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDY1LjUyOTI1NTU1MzAyMywgMCkgcm90YXRlKDE4MCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iIzIyMiIgZmlsbC1vcGFjaXR5PSIwLjExNTMzMzMzMzMzMzMzIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMzEuMDU4NTExMTA2MDUsIDApIHJvdGF0ZSgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjMjIyIiBmaWxsLW9wYWNpdHk9IjAuMDgwNjY2NjY2NjY2NjY3IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxOTYuNTg3NzY2NjU5MDcsIDApIHJvdGF0ZSgxODAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiMyMjIiIGZpbGwtb3BhY2l0eT0iMC4wODA2NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI2Mi4xMTcwMjIyMTIwOSwgMCkgcm90YXRlKDAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4wMiIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzI3LjY0NjI3Nzc2NTExLCAwKSByb3RhdGUoMTgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjMjIyIiBmaWxsLW9wYWNpdHk9IjAuMDgwNjY2NjY2NjY2NjY3IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAzNy44MzMzMzMzMzMzMzMpIHJvdGF0ZSgxODAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4wMiIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMpIHJvdGF0ZSgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjMjIyIiBmaWxsLW9wYWNpdHk9IjAuMDk4IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMzEuMDU4NTExMTA2MDUsIDM3LjgzMzMzMzMzMzMzMykgcm90YXRlKDE4MCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iIzIyMiIgZmlsbC1vcGFjaXR5PSIwLjE1IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxOTYuNTg3NzY2NjU5MDcsIDM3LjgzMzMzMzMzMzMzMykgcm90YXRlKDAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiMyMjIiIGZpbGwtb3BhY2l0eT0iMC4wMjg2NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI2Mi4xMTcwMjIyMTIwOSwgMzcuODMzMzMzMzMzMzMzKSByb3RhdGUoMTgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjMjIyIiBmaWxsLW9wYWNpdHk9IjAuMDQ2IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzMjcuNjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykgcm90YXRlKDAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4wMzczMzMzMzMzMzMzMzMiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDc1LjY2NjY2NjY2NjY2Nykgcm90YXRlKDAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4wMiIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjUuNTI5MjU1NTUzMDIzLCA3NS42NjY2NjY2NjY2NjcpIHJvdGF0ZSgxODAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiMyMjIiIGZpbGwtb3BhY2l0eT0iMC4xNSIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTMxLjA1ODUxMTEwNjA1LCA3NS42NjY2NjY2NjY2NjcpIHJvdGF0ZSgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjZGRkIiBmaWxsLW9wYWNpdHk9IjAuMDIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE5Ni41ODc3NjY2NTkwNywgNzUuNjY2NjY2NjY2NjY3KSByb3RhdGUoMTgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjMjIyIiBmaWxsLW9wYWNpdHk9IjAuMDk4IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNjIuMTE3MDIyMjEyMDksIDc1LjY2NjY2NjY2NjY2Nykgcm90YXRlKDAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiMyMjIiIGZpbGwtb3BhY2l0eT0iMC4wNjMzMzMzMzMzMzMzMzMiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMyNy42NDYyNzc3NjUxMSwgNzUuNjY2NjY2NjY2NjY3KSByb3RhdGUoMTgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjZGRkIiBmaWxsLW9wYWNpdHk9IjAuMTI0IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAxMTMuNSkgcm90YXRlKDE4MCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iIzIyMiIgZmlsbC1vcGFjaXR5PSIwLjE1IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2NS41MjkyNTU1NTMwMjMsIDExMy41KSByb3RhdGUoMCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iI2RkZCIgZmlsbC1vcGFjaXR5PSIwLjEyNCIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTMxLjA1ODUxMTEwNjA1LCAxMTMuNSkgcm90YXRlKDE4MCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iI2RkZCIgZmlsbC1vcGFjaXR5PSIwLjEwNjY2NjY2NjY2NjY3IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxOTYuNTg3NzY2NjU5MDcsIDExMy41KSByb3RhdGUoMCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iI2RkZCIgZmlsbC1vcGFjaXR5PSIwLjEyNCIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjYyLjExNzAyMjIxMjA5LCAxMTMuNSkgcm90YXRlKDE4MCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iIzIyMiIgZmlsbC1vcGFjaXR5PSIwLjEzMjY2NjY2NjY2NjY3IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzMjcuNjQ2Mjc3NzY1MTEsIDExMy41KSByb3RhdGUoMCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iI2RkZCIgZmlsbC1vcGFjaXR5PSIwLjEwNjY2NjY2NjY2NjY3IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAxNTEuMzMzMzMzMzMzMzMpIHJvdGF0ZSgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjMjIyIiBmaWxsLW9wYWNpdHk9IjAuMDYzMzMzMzMzMzMzMzMzIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2NS41MjkyNTU1NTMwMjMsIDE1MS4zMzMzMzMzMzMzMykgcm90YXRlKDE4MCwgMzIuNzY0NjI3Nzc2NTExLCAzNy44MzMzMzMzMzMzMzMpIi8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgNjUuNTI5MjU1NTUzMDIzLCAzNy44MzMzMzMzMzMzMzMsIDAsIDc1LjY2NjY2NjY2NjY2NywgMCwgMCIgZmlsbD0iIzIyMiIgZmlsbC1vcGFjaXR5PSIwLjA4MDY2NjY2NjY2NjY2NyIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTMxLjA1ODUxMTEwNjA1LCAxNTEuMzMzMzMzMzMzMzMpIHJvdGF0ZSgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjZGRkIiBmaWxsLW9wYWNpdHk9IjAuMDIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE5Ni41ODc3NjY2NTkwNywgMTUxLjMzMzMzMzMzMzMzKSByb3RhdGUoMTgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCA2NS41MjkyNTU1NTMwMjMsIDM3LjgzMzMzMzMzMzMzMywgMCwgNzUuNjY2NjY2NjY2NjY3LCAwLCAwIiBmaWxsPSIjMjIyIiBmaWxsLW9wYWNpdHk9IjAuMDk4IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNjIuMTE3MDIyMjEyMDksIDE1MS4zMzMzMzMzMzMzMykgcm90YXRlKDAsIDMyLjc2NDYyNzc3NjUxMSwgMzcuODMzMzMzMzMzMzMzKSIvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDY1LjUyOTI1NTU1MzAyMywgMzcuODMzMzMzMzMzMzMzLCAwLCA3NS42NjY2NjY2NjY2NjcsIDAsIDAiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4xMjQiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMyNy42NDYyNzc3NjUxMSwgMTUxLjMzMzMzMzMzMzMzKSByb3RhdGUoMTgwLCAzMi43NjQ2Mjc3NzY1MTEsIDM3LjgzMzMzMzMzMzMzMykiLz48L3N2Zz4=');"></div>
  13 + <div class="carousel-body">
  14 + <div class="container">
  15 + <h1 class="display-1 text-white">开发示例</h1>
  16 + <h2 class="display-4 text-white">表格、登录相关示例</h2>
  17 + </div>
  18 + </div>
  19 + </a>
  20 + </div>
  21 + </div>
  22 +</header>
  23 +
  24 +<!-- Page Content -->
  25 +<div class="container">
  26 +
  27 + <!-- Marketing Icons Section -->
  28 + <div class="row">
  29 + <div class="col-lg-12">
  30 + <h2 class="page-header">
  31 + 基础模块
  32 + </h2>
  33 + </div>
  34 + <div class="col-md-4">
  35 + <div class="panel panel-default">
  36 + <div class="panel-heading">
  37 + <h4><i class="fa fa-fw fa-user"></i> 前台模块</h4>
  38 + </div>
  39 + <div class="panel-body">
  40 + <p>前台模块中包含基础的会员模块,前台模块中的会员账号和API模块中的会员账号是同一账号体系</p>
  41 + <a href="{:url('index/index/index')}" target="_blank" class="btn btn-primary">立即访问</a>
  42 + <a href="{:url('index/user/index')}" target="_blank" class="btn btn-default">会员中心</a>
  43 + </div>
  44 + </div>
  45 + </div>
  46 + <div class="col-md-4">
  47 + <div class="panel panel-default">
  48 + <div class="panel-heading">
  49 + <h4><i class="fa fa-fw fa-gift"></i> API模块</h4>
  50 + </div>
  51 + <div class="panel-body">
  52 + <p>API模块中包含基础的会员模块,初始化模块、短信发送模块、验证模块</p>
  53 + <a href="{:url('api/index/index')}" target="_blank" class="btn btn-primary">立即访问</a>
  54 + <a href="{:url('api/common/init')}?version=1.0.0" target="_blank" class="btn btn-default">初始化接口</a>
  55 + </div>
  56 + </div>
  57 + </div>
  58 + <div class="col-md-4">
  59 + <div class="panel panel-default">
  60 + <div class="panel-heading">
  61 + <h4><i class="fa fa-fw fa-compass"></i> API文档</h4>
  62 + </div>
  63 + <div class="panel-body">
  64 + <p>当写完API接口以后,可通过执行php think api一键生成我们所需要的API文档,并且可以直接在线测试</p>
  65 + <a href="{:url('/')}api.html" target="_blank" class="btn btn-primary">立即访问</a>
  66 + </div>
  67 + </div>
  68 + </div>
  69 + </div>
  70 + <div class="row">
  71 + <div class="col-lg-12">
  72 + <h2 class="page-header">
  73 + 功能示例
  74 + </h2>
  75 + </div>
  76 + <div class="col-md-4">
  77 + <div class="panel panel-default">
  78 + <div class="panel-heading">
  79 + <h4><i class="fa fa-fw fa-check"></i> 使用模板标签和变量</h4>
  80 + </div>
  81 + <div class="panel-body">
  82 + <a href="{:addon_url('example/demo/index',[':name'=>'s1'])}" class="btn btn-success">查看示例</a>
  83 + </div>
  84 + </div>
  85 + </div>
  86 + <div class="col-md-4">
  87 + <div class="panel panel-default">
  88 + <div class="panel-heading">
  89 + <h4><i class="fa fa-fw fa-gift"></i> 访问不需要登录的页面</h4>
  90 + </div>
  91 + <div class="panel-body">
  92 + <a href="{:addon_url('example/demo/demo1',[':name'=>'s2'])}" class="btn btn-success">立即访问</a>
  93 + </div>
  94 + </div>
  95 + </div>
  96 + <div class="col-md-4">
  97 + <div class="panel panel-default">
  98 + <div class="panel-heading">
  99 + <h4><i class="fa fa-fw fa-compass"></i> 访问需要登录的页面</h4>
  100 + </div>
  101 + <div class="panel-body">
  102 + <a href="{:addon_url('example/demo/demo2',[':name'=>'s3'])}" class="btn btn-success">立即访问</a>
  103 + </div>
  104 + </div>
  105 + </div>
  106 + </div>
  107 + <!-- /.row -->
  108 +
  109 + <hr>
  110 +
  111 +</div>
  1 +<!DOCTYPE html>
  2 +<html lang="en">
  3 +
  4 + <head>
  5 +
  6 + <meta charset="utf-8">
  7 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
  8 + <meta name="viewport" content="width=device-width, initial-scale=1">
  9 + <meta name="description" content="">
  10 + <meta name="author" content="">
  11 +
  12 + <title>开发示例 - {$site.name|htmlentities}</title>
  13 +
  14 + <!-- Bootstrap Core CSS -->
  15 + <link href="__CDN__/assets/libs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
  16 +
  17 + <!-- Custom CSS -->
  18 + <link href="__ADDON__/css/common.css" rel="stylesheet">
  19 +
  20 + <!-- Custom Fonts -->
  21 + <link href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css" rel="stylesheet">
  22 +
  23 + <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
  24 + <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
  25 + <!--[if lt IE 9]>
  26 + <script src="https://cdn.bootcdn.net/ajax/libs/html5shiv/3.7.0/html5shiv.min.js"></script>
  27 + <script src="https://cdn.bootcdn.net/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
  28 + <![endif]-->
  29 +
  30 + </head>
  31 +
  32 + <body>
  33 +
  34 + <!-- Navigation -->
  35 + <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
  36 + <div class="container">
  37 + <!-- Brand and toggle get grouped for better mobile display -->
  38 + <div class="navbar-header">
  39 + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
  40 + <span class="sr-only">Toggle navigation</span>
  41 + <span class="icon-bar"></span>
  42 + <span class="icon-bar"></span>
  43 + <span class="icon-bar"></span>
  44 + </button>
  45 + <a class="navbar-brand" href="{:addon_url('example/index/index')}">{$site.name|htmlentities}</a>
  46 + </div>
  47 + <!-- Collect the nav links, forms, and other content for toggling -->
  48 + <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
  49 + <ul class="nav navbar-nav navbar-right">
  50 + <li>
  51 + <a href="{:addon_url('example/index/index')}">插件首页</a>
  52 + </li>
  53 + <li>
  54 + <a href="{:addon_url('example/demo/demo1', [':name'=>'s1'])}">无需登录页面</a>
  55 + </li>
  56 + <li>
  57 + <a href="{:addon_url('example/demo/demo2', [':name'=>'s2'])}">需登录页面</a>
  58 + </li>
  59 + {if $user}
  60 + <li class="dropdown">
  61 + <a href="#" class="dropdown-toggle" data-toggle="dropdown">欢迎你! {$user.nickname|htmlentities}<b class="caret"></b></a>
  62 + <ul class="dropdown-menu">
  63 + <li>
  64 + <a href="{:url('index/user/index')}">会员中心</a>
  65 + </li>
  66 + <li>
  67 + <a href="{:url('index/user/profile')}">个人资料</a>
  68 + </li>
  69 + <li>
  70 + <a href="{:url('index/user/logout')}">退出登录</a>
  71 + </li>
  72 + </ul>
  73 + </li>
  74 + {else /}
  75 + <li class="dropdown">
  76 + <a href="#" class="dropdown-toggle" data-toggle="dropdown">会员中心 <b class="caret"></b></a>
  77 + <ul class="dropdown-menu">
  78 + <li>
  79 + <a href="{:url('index/user/login')}">登录</a>
  80 + </li>
  81 + <li>
  82 + <a href="{:url('index/user/register')}">注册</a>
  83 + </li>
  84 + </ul>
  85 + </li>
  86 + {/if}
  87 + </ul>
  88 + </div>
  89 + <!-- /.navbar-collapse -->
  90 + </div>
  91 + <!-- /.container -->
  92 + </nav>
  93 +
  94 + {__CONTENT__}
  95 +
  96 + <div class="container">
  97 + <!-- Footer -->
  98 + <footer>
  99 + <div class="row">
  100 + <div class="col-lg-12">
  101 + <p>Copyright &copy; {$site.name|htmlentities} 2022</p>
  102 + </div>
  103 + </div>
  104 + </footer>
  105 +
  106 + </div>
  107 + <!-- /.container -->
  108 +
  109 + <!-- jQuery -->
  110 + <script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>
  111 +
  112 + <!-- Bootstrap Core JavaScript -->
  113 + <script src="__CDN__/assets/libs/bootstrap/dist/js/bootstrap.min.js"></script>
  114 +
  115 + <!-- Script to Activate the Carousel -->
  116 + <script>
  117 + $('.carousel').carousel({
  118 + interval: 5000 //changes the speed
  119 + })
  120 + </script>
  121 +
  122 + </body>
  123 +
  124 +</html>
  1 +{"files":["public\\assets\\addons\\simditor\\css\\simditor.min.css","public\\assets\\addons\\simditor\\images\\image.png","public\\assets\\addons\\simditor\\js\\simditor.min.js"],"license":"regular","licenseto":"15629","licensekey":"0bng3VGoD9JSQWKx i7JCSMq8KNNUA9vhGkgbYQ==","domains":["cardverification.com"],"licensecodes":[],"validations":["867a7ee97b89c3a1f31235c70da23ecf"]}
  1 +<?php
  2 +
  3 +namespace addons\simditor;
  4 +
  5 +use app\common\library\Menu;
  6 +use think\Addons;
  7 +
  8 +/**
  9 + * 插件
  10 + */
  11 +class Simditor extends Addons
  12 +{
  13 +
  14 + /**
  15 + * 插件安装方法
  16 + * @return bool
  17 + */
  18 + public function install()
  19 + {
  20 + return true;
  21 + }
  22 +
  23 + /**
  24 + * 插件卸载方法
  25 + * @return bool
  26 + */
  27 + public function uninstall()
  28 + {
  29 + return true;
  30 + }
  31 +
  32 + public function upgrade()
  33 + {
  34 + return true;
  35 + }
  36 +
  37 + /**
  38 + * @param $params
  39 + */
  40 + public function configInit(&$params)
  41 + {
  42 + $config = $this->getConfig();
  43 + $params['simditor'] = ['classname' => $config['classname'] ?? '.editor'];
  44 + }
  45 +
  46 +}
  1 +require.config({
  2 + paths: {
  3 + 'simditor': '../addons/simditor/js/simditor.min',
  4 + },
  5 + shim: {
  6 + 'simditor': [
  7 + 'css!../addons/simditor/css/simditor.min.css',
  8 + ]
  9 + }
  10 +});
  11 +require(['form'], function (Form) {
  12 + var _bindevent = Form.events.bindevent;
  13 + Form.events.bindevent = function (form) {
  14 + _bindevent.apply(this, [form]);
  15 + if ($(Config.simditor.classname || '.editor', form).size() > 0) {
  16 + //修改上传的接口调用
  17 + require(['upload', 'simditor'], function (Upload, Simditor) {
  18 + var editor, mobileToolbar, toolbar;
  19 + Simditor.locale = 'zh-CN';
  20 + Simditor.list = {};
  21 + toolbar = ['title', 'bold', 'italic', 'underline', 'strikethrough', 'fontScale', 'color', '|', 'ol', 'ul', 'blockquote', 'code', 'table', '|', 'link', 'image', 'hr', '|', 'indent', 'outdent', 'alignment'];
  22 + mobileToolbar = ["bold", "underline", "strikethrough", "color", "ul", "ol"];
  23 + $(Config.simditor.classname || '.editor', form).each(function () {
  24 + var id = $(this).attr("id");
  25 + editor = new Simditor({
  26 + textarea: this,
  27 + toolbarFloat: false,
  28 + toolbar: toolbar,
  29 + pasteImage: true,
  30 + defaultImage: Config.__CDN__ + '/assets/addons/simditor/images/image.png',
  31 + upload: {url: '/'},
  32 + allowedTags: ['div', 'br', 'span', 'a', 'img', 'b', 'strong', 'i', 'strike', 'u', 'font', 'p', 'ul', 'ol', 'li', 'blockquote', 'pre', 'code', 'h1', 'h2', 'h3', 'h4', 'hr'],
  33 + allowedAttributes: {
  34 + div: ['data-tpl', 'data-source', 'data-id'],
  35 + span: ['data-id']
  36 + },
  37 + allowedStyles: {
  38 + div: ['width', 'height', 'padding', 'background', 'color', 'display', 'justify-content', 'border', 'box-sizing', 'max-width', 'min-width', 'position', 'margin-left', 'bottom', 'left', 'margin', 'float'],
  39 + p: ['margin', 'color', 'height', 'line-height', 'position', 'width', 'border', 'bottom', 'float'],
  40 + span: ['text-decoration', 'color', 'margin-left', 'float', 'background', 'padding', 'margin-right', 'border-radius', 'font-size', 'border', 'float'],
  41 + img: ['vertical-align', 'width', 'height', 'object-fit', 'float', 'margin', 'float'],
  42 + a: ['text-decoration']
  43 + }
  44 + });
  45 + editor.uploader.on('beforeupload', function (e, file) {
  46 + Upload.api.send(file.obj, function (data) {
  47 + var url = Fast.api.cdnurl(data.url);
  48 + editor.uploader.trigger("uploadsuccess", [file, {success: true, file_path: url}]);
  49 + });
  50 + return false;
  51 + });
  52 + editor.on("blur", function () {
  53 + this.textarea.trigger("blur");
  54 + });
  55 + Simditor.list[id] = editor;
  56 + });
  57 + });
  58 + }
  59 + }
  60 +});
  1 +#!/bin/bash
  2 +
  3 +/usr/local/bin/node r.js -o ./js.js name=simditor baseUrl=../src/js out=../assets/js/simditor.min.js
  4 +/usr/local/bin/node r.js -o ./css.js cssIn=../src/css/simditor.css out=../assets/css/simditor.min.css
  1 +({
  2 + optimizeCss: "default",
  3 + optimize: "uglify"
  4 +})
  1 +({
  2 + name: "simditor",
  3 + paths: {
  4 + 'jquery': 'empty:',
  5 + 'simditor': 'simditor',
  6 + 'simple-module': 'module',
  7 + 'simple-uploader': 'uploader',
  8 + 'simple-hotkeys': 'hotkeys',
  9 + },
  10 +});
此 diff 太大无法显示。
  1 +<?php
  2 +
  3 +return [
  4 + [
  5 + 'name' => 'classname',
  6 + 'title' => '渲染文本框元素',
  7 + 'type' => 'string',
  8 + 'content' => [],
  9 + 'value' => '.editor',
  10 + 'rule' => 'required',
  11 + 'msg' => '',
  12 + 'tip' => '用于对指定的元素渲染,一般情况下无需修改',
  13 + 'ok' => '',
  14 + 'extend' => '',
  15 + ],
  16 +];
  1 +name = simditor
  2 +title = Simditor
  3 +intro = 简洁清晰的富文本插件
  4 +author = FastAdmin
  5 +website = http://www.fastadmin.net
  6 +version = 1.0.6
  7 +state = 1
  8 +url = /addons/simditor
  9 +license = regular
  10 +licenseto = 15629
  1 +@media screen and (max-device-width: 240px) and (min-device-width: 220px) {
  2 + body {
  3 + width: 240px;
  4 + margin: 0 auto;
  5 + }
  6 + body .wrapper {
  7 + width: 100%;
  8 + }
  9 + body .wrapper header {
  10 + padding: 30px 0 20px;
  11 + }
  12 + body .wrapper header h1 {
  13 + background-size: 200px auto;
  14 + background-position: 50px 0;
  15 + padding-top: 90px;
  16 + height: 45px;
  17 + }
  18 + body .wrapper header h1 a {
  19 + background-size: 160px auto;
  20 + background-position: 10px 0;
  21 + }
  22 + body .wrapper header p.desc {
  23 + font-size: 16px;
  24 + }
  25 + body .wrapper footer {
  26 + margin: 20px 0;
  27 + }
  28 + body .wrapper #page-demo {
  29 + width: 96%;
  30 + margin: 0 2%;
  31 + }
  32 + body .wrapper #link-fork {
  33 + z-index: -1;
  34 + width: 80px;
  35 + height: auto;
  36 + }
  37 + body .wrapper #link-fork img {
  38 + max-width: 80px;
  39 + height: auto;
  40 + }
  41 +
  42 + nav {
  43 + display: none;
  44 + }
  45 +}
  46 +@media screen and (max-device-width: 320px) and (min-device-width: 300px) {
  47 + body {
  48 + width: 320px;
  49 + margin: 0 auto;
  50 + }
  51 + body .wrapper {
  52 + width: 100%;
  53 + }
  54 + body .wrapper header {
  55 + padding: 30px 0 20px;
  56 + }
  57 + body .wrapper header h1 {
  58 + background-size: 200px auto;
  59 + background-position: 50px 0;
  60 + padding-top: 90px;
  61 + height: 45px;
  62 + }
  63 + body .wrapper header h1 a {
  64 + background-size: 160px auto;
  65 + background-position: 10px 0;
  66 + }
  67 + body .wrapper header p.desc {
  68 + font-size: 16px;
  69 + }
  70 + body .wrapper footer {
  71 + margin: 20px 0;
  72 + }
  73 + body .wrapper #page-demo {
  74 + width: 96%;
  75 + margin: 0 2%;
  76 + }
  77 + body .wrapper #link-fork {
  78 + z-index: -1;
  79 + width: 80px;
  80 + height: auto;
  81 + }
  82 + body .wrapper #link-fork img {
  83 + max-width: 80px;
  84 + height: auto;
  85 + }
  86 +
  87 + nav {
  88 + display: none;
  89 + }
  90 +}
  91 +@media screen and (max-device-width: 360px) and (min-device-width: 340px) {
  92 + body {
  93 + width: 360px;
  94 + margin: 0 auto;
  95 + }
  96 + body .wrapper {
  97 + width: 100%;
  98 + }
  99 + body .wrapper header {
  100 + padding: 30px 0 20px;
  101 + }
  102 + body .wrapper header h1 {
  103 + background-size: 200px auto;
  104 + background-position: 50px 0;
  105 + padding-top: 90px;
  106 + height: 45px;
  107 + }
  108 + body .wrapper header h1 a {
  109 + background-size: 160px auto;
  110 + background-position: 10px 0;
  111 + }
  112 + body .wrapper header p.desc {
  113 + font-size: 16px;
  114 + }
  115 + body .wrapper footer {
  116 + margin: 20px 0;
  117 + }
  118 + body .wrapper #page-demo {
  119 + width: 96%;
  120 + margin: 0 2%;
  121 + }
  122 + body .wrapper #link-fork {
  123 + z-index: -1;
  124 + width: 80px;
  125 + height: auto;
  126 + }
  127 + body .wrapper #link-fork img {
  128 + max-width: 80px;
  129 + height: auto;
  130 + }
  131 +
  132 + nav {
  133 + display: none;
  134 + }
  135 +}
  136 +@media screen and (max-device-width: 480px) and (min-device-width: 460px) {
  137 + body {
  138 + width: 480px;
  139 + margin: 0 auto;
  140 + }
  141 + body .wrapper {
  142 + width: 100%;
  143 + }
  144 + body .wrapper header {
  145 + padding: 30px 0 20px;
  146 + }
  147 + body .wrapper header h1 {
  148 + background-size: 200px auto;
  149 + background-position: 50px 0;
  150 + padding-top: 90px;
  151 + height: 45px;
  152 + }
  153 + body .wrapper header h1 a {
  154 + background-size: 160px auto;
  155 + background-position: 10px 0;
  156 + }
  157 + body .wrapper header p.desc {
  158 + font-size: 16px;
  159 + }
  160 + body .wrapper footer {
  161 + margin: 20px 0;
  162 + }
  163 + body .wrapper #page-demo {
  164 + width: 96%;
  165 + margin: 0 2%;
  166 + }
  167 + body .wrapper #link-fork {
  168 + z-index: -1;
  169 + width: 80px;
  170 + height: auto;
  171 + }
  172 + body .wrapper #link-fork img {
  173 + max-width: 80px;
  174 + height: auto;
  175 + }
  176 +
  177 + nav {
  178 + display: none;
  179 + }
  180 +}
  181 +@media screen and (max-device-width: 640px) and (min-device-width: 620px) {
  182 + body {
  183 + width: 320px;
  184 + margin: 0 auto;
  185 + }
  186 + body .wrapper {
  187 + width: 100%;
  188 + }
  189 + body .wrapper header {
  190 + padding: 30px 0 20px;
  191 + }
  192 + body .wrapper header h1 {
  193 + background-size: 200px auto;
  194 + background-position: 50px 0;
  195 + padding-top: 90px;
  196 + height: 45px;
  197 + }
  198 + body .wrapper header h1 a {
  199 + background-size: 160px auto;
  200 + background-position: 10px 0;
  201 + }
  202 + body .wrapper header p.desc {
  203 + font-size: 16px;
  204 + }
  205 + body .wrapper footer {
  206 + margin: 20px 0;
  207 + }
  208 + body .wrapper #page-demo {
  209 + width: 96%;
  210 + margin: 0 2%;
  211 + }
  212 + body .wrapper #link-fork {
  213 + z-index: -1;
  214 + width: 80px;
  215 + height: auto;
  216 + }
  217 + body .wrapper #link-fork img {
  218 + max-width: 80px;
  219 + height: auto;
  220 + }
  221 +
  222 + nav {
  223 + display: none;
  224 + }
  225 +}
  226 +@media screen and (max-device-width: 720px) and (min-device-width: 700px) {
  227 + body {
  228 + width: 360px;
  229 + margin: 0 auto;
  230 + }
  231 + body .wrapper {
  232 + width: 100%;
  233 + }
  234 + body .wrapper header {
  235 + padding: 30px 0 20px;
  236 + }
  237 + body .wrapper header h1 {
  238 + background-size: 200px auto;
  239 + background-position: 50px 0;
  240 + padding-top: 90px;
  241 + height: 45px;
  242 + }
  243 + body .wrapper header h1 a {
  244 + background-size: 160px auto;
  245 + background-position: 10px 0;
  246 + }
  247 + body .wrapper header p.desc {
  248 + font-size: 16px;
  249 + }
  250 + body .wrapper footer {
  251 + margin: 20px 0;
  252 + }
  253 + body .wrapper #page-demo {
  254 + width: 96%;
  255 + margin: 0 2%;
  256 + }
  257 + body .wrapper #link-fork {
  258 + z-index: -1;
  259 + width: 80px;
  260 + height: auto;
  261 + }
  262 + body .wrapper #link-fork img {
  263 + max-width: 80px;
  264 + height: auto;
  265 + }
  266 +
  267 + nav {
  268 + display: none;
  269 + }
  270 +}
  271 +@media screen and (max-device-width: 800px) and (min-device-width: 780px) {
  272 + body {
  273 + width: 400px;
  274 + margin: 0 auto;
  275 + }
  276 + body .wrapper {
  277 + width: 100%;
  278 + }
  279 + body .wrapper header {
  280 + padding: 30px 0 20px;
  281 + }
  282 + body .wrapper header h1 {
  283 + background-size: 200px auto;
  284 + background-position: 50px 0;
  285 + padding-top: 90px;
  286 + height: 45px;
  287 + }
  288 + body .wrapper header h1 a {
  289 + background-size: 160px auto;
  290 + background-position: 10px 0;
  291 + }
  292 + body .wrapper header p.desc {
  293 + font-size: 16px;
  294 + }
  295 + body .wrapper footer {
  296 + margin: 20px 0;
  297 + }
  298 + body .wrapper #page-demo {
  299 + width: 96%;
  300 + margin: 0 2%;
  301 + }
  302 + body .wrapper #link-fork {
  303 + z-index: -1;
  304 + width: 88.8888888889px;
  305 + height: auto;
  306 + }
  307 + body .wrapper #link-fork img {
  308 + max-width: 88.8888888889px;
  309 + height: auto;
  310 + }
  311 +
  312 + nav {
  313 + display: none;
  314 + }
  315 +}
  316 +@media screen and (max-device-width: 960px) and (min-device-width: 940px) {
  317 + body {
  318 + width: 480px;
  319 + margin: 0 auto;
  320 + }
  321 + body .wrapper {
  322 + width: 100%;
  323 + }
  324 + body .wrapper header {
  325 + padding: 30px 0 20px;
  326 + }
  327 + body .wrapper header h1 {
  328 + background-size: 200px auto;
  329 + background-position: 50px 0;
  330 + padding-top: 90px;
  331 + height: 45px;
  332 + }
  333 + body .wrapper header h1 a {
  334 + background-size: 160px auto;
  335 + background-position: 10px 0;
  336 + }
  337 + body .wrapper header p.desc {
  338 + font-size: 16px;
  339 + }
  340 + body .wrapper footer {
  341 + margin: 20px 0;
  342 + }
  343 + body .wrapper #page-demo {
  344 + width: 96%;
  345 + margin: 0 2%;
  346 + }
  347 + body .wrapper #link-fork {
  348 + z-index: -1;
  349 + width: 100px;
  350 + height: auto;
  351 + }
  352 + body .wrapper #link-fork img {
  353 + max-width: 100px;
  354 + height: auto;
  355 + }
  356 +
  357 + nav {
  358 + display: none;
  359 + }
  360 +}
  361 +@media screen and (max-device-width: 1024px) and (min-device-width: 1004px) {
  362 + body {
  363 + width: 512px;
  364 + margin: 0 auto;
  365 + }
  366 + body .wrapper {
  367 + width: 100%;
  368 + }
  369 + body .wrapper header {
  370 + padding: 30px 0 20px;
  371 + }
  372 + body .wrapper header h1 {
  373 + background-size: 200px auto;
  374 + background-position: 50px 0;
  375 + padding-top: 90px;
  376 + height: 45px;
  377 + }
  378 + body .wrapper header h1 a {
  379 + background-size: 160px auto;
  380 + background-position: 10px 0;
  381 + }
  382 + body .wrapper header p.desc {
  383 + font-size: 16px;
  384 + }
  385 + body .wrapper footer {
  386 + margin: 20px 0;
  387 + }
  388 + body .wrapper #page-demo {
  389 + width: 96%;
  390 + margin: 0 2%;
  391 + }
  392 + body .wrapper #link-fork {
  393 + z-index: -1;
  394 + width: 100px;
  395 + height: auto;
  396 + }
  397 + body .wrapper #link-fork img {
  398 + max-width: 100px;
  399 + height: auto;
  400 + }
  401 +
  402 + nav {
  403 + display: none;
  404 + }
  405 +}
  406 +@media screen and (max-device-width: 1280px) and (min-device-width: 1260px) {
  407 + body {
  408 + width: 640px;
  409 + margin: 0 auto;
  410 + }
  411 + body .wrapper {
  412 + width: 100%;
  413 + }
  414 + body .wrapper header {
  415 + padding: 30px 0 20px;
  416 + }
  417 + body .wrapper header h1 {
  418 + background-size: 200px auto;
  419 + background-position: 50px 0;
  420 + padding-top: 90px;
  421 + height: 45px;
  422 + }
  423 + body .wrapper header h1 a {
  424 + background-size: 160px auto;
  425 + background-position: 10px 0;
  426 + }
  427 + body .wrapper header p.desc {
  428 + font-size: 16px;
  429 + }
  430 + body .wrapper footer {
  431 + margin: 20px 0;
  432 + }
  433 + body .wrapper #page-demo {
  434 + width: 96%;
  435 + margin: 0 2%;
  436 + }
  437 + body .wrapper #link-fork {
  438 + z-index: -1;
  439 + width: 100px;
  440 + height: auto;
  441 + }
  442 + body .wrapper #link-fork img {
  443 + max-width: 100px;
  444 + height: auto;
  445 + }
  446 +
  447 + nav {
  448 + display: none;
  449 + }
  450 +}
  451 +@media screen and (device-aspect-ratio: 40 / 71) and (orientation: landscape) {
  452 + body {
  453 + width: 568px;
  454 + }
  455 +}
  456 +@media screen and (device-aspect-ratio: 2 / 3) and (orientation: landscape) {
  457 + body {
  458 + width: 480px;
  459 + }
  460 +}
  1 +@font-face {
  2 + font-family: 'Simditor';
  3 + src: url(data:application/font-woff;charset=utf-8;base64,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) format("woff");
  4 + font-weight: normal;
  5 + font-style: normal;
  6 +}
  7 +.simditor-icon {
  8 + display: inline-block;
  9 + font: normal normal normal 14px/1 'Simditor';
  10 + font-size: inherit;
  11 + text-rendering: auto;
  12 + -webkit-font-smoothing: antialiased;
  13 + -moz-osx-font-smoothing: grayscale;
  14 + transform: translate(0, 0);
  15 +}
  16 +
  17 +.simditor-icon-code:before {
  18 + content: '\f000';
  19 +}
  20 +
  21 +.simditor-icon-bold:before {
  22 + content: '\f001';
  23 +}
  24 +
  25 +.simditor-icon-italic:before {
  26 + content: '\f002';
  27 +}
  28 +
  29 +.simditor-icon-underline:before {
  30 + content: '\f003';
  31 +}
  32 +
  33 +.simditor-icon-times:before {
  34 + content: '\f004';
  35 +}
  36 +
  37 +.simditor-icon-strikethrough:before {
  38 + content: '\f005';
  39 +}
  40 +
  41 +.simditor-icon-list-ol:before {
  42 + content: '\f006';
  43 +}
  44 +
  45 +.simditor-icon-list-ul:before {
  46 + content: '\f007';
  47 +}
  48 +
  49 +.simditor-icon-quote-left:before {
  50 + content: '\f008';
  51 +}
  52 +
  53 +.simditor-icon-table:before {
  54 + content: '\f009';
  55 +}
  56 +
  57 +.simditor-icon-link:before {
  58 + content: '\f00a';
  59 +}
  60 +
  61 +.simditor-icon-picture-o:before {
  62 + content: '\f00b';
  63 +}
  64 +
  65 +.simditor-icon-minus:before {
  66 + content: '\f00c';
  67 +}
  68 +
  69 +.simditor-icon-indent:before {
  70 + content: '\f00d';
  71 +}
  72 +
  73 +.simditor-icon-outdent:before {
  74 + content: '\f00e';
  75 +}
  76 +
  77 +.simditor-icon-unlink:before {
  78 + content: '\f00f';
  79 +}
  80 +
  81 +.simditor-icon-caret-down:before {
  82 + content: '\f010';
  83 +}
  84 +
  85 +.simditor-icon-caret-right:before {
  86 + content: '\f011';
  87 +}
  88 +
  89 +.simditor-icon-upload:before {
  90 + content: '\f012';
  91 +}
  92 +
  93 +.simditor-icon-undo:before {
  94 + content: '\f013';
  95 +}
  96 +
  97 +.simditor-icon-smile-o:before {
  98 + content: '\f014';
  99 +}
  100 +
  101 +.simditor-icon-tint:before {
  102 + content: '\f015';
  103 +}
  104 +
  105 +.simditor-icon-font:before {
  106 + content: '\f016';
  107 +}
  108 +
  109 +.simditor-icon-html5:before {
  110 + content: '\f017';
  111 +}
  112 +
  113 +.simditor-icon-mark:before {
  114 + content: '\f018';
  115 +}
  116 +
  117 +.simditor-icon-align-center:before {
  118 + content: '\f019';
  119 +}
  120 +
  121 +.simditor-icon-align-left:before {
  122 + content: '\f01a';
  123 +}
  124 +
  125 +.simditor-icon-align-right:before {
  126 + content: '\f01b';
  127 +}
  128 +
  129 +.simditor-icon-font-minus:before {
  130 + content: '\f01c';
  131 +}
  132 +
  133 +.simditor-icon-markdown:before {
  134 + content: '\f01d';
  135 +}
  136 +
  137 +.simditor-icon-checklist:before {
  138 + content: '\f01e';
  139 +}
  140 +
  141 +.simditor {
  142 + position: relative;
  143 + border: 1px solid #c9d8db;
  144 +}
  145 +.simditor .simditor-wrapper {
  146 + position: relative;
  147 + background: #ffffff;
  148 +}
  149 +.simditor .simditor-wrapper > textarea {
  150 + display: none !important;
  151 + width: 100%;
  152 + box-sizing: border-box;
  153 + font-family: monaco;
  154 + font-size: 14px;
  155 + line-height: 1.6;
  156 + border: none;
  157 + padding: 22px 15px 36px;
  158 + min-height: 300px;
  159 + outline: none;
  160 + background: transparent;
  161 + resize: none;
  162 +}
  163 +.simditor .simditor-wrapper .simditor-placeholder {
  164 + display: none;
  165 + position: absolute;
  166 + left: 0;
  167 + z-index: 0;
  168 + padding: 22px 15px;
  169 + font-size: 16px;
  170 + font-family: arial, sans-serif;
  171 + line-height: 1.5;
  172 + color: #999999;
  173 + background: transparent;
  174 +}
  175 +.simditor .simditor-wrapper.toolbar-floating .simditor-toolbar {
  176 + position: fixed;
  177 + top: 0;
  178 + z-index: 10;
  179 + box-shadow: 0 0 6px rgba(0, 0, 0, 0.1);
  180 +}
  181 +.simditor .simditor-wrapper .simditor-image-loading {
  182 + width: 100%;
  183 + height: 100%;
  184 + position: absolute;
  185 + top: 0;
  186 + left: 0;
  187 + z-index: 2;
  188 +}
  189 +.simditor .simditor-wrapper .simditor-image-loading .progress {
  190 + width: 100%;
  191 + height: 100%;
  192 + background: rgba(0, 0, 0, 0.4);
  193 + position: absolute;
  194 + bottom: 0;
  195 + left: 0;
  196 +}
  197 +.simditor .simditor-body {
  198 + padding: 10px;
  199 + min-height: 300px;
  200 + outline: none;
  201 + cursor: text;
  202 + position: relative;
  203 + z-index: 1;
  204 + background: transparent;
  205 + width:100%;
  206 +}
  207 +.simditor .simditor-body a.selected {
  208 + background: #b3d4fd;
  209 +}
  210 +.simditor .simditor-body a.simditor-mention {
  211 + cursor: pointer;
  212 +}
  213 +.simditor .simditor-body .simditor-table {
  214 + position: relative;
  215 +}
  216 +.simditor .simditor-body .simditor-table.resizing {
  217 + cursor: col-resize;
  218 +}
  219 +.simditor .simditor-body .simditor-table .simditor-resize-handle {
  220 + position: absolute;
  221 + left: 0;
  222 + top: 0;
  223 + width: 10px;
  224 + height: 100%;
  225 + cursor: col-resize;
  226 +}
  227 +.simditor .simditor-body pre {
  228 + /*min-height: 28px;*/
  229 + box-sizing: border-box;
  230 + -moz-box-sizing: border-box;
  231 + word-wrap: break-word !important;
  232 + white-space: pre-wrap !important;
  233 +}
  234 +.simditor .simditor-body img {
  235 + cursor: pointer;
  236 +}
  237 +.simditor .simditor-body img.selected {
  238 + box-shadow: 0 0 0 4px #cccccc;
  239 +}
  240 +.simditor .simditor-paste-bin {
  241 + position: fixed;
  242 + bottom: 10px;
  243 + right: 10px;
  244 + width: 1px;
  245 + height: 20px;
  246 + font-size: 1px;
  247 + line-height: 1px;
  248 + overflow: hidden;
  249 + padding: 0;
  250 + margin: 0;
  251 + opacity: 0;
  252 + -webkit-user-select: text;
  253 +}
  254 +.simditor .simditor-toolbar {
  255 + border-bottom: 1px solid #eeeeee;
  256 + background: #ffffff;
  257 + width: 100%;
  258 +}
  259 +.simditor .simditor-toolbar > ul {
  260 + margin: 0;
  261 + padding: 0 0 0 6px;
  262 + list-style: none;
  263 +}
  264 +.simditor .simditor-toolbar > ul > li {
  265 + position: relative;
  266 + display: inline-block;
  267 + font-size: 0;
  268 +}
  269 +.simditor .simditor-toolbar > ul > li > span.separator {
  270 + display: inline-block;
  271 + background: #cfcfcf;
  272 + width: 1px;
  273 + height: 18px;
  274 + margin: 11px 15px;
  275 + vertical-align: middle;
  276 +}
  277 +.simditor .simditor-toolbar > ul > li > .toolbar-item {
  278 + display: inline-block;
  279 + width: 36px;
  280 + height: 36px;
  281 + outline: none;
  282 + color: #333333;
  283 + font-size: 15px;
  284 + line-height: 36px;
  285 + vertical-align: middle;
  286 + text-align: center;
  287 + text-decoration: none;
  288 +}
  289 +.simditor .simditor-toolbar > ul > li > .toolbar-item span {
  290 + opacity: 0.6;
  291 +}
  292 +.simditor .simditor-toolbar > ul > li > .toolbar-item span.simditor-icon {
  293 + display: inline;
  294 + line-height: normal;
  295 +}
  296 +.simditor .simditor-toolbar > ul > li > .toolbar-item:hover span {
  297 + opacity: 1;
  298 +}
  299 +.simditor .simditor-toolbar > ul > li > .toolbar-item.active {
  300 + background: #eeeeee;
  301 +}
  302 +.simditor .simditor-toolbar > ul > li > .toolbar-item.active span {
  303 + opacity: 1;
  304 +}
  305 +.simditor .simditor-toolbar > ul > li > .toolbar-item.disabled {
  306 + cursor: default;
  307 +}
  308 +.simditor .simditor-toolbar > ul > li > .toolbar-item.disabled span {
  309 + opacity: 0.3;
  310 +}
  311 +.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title span:before {
  312 + content: "H";
  313 + font-size: 19px;
  314 + font-weight: bold;
  315 + font-family: 'Times New Roman';
  316 +}
  317 +.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title.active-h1 span:before {
  318 + content: 'H1';
  319 + font-size: 18px;
  320 +}
  321 +.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title.active-h2 span:before {
  322 + content: 'H2';
  323 + font-size: 18px;
  324 +}
  325 +.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title.active-h3 span:before {
  326 + content: 'H3';
  327 + font-size: 18px;
  328 +}
  329 +.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-image {
  330 + position: relative;
  331 + overflow: hidden;
  332 +}
  333 +.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-image > input[type=file] {
  334 + position: absolute;
  335 + right: 0px;
  336 + top: 0px;
  337 + opacity: 0;
  338 + font-size: 100px;
  339 + cursor: pointer;
  340 +}
  341 +.simditor .simditor-toolbar > ul > li.menu-on .toolbar-item {
  342 + position: relative;
  343 + z-index: 20;
  344 + background: #ffffff;
  345 + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
  346 +}
  347 +.simditor .simditor-toolbar > ul > li.menu-on .toolbar-item span {
  348 + opacity: 1;
  349 +}
  350 +.simditor .simditor-toolbar > ul > li.menu-on .toolbar-menu {
  351 + display: block;
  352 +}
  353 +.simditor .simditor-toolbar .toolbar-menu {
  354 + display: none;
  355 + position: absolute;
  356 + top: 36px;
  357 + left: 0;
  358 + z-index: 21;
  359 + background: #ffffff;
  360 + text-align: left;
  361 + box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
  362 +}
  363 +.simditor .simditor-toolbar .toolbar-menu:before {
  364 + content: '';
  365 + display: block;
  366 + width: 36px;
  367 + height: 4px;
  368 + background: #ffffff;
  369 + position: absolute;
  370 + top: -3px;
  371 + left: 0;
  372 +}
  373 +.simditor .simditor-toolbar .toolbar-menu ul {
  374 + min-width: 160px;
  375 + list-style: none;
  376 + margin: 0;
  377 + padding: 10px 1px;
  378 +}
  379 +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item {
  380 + display: block;
  381 + font-size: 14px;
  382 + line-height: 2em;
  383 + padding: 0 10px;
  384 + text-decoration: none;
  385 + color: #666666;
  386 +}
  387 +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item:hover {
  388 + background: #f6f6f6;
  389 +}
  390 +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h1 {
  391 + font-size: 24px;
  392 + color: #333333;
  393 +}
  394 +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h2 {
  395 + font-size: 22px;
  396 + color: #333333;
  397 +}
  398 +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h3 {
  399 + font-size: 20px;
  400 + color: #333333;
  401 +}
  402 +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h4 {
  403 + font-size: 18px;
  404 + color: #333333;
  405 +}
  406 +.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h5 {
  407 + font-size: 16px;
  408 + color: #333333;
  409 +}
  410 +.simditor .simditor-toolbar .toolbar-menu ul > li .separator {
  411 + display: block;
  412 + border-top: 1px solid #cccccc;
  413 + height: 0;
  414 + line-height: 0;
  415 + font-size: 0;
  416 + margin: 6px 0;
  417 +}
  418 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color {
  419 + width: 96px;
  420 +}
  421 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list {
  422 + height: 36px;
  423 + margin: 10px 6px 6px 10px;
  424 + padding: 0;
  425 + min-width: 0;
  426 +}
  427 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li {
  428 + float: left;
  429 + margin: 0 4px 4px 0;
  430 +}
  431 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color {
  432 + display: block;
  433 + width: 16px;
  434 + height: 16px;
  435 + background: #dfdfdf;
  436 + border-radius: 2px;
  437 +}
  438 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color:hover {
  439 + opacity: 0.8;
  440 +}
  441 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color.font-color-default {
  442 + background: #333333;
  443 +}
  444 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-1 {
  445 + background: #E33737;
  446 +}
  447 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-2 {
  448 + background: #e28b41;
  449 +}
  450 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-3 {
  451 + background: #c8a732;
  452 +}
  453 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-4 {
  454 + background: #209361;
  455 +}
  456 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-5 {
  457 + background: #418caf;
  458 +}
  459 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-6 {
  460 + background: #aa8773;
  461 +}
  462 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-7 {
  463 + background: #999999;
  464 +}
  465 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table {
  466 + background: #ffffff;
  467 + padding: 1px;
  468 +}
  469 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table {
  470 + border: none;
  471 + border-collapse: collapse;
  472 + border-spacing: 0;
  473 + table-layout: fixed;
  474 +}
  475 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table td {
  476 + padding: 0;
  477 + cursor: pointer;
  478 +}
  479 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table td:before {
  480 + width: 16px;
  481 + height: 16px;
  482 + border: 1px solid #ffffff;
  483 + background: #f3f3f3;
  484 + display: block;
  485 + content: "";
  486 +}
  487 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table td.selected:before {
  488 + background: #cfcfcf;
  489 +}
  490 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-edit-table {
  491 + display: none;
  492 +}
  493 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-edit-table ul li {
  494 + white-space: nowrap;
  495 +}
  496 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-image .menu-item-upload-image {
  497 + position: relative;
  498 + overflow: hidden;
  499 +}
  500 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-image .menu-item-upload-image input[type=file] {
  501 + position: absolute;
  502 + right: 0px;
  503 + top: 0px;
  504 + opacity: 0;
  505 + font-size: 100px;
  506 + cursor: pointer;
  507 +}
  508 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-alignment {
  509 + width: 100%;
  510 +}
  511 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-alignment ul {
  512 + min-width: 100%;
  513 +}
  514 +.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-alignment .menu-item {
  515 + text-align: center;
  516 +}
  517 +.simditor .simditor-popover {
  518 + display: none;
  519 + padding: 5px 8px 0;
  520 + background: #ffffff;
  521 + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
  522 + border-radius: 2px;
  523 + position: absolute;
  524 + z-index: 2;
  525 +}
  526 +.simditor .simditor-popover .settings-field {
  527 + margin: 0 0 5px 0;
  528 + font-size: 12px;
  529 + height: 25px;
  530 + line-height: 25px;
  531 +}
  532 +.simditor .simditor-popover .settings-field label {
  533 + display: inline-block;
  534 + margin: 0 5px 0 0;
  535 +}
  536 +.simditor .simditor-popover .settings-field input[type=text] {
  537 + display: inline-block;
  538 + width: 200px;
  539 + box-sizing: border-box;
  540 + font-size: 12px;
  541 +}
  542 +.simditor .simditor-popover .settings-field input[type=text].image-size {
  543 + width: 83px;
  544 +}
  545 +.simditor .simditor-popover .settings-field .times {
  546 + display: inline-block;
  547 + width: 26px;
  548 + font-size: 12px;
  549 + text-align: center;
  550 +}
  551 +.simditor .simditor-popover.link-popover .btn-unlink, .simditor .simditor-popover.image-popover .btn-upload, .simditor .simditor-popover.image-popover .btn-restore {
  552 + display: inline-block;
  553 + margin: 0 0 0 5px;
  554 + color: #333333;
  555 + font-size: 14px;
  556 + outline: 0;
  557 +}
  558 +.simditor .simditor-popover.link-popover .btn-unlink span, .simditor .simditor-popover.image-popover .btn-upload span, .simditor .simditor-popover.image-popover .btn-restore span {
  559 + opacity: 0.6;
  560 +}
  561 +.simditor .simditor-popover.link-popover .btn-unlink:hover span, .simditor .simditor-popover.image-popover .btn-upload:hover span, .simditor .simditor-popover.image-popover .btn-restore:hover span {
  562 + opacity: 1;
  563 +}
  564 +.simditor .simditor-popover.image-popover .btn-upload {
  565 + position: relative;
  566 + display: inline-block;
  567 + overflow: hidden;
  568 + vertical-align: middle;
  569 +}
  570 +.simditor .simditor-popover.image-popover .btn-upload input[type=file] {
  571 + position: absolute;
  572 + right: 0px;
  573 + top: 0px;
  574 + opacity: 0;
  575 + height: 100%;
  576 + width: 28px;
  577 +}
  578 +.simditor.simditor-mobile .simditor-wrapper.toolbar-floating .simditor-toolbar {
  579 + position: absolute;
  580 + top: 0;
  581 + z-index: 10;
  582 + box-shadow: 0 0 6px rgba(0, 0, 0, 0.1);
  583 +}
  584 +
  585 +.simditor .simditor-body, .editor-style {
  586 + font-size: 14px;
  587 + font-family: arial, sans-serif;
  588 + line-height: 1.6;
  589 + color: #333;
  590 + outline: none;
  591 + word-wrap: break-word;
  592 +}
  593 +.simditor .simditor-body > :first-child, .editor-style > :first-child {
  594 + margin-top: 0 !important;
  595 +}
  596 +.simditor .simditor-body a, .editor-style a {
  597 + color: #4298BA;
  598 + text-decoration: none;
  599 + word-break: break-all;
  600 +}
  601 +.simditor .simditor-body a:visited, .editor-style a:visited {
  602 + color: #4298BA;
  603 +}
  604 +.simditor .simditor-body a:hover, .editor-style a:hover {
  605 + color: #0F769F;
  606 +}
  607 +.simditor .simditor-body a:active, .editor-style a:active {
  608 + color: #9E792E;
  609 +}
  610 +.simditor .simditor-body a:hover, .simditor .simditor-body a:active, .editor-style a:hover, .editor-style a:active {
  611 + outline: 0;
  612 +}
  613 +.simditor .simditor-body h1, .simditor .simditor-body h2, .simditor .simditor-body h3, .simditor .simditor-body h4, .simditor .simditor-body h5, .simditor .simditor-body h6, .editor-style h1, .editor-style h2, .editor-style h3, .editor-style h4, .editor-style h5, .editor-style h6 {
  614 + font-weight: normal;
  615 + margin: 36px 0 20px;
  616 + color: #000000;
  617 +}
  618 +.simditor .simditor-body h1, .editor-style h1 {
  619 + font-size: 24px;
  620 +}
  621 +.simditor .simditor-body h2, .editor-style h2 {
  622 + font-size: 22px;
  623 +}
  624 +.simditor .simditor-body h3, .editor-style h3 {
  625 + font-size: 20px;
  626 +}
  627 +.simditor .simditor-body h4, .editor-style h4 {
  628 + font-size: 18px;
  629 +}
  630 +.simditor .simditor-body h5, .editor-style h5 {
  631 + font-size: 16px;
  632 +}
  633 +.simditor .simditor-body h6, .editor-style h6 {
  634 + font-size: 16px;
  635 +}
  636 +.simditor .simditor-body p, .simditor .simditor-body div, .editor-style p, .editor-style div {
  637 + word-wrap: break-word;
  638 + margin: 0 0 10px 0;
  639 + color: #333;
  640 + word-wrap: break-word;
  641 +}
  642 +.simditor .simditor-body b, .simditor .simditor-body strong, .editor-style b, .editor-style strong {
  643 + font-weight: bold;
  644 +}
  645 +.simditor .simditor-body i, .simditor .simditor-body em, .editor-style i, .editor-style em {
  646 + font-style: italic;
  647 +}
  648 +.simditor .simditor-body u, .editor-style u {
  649 + text-decoration: underline;
  650 +}
  651 +.simditor .simditor-body strike, .simditor .simditor-body del, .editor-style strike, .editor-style del {
  652 + text-decoration: line-through;
  653 +}
  654 +.simditor .simditor-body ul, .simditor .simditor-body ol, .editor-style ul, .editor-style ol {
  655 + list-style: disc outside none;
  656 + margin: 15px 0;
  657 + padding: 0 0 0 36px;
  658 + line-height: 1.6;
  659 +}
  660 +.simditor .simditor-body ul li, .simditor .simditor-body ol li, .editor-style ul li, .editor-style ol li {
  661 + list-style-type: inherit;
  662 +}
  663 +.simditor .simditor-body ul ul, .simditor .simditor-body ul ol, .simditor .simditor-body ol ul, .simditor .simditor-body ol ol, .editor-style ul ul, .editor-style ul ol, .editor-style ol ul, .editor-style ol ol {
  664 + padding-left: 30px;
  665 +}
  666 +.simditor .simditor-body ul ul, .simditor .simditor-body ol ul, .editor-style ul ul, .editor-style ol ul {
  667 + list-style: circle outside none;
  668 +}
  669 +.simditor .simditor-body ul ul ul, .simditor .simditor-body ol ul ul, .editor-style ul ul ul, .editor-style ol ul ul {
  670 + list-style: square outside none;
  671 +}
  672 +.simditor .simditor-body ol, .editor-style ol {
  673 + list-style: decimal;
  674 +}
  675 +.simditor .simditor-body blockquote, .editor-style blockquote {
  676 + border-left: 6px solid #ddd;
  677 + padding: 5px 0 5px 10px;
  678 + margin: 15px 0 15px 15px;
  679 +}
  680 +.simditor .simditor-body blockquote > :first-child, .editor-style blockquote > :first-child {
  681 + margin-top: 0;
  682 +}
  683 +.simditor .simditor-body code, .editor-style code {
  684 + display: inline-block;
  685 + padding: 0 4px;
  686 + margin: 0 5px;
  687 + background: #eeeeee;
  688 + border-radius: 3px;
  689 + font-size: 13px;
  690 + font-family: 'monaco', 'Consolas', "Liberation Mono", Courier, monospace;
  691 +}
  692 +.simditor .simditor-body pre, .editor-style pre {
  693 + padding: 10px 5px 10px 10px;
  694 + margin: 15px 0;
  695 + display: block;
  696 + line-height: 18px;
  697 + background: #F0F0F0;
  698 + border-radius: 3px;
  699 + font-size: 13px;
  700 + font-family: 'monaco', 'Consolas', "Liberation Mono", Courier, monospace;
  701 + white-space: pre;
  702 + word-wrap: normal;
  703 + overflow-x: auto;
  704 +}
  705 +.simditor .simditor-body pre code, .editor-style pre code {
  706 + display: block;
  707 + padding: 0;
  708 + margin: 0;
  709 + background: none;
  710 + border-radius: 0;
  711 +}
  712 +.simditor .simditor-body hr, .editor-style hr {
  713 + display: block;
  714 + height: 0px;
  715 + border: 0;
  716 + border-top: 1px solid #ccc;
  717 + margin: 15px 0;
  718 + padding: 0;
  719 +}
  720 +.simditor .simditor-body table, .editor-style table {
  721 + width: 100%;
  722 + table-layout: fixed;
  723 + border-collapse: collapse;
  724 + border-spacing: 0;
  725 + margin: 15px 0;
  726 +}
  727 +.simditor .simditor-body table thead, .editor-style table thead {
  728 + background-color: #f9f9f9;
  729 +}
  730 +.simditor .simditor-body table td, .simditor .simditor-body table th, .editor-style table td, .editor-style table th {
  731 + min-width: 36px;
  732 + height: 30px;
  733 + border: 1px solid #ccc;
  734 + vertical-align: top;
  735 + padding: 2px 4px;
  736 + text-align: left;
  737 + box-sizing: border-box;
  738 +}
  739 +.simditor .simditor-body table td.active, .simditor .simditor-body table th.active, .editor-style table td.active, .editor-style table th.active {
  740 + background-color: #ffffee;
  741 +}
  742 +.simditor .simditor-body img, .editor-style img {
  743 + margin: 0 5px;
  744 + vertical-align: middle;
  745 +}
  1 +(function (root, factory) {
  2 + if (typeof define === 'function' && define.amd) {
  3 + // AMD. Register as an anonymous module unless amdModuleId is set
  4 + define('simple-hotkeys', ["jquery","simple-module"], function ($, SimpleModule) {
  5 + return (root['hotkeys'] = factory($, SimpleModule));
  6 + });
  7 + } else if (typeof exports === 'object') {
  8 + // Node. Does not work with strict CommonJS, but
  9 + // only CommonJS-like environments that support module.exports,
  10 + // like Node.
  11 + module.exports = factory(require("jquery"),require("simple-module"));
  12 + } else {
  13 + root.simple = root.simple || {};
  14 + root.simple['hotkeys'] = factory(jQuery,SimpleModule);
  15 + }
  16 +}(this, function ($, SimpleModule) {
  17 +
  18 +var Hotkeys, hotkeys,
  19 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  20 + hasProp = {}.hasOwnProperty;
  21 +
  22 +Hotkeys = (function(superClass) {
  23 + extend(Hotkeys, superClass);
  24 +
  25 + function Hotkeys() {
  26 + return Hotkeys.__super__.constructor.apply(this, arguments);
  27 + }
  28 +
  29 + Hotkeys.count = 0;
  30 +
  31 + Hotkeys.keyNameMap = {
  32 + 8: "Backspace",
  33 + 9: "Tab",
  34 + 13: "Enter",
  35 + 16: "Shift",
  36 + 17: "Control",
  37 + 18: "Alt",
  38 + 19: "Pause",
  39 + 20: "CapsLock",
  40 + 27: "Esc",
  41 + 32: "Spacebar",
  42 + 33: "PageUp",
  43 + 34: "PageDown",
  44 + 35: "End",
  45 + 36: "Home",
  46 + 37: "Left",
  47 + 38: "Up",
  48 + 39: "Right",
  49 + 40: "Down",
  50 + 45: "Insert",
  51 + 46: "Del",
  52 + 91: "Meta",
  53 + 93: "Meta",
  54 + 48: "0",
  55 + 49: "1",
  56 + 50: "2",
  57 + 51: "3",
  58 + 52: "4",
  59 + 53: "5",
  60 + 54: "6",
  61 + 55: "7",
  62 + 56: "8",
  63 + 57: "9",
  64 + 65: "A",
  65 + 66: "B",
  66 + 67: "C",
  67 + 68: "D",
  68 + 69: "E",
  69 + 70: "F",
  70 + 71: "G",
  71 + 72: "H",
  72 + 73: "I",
  73 + 74: "J",
  74 + 75: "K",
  75 + 76: "L",
  76 + 77: "M",
  77 + 78: "N",
  78 + 79: "O",
  79 + 80: "P",
  80 + 81: "Q",
  81 + 82: "R",
  82 + 83: "S",
  83 + 84: "T",
  84 + 85: "U",
  85 + 86: "V",
  86 + 87: "W",
  87 + 88: "X",
  88 + 89: "Y",
  89 + 90: "Z",
  90 + 96: "0",
  91 + 97: "1",
  92 + 98: "2",
  93 + 99: "3",
  94 + 100: "4",
  95 + 101: "5",
  96 + 102: "6",
  97 + 103: "7",
  98 + 104: "8",
  99 + 105: "9",
  100 + 106: "Multiply",
  101 + 107: "Add",
  102 + 109: "Subtract",
  103 + 110: "Decimal",
  104 + 111: "Divide",
  105 + 112: "F1",
  106 + 113: "F2",
  107 + 114: "F3",
  108 + 115: "F4",
  109 + 116: "F5",
  110 + 117: "F6",
  111 + 118: "F7",
  112 + 119: "F8",
  113 + 120: "F9",
  114 + 121: "F10",
  115 + 122: "F11",
  116 + 123: "F12",
  117 + 124: "F13",
  118 + 125: "F14",
  119 + 126: "F15",
  120 + 127: "F16",
  121 + 128: "F17",
  122 + 129: "F18",
  123 + 130: "F19",
  124 + 131: "F20",
  125 + 132: "F21",
  126 + 133: "F22",
  127 + 134: "F23",
  128 + 135: "F24",
  129 + 59: ";",
  130 + 61: "=",
  131 + 186: ";",
  132 + 187: "=",
  133 + 188: ",",
  134 + 190: ".",
  135 + 191: "/",
  136 + 192: "`",
  137 + 219: "[",
  138 + 220: "\\",
  139 + 221: "]",
  140 + 222: "'"
  141 + };
  142 +
  143 + Hotkeys.aliases = {
  144 + "escape": "esc",
  145 + "delete": "del",
  146 + "return": "enter",
  147 + "ctrl": "control",
  148 + "space": "spacebar",
  149 + "ins": "insert",
  150 + "cmd": "meta",
  151 + "command": "meta",
  152 + "wins": "meta",
  153 + "windows": "meta"
  154 + };
  155 +
  156 + Hotkeys.normalize = function(shortcut) {
  157 + var i, j, key, keyname, keys, len;
  158 + keys = shortcut.toLowerCase().replace(/\s+/gi, "").split("+");
  159 + for (i = j = 0, len = keys.length; j < len; i = ++j) {
  160 + key = keys[i];
  161 + keys[i] = this.aliases[key] || key;
  162 + }
  163 + keyname = keys.pop();
  164 + keys.sort().push(keyname);
  165 + return keys.join("_");
  166 + };
  167 +
  168 + Hotkeys.prototype.opts = {
  169 + el: document
  170 + };
  171 +
  172 + Hotkeys.prototype._init = function() {
  173 + this.id = ++this.constructor.count;
  174 + this._map = {};
  175 + this._delegate = typeof this.opts.el === "string" ? document : this.opts.el;
  176 + return $(this._delegate).on("keydown.simple-hotkeys-" + this.id, this.opts.el, (function(_this) {
  177 + return function(e) {
  178 + var ref;
  179 + return (ref = _this._getHander(e)) != null ? ref.call(_this, e) : void 0;
  180 + };
  181 + })(this));
  182 + };
  183 +
  184 + Hotkeys.prototype._getHander = function(e) {
  185 + var keyname, shortcut;
  186 + if (!(keyname = this.constructor.keyNameMap[e.which])) {
  187 + return;
  188 + }
  189 + shortcut = "";
  190 + if (e.altKey) {
  191 + shortcut += "alt_";
  192 + }
  193 + if (e.ctrlKey) {
  194 + shortcut += "control_";
  195 + }
  196 + if (e.metaKey) {
  197 + shortcut += "meta_";
  198 + }
  199 + if (e.shiftKey) {
  200 + shortcut += "shift_";
  201 + }
  202 + shortcut += keyname.toLowerCase();
  203 + return this._map[shortcut];
  204 + };
  205 +
  206 + Hotkeys.prototype.respondTo = function(subject) {
  207 + if (typeof subject === 'string') {
  208 + return this._map[this.constructor.normalize(subject)] != null;
  209 + } else {
  210 + return this._getHander(subject) != null;
  211 + }
  212 + };
  213 +
  214 + Hotkeys.prototype.add = function(shortcut, handler) {
  215 + this._map[this.constructor.normalize(shortcut)] = handler;
  216 + return this;
  217 + };
  218 +
  219 + Hotkeys.prototype.remove = function(shortcut) {
  220 + delete this._map[this.constructor.normalize(shortcut)];
  221 + return this;
  222 + };
  223 +
  224 + Hotkeys.prototype.destroy = function() {
  225 + $(this._delegate).off(".simple-hotkeys-" + this.id);
  226 + this._map = {};
  227 + return this;
  228 + };
  229 +
  230 + return Hotkeys;
  231 +
  232 +})(SimpleModule);
  233 +
  234 +hotkeys = function(opts) {
  235 + return new Hotkeys(opts);
  236 +};
  237 +
  238 +return hotkeys;
  239 +
  240 +}));
  241 +
  1 +(function (root, factory) {
  2 + if (typeof define === 'function' && define.amd) {
  3 + // AMD. Register as an anonymous module unless amdModuleId is set
  4 + define('simple-module', ["jquery"], function (a0) {
  5 + return (root['Module'] = factory(a0));
  6 + });
  7 + } else if (typeof exports === 'object') {
  8 + // Node. Does not work with strict CommonJS, but
  9 + // only CommonJS-like environments that support module.exports,
  10 + // like Node.
  11 + module.exports = factory(require("jquery"));
  12 + } else {
  13 + root['SimpleModule'] = factory(jQuery);
  14 + }
  15 +}(this, function ($) {
  16 +
  17 +var Module,
  18 + slice = [].slice;
  19 +
  20 +Module = (function() {
  21 + Module.extend = function(obj) {
  22 + var key, ref, val;
  23 + if (!((obj != null) && typeof obj === 'object')) {
  24 + return;
  25 + }
  26 + for (key in obj) {
  27 + val = obj[key];
  28 + if (key !== 'included' && key !== 'extended') {
  29 + this[key] = val;
  30 + }
  31 + }
  32 + return (ref = obj.extended) != null ? ref.call(this) : void 0;
  33 + };
  34 +
  35 + Module.include = function(obj) {
  36 + var key, ref, val;
  37 + if (!((obj != null) && typeof obj === 'object')) {
  38 + return;
  39 + }
  40 + for (key in obj) {
  41 + val = obj[key];
  42 + if (key !== 'included' && key !== 'extended') {
  43 + this.prototype[key] = val;
  44 + }
  45 + }
  46 + return (ref = obj.included) != null ? ref.call(this) : void 0;
  47 + };
  48 +
  49 + Module.connect = function(cls) {
  50 + if (typeof cls !== 'function') {
  51 + return;
  52 + }
  53 + if (!cls.pluginName) {
  54 + throw new Error('Module.connect: cannot connect plugin without pluginName');
  55 + return;
  56 + }
  57 + cls.prototype._connected = true;
  58 + if (!this._connectedClasses) {
  59 + this._connectedClasses = [];
  60 + }
  61 + this._connectedClasses.push(cls);
  62 + if (cls.pluginName) {
  63 + return this[cls.pluginName] = cls;
  64 + }
  65 + };
  66 +
  67 + Module.prototype.opts = {};
  68 +
  69 + function Module(opts) {
  70 + var base, cls, i, instance, instances, len, name;
  71 + this.opts = $.extend({}, this.opts, opts);
  72 + (base = this.constructor)._connectedClasses || (base._connectedClasses = []);
  73 + instances = (function() {
  74 + var i, len, ref, results;
  75 + ref = this.constructor._connectedClasses;
  76 + results = [];
  77 + for (i = 0, len = ref.length; i < len; i++) {
  78 + cls = ref[i];
  79 + name = cls.pluginName.charAt(0).toLowerCase() + cls.pluginName.slice(1);
  80 + if (cls.prototype._connected) {
  81 + cls.prototype._module = this;
  82 + }
  83 + results.push(this[name] = new cls());
  84 + }
  85 + return results;
  86 + }).call(this);
  87 + if (this._connected) {
  88 + this.opts = $.extend({}, this.opts, this._module.opts);
  89 + } else {
  90 + this._init();
  91 + for (i = 0, len = instances.length; i < len; i++) {
  92 + instance = instances[i];
  93 + if (typeof instance._init === "function") {
  94 + instance._init();
  95 + }
  96 + }
  97 + }
  98 + this.trigger('initialized');
  99 + }
  100 +
  101 + Module.prototype._init = function() {};
  102 +
  103 + Module.prototype.on = function() {
  104 + var args, ref;
  105 + args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
  106 + (ref = $(this)).on.apply(ref, args);
  107 + return this;
  108 + };
  109 +
  110 + Module.prototype.one = function() {
  111 + var args, ref;
  112 + args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
  113 + (ref = $(this)).one.apply(ref, args);
  114 + return this;
  115 + };
  116 +
  117 + Module.prototype.off = function() {
  118 + var args, ref;
  119 + args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
  120 + (ref = $(this)).off.apply(ref, args);
  121 + return this;
  122 + };
  123 +
  124 + Module.prototype.trigger = function() {
  125 + var args, ref;
  126 + args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
  127 + (ref = $(this)).trigger.apply(ref, args);
  128 + return this;
  129 + };
  130 +
  131 + Module.prototype.triggerHandler = function() {
  132 + var args, ref;
  133 + args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
  134 + return (ref = $(this)).triggerHandler.apply(ref, args);
  135 + };
  136 +
  137 + Module.prototype._t = function() {
  138 + var args, ref;
  139 + args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
  140 + return (ref = this.constructor)._t.apply(ref, args);
  141 + };
  142 +
  143 + Module._t = function() {
  144 + var args, key, ref, result;
  145 + key = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
  146 + result = ((ref = this.i18n[this.locale]) != null ? ref[key] : void 0) || '';
  147 + if (!(args.length > 0)) {
  148 + return result;
  149 + }
  150 + result = result.replace(/([^%]|^)%(?:(\d+)\$)?s/g, function(p0, p, position) {
  151 + if (position) {
  152 + return p + args[parseInt(position) - 1];
  153 + } else {
  154 + return p + args.shift();
  155 + }
  156 + });
  157 + return result.replace(/%%s/g, '%s');
  158 + };
  159 +
  160 + Module.i18n = {
  161 + 'zh-CN': {}
  162 + };
  163 +
  164 + Module.locale = 'zh-CN';
  165 +
  166 + return Module;
  167 +
  168 +})();
  169 +
  170 +return Module;
  171 +
  172 +}));
此 diff 太大无法显示。
  1 +(function (root, factory) {
  2 + if (typeof define === 'function' && define.amd) {
  3 + // AMD. Register as an anonymous module unless amdModuleId is set
  4 + define('simple-uploader', ["jquery","simple-module"], function ($, SimpleModule) {
  5 + return (root['uploader'] = factory($, SimpleModule));
  6 + });
  7 + } else if (typeof exports === 'object') {
  8 + // Node. Does not work with strict CommonJS, but
  9 + // only CommonJS-like environments that support module.exports,
  10 + // like Node.
  11 + module.exports = factory(require("jquery"),require("simple-module"));
  12 + } else {
  13 + root.simple = root.simple || {};
  14 + root.simple['uploader'] = factory(jQuery,SimpleModule);
  15 + }
  16 +}(this, function ($, SimpleModule) {
  17 +
  18 +var Uploader, uploader,
  19 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  20 + hasProp = {}.hasOwnProperty;
  21 +
  22 +Uploader = (function(superClass) {
  23 + extend(Uploader, superClass);
  24 +
  25 + function Uploader() {
  26 + return Uploader.__super__.constructor.apply(this, arguments);
  27 + }
  28 +
  29 + Uploader.count = 0;
  30 +
  31 + Uploader.prototype.opts = {
  32 + url: '',
  33 + params: null,
  34 + fileKey: 'upload_file',
  35 + connectionCount: 3
  36 + };
  37 +
  38 + Uploader.prototype._init = function() {
  39 + this.files = [];
  40 + this.queue = [];
  41 + this.id = ++Uploader.count;
  42 + this.on('uploadcomplete', (function(_this) {
  43 + return function(e, file) {
  44 + _this.files.splice($.inArray(file, _this.files), 1);
  45 + if (_this.queue.length > 0 && _this.files.length < _this.opts.connectionCount) {
  46 + return _this.upload(_this.queue.shift());
  47 + } else if (_this.files.length === 0) {
  48 + return _this.uploading = false;
  49 + }
  50 + };
  51 + })(this));
  52 + return $(window).on('beforeunload.uploader-' + this.id, (function(_this) {
  53 + return function(e) {
  54 + if (!_this.uploading) {
  55 + return;
  56 + }
  57 + e.originalEvent.returnValue = _this._t('leaveConfirm');
  58 + return _this._t('leaveConfirm');
  59 + };
  60 + })(this));
  61 + };
  62 +
  63 + Uploader.prototype.generateId = (function() {
  64 + var id;
  65 + id = 0;
  66 + return function() {
  67 + return id += 1;
  68 + };
  69 + })();
  70 +
  71 + Uploader.prototype.upload = function(file, opts) {
  72 + var f, i, key, len;
  73 + if (opts == null) {
  74 + opts = {};
  75 + }
  76 + if (file == null) {
  77 + return;
  78 + }
  79 + if ($.isArray(file) || file instanceof FileList) {
  80 + for (i = 0, len = file.length; i < len; i++) {
  81 + f = file[i];
  82 + this.upload(f, opts);
  83 + }
  84 + } else if ($(file).is('input:file')) {
  85 + key = $(file).attr('name');
  86 + if (key) {
  87 + opts.fileKey = key;
  88 + }
  89 + this.upload($.makeArray($(file)[0].files), opts);
  90 + } else if (!file.id || !file.obj) {
  91 + file = this.getFile(file);
  92 + }
  93 + if (!(file && file.obj)) {
  94 + return;
  95 + }
  96 + $.extend(file, opts);
  97 + if (this.files.length >= this.opts.connectionCount) {
  98 + this.queue.push(file);
  99 + return;
  100 + }
  101 + if (this.triggerHandler('beforeupload', [file]) === false) {
  102 + return;
  103 + }
  104 + this.files.push(file);
  105 + this._xhrUpload(file);
  106 + return this.uploading = true;
  107 + };
  108 +
  109 + Uploader.prototype.getFile = function(fileObj) {
  110 + var name, ref, ref1;
  111 + if (fileObj instanceof window.File || fileObj instanceof window.Blob) {
  112 + name = (ref = fileObj.fileName) != null ? ref : fileObj.name;
  113 + } else {
  114 + return null;
  115 + }
  116 + return {
  117 + id: this.generateId(),
  118 + url: this.opts.url,
  119 + params: this.opts.params,
  120 + fileKey: this.opts.fileKey,
  121 + name: name,
  122 + size: (ref1 = fileObj.fileSize) != null ? ref1 : fileObj.size,
  123 + ext: name ? name.split('.').pop().toLowerCase() : '',
  124 + obj: fileObj
  125 + };
  126 + };
  127 +
  128 + Uploader.prototype._xhrUpload = function(file) {
  129 + var formData, k, ref, v;
  130 + formData = new FormData();
  131 + formData.append(file.fileKey, file.obj);
  132 + formData.append("original_filename", file.name);
  133 + if (file.params) {
  134 + ref = file.params;
  135 + for (k in ref) {
  136 + v = ref[k];
  137 + formData.append(k, v);
  138 + }
  139 + }
  140 + return file.xhr = $.ajax({
  141 + url: file.url,
  142 + data: formData,
  143 + processData: false,
  144 + contentType: false,
  145 + type: 'POST',
  146 + headers: {
  147 + 'X-File-Name': encodeURIComponent(file.name)
  148 + },
  149 + xhr: function() {
  150 + var req;
  151 + req = $.ajaxSettings.xhr();
  152 + if (req) {
  153 + req.upload.onprogress = (function(_this) {
  154 + return function(e) {
  155 + return _this.progress(e);
  156 + };
  157 + })(this);
  158 + }
  159 + return req;
  160 + },
  161 + progress: (function(_this) {
  162 + return function(e) {
  163 + if (!e.lengthComputable) {
  164 + return;
  165 + }
  166 + return _this.trigger('uploadprogress', [file, e.loaded, e.total]);
  167 + };
  168 + })(this),
  169 + error: (function(_this) {
  170 + return function(xhr, status, err) {
  171 + return _this.trigger('uploaderror', [file, xhr, status]);
  172 + };
  173 + })(this),
  174 + success: (function(_this) {
  175 + return function(result) {
  176 + _this.trigger('uploadprogress', [file, file.size, file.size]);
  177 + _this.trigger('uploadsuccess', [file, result]);
  178 + return $(document).trigger('uploadsuccess', [file, result, _this]);
  179 + };
  180 + })(this),
  181 + complete: (function(_this) {
  182 + return function(xhr, status) {
  183 + return _this.trigger('uploadcomplete', [file, xhr.responseText]);
  184 + };
  185 + })(this)
  186 + });
  187 + };
  188 +
  189 + Uploader.prototype.cancel = function(file) {
  190 + var f, i, len, ref;
  191 + if (!file.id) {
  192 + ref = this.files;
  193 + for (i = 0, len = ref.length; i < len; i++) {
  194 + f = ref[i];
  195 + if (f.id === file * 1) {
  196 + file = f;
  197 + break;
  198 + }
  199 + }
  200 + }
  201 + this.trigger('uploadcancel', [file]);
  202 + if (file.xhr) {
  203 + file.xhr.abort();
  204 + }
  205 + return file.xhr = null;
  206 + };
  207 +
  208 + Uploader.prototype.readImageFile = function(fileObj, callback) {
  209 + var fileReader, img;
  210 + if (!$.isFunction(callback)) {
  211 + return;
  212 + }
  213 + img = new Image();
  214 + img.onload = function() {
  215 + return callback(img);
  216 + };
  217 + img.onerror = function() {
  218 + return callback();
  219 + };
  220 + if (window.FileReader && FileReader.prototype.readAsDataURL && /^image/.test(fileObj.type)) {
  221 + fileReader = new FileReader();
  222 + fileReader.onload = function(e) {
  223 + return img.src = e.target.result;
  224 + };
  225 + return fileReader.readAsDataURL(fileObj);
  226 + } else {
  227 + return callback();
  228 + }
  229 + };
  230 +
  231 + Uploader.prototype.destroy = function() {
  232 + var file, i, len, ref;
  233 + this.queue.length = 0;
  234 + ref = this.files;
  235 + for (i = 0, len = ref.length; i < len; i++) {
  236 + file = ref[i];
  237 + this.cancel(file);
  238 + }
  239 + $(window).off('.uploader-' + this.id);
  240 + return $(document).off('.uploader-' + this.id);
  241 + };
  242 +
  243 + Uploader.i18n = {
  244 + 'zh-CN': {
  245 + leaveConfirm: '正在上传文件,如果离开上传会自动取消'
  246 + }
  247 + };
  248 +
  249 + Uploader.locale = 'zh-CN';
  250 +
  251 + return Uploader;
  252 +
  253 +})(SimpleModule);
  254 +
  255 +uploader = function(opts) {
  256 + return new Uploader(opts);
  257 +};
  258 +
  259 +return uploader;
  260 +
  261 +}));
  1 +<?php
  2 +
  3 +namespace app\admin\behavior;
  4 +
  5 +class AdminLog
  6 +{
  7 + public function run(&$params)
  8 + {
  9 + //只记录POST请求的日志
  10 + if (request()->isPost() && config('fastadmin.auto_record_log')) {
  11 + \app\admin\model\AdminLog::record();
  12 + }
  13 + }
  14 +}
  1 +<?php
  2 +
  3 +namespace app\admin\command;
  4 +
  5 +use think\addons\AddonException;
  6 +use think\addons\Service;
  7 +use think\Config;
  8 +use think\console\Command;
  9 +use think\console\Input;
  10 +use think\console\input\Option;
  11 +use think\console\Output;
  12 +use think\Db;
  13 +use think\Exception;
  14 +use think\exception\PDOException;
  15 +
  16 +class Addon extends Command
  17 +{
  18 +
  19 + protected function configure()
  20 + {
  21 + $this
  22 + ->setName('addon')
  23 + ->addOption('name', 'a', Option::VALUE_REQUIRED, 'addon name', null)
  24 + ->addOption('action', 'c', Option::VALUE_REQUIRED, 'action(create/enable/disable/uninstall/refresh/package/move)', 'create')
  25 + ->addOption('force', 'f', Option::VALUE_OPTIONAL, 'force override', null)
  26 + ->addOption('release', 'r', Option::VALUE_OPTIONAL, 'addon release version', null)
  27 + ->addOption('uid', 'u', Option::VALUE_OPTIONAL, 'fastadmin uid', null)
  28 + ->addOption('token', 't', Option::VALUE_OPTIONAL, 'fastadmin token', null)
  29 + ->addOption('domain', 'd', Option::VALUE_OPTIONAL, 'domain', null)
  30 + ->addOption('local', 'l', Option::VALUE_OPTIONAL, 'local package', null)
  31 + ->setDescription('Addon manager');
  32 + }
  33 +
  34 + protected function execute(Input $input, Output $output)
  35 + {
  36 + $name = $input->getOption('name') ?: '';
  37 + $action = $input->getOption('action') ?: '';
  38 + if (stripos($name, 'addons' . DS) !== false) {
  39 + $name = explode(DS, $name)[1];
  40 + }
  41 + //强制覆盖
  42 + $force = $input->getOption('force');
  43 + //版本
  44 + $release = $input->getOption('release') ?: '';
  45 + //uid
  46 + $uid = $input->getOption('uid') ?: '';
  47 + //token
  48 + $token = $input->getOption('token') ?: '';
  49 +
  50 + include dirname(__DIR__) . DS . 'common.php';
  51 +
  52 + if (!$name && !in_array($action, ['refresh'])) {
  53 + throw new Exception('Addon name could not be empty');
  54 + }
  55 + if (!$action || !in_array($action, ['create', 'disable', 'enable', 'install', 'uninstall', 'refresh', 'upgrade', 'package', 'move'])) {
  56 + throw new Exception('Please input correct action name');
  57 + }
  58 +
  59 + // 查询一次SQL,判断连接是否正常
  60 + Db::execute("SELECT 1");
  61 +
  62 + $addonDir = ADDON_PATH . $name . DS;
  63 + switch ($action) {
  64 + case 'create':
  65 + //非覆盖模式时如果存在则报错
  66 + if (is_dir($addonDir) && !$force) {
  67 + throw new Exception("addon already exists!\nIf you need to create again, use the parameter --force=true ");
  68 + }
  69 + //如果存在先移除
  70 + if (is_dir($addonDir)) {
  71 + rmdirs($addonDir);
  72 + }
  73 + mkdir($addonDir, 0755, true);
  74 + mkdir($addonDir . DS . 'controller', 0755, true);
  75 + $menuList = \app\common\library\Menu::export($name);
  76 + $createMenu = $this->getCreateMenu($menuList);
  77 + $prefix = Config::get('database.prefix');
  78 + $createTableSql = '';
  79 + try {
  80 + $result = Db::query("SHOW CREATE TABLE `" . $prefix . $name . "`;");
  81 + if (isset($result[0]) && isset($result[0]['Create Table'])) {
  82 + $createTableSql = $result[0]['Create Table'];
  83 + }
  84 + } catch (PDOException $e) {
  85 +
  86 + }
  87 +
  88 + $data = [
  89 + 'name' => $name,
  90 + 'addon' => $name,
  91 + 'addonClassName' => ucfirst($name),
  92 + 'addonInstallMenu' => $createMenu ? "\$menu = " . var_export_short($createMenu) . ";\n\tMenu::create(\$menu);" : '',
  93 + 'addonUninstallMenu' => $menuList ? 'Menu::delete("' . $name . '");' : '',
  94 + 'addonEnableMenu' => $menuList ? 'Menu::enable("' . $name . '");' : '',
  95 + 'addonDisableMenu' => $menuList ? 'Menu::disable("' . $name . '");' : '',
  96 + ];
  97 + $this->writeToFile("addon", $data, $addonDir . ucfirst($name) . '.php');
  98 + $this->writeToFile("config", $data, $addonDir . 'config.php');
  99 + $this->writeToFile("info", $data, $addonDir . 'info.ini');
  100 + $this->writeToFile("controller", $data, $addonDir . 'controller' . DS . 'Index.php');
  101 + if ($createTableSql) {
  102 + $createTableSql = str_replace("`" . $prefix, '`__PREFIX__', $createTableSql);
  103 + file_put_contents($addonDir . 'install.sql', $createTableSql);
  104 + }
  105 +
  106 + $output->info("Create Successed!");
  107 + break;
  108 + case 'disable':
  109 + case 'enable':
  110 + try {
  111 + //调用启用、禁用的方法
  112 + Service::$action($name, 0);
  113 + } catch (AddonException $e) {
  114 + if ($e->getCode() != -3) {
  115 + throw new Exception($e->getMessage());
  116 + }
  117 + if (!$force) {
  118 + //如果有冲突文件则提醒
  119 + $data = $e->getData();
  120 + foreach ($data['conflictlist'] as $k => $v) {
  121 + $output->warning($v);
  122 + }
  123 + $output->info("Are you sure you want to " . ($action == 'enable' ? 'override' : 'delete') . " all those files? Type 'yes' to continue: ");
  124 + $line = fgets(defined('STDIN') ? STDIN : fopen('php://stdin', 'r'));
  125 + if (trim($line) != 'yes') {
  126 + throw new Exception("Operation is aborted!");
  127 + }
  128 + }
  129 + //调用启用、禁用的方法
  130 + Service::$action($name, 1);
  131 + } catch (Exception $e) {
  132 + throw new Exception($e->getMessage());
  133 + }
  134 + $output->info(ucfirst($action) . " Successed!");
  135 + break;
  136 + case 'uninstall':
  137 + //非覆盖模式时如果存在则报错
  138 + if (!$force) {
  139 + throw new Exception("If you need to uninstall addon, use the parameter --force=true ");
  140 + }
  141 + try {
  142 + Service::uninstall($name, 0);
  143 + } catch (AddonException $e) {
  144 + if ($e->getCode() != -3) {
  145 + throw new Exception($e->getMessage());
  146 + }
  147 + if (!$force) {
  148 + //如果有冲突文件则提醒
  149 + $data = $e->getData();
  150 + foreach ($data['conflictlist'] as $k => $v) {
  151 + $output->warning($v);
  152 + }
  153 + $output->info("Are you sure you want to delete all those files? Type 'yes' to continue: ");
  154 + $line = fgets(defined('STDIN') ? STDIN : fopen('php://stdin', 'r'));
  155 + if (trim($line) != 'yes') {
  156 + throw new Exception("Operation is aborted!");
  157 + }
  158 + }
  159 + Service::uninstall($name, 1);
  160 + } catch (Exception $e) {
  161 + throw new Exception($e->getMessage());
  162 + }
  163 +
  164 + $output->info("Uninstall Successed!");
  165 + break;
  166 + case 'refresh':
  167 + Service::refresh();
  168 + $output->info("Refresh Successed!");
  169 + break;
  170 + case 'package':
  171 + $infoFile = $addonDir . 'info.ini';
  172 + if (!is_file($infoFile)) {
  173 + throw new Exception(__('Addon info file was not found'));
  174 + }
  175 +
  176 + $info = get_addon_info($name);
  177 + if (!$info) {
  178 + throw new Exception(__('Addon info file data incorrect'));
  179 + }
  180 + $infoname = isset($info['name']) ? $info['name'] : '';
  181 + if (!$infoname || !preg_match("/^[a-z]+$/i", $infoname) || $infoname != $name) {
  182 + throw new Exception(__('Addon info name incorrect'));
  183 + }
  184 +
  185 + $infoversion = isset($info['version']) ? $info['version'] : '';
  186 + if (!$infoversion || !preg_match("/^\d+\.\d+\.\d+$/i", $infoversion)) {
  187 + throw new Exception(__('Addon info version incorrect'));
  188 + }
  189 +
  190 + $addonTmpDir = RUNTIME_PATH . 'addons' . DS;
  191 + if (!is_dir($addonTmpDir)) {
  192 + @mkdir($addonTmpDir, 0755, true);
  193 + }
  194 + $addonFile = $addonTmpDir . $infoname . '-' . $infoversion . '.zip';
  195 + if (!class_exists('ZipArchive')) {
  196 + throw new Exception(__('ZinArchive not install'));
  197 + }
  198 + $zip = new \ZipArchive;
  199 + $zip->open($addonFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
  200 +
  201 + $files = new \RecursiveIteratorIterator(
  202 + new \RecursiveDirectoryIterator($addonDir), \RecursiveIteratorIterator::LEAVES_ONLY
  203 + );
  204 +
  205 + foreach ($files as $name => $file) {
  206 + if (!$file->isDir()) {
  207 + $filePath = $file->getRealPath();
  208 + $relativePath = str_replace(DS, '/', substr($filePath, strlen($addonDir)));
  209 + if (!in_array($file->getFilename(), ['.git', '.DS_Store', 'Thumbs.db'])) {
  210 + $zip->addFile($filePath, $relativePath);
  211 + }
  212 + }
  213 + }
  214 + $zip->close();
  215 + $output->info("Package Successed!");
  216 + break;
  217 + case 'move':
  218 + $movePath = [
  219 + 'adminOnlySelfDir' => ['admin/behavior', 'admin/controller', 'admin/library', 'admin/model', 'admin/validate', 'admin/view'],
  220 + 'adminAllSubDir' => ['admin/lang'],
  221 + 'publicDir' => ['public/assets/addons', 'public/assets/js/backend']
  222 + ];
  223 + $paths = [];
  224 + $appPath = str_replace('/', DS, APP_PATH);
  225 + $rootPath = str_replace('/', DS, ROOT_PATH);
  226 + foreach ($movePath as $k => $items) {
  227 + switch ($k) {
  228 + case 'adminOnlySelfDir':
  229 + foreach ($items as $v) {
  230 + $v = str_replace('/', DS, $v);
  231 + $oldPath = $appPath . $v . DS . $name;
  232 + $newPath = $rootPath . "addons" . DS . $name . DS . "application" . DS . $v . DS . $name;
  233 + $paths[$oldPath] = $newPath;
  234 + }
  235 + break;
  236 + case 'adminAllSubDir':
  237 + foreach ($items as $v) {
  238 + $v = str_replace('/', DS, $v);
  239 + $vPath = $appPath . $v;
  240 + $list = scandir($vPath);
  241 + foreach ($list as $_v) {
  242 + if (!in_array($_v, ['.', '..']) && is_dir($vPath . DS . $_v)) {
  243 + $oldPath = $appPath . $v . DS . $_v . DS . $name;
  244 + $newPath = $rootPath . "addons" . DS . $name . DS . "application" . DS . $v . DS . $_v . DS . $name;
  245 + $paths[$oldPath] = $newPath;
  246 + }
  247 + }
  248 + }
  249 + break;
  250 + case 'publicDir':
  251 + foreach ($items as $v) {
  252 + $v = str_replace('/', DS, $v);
  253 + $oldPath = $rootPath . $v . DS . $name;
  254 + $newPath = $rootPath . 'addons' . DS . $name . DS . $v . DS . $name;
  255 + $paths[$oldPath] = $newPath;
  256 + }
  257 + break;
  258 + }
  259 + }
  260 + foreach ($paths as $oldPath => $newPath) {
  261 + if (is_dir($oldPath)) {
  262 + if ($force) {
  263 + if (is_dir($newPath)) {
  264 + $list = scandir($newPath);
  265 + foreach ($list as $_v) {
  266 + if (!in_array($_v, ['.', '..'])) {
  267 + $file = $newPath . DS . $_v;
  268 + @chmod($file, 0777);
  269 + @unlink($file);
  270 + }
  271 + }
  272 + @rmdir($newPath);
  273 + }
  274 + }
  275 + copydirs($oldPath, $newPath);
  276 + }
  277 + }
  278 + break;
  279 + default:
  280 + break;
  281 + }
  282 + }
  283 +
  284 + /**
  285 + * 获取创建菜单的数组
  286 + * @param array $menu
  287 + * @return array
  288 + */
  289 + protected function getCreateMenu($menu)
  290 + {
  291 + $result = [];
  292 + foreach ($menu as $k => & $v) {
  293 + $arr = [
  294 + 'name' => $v['name'],
  295 + 'title' => $v['title'],
  296 + ];
  297 + if ($v['icon'] != 'fa fa-circle-o') {
  298 + $arr['icon'] = $v['icon'];
  299 + }
  300 + if ($v['ismenu']) {
  301 + $arr['ismenu'] = $v['ismenu'];
  302 + }
  303 + if (isset($v['childlist']) && $v['childlist']) {
  304 + $arr['sublist'] = $this->getCreateMenu($v['childlist']);
  305 + }
  306 + $result[] = $arr;
  307 + }
  308 + return $result;
  309 + }
  310 +
  311 + /**
  312 + * 写入到文件
  313 + * @param string $name
  314 + * @param array $data
  315 + * @param string $pathname
  316 + * @return mixed
  317 + */
  318 + protected function writeToFile($name, $data, $pathname)
  319 + {
  320 + $search = $replace = [];
  321 + foreach ($data as $k => $v) {
  322 + $search[] = "{%{$k}%}";
  323 + $replace[] = $v;
  324 + }
  325 + $stub = file_get_contents($this->getStub($name));
  326 + $content = str_replace($search, $replace, $stub);
  327 +
  328 + if (!is_dir(dirname($pathname))) {
  329 + mkdir(strtolower(dirname($pathname)), 0755, true);
  330 + }
  331 + return file_put_contents($pathname, $content);
  332 + }
  333 +
  334 + /**
  335 + * 获取基础模板
  336 + * @param string $name
  337 + * @return string
  338 + */
  339 + protected function getStub($name)
  340 + {
  341 + return __DIR__ . '/Addon/stubs/' . $name . '.stub';
  342 + }
  343 +
  344 +}
  1 +<?php
  2 +
  3 +namespace addons\{%name%};
  4 +
  5 +use app\common\library\Menu;
  6 +use think\Addons;
  7 +
  8 +/**
  9 + * 插件
  10 + */
  11 +class {%addonClassName%} extends Addons
  12 +{
  13 +
  14 + /**
  15 + * 插件安装方法
  16 + * @return bool
  17 + */
  18 + public function install()
  19 + {
  20 + {%addonInstallMenu%}
  21 + return true;
  22 + }
  23 +
  24 + /**
  25 + * 插件卸载方法
  26 + * @return bool
  27 + */
  28 + public function uninstall()
  29 + {
  30 + {%addonUninstallMenu%}
  31 + return true;
  32 + }
  33 +
  34 + /**
  35 + * 插件启用方法
  36 + * @return bool
  37 + */
  38 + public function enable()
  39 + {
  40 + {%addonEnableMenu%}
  41 + return true;
  42 + }
  43 +
  44 + /**
  45 + * 插件禁用方法
  46 + * @return bool
  47 + */
  48 + public function disable()
  49 + {
  50 + {%addonDisableMenu%}
  51 + return true;
  52 + }
  53 +
  54 +}
  1 +<?php
  2 +
  3 +return [
  4 + [
  5 + //配置唯一标识
  6 + 'name' => 'usernmae',
  7 + //显示的标题
  8 + 'title' => '用户名',
  9 + //类型
  10 + 'type' => 'string',
  11 + //分组
  12 + 'group' => '',
  13 + //动态显示
  14 + 'visible' => '',
  15 + //数据字典
  16 + 'content' => [
  17 + ],
  18 + //值
  19 + 'value' => '',
  20 + //验证规则
  21 + 'rule' => 'required',
  22 + //错误消息
  23 + 'msg' => '',
  24 + //提示消息
  25 + 'tip' => '',
  26 + //成功消息
  27 + 'ok' => '',
  28 + //扩展信息
  29 + 'extend' => ''
  30 + ],
  31 + [
  32 + 'name' => 'password',
  33 + 'title' => '密码',
  34 + 'type' => 'string',
  35 + 'content' => [
  36 + ],
  37 + 'value' => '',
  38 + 'rule' => 'required',
  39 + 'msg' => '',
  40 + 'tip' => '',
  41 + 'ok' => '',
  42 + 'extend' => ''
  43 + ],
  44 +];
  1 +<?php
  2 +
  3 +namespace addons\{%addon%}\controller;
  4 +
  5 +use think\addons\Controller;
  6 +
  7 +class Index extends Controller
  8 +{
  9 +
  10 + public function index()
  11 + {
  12 + $this->error("当前插件暂无前台页面");
  13 + }
  14 +
  15 +}
  1 +name = {%name%}
  2 +title = 插件名称{%name%}
  3 +intro = 插件介绍
  4 +author = yourname
  5 +website = https://www.fastadmin.net
  6 +version = 1.0.0
  7 +state = 1