作者 黄超

第一次提交

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

要显示太多修改。

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

  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 +.idea/
  2 +.git/
  3 +/runtime/*
  4 +/application/database.php
  5 +/application/database_b.php
  6 +/public/uploads/*
  7 +/public/.user.ini
  8 +/nbproject/
  9 +/public/.htaccess
  10 +/public/nginx.htaccess
  11 +composer.lock
  12 +*.log
  13 +*.css.map
  14 +!.gitkeep
  15 +.env
  16 +.svn
  17 +.vscode
  18 +node_modules
  19 +/public/xj/qrcode/*
  1 +<!doctype html>
  2 +<html>
  3 +<head>
  4 +<meta charset="utf-8">
  5 +<meta http-equiv="X-UA-Compatible" content="IE=edge">
  6 +<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  7 +<title>404</title>
  8 +<style>
  9 + body{
  10 + background-color:#444;
  11 + font-size:14px;
  12 + }
  13 + h3{
  14 + font-size:60px;
  15 + color:#eee;
  16 + text-align:center;
  17 + padding-top:30px;
  18 + font-weight:normal;
  19 + }
  20 +</style>
  21 +</head>
  22 +
  23 +<body>
  24 +<h3>404,您请求的文件不存在!</h3>
  25 +</body>
  26 +</html>
  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群: [636393962](https://jq.qq.com/?_wv=1027&k=487PNBb)() [708784003](https://jq.qq.com/?_wv=1027&k=5ObjtwM)(满) [964776039](https://jq.qq.com/?_wv=1027&k=59qjU2P)(3群) [749803490](https://jq.qq.com/?_wv=1027&k=5tczi88)(满) [767103006](https://jq.qq.com/?_wv=1027&k=5Z1U751)() [675115483](https://jq.qq.com/?_wv=1027&k=54I6mts)(6群)
  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://layer.layui.com
  85 +
  86 +DropzoneJS: https://www.dropzonejs.com
  87 +
  88 +
  89 +## 版权信息
  90 +
  91 +FastAdmin遵循Apache2开源协议发布,并提供免费使用。
  92 +
  93 +本项目包含的第三方源码和二进制文件之版权信息另行标注。
  94 +
  95 +版权所有Copyright © 2017-2020 by FastAdmin (https://www.fastadmin.net)
  96 +
  97 +All rights reserved。
  1 +deny from all
  1 +{"files":[],"license":"regular","licenseto":"7679","licensekey":"1LBZYUde0o97sNH3 ZljWKi56L3L24P3SRrJD6Q==","domains":["jswg"],"licensecodes":[],"validations":["bcfa3bfe719a8a7970c90992c2c80196"]}
  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' => 'amap',
  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' => '16',
  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' => '23.361086',
  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' => '102.366527',
  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' => '7Mt3R8k1PGyB1gOEk60Ksfsg90S1cQTR',
  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' => 'd7700b2fe9adfdf30b527a394cb9c044',
  74 + 'rule' => '',
  75 + 'msg' => '',
  76 + 'tip' => '',
  77 + 'ok' => '',
  78 + 'extend' => '',
  79 + ],
  80 + [
  81 + 'name' => 'amapsecurityjscode',
  82 + 'title' => '高德地图安全密钥',
  83 + 'type' => 'string',
  84 + 'content' => [],
  85 + 'value' => '25563cb543935da2683f882697b9a012',
  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' => 'QWNBZ-OV6C2-7UMUS-CSOJB-L3AFT-QTBR5',
  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 = 7679
  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 +{"license":"regular","licenseto":"44234","licensekey":"82jyXWeYPFpiE1C4 kxxHOwiOqPyuag4dlI\/v3w=="}
  1 +<?php
  2 +
  3 +namespace addons\alisms;
  4 +
  5 +use think\Addons;
  6 +
  7 +/**
  8 + * Alisms
  9 + */
  10 +class Alisms extends Addons
  11 +{
  12 +
  13 + /**
  14 + * 插件安装方法
  15 + * @return bool
  16 + */
  17 + public function install()
  18 + {
  19 + return true;
  20 + }
  21 +
  22 + /**
  23 + * 插件卸载方法
  24 + * @return bool
  25 + */
  26 + public function uninstall()
  27 + {
  28 + return true;
  29 + }
  30 +
  31 + /**
  32 + * 短信发送行为
  33 + * @param array $params 必须包含mobile,event,code
  34 + * @return boolean
  35 + */
  36 + public function smsSend(&$params)
  37 + {
  38 + $config = get_addon_config('alisms');
  39 + $alisms = new \addons\alisms\library\Alisms();
  40 + $result = $alisms->mobile($params['mobile'])
  41 + ->template($config['template'][$params['event']])
  42 + ->param(['code' => $params['code']])
  43 + ->send();
  44 + return $result;
  45 + }
  46 +
  47 + /**
  48 + * 短信发送通知
  49 + * @param array $params 必须包含 mobile,event,msg
  50 + * @return boolean
  51 + */
  52 + public function smsNotice(&$params)
  53 + {
  54 + $config = get_addon_config('alisms');
  55 + $alisms = \addons\alisms\library\Alisms::instance();
  56 + if (isset($params['msg'])) {
  57 + if (is_array($params['msg'])) {
  58 + $param = $params['msg'];
  59 + } else {
  60 + parse_str($params['msg'], $param);
  61 + }
  62 + } else {
  63 + $param = [];
  64 + }
  65 + $param = $param ? $param : [];
  66 + $params['template'] = isset($params['template']) ? $params['template'] : (isset($params['event']) && isset($config['template'][$params['event']]) ? $config['template'][$params['event']] : '');
  67 + $result = $alisms->mobile($params['mobile'])
  68 + ->template($params['template'])
  69 + ->param($param)
  70 + ->send();
  71 + return $result;
  72 + }
  73 +
  74 + /**
  75 + * 检测验证是否正确
  76 + * @param $params
  77 + * @return boolean
  78 + */
  79 + public function smsCheck(&$params)
  80 + {
  81 + return true;
  82 + }
  83 +}
  1 +<?php
  2 +
  3 +return [
  4 + [
  5 + 'name' => 'key',
  6 + 'title' => '应用key',
  7 + 'type' => 'string',
  8 + 'content' => [],
  9 + 'value' => 'LTAI4G5vhKpKAdRrJvbpbhXy',
  10 + 'rule' => 'required',
  11 + 'msg' => '',
  12 + 'tip' => '',
  13 + 'ok' => '',
  14 + 'extend' => '',
  15 + ],
  16 + [
  17 + 'name' => 'secret',
  18 + 'title' => '密钥secret',
  19 + 'type' => 'string',
  20 + 'content' => [],
  21 + 'value' => 'BIXrRKuLb8jELqPKAzYjF9eyW4DjTr',
  22 + 'rule' => 'required',
  23 + 'msg' => '',
  24 + 'tip' => '',
  25 + 'ok' => '',
  26 + 'extend' => '',
  27 + ],
  28 + [
  29 + 'name' => 'sign',
  30 + 'title' => '签名',
  31 + 'type' => 'string',
  32 + 'content' => [],
  33 + 'value' => '云南智慧水库安全云平台',
  34 + 'rule' => 'required',
  35 + 'msg' => '',
  36 + 'tip' => '',
  37 + 'ok' => '',
  38 + 'extend' => '',
  39 + ],
  40 + [
  41 + 'name' => 'template',
  42 + 'title' => '短信模板',
  43 + 'type' => 'array',
  44 + 'content' => [],
  45 + 'value' => [
  46 + 'register' => 'SMS_226785328',
  47 + 'resetpwd' => 'SMS_114000000',
  48 + 'changepwd' => 'SMS_114000000',
  49 + 'changemobile' => 'SMS_114000000',
  50 + 'profile' => 'SMS_114000000',
  51 + 'password' => 'SMS_227747048',
  52 + ],
  53 + 'rule' => 'required',
  54 + 'msg' => '',
  55 + 'tip' => '',
  56 + 'ok' => '',
  57 + 'extend' => '',
  58 + ],
  59 + [
  60 + 'name' => '__tips__',
  61 + 'title' => '温馨提示',
  62 + 'type' => 'string',
  63 + 'content' => [],
  64 + 'value' => '应用key和密钥你可以通过 https://ak-console.aliyun.com/?spm=a2c4g.11186623.2.13.fd315777PX3tjy#/accesskey 获取',
  65 + 'rule' => 'required',
  66 + 'msg' => '',
  67 + 'tip' => '',
  68 + 'ok' => '',
  69 + 'extend' => '',
  70 + ],
  71 +];
  1 +<?php
  2 +
  3 +namespace addons\alisms\controller;
  4 +
  5 +use think\addons\Controller;
  6 +
  7 +/**
  8 + * 阿里短信
  9 + */
  10 +class Index extends Controller
  11 +{
  12 +
  13 + protected $model = null;
  14 +
  15 + public function _initialize()
  16 + {
  17 + // if (!\app\admin\library\Auth::instance()->id) {
  18 + // $this->error('暂无权限浏览');
  19 + // }
  20 + parent::_initialize();
  21 + }
  22 +
  23 + public function index()
  24 + {
  25 + return $this->view->fetch();
  26 + }
  27 +
  28 + public function send()
  29 + {
  30 + $config = get_addon_config('alisms');
  31 + $mobile = $this->request->post('mobile');
  32 + $template = $this->request->post('template');
  33 + $sign = $this->request->post('sign');
  34 + if (!$mobile || !$template) {
  35 + $this->error('手机号、模板ID不能为空');
  36 + }
  37 + $sign = $sign ? $sign : $config['sign'];
  38 + $param = (array)json_decode($this->request->post('param', '', 'trim'));
  39 + $alisms = new \addons\alisms\library\Alisms();
  40 + $ret = $alisms->mobile($mobile)
  41 + ->template($template)
  42 + ->sign($sign)
  43 + ->param($param)
  44 + ->send();
  45 + if ($ret) {
  46 + $this->success("发送成功");
  47 + } else {
  48 + $this->error("发送失败!失败原因:" . $alisms->getError());
  49 + }
  50 + }
  51 + //发送短信带参数
  52 + public function send_param($mobile,$template,$sign,$param)
  53 + {
  54 + $config = get_addon_config('alisms');
  55 + if (!$mobile || !$template) {
  56 + $this->error('手机号、模板ID不能为空');
  57 + }
  58 + $alisms = new \addons\alisms\library\Alisms();
  59 + $ret = $alisms->mobile($mobile)
  60 + ->template($template)
  61 + ->sign($sign)
  62 + ->param($param)
  63 + ->send();
  64 + // if ($ret) {
  65 + // $this->success("发送成功");
  66 + // } else {
  67 + // $this->error("发送失败!失败原因:" . $alisms->getError());
  68 + // }
  69 + }
  70 +
  71 +}
  1 +<?php
  2 +
  3 +// This file is auto-generated, don't edit it. Thanks.
  4 +namespace addons\alisms\controller;
  5 +
  6 +use AlibabaCloud\SDK\Dyvmsapi\V20170525\Dyvmsapi;
  7 +
  8 +use Darabonba\OpenApi\Models\Config;
  9 +use AlibabaCloud\SDK\Dyvmsapi\V20170525\Models\SingleCallByTtsRequest;
  10 +
  11 +class Sample {
  12 +
  13 + /**
  14 + * 使用AK&SK初始化账号Client
  15 + * @param string $accessKeyId
  16 + * @param string $accessKeySecret
  17 + * @return Dyvmsapi Client
  18 + */
  19 + public static function createClient($accessKeyId, $accessKeySecret){
  20 + $config = new Config([
  21 + // 您的AccessKey ID
  22 + "accessKeyId" => $accessKeyId,
  23 + // 您的AccessKey Secret
  24 + "accessKeySecret" => $accessKeySecret
  25 + ]);
  26 + // 访问的域名
  27 + $config->endpoint = "dyvmsapi.aliyuncs.com";
  28 + return new Dyvmsapi($config);
  29 + }
  30 +
  31 + /**
  32 + * @param string[] $args
  33 + * @return void
  34 + */
  35 + public static function main($mobile='',$template='',$data=[])
  36 + {
  37 + $client = self::createClient("LTAI4G5vhKpKAdRrJvbpbhXy", "BIXrRKuLb8jELqPKAzYjF9eyW4DjTr");
  38 + $singleCallByTtsRequest = new SingleCallByTtsRequest([
  39 + "calledNumber" => $mobile,
  40 + "ttsCode" => $template,
  41 + "ttsParam" => json_encode($data)
  42 + //"ttsParam" => json_encode($data,TRUE)
  43 + ]);
  44 + // 复制代码运行请自行打印 API 的返回值
  45 + $res = $client->singleCallByTts($singleCallByTtsRequest);
  46 +
  47 +
  48 + }
  49 + public static function sendsms($mobile='',$template='',$data=[])
  50 + {
  51 + $path = __DIR__ . \DIRECTORY_SEPARATOR . '..' . \DIRECTORY_SEPARATOR . 'vendor' . \DIRECTORY_SEPARATOR . 'autoload.php';
  52 + if (file_exists($path)) {
  53 + require_once $path;
  54 + }
  55 + self::main($mobile,$template,$data);
  56 + }
  57 +}
  1 +name = alisms
  2 +title = 阿里云短信发送
  3 +intro = 阿里云短信发送插件
  4 +author = FastAdmin
  5 +website = https://www.fastadmin.net
  6 +version = 1.0.9
  7 +state = 1
  8 +url = /addons/alisms
  9 +license = regular
  10 +licenseto = 44234
  1 +<?php
  2 +
  3 +namespace addons\alisms\library;
  4 +
  5 +/**
  6 + * 阿里大于SMS短信发送
  7 + */
  8 +class Alisms
  9 +{
  10 + private $_params = [];
  11 + public $error = '';
  12 + protected $config = [];
  13 + protected static $instance;
  14 +
  15 + public function __construct($options = [])
  16 + {
  17 + if ($config = get_addon_config('alisms')) {
  18 + $this->config = array_merge($this->config, $config);
  19 + }
  20 + $this->config = array_merge($this->config, is_array($options) ? $options : []);
  21 + }
  22 +
  23 + /**
  24 + * 单例
  25 + * @param array $options 参数
  26 + * @return Alisms
  27 + */
  28 + public static function instance($options = [])
  29 + {
  30 + if (is_null(self::$instance)) {
  31 + self::$instance = new static($options);
  32 + }
  33 +
  34 + return self::$instance;
  35 + }
  36 +
  37 + /**
  38 + * 设置签名
  39 + * @param string $sign
  40 + * @return Alisms
  41 + */
  42 + public function sign($sign = '')
  43 + {
  44 + $this->_params['SignName'] = $sign;
  45 + return $this;
  46 + }
  47 +
  48 + /**
  49 + * 设置参数
  50 + * @param array $param
  51 + * @return Alisms
  52 + */
  53 + public function param(array $param = [])
  54 + {
  55 + foreach ($param as $k => &$v) {
  56 + $v = (string)$v;
  57 + }
  58 + unset($v);
  59 + $param = array_filter($param);
  60 + $this->_params['TemplateParam'] = $param ? json_encode($param) : '{}';
  61 + return $this;
  62 + }
  63 +
  64 + /**
  65 + * 设置模板
  66 + * @param string $code 短信模板
  67 + * @return Alisms
  68 + */
  69 + public function template($code = '')
  70 + {
  71 + $this->_params['TemplateCode'] = $code;
  72 + return $this;
  73 + }
  74 +
  75 + /**
  76 + * 接收手机
  77 + * @param string $mobile 手机号码
  78 + * @return Alisms
  79 + */
  80 + public function mobile($mobile = '')
  81 + {
  82 + $this->_params['PhoneNumbers'] = $mobile;
  83 + return $this;
  84 + }
  85 +
  86 + /**
  87 + * 立即发送
  88 + * @return boolean
  89 + */
  90 + public function send()
  91 + {
  92 + $this->error = '';
  93 + $params = $this->_params();
  94 + $params['Signature'] = $this->_signed($params);
  95 + $response = $this->_curl($params);
  96 + if ($response !== false) {
  97 + $res = (array)json_decode($response, true);
  98 + if (isset($res['Code']) && $res['Code'] == 'OK') {
  99 + return true;
  100 + }
  101 + $this->error = isset($res['Message']) ? $res['Message'] : 'InvalidResult';
  102 + } else {
  103 + $this->error = 'InvalidResult';
  104 + }
  105 + return false;
  106 + }
  107 +
  108 + /**
  109 + * 获取错误信息
  110 + * @return string
  111 + */
  112 + public function getError()
  113 + {
  114 + return $this->error;
  115 + }
  116 +
  117 + private function _params()
  118 + {
  119 + return array_merge([
  120 + 'AccessKeyId' => $this->config['key'],
  121 + 'SignName' => isset($this->config['sign']) ? $this->config['sign'] : '',
  122 + 'Action' => 'SendSms',
  123 + 'Format' => 'JSON',
  124 + 'Version' => '2017-05-25',
  125 + 'SignatureVersion' => '1.0',
  126 + 'SignatureMethod' => 'HMAC-SHA1',
  127 + 'SignatureNonce' => uniqid(),
  128 + 'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
  129 + ], $this->_params);
  130 + }
  131 +
  132 + private function percentEncode($string)
  133 + {
  134 + $string = urlencode($string);
  135 + $string = preg_replace('/\+/', '%20', $string);
  136 + $string = preg_replace('/\*/', '%2A', $string);
  137 + $string = preg_replace('/%7E/', '~', $string);
  138 + return $string;
  139 + }
  140 +
  141 + private function _signed($params)
  142 + {
  143 + $sign = $this->config['secret'];
  144 + ksort($params);
  145 + $canonicalizedQueryString = '';
  146 + foreach ($params as $key => $value) {
  147 + $canonicalizedQueryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
  148 + }
  149 + $stringToSign = 'GET&%2F&' . $this->percentencode(substr($canonicalizedQueryString, 1));
  150 + $signature = base64_encode(hash_hmac('sha1', $stringToSign, $sign . '&', true));
  151 + return $signature;
  152 + }
  153 +
  154 + private function _curl($params)
  155 + {
  156 + $uri = 'http://dysmsapi.aliyuncs.com/?' . http_build_query($params);
  157 + $ch = curl_init();
  158 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  159 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  160 + curl_setopt($ch, CURLOPT_URL, $uri);
  161 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  162 + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
  163 + curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.98 Safari/537.36");
  164 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  165 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  166 + $reponse = curl_exec($ch);
  167 + curl_close($ch);
  168 + return $reponse;
  169 + }
  170 +}
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
  5 + <title>阿里云通信短信发送示例 - FastAdmin</title>
  6 +
  7 + <!-- Bootstrap Core CSS -->
  8 + <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  9 +
  10 + <!-- Custom CSS -->
  11 + <link href="__CDN__/assets/css/frontend.css" rel="stylesheet">
  12 +
  13 + <!-- Plugin CSS -->
  14 + <link href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  15 + <link href="https://cdn.staticfile.org/simple-line-icons/2.4.1/css/simple-line-icons.min.css" rel="stylesheet">
  16 +
  17 + <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
  18 + <!--[if lt IE 9]>
  19 + <script src="https://cdn.staticfile.org/html5shiv/3.7.3/html5shiv.min.js"></script>
  20 + <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
  21 + <![endif]-->
  22 +</head>
  23 +<body>
  24 +<div class="container">
  25 + <div class="well" style="margin-top:30px;">
  26 + <form class="form-horizontal" action="{:addon_url('alisms/index/send')}" method="POST">
  27 + <fieldset>
  28 + <legend>阿里云通信短信发送</legend>
  29 + <div class="form-group">
  30 + <label class="col-lg-2 control-label">手机号</label>
  31 + <div class="col-lg-10">
  32 + <input type="text" class="form-control" name="mobile" placeholder="手机号">
  33 + </div>
  34 + </div>
  35 + <div class="form-group">
  36 + <label class="col-lg-2 control-label">消息模板ID</label>
  37 + <div class="col-lg-10">
  38 + <input type="text" class="form-control" name="template" placeholder="消息模板ID,从阿里云通信获得,通常是:SMS_114000000这种格式">
  39 + </div>
  40 + </div>
  41 + <div class="form-group">
  42 + <label class="col-lg-2 control-label">签名</label>
  43 + <div class="col-lg-10">
  44 + <input type="text" class="form-control" name="sign" placeholder="消息模板(可以留空,留空使用后台插件管理中的配置)">
  45 + </div>
  46 + </div>
  47 + <div class="form-group">
  48 + <label class="col-lg-2 control-label">模板变量参数</label>
  49 + <div class="col-lg-10">
  50 + <textarea name="param" class="form-control" cols="30" rows="10" placeholder='必须是JSON字符串,如{"name":"李明"}'></textarea>
  51 + </div>
  52 + </div>
  53 + <div class="form-group">
  54 + <div class="col-lg-10 col-lg-offset-2">
  55 + <button type="submit" class="btn btn-primary">发送</button>
  56 + <button type="reset" class="btn btn-default">重置</button>
  57 + </div>
  58 + </div>
  59 + </fieldset>
  60 + </form>
  61 + </div>
  62 +</div>
  63 +<!-- jQuery -->
  64 +<script src="https://cdn.staticfile.org/jquery/2.1.4/jquery.min.js"></script>
  65 +
  66 +<!-- Bootstrap Core JavaScript -->
  67 +<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
  68 +
  69 +<script type="text/javascript">
  70 + $(function () {
  71 +
  72 + });
  73 +</script>
  74 +</body>
  75 +</html>
  1 +{"license":"regular","licenseto":"44234","licensekey":"D2yxpZc1bAemkhoC s\/ru7SGEWHfZByprwvxJuQ==","menus":["command","command\/index","command\/add","command\/detail","command\/execute","command\/del","command\/multi"],"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"]}
  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/execute', 'title' => '运行'],
  30 + ['name' => 'command/del', 'title' => '删除'],
  31 + ['name' => 'command/multi', 'title' => '批量更新'],
  32 + ]
  33 + ]
  34 + ];
  35 + Menu::create($menu);
  36 + return true;
  37 + }
  38 +
  39 + /**
  40 + * 插件卸载方法
  41 + * @return bool
  42 + */
  43 + public function uninstall()
  44 + {
  45 + Menu::delete('command');
  46 + return true;
  47 + }
  48 +
  49 + /**
  50 + * 插件启用方法
  51 + * @return bool
  52 + */
  53 + public function enable()
  54 + {
  55 + Menu::enable('command');
  56 + return true;
  57 + }
  58 +
  59 + /**
  60 + * 插件禁用方法
  61 + * @return bool
  62 + */
  63 + public function disable()
  64 + {
  65 + Menu::disable('command');
  66 + return true;
  67 + }
  68 +
  69 +}
  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 = 可在线执行FastAdmin的命令行相关命令
  4 +author = Karson
  5 +website = https://www.fastadmin.net
  6 +version = 1.0.6
  7 +state = 1
  8 +url = /addons/command
  9 +license = regular
  10 +licenseto = 44234
  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` int(10) UNSIGNED DEFAULT NULL COMMENT '执行时间',
  8 + `createtime` int(10) UNSIGNED DEFAULT NULL COMMENT '创建时间',
  9 + `updatetime` int(10) 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 +{"license":"regular","licenseto":"44234","licensekey":"vjgmpx9f3c8FsnB0 tZUWQ7bPsRVC6a9sUFSfQQ==","menus":["dinghorn","dinghorn\/robot","dinghorn\/robot\/index","dinghorn\/robot\/add","dinghorn\/robot\/edit","dinghorn\/robot\/del","dinghorn\/robot\/multi","dinghorn\/robot\/recyclebin","dinghorn\/robot\/destroy","dinghorn\/robot\/restore","dinghorn\/variable","dinghorn\/variable\/index","dinghorn\/variable\/add","dinghorn\/variable\/edit","dinghorn\/variable\/del","dinghorn\/variable\/multi","dinghorn\/variable\/recyclebin","dinghorn\/variable\/destroy","dinghorn\/variable\/restore","dinghorn\/variable\/view_variable","dinghorn\/template","dinghorn\/template\/index","dinghorn\/template\/add","dinghorn\/template\/edit","dinghorn\/template\/del","dinghorn\/template\/multi","dinghorn\/template\/recyclebin","dinghorn\/template\/destroy","dinghorn\/template\/restore","dinghorn\/msglog","dinghorn\/msglog\/index","dinghorn\/msglog\/edit","dinghorn\/msglog\/del","dinghorn\/msglog\/multi","dinghorn\/msglog\/recyclebin","dinghorn\/msglog\/destroy","dinghorn\/msglog\/restore"],"files":["application\/admin\/lang\/zh-cn\/dinghorn\/msglog.php","application\/admin\/lang\/zh-cn\/dinghorn\/template.php","application\/admin\/lang\/zh-cn\/dinghorn\/variable.php","application\/admin\/lang\/zh-cn\/dinghorn\/robot.php","application\/admin\/model\/DinghornMsglog.php","application\/admin\/model\/DinghornVariable.php","application\/admin\/model\/DinghornRobot.php","application\/admin\/model\/DinghornTemplate.php","application\/admin\/view\/dinghorn\/msglog\/recyclebin.html","application\/admin\/view\/dinghorn\/msglog\/edit.html","application\/admin\/view\/dinghorn\/msglog\/add.html","application\/admin\/view\/dinghorn\/msglog\/index.html","application\/admin\/view\/dinghorn\/robot\/recyclebin.html","application\/admin\/view\/dinghorn\/robot\/edit.html","application\/admin\/view\/dinghorn\/robot\/add.html","application\/admin\/view\/dinghorn\/robot\/index.html","application\/admin\/view\/dinghorn\/variable\/recyclebin.html","application\/admin\/view\/dinghorn\/variable\/edit.html","application\/admin\/view\/dinghorn\/variable\/add.html","application\/admin\/view\/dinghorn\/variable\/index.html","application\/admin\/view\/dinghorn\/template\/recyclebin.html","application\/admin\/view\/dinghorn\/template\/edit.html","application\/admin\/view\/dinghorn\/template\/add.html","application\/admin\/view\/dinghorn\/template\/index.html","application\/admin\/validate\/DinghornMsglog.php","application\/admin\/validate\/DinghornVariable.php","application\/admin\/validate\/DinghornRobot.php","application\/admin\/validate\/DinghornTemplate.php","application\/admin\/controller\/dinghorn\/Msglog.php","application\/admin\/controller\/dinghorn\/Robot.php","application\/admin\/controller\/dinghorn\/Template.php","application\/admin\/controller\/dinghorn\/Variable.php","application\/admin\/controller\/dinghorn\/Example.php","public\/assets\/js\/backend\/dinghorn\/msglog.js","public\/assets\/js\/backend\/dinghorn\/robot.js","public\/assets\/js\/backend\/dinghorn\/variable.js","public\/assets\/js\/backend\/dinghorn\/template.js"]}
  1 +<?php
  2 +
  3 +namespace addons\dinghorn;
  4 +
  5 +use addons\dinghorn\library\DinghornLib;
  6 +use app\common\library\Menu;
  7 +use think\Addons;
  8 +use think\Db;
  9 +
  10 +/**
  11 + * 钉钉小喇叭
  12 + */
  13 +class Dinghorn extends Addons
  14 +{
  15 + /**
  16 + * 通过模板发送通知消息
  17 + * @param string $template 消息模板Id或Code
  18 + * @param array $tpl_data 要覆盖的模板数据 (参见:\application\admin\controller\dinghorn\Example.php 的 example2 方法)
  19 + * @param array $tpl_variable 模板变量键值对,若模板变量已预先定义,则会自动获取值,无需在此传递
  20 + * @return array 发送结果
  21 + */
  22 + public static function msgNotice($template, $tpl_data = array(), $tpl_variable = array())
  23 + {
  24 + $now_time = time();
  25 + $dinghorn_config = get_addon_config('dinghorn');
  26 + $template = Db::name('dinghorn_template')
  27 + ->where('id = :tpl OR code = :tpl_code', ['tpl' => $template, 'tpl_code' => $template])
  28 + ->where('deletetime', null)
  29 + ->find();
  30 +
  31 + if (!$template || !$template['openswitch']) {
  32 +
  33 + if ($dinghorn_config['error_log']) {
  34 +
  35 + $log_arr = array(
  36 + 'robot_id' => 0,
  37 + 'template_id' => isset($template['id']) ? $template['id'] : 0,
  38 + 'template_data' => json_encode($tpl_data),
  39 + 'errmsg' => '消息模板未找到或已禁用!(-1)',
  40 + 'status' => '0',
  41 + 'createtime' => $now_time
  42 + );
  43 +
  44 + Db::name('dinghorn_msglog')->insert($log_arr);
  45 + }
  46 +
  47 + return ['errcode' => -1, 'errmsg' => '消息模板未找到或已禁用!'];
  48 + }
  49 +
  50 + $DinghornLib = new DinghornLib($template, $tpl_data, $tpl_variable);
  51 +
  52 + // 获取模板内的机器人
  53 + $robot_ids = isset($tpl_data['robot_ids']) ? $tpl_data['robot_ids'] : $template['robot_ids'];
  54 + $robots = Db::name('dinghorn_robot')
  55 + ->whereIn('id', $robot_ids)
  56 + ->where('openswitch', 1)
  57 + ->where('deletetime', null)
  58 + ->select();
  59 +
  60 + // 组装消息数据
  61 + $msg_data = $DinghornLib->deal_with_msg();
  62 +
  63 + $log_arr = [];//要插入的日志
  64 + $is_err = false;//是否有错误,用于判定本次操作的返回值
  65 +
  66 + // 循环所有要发送的机器人
  67 + foreach ($robots as $key => $value) {
  68 + $res = $DinghornLib->msgSend($value['access_token'], $msg_data, $value['sign']);
  69 +
  70 + if ($res['errcode'] == 0 && $dinghorn_config['success_log']) {
  71 +
  72 + $log_arr[] = array(
  73 + 'robot_id' => $value['id'],
  74 + 'template_id' => $template['id'],
  75 + 'template_data' => json_encode($msg_data),
  76 + 'errmsg' => '',
  77 + 'status' => '1',
  78 + 'createtime' => $now_time
  79 + );
  80 + } else if ($res['errcode'] != 0) {
  81 +
  82 + $is_err = true;
  83 + $errmsg = $res['errmsg'] . '(' . $res['errcode'] . ')';
  84 +
  85 + if ($dinghorn_config['error_log']) {
  86 + $log_arr[] = array(
  87 + 'robot_id' => $value['id'],
  88 + 'template_id' => $template['id'],
  89 + 'template_data' => json_encode($msg_data),
  90 + 'errmsg' => $errmsg,
  91 + 'status' => '0',
  92 + 'createtime' => $now_time
  93 + );
  94 + }
  95 + }
  96 + }
  97 +
  98 + if ($log_arr) {
  99 + Db::startTrans();
  100 + try {
  101 + Db::name('dinghorn_msglog')->insertAll($log_arr);
  102 + Db::commit();
  103 + } catch (\Exception $e) {
  104 + Db::rollback();
  105 + }
  106 + }
  107 +
  108 + return $is_err ? ['errcode' => -2, 'errmsg' => '消息发送失败:' . $errmsg] : ['errcode' => 0];
  109 + }
  110 +
  111 + /**
  112 + * 插件安装方法
  113 + * @return bool
  114 + */
  115 + public function install()
  116 + {
  117 + $menu = [
  118 + [
  119 + 'name' => 'dinghorn',
  120 + 'title' => '钉钉小喇叭',
  121 + 'icon' => 'fa fa-volume-up',
  122 + 'sublist' => [
  123 + [
  124 + 'name' => 'dinghorn/robot',
  125 + 'title' => '机器人管理',
  126 + 'icon' => 'fa fa-circle-o',
  127 + 'sublist' => [
  128 + ['name' => 'dinghorn/robot/index', 'title' => '查看'],
  129 + ['name' => 'dinghorn/robot/add', 'title' => '添加'],
  130 + ['name' => 'dinghorn/robot/edit', 'title' => '编辑'],
  131 + ['name' => 'dinghorn/robot/del', 'title' => '删除'],
  132 + ['name' => 'dinghorn/robot/multi', 'title' => '批量更新'],
  133 + ['name' => 'dinghorn/robot/recyclebin', 'title' => '回收站'],
  134 + ['name' => 'dinghorn/robot/destroy', 'title' => '真实删除'],
  135 + ['name' => 'dinghorn/robot/restore', 'title' => '还原'],
  136 + ]
  137 + ],
  138 + [
  139 + 'name' => 'dinghorn/variable',
  140 + 'title' => '模板变量管理',
  141 + 'icon' => 'fa fa-circle-o',
  142 + 'remark' => '在此处设置变量,随后可在模板通知内使用变量,变量值可来源于方法返回值或SQL查询结果',
  143 + 'sublist' => [
  144 + ['name' => 'dinghorn/variable/index', 'title' => '查看'],
  145 + ['name' => 'dinghorn/variable/add', 'title' => '添加'],
  146 + ['name' => 'dinghorn/variable/edit', 'title' => '编辑'],
  147 + ['name' => 'dinghorn/variable/del', 'title' => '删除'],
  148 + ['name' => 'dinghorn/variable/multi', 'title' => '批量更新'],
  149 + ['name' => 'dinghorn/variable/recyclebin', 'title' => '回收站'],
  150 + ['name' => 'dinghorn/variable/destroy', 'title' => '真实删除'],
  151 + ['name' => 'dinghorn/variable/restore', 'title' => '还原'],
  152 + ['name' => 'dinghorn/variable/view_variable', 'title' => '计算变量值'],
  153 + ]
  154 + ],
  155 + [
  156 + 'name' => 'dinghorn/template',
  157 + 'title' => '通知模板管理',
  158 + 'icon' => 'fa fa-circle-o',
  159 + 'sublist' => [
  160 + ['name' => 'dinghorn/template/index', 'title' => '查看'],
  161 + ['name' => 'dinghorn/template/add', 'title' => '添加'],
  162 + ['name' => 'dinghorn/template/edit', 'title' => '编辑'],
  163 + ['name' => 'dinghorn/template/del', 'title' => '删除'],
  164 + ['name' => 'dinghorn/template/multi', 'title' => '批量更新'],
  165 + ['name' => 'dinghorn/template/recyclebin', 'title' => '回收站'],
  166 + ['name' => 'dinghorn/template/destroy', 'title' => '真实删除'],
  167 + ['name' => 'dinghorn/template/restore', 'title' => '还原'],
  168 + ]
  169 + ],
  170 + [
  171 + 'name' => 'dinghorn/msglog',
  172 + 'title' => '通知发送日志管理',
  173 + 'icon' => 'fa fa-circle-o',
  174 + 'sublist' => [
  175 + ['name' => 'dinghorn/msglog/index', 'title' => '查看'],
  176 + ['name' => 'dinghorn/msglog/edit', 'title' => '编辑'],
  177 + ['name' => 'dinghorn/msglog/del', 'title' => '删除'],
  178 + ['name' => 'dinghorn/msglog/multi', 'title' => '批量更新'],
  179 + ['name' => 'dinghorn/msglog/recyclebin', 'title' => '回收站'],
  180 + ['name' => 'dinghorn/msglog/destroy', 'title' => '真实删除'],
  181 + ['name' => 'dinghorn/msglog/restore', 'title' => '还原'],
  182 + ]
  183 + ],
  184 + ]
  185 + ]
  186 + ];
  187 + Menu::create($menu);
  188 + return true;
  189 + }
  190 +
  191 + /**
  192 + * 插件卸载方法
  193 + * @return bool
  194 + */
  195 + public function uninstall()
  196 + {
  197 + Menu::delete('dinghorn');
  198 + return true;
  199 + }
  200 +
  201 + /**
  202 + * 插件启用方法
  203 + * @return bool
  204 + */
  205 + public function enable()
  206 + {
  207 + Menu::enable('dinghorn');
  208 + return true;
  209 + }
  210 +
  211 + /**
  212 + * 插件禁用方法
  213 + * @return bool
  214 + */
  215 + public function disable()
  216 + {
  217 + Menu::disable('dinghorn');
  218 + return true;
  219 + }
  220 +}
  1 +<?php
  2 +
  3 +return [
  4 + [
  5 + 'name' => 'success_log',
  6 + 'title' => '成功日志',
  7 + 'type' => 'radio',
  8 + 'options' => [
  9 + '1' => '记录',
  10 + '0' => '不记录'
  11 + ],
  12 + 'content' => array(
  13 + '1' => '记录',
  14 + '0' => '不记录'
  15 + ),
  16 + 'value' => '0',
  17 + 'rule' => 'required',
  18 + 'msg' => '',
  19 + 'tip' => '机器人发送消息成功后,记录日志',
  20 + 'ok' => '',
  21 + 'extend' => ''
  22 + ],
  23 + [
  24 + 'name' => 'error_log',
  25 + 'title' => '失败日志',
  26 + 'type' => 'radio',
  27 + 'options' => [
  28 + '1' => '记录',
  29 + '0' => '不记录'
  30 + ],
  31 + 'content' => array(
  32 + '1' => '记录',
  33 + '0' => '不记录'
  34 + ),
  35 + 'value' => '1',
  36 + 'rule' => 'required',
  37 + 'msg' => '',
  38 + 'tip' => '机器人发送消息失败时,记录日志',
  39 + 'ok' => '',
  40 + 'extend' => ''
  41 + ],
  42 +];
  1 +<?php
  2 +
  3 +namespace addons\dinghorn\controller;
  4 +
  5 +use think\addons\Controller;
  6 +
  7 +class Index extends Controller
  8 +{
  9 +
  10 + public function index()
  11 + {
  12 + $update_log = <<<html
  13 + <h4>V1.0.1更新内容</h4>
  14 + <p>1. 后台增加模板变量测试功能</p>
  15 + <p>2. 模板内现已可使用未定义的模板变量,在调用时传递变量值</p>
  16 + <p>3. 模板增加Code,业务代码中调用时比ID更易识别</p>
  17 + <p>4. 后台发送模板消息失败提示成功的问题</p>
  18 + <p>5. 模板不存在或禁用时,无失败日志的问题</p>
  19 + <p>6. 模板变量名重复检测</p>
  20 + <p>7. 优化多处代码逻辑</p>
  21 +html;
  22 + echo $update_log;
  23 + }
  24 +
  25 +}
  1 +name = dinghorn
  2 +title = 钉钉小喇叭
  3 +intro = 利用钉钉机器人,实时接受业务提醒,快速接入、使用方便、免费无限制的通知服务,支持发送文本、链接、 markdown、ActionCard、FeedCard消息类型
  4 +author = 白衣素袖
  5 +website = https://www.fastadmin.net
  6 +version = 1.0.2
  7 +state = 1
  8 +url = /addons/dinghorn
  9 +license = regular
  10 +licenseto = 44234
  1 +
  2 +-- ---------------------------
  3 +-- 机器人表
  4 +-- ---------------------------
  5 +CREATE TABLE IF NOT EXISTS `__PREFIX__dinghorn_robot` (
  6 + `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  7 + `name` varchar(50) NOT NULL DEFAULT '' COMMENT '机器人名称',
  8 + `logo_image` varchar(100) NOT NULL DEFAULT '' COMMENT '机器人logo',
  9 + `access_token` varchar(100) NOT NULL DEFAULT '' COMMENT 'Hook地址',
  10 + `sign` varchar(100) NOT NULL DEFAULT '' COMMENT '签名密匙',
  11 + `keywords` varchar(100) NOT NULL DEFAULT '' COMMENT '自定义关键词',
  12 + `weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重',
  13 + `openswitch` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否开启:0=否,1=是',
  14 + `updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
  15 + `createtime` int(10) DEFAULT NULL COMMENT '创建时间',
  16 + `deletetime` int(10) DEFAULT NULL COMMENT '删除时间',
  17 + PRIMARY KEY (`id`)
  18 +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='钉钉机器人表';
  19 +
  20 +-- ----------------------------
  21 +-- 插入机器人
  22 +-- ----------------------------
  23 +BEGIN;
  24 +INSERT IGNORE INTO `__PREFIX__dinghorn_robot` VALUES ('1', '测试机器人', '', '1f81037666a7f9255827b916e0bdd7d4be382afc774d893be82d977bb926286a6','' , '', '1', '1', '1561962387', '1561962247', null);
  25 +COMMIT;
  26 +
  27 +-- ----------------------------
  28 +-- 通知发送日志表
  29 +-- ----------------------------
  30 +CREATE TABLE IF NOT EXISTS `__PREFIX__dinghorn_msglog` (
  31 + `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  32 + `robot_id` int(10) NOT NULL DEFAULT '0' COMMENT '发送机器人',
  33 + `template_id` int(10) NOT NULL DEFAULT '0' COMMENT '通知模板',
  34 + `template_data` text COMMENT '发送的数据',
  35 + `errmsg` varchar(255) NOT NULL DEFAULT '' COMMENT '错误消息',
  36 + `status` enum('1','0') NOT NULL DEFAULT '0' COMMENT '状态:0=失败,1=成功',
  37 + `createtime` int(10) DEFAULT NULL COMMENT '发送时间',
  38 + `deletetime` int(10) DEFAULT NULL COMMENT '删除时间',
  39 + PRIMARY KEY (`id`)
  40 +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='通知发送日志表';
  41 +
  42 +-- ----------------------------
  43 +-- 通知消息模板表
  44 +-- ----------------------------
  45 +CREATE TABLE IF NOT EXISTS `__PREFIX__dinghorn_template` (
  46 + `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  47 + `code` varchar(50) NOT NULL DEFAULT '' COMMENT '模板Code',
  48 + `name` varchar(50) NOT NULL DEFAULT '' COMMENT '模板名称',
  49 + `robot_ids` varchar(100) NOT NULL DEFAULT '0' COMMENT '发送机器人',
  50 + `typelist` enum('feedCard','actionCard_whole','actionCard','markdown','link','text') NOT NULL DEFAULT 'text' COMMENT '消息类型:text=文本,link=链接,markdown=markdown,actionCard=ActionCard多按钮跳转,actionCard_whole=ActionCard整体跳转,feedCard=FeedCard',
  51 + `content` text DEFAULT NULL COMMENT '默认消息内容',
  52 + `title` varchar(100) NOT NULL DEFAULT '' COMMENT '默认消息标题',
  53 + `msg_url` varchar(255) NOT NULL DEFAULT '' COMMENT '默认链接URL',
  54 + `picurl_image` varchar(255) NOT NULL DEFAULT '' COMMENT '默认图片URL',
  55 + `single_title` varchar(100) NOT NULL DEFAULT '' COMMENT '按钮文字',
  56 + `btn_orientation` tinyint(1) NOT NULL DEFAULT '0' COMMENT '按钮排列方式:0=竖直排列,1=横向排列',
  57 + `hide_avatar` tinyint(1) NOT NULL DEFAULT '0' COMMENT '隐藏机器人头像:0=否,1=是',
  58 + `btns` text COMMENT '按钮组',
  59 + `links` text COMMENT '默认链接组',
  60 + `at_mobiles` varchar(100) NOT NULL DEFAULT '' COMMENT '被AT人的手机号',
  61 + `is_atall` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'AT所有人:0=否,1=是',
  62 + `openswitch` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否开启:0=否,1=是',
  63 + `updatetime` int(10) DEFAULT NULL COMMENT '修改时间',
  64 + `createtime` int(10) DEFAULT NULL COMMENT '创建时间',
  65 + `deletetime` int(10) DEFAULT NULL COMMENT '删除时间',
  66 + PRIMARY KEY (`id`)
  67 +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='通知消息模板表';
  68 +
  69 +-- ----------------------------
  70 +-- 插入一个初始模板
  71 +-- ----------------------------
  72 +BEGIN;
  73 +INSERT IGNORE INTO `__PREFIX__dinghorn_template` VALUES ('1', 'test_tpl', '测试模板', '1', 'markdown', '### 系统通知-测试消息\r\n#### 当前系统内有${user_count}位用户\r\n##### ${test}\r\n###### Markdown 是一种标记语言\r\n###### Markdown 具有一系列衍生版本\r\n###### Markdown 的语法简洁明了\r\n###### 学习容易,而且功能比纯文本更强\r\n###### 调用时才赋值的变量值:${dynamic_variable}', '来自测试模板的消息', '', '', '', '0', '0', '', '', '', '1', '1', '1562052667', '1561970665', null);
  74 +COMMIT;
  75 +
  76 +-- ----------------------------
  77 +-- 模板变量表
  78 +-- ----------------------------
  79 +CREATE TABLE IF NOT EXISTS `__PREFIX__dinghorn_variable` (
  80 + `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  81 + `name` varchar(50) NOT NULL DEFAULT '' COMMENT '变量名',
  82 + `value_source` tinyint(1) NOT NULL DEFAULT '0' COMMENT '变量值来源:0=SQL查询结果,1=方法返回值',
  83 + `sql` varchar(255) NOT NULL DEFAULT '' COMMENT 'SQL',
  84 + `namespace` varchar(200) NOT NULL DEFAULT '' COMMENT '命名空间',
  85 + `class` varchar(50) NOT NULL DEFAULT '' COMMENT '类',
  86 + `function` varchar(50) NOT NULL DEFAULT '' COMMENT '方法',
  87 + `params` varchar(100) NOT NULL DEFAULT '' COMMENT '参数',
  88 + `updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
  89 + `createtime` int(10) DEFAULT NULL COMMENT '创建时间',
  90 + `deletetime` int(10) DEFAULT NULL COMMENT '删除时间',
  91 + PRIMARY KEY (`id`)
  92 +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='模板变量表';
  93 +
  94 +-- ----------------------------
  95 +-- 插入两个初始变量
  96 +-- ----------------------------
  97 +BEGIN;
  98 +INSERT IGNORE INTO `__PREFIX__dinghorn_variable` VALUES ('1', 'user_count', '0', 'SELECT count(id) as id FROM __PREFIX__user', '', '', '', '', '1562132190', '1562123868', null);
  99 +INSERT IGNORE INTO `__PREFIX__dinghorn_variable` VALUES ('2', 'test', '1', '', 'app\\admin\\controller\\dinghorn', 'Example', 'test', '我是传递过来的参数', '1562132323', '1562124050', null);
  100 +COMMIT;
  101 +
  102 +-- ----------------------------
  103 +-- 旧版本增加字段处理
  104 +-- ----------------------------
  105 +BEGIN;
  106 +ALTER TABLE `__PREFIX__dinghorn_robot` ADD COLUMN `keywords` varchar(100) NOT NULL DEFAULT '' COMMENT '自定义关键词' AFTER `access_token`;
  107 +ALTER TABLE `__PREFIX__dinghorn_robot` ADD COLUMN `sign` varchar(100) NOT NULL DEFAULT '' COMMENT '签名密匙' AFTER `access_token`;
  108 +COMMIT;
  109 +BEGIN;
  110 +ALTER TABLE `__PREFIX__dinghorn_template` ADD COLUMN `code` varchar(50) NOT NULL DEFAULT '' COMMENT '模板Code' AFTER `id`;
  111 +COMMIT;
  112 +
  113 +-- ----------------------------
  114 +-- 旧版本修改字段处理
  115 +-- ----------------------------
  116 +BEGIN;
  117 +ALTER TABLE `__PREFIX__dinghorn_template` MODIFY COLUMN `content` text DEFAULT NULL COMMENT '默认消息内容' AFTER `typelist`;
  118 +ALTER TABLE `__PREFIX__dinghorn_template` MODIFY COLUMN `msg_url` varchar(255) NOT NULL DEFAULT '' COMMENT '默认图片URL' AFTER `title`;
  119 +ALTER TABLE `__PREFIX__dinghorn_template` MODIFY COLUMN `picurl_image` varchar(255) NOT NULL DEFAULT '' COMMENT '默认图片URL' AFTER `msg_url`;
  120 +COMMIT;
  121 +
  122 +BEGIN;
  123 +ALTER TABLE `__PREFIX__dinghorn_msglog` MODIFY COLUMN `errmsg` varchar(255) NOT NULL DEFAULT '' COMMENT '错误消息' AFTER `template_data`;
  124 +ALTER TABLE `__PREFIX__dinghorn_variable` MODIFY COLUMN `sql` varchar(255) NOT NULL DEFAULT '' COMMENT 'SQL' AFTER `value_source`;
  125 +COMMIT;
  1 +<?php
  2 +
  3 +namespace addons\dinghorn\library;
  4 +
  5 +/**
  6 + *
  7 + */
  8 +class DinghornLib
  9 +{
  10 + // 模板数据
  11 + public $template;
  12 +
  13 + // 要覆盖的模板数据 (参见:\application\admin\controller\dinghorn\Example.php 的 example2 方法)
  14 + public $tpl_data;
  15 +
  16 + // 模板变量键值对,若模板变量已预先定义,则会自动获取值,无需在此传递
  17 + public $tpl_variable;
  18 +
  19 + /**
  20 + * 构造方法
  21 + * @param array $template 模板数据
  22 + * @param array $tpl_data 要覆盖的模板数据
  23 + * @param array $tpl_variable 模板变量键值对
  24 + */
  25 + public function __construct($template = array(), $tpl_data = array(), $tpl_variable = array())
  26 + {
  27 + $this->template = $template;
  28 + $this->tpl_data = $tpl_data;
  29 + $this->tpl_variable = $tpl_variable;
  30 + }
  31 +
  32 + /**
  33 + * 发起请求
  34 + * @param string $access_token 机器人的 access_token
  35 + * @param array $post_data 请求数据
  36 + * @return array 请求结果
  37 + */
  38 + public function msgSend($access_token, $post_data, $sign = false)
  39 + {
  40 + $remote_server = 'https://oapi.dingtalk.com/robot/send?access_token=' . $access_token;
  41 +
  42 + if ($sign) {
  43 + $millisecond = $this->getMillisecond();
  44 + $sign_str = $millisecond . "\n" . $sign;
  45 + $sign_str = hash_hmac('sha256', $sign_str, $sign, true);
  46 + $sign_str = urlencode(base64_encode($sign_str));
  47 + $remote_server .= '&timestamp=' . $millisecond . '&sign=' . $sign_str;
  48 + }
  49 +
  50 + $ch = curl_init();
  51 + curl_setopt($ch, CURLOPT_URL, $remote_server);
  52 + curl_setopt($ch, CURLOPT_POST, 1);
  53 + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
  54 + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json;charset=utf-8'));
  55 + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
  56 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  57 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
  58 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
  59 + $ret = curl_exec($ch);
  60 +
  61 + if (false == $ret) {
  62 + // curl_exec failed
  63 + $result = ['errcode' => -2, 'errmsg' => curl_error($ch)];
  64 + } else {
  65 + $rsp = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  66 + if (200 != $rsp) {
  67 + $result = ['errcode' => -1, 'errmsg' => $rsp . ' ' . curl_error($ch)];
  68 + } else {
  69 + $result = json_decode($ret, true);
  70 + if (!$result) {
  71 + $result = ['errcode' => -3, 'errmsg' => '转换请求结果数据失败!'];
  72 + }
  73 + }
  74 + }
  75 +
  76 + curl_close($ch);
  77 + return $result;
  78 + }
  79 +
  80 + public function getMillisecond()
  81 + {
  82 + list($microsecond, $time) = explode(' ', microtime()); //' '中间是一个空格
  83 + return (float)sprintf('%.0f', (floatval($microsecond) + floatval($time)) * 1000);
  84 + }
  85 +
  86 + /**
  87 + * 组装消息数据
  88 + * @return array 组装结果
  89 + */
  90 + public function deal_with_msg()
  91 + {
  92 + $msg_data = array();
  93 + $msgtype = $msg_data['msgtype'] = $this->template['typelist'];
  94 +
  95 + if (isset($this->tpl_data['content'])) {
  96 + $content = $this->analysis_variable($this->tpl_data['content']);
  97 + } else {
  98 + $content = $this->analysis_variable($this->template['content']);
  99 + }
  100 +
  101 + if (isset($this->tpl_data['title'])) {
  102 + $title = $this->analysis_variable($this->tpl_data['title']);
  103 + } else {
  104 + $title = $this->analysis_variable($this->template['title']);
  105 + }
  106 +
  107 + if ($msgtype == 'text') {
  108 +
  109 + $msg_data['text'] = [
  110 + 'content' => $content
  111 + ];
  112 + $msg_data['at'] = $this->deal_with_at();
  113 + } elseif ($msgtype == 'link') {
  114 +
  115 + $msg_data['link'] = [
  116 + 'title' => $title,
  117 + 'text' => $content,
  118 + 'picUrl' => request()->domain() . (isset($this->tpl_data['picurl_image']) ? $this->tpl_data['picurl_image'] : cdnurl($this->template['picurl_image'])),
  119 + 'messageUrl' => isset($this->tpl_data['msg_url']) ? $this->tpl_data['msg_url'] : $this->template['msg_url'],
  120 + ];
  121 + } elseif ($msgtype == 'markdown') {
  122 +
  123 + $msg_data['markdown'] = [
  124 + 'title' => $title,
  125 + 'text' => $content
  126 + ];
  127 + $msg_data['at'] = $this->deal_with_at();
  128 + } elseif ($msgtype == 'actionCard_whole') {
  129 +
  130 + $msg_data['msgtype'] = 'actionCard';
  131 + $msg_data['actionCard'] = [
  132 + 'title' => $title,
  133 + 'text' => $content,
  134 + 'hideAvatar' => isset($this->tpl_data['hide_avatar']) ? $this->tpl_data['hide_avatar'] : $this->template['hide_avatar'],
  135 + 'btnOrientation' => 1,
  136 + 'singleTitle' => isset($this->tpl_data['single_title']) ? $this->analysis_variable($this->tpl_data['single_title']) : $this->analysis_variable($this->template['single_title']),
  137 + 'singleURL' => isset($this->tpl_data['msg_url']) ? $this->tpl_data['msg_url'] : $this->template['msg_url']
  138 + ];
  139 + } elseif ($msgtype == 'actionCard') {
  140 +
  141 + $btns = isset($this->tpl_data['btns']) ? $this->tpl_data['btns'] : json_decode($this->template['btns'], true);
  142 + $btns_temp = [];
  143 + foreach ($btns as $key => $value) {
  144 + $btns_temp[] = array(
  145 + 'title' => $this->analysis_variable($key),
  146 + 'actionURL' => $value
  147 + );
  148 + }
  149 +
  150 + $msg_data['actionCard'] = [
  151 + 'title' => $title,
  152 + 'text' => $content,
  153 + 'hideAvatar' => isset($this->tpl_data['hide_avatar']) ? $this->tpl_data['hide_avatar'] : $this->template['hide_avatar'],
  154 + 'btnOrientation' => isset($this->tpl_data['btn_orientation']) ? $this->tpl_data['btn_orientation'] : $this->template['btn_orientation'],
  155 + 'btns' => $btns_temp
  156 + ];
  157 + } elseif ($msgtype == 'feedCard') {
  158 +
  159 + $links = isset($this->tpl_data['links']) ? $this->tpl_data['links'] : json_decode($this->template['links'], true);
  160 + foreach ($links as $key => $value) {
  161 + $links[$key]['title'] = $this->analysis_variable($links[$key]['title']);
  162 + }
  163 + $msg_data['feedCard'] = array(
  164 + 'links' => $links
  165 + );
  166 + }
  167 +
  168 + return $msg_data;
  169 + }
  170 +
  171 + /**
  172 + * 分析字符串中的自定义变量
  173 + * @param string $str 要分析的字符串
  174 + * @return string 解析过变量的字符串
  175 + */
  176 + public function analysis_variable($str)
  177 + {
  178 + if (!$str) {
  179 + return '';
  180 + }
  181 +
  182 + $variables = array();
  183 + $match = array();
  184 + preg_match_all('/\${(.*?)}/', $str, $match);// 匹配到所有变量
  185 +
  186 + // 读取数据库中的模板变量
  187 + $variable_tmp = \think\Db::name('dinghorn_variable')->where('deletetime', null)->select();
  188 + foreach ($variable_tmp as $key => $value) {
  189 + $value['variable_type'] = 'predefined';// 标记为预定义
  190 + $variable_arr[$value['name']] = $value;
  191 + }
  192 + unset($variable_tmp);
  193 +
  194 + // 准备传递过来的模板变量
  195 + foreach ($this->tpl_variable as $key => $value) {
  196 + $variable_arr[$key] = [
  197 + 'variable_type' => 'definition_now',// 标记为现在定义
  198 + 'variable_value' => $value,
  199 + ];
  200 + }
  201 +
  202 + foreach ($match[1] as $key => $value) {
  203 +
  204 + if (array_key_exists($value, $variable_arr)) {
  205 +
  206 + if ($variable_arr[$value]['variable_type'] == 'definition_now') {
  207 +
  208 + $str = str_replace($match[0][$key], $variable_arr[$value]['variable_value'], $str);
  209 + } else if ($variable_arr[$value]['variable_type'] == 'predefined') {
  210 +
  211 + $variable_value = $this->get_variable_value($variable_arr[$value]);
  212 + $str = str_replace($match[0][$key], $variable_value, $str);
  213 + }
  214 + }
  215 + }
  216 +
  217 + return $str;
  218 + }
  219 +
  220 + /**
  221 + * 获取数据库中的模板变量的值
  222 + * @param string $var 变量数据
  223 + * @return string 变量值
  224 + */
  225 + public function get_variable_value($var)
  226 + {
  227 + if ($var['value_source'] == 0) {
  228 + $var['sql'] = str_replace('__PREFIX__', config('database.prefix'), $var['sql']);
  229 + $res = \think\Db::query($var['sql']);
  230 +
  231 + if ($res) {
  232 + if (is_array($res[0])) {
  233 + foreach ($res[0] as $key => $value) {
  234 + return $value;
  235 + }
  236 + } else {
  237 + return $res[0];
  238 + }
  239 + } else {
  240 + return false;
  241 + }
  242 + } else if ($var['value_source'] == 1) {
  243 + return \think\Hook::exec($var['namespace'] . '\\' . $var['class'], $var['function'], $var['params']);
  244 + }
  245 + }
  246 +
  247 + /**
  248 + * 组装at数据
  249 + * @return array 组装结果
  250 + */
  251 + public function deal_with_at()
  252 + {
  253 + // 数据覆盖
  254 + if (isset($this->tpl_data['is_atall']) || isset($this->tpl_data['at_mobiles'])) {
  255 + $this->template['is_atall'] = $this->tpl_data['is_atall'];
  256 + $this->template['at_mobiles'] = $this->tpl_data['at_mobiles'];
  257 + }
  258 +
  259 + if ($this->template['is_atall']) {
  260 + return [
  261 + 'atMobiles' => [],
  262 + 'isAtAll' => true
  263 + ];
  264 + } else {
  265 + $at_mobiles = explode(',', rtrim($this->template['at_mobiles'], ','));
  266 +
  267 + return [
  268 + 'atMobiles' => $at_mobiles,
  269 + 'isAtAll' => false
  270 + ];
  271 + }
  272 + }
  273 +}
  1 +{"license":"regular","licenseto":"44234","licensekey":"6qJ3LtcpOF9kyEMe zkiFXjRlekb5mI3LKKPbQw==","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\/baidumap","example\/baidumap\/index","example\/baidumap\/map","example\/baidumap\/del","example\/echarts","example\/echarts\/index"],"files":["application\\admin\\controller\\example\\Baidumap.php","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\\baidumap\\index.html","application\\admin\\view\\example\\baidumap\\map.html","application\\admin\\view\\example\\bootstraptable\\detail.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\\baidumap.js","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\\js\\async.js"]}
  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/baidumap',
  134 + 'title' => '百度地图示例',
  135 + 'icon' => 'fa fa-map-pin',
  136 + 'sublist' => [
  137 + ['name' => 'example/baidumap/index', 'title' => '查看'],
  138 + ['name' => 'example/baidumap/map', 'title' => '详情'],
  139 + ['name' => 'example/baidumap/del', 'title' => '删除'],
  140 + ]
  141 + ],
  142 + [
  143 + 'name' => 'example/echarts',
  144 + 'title' => '统计图表示例',
  145 + 'icon' => 'fa fa-bar-chart',
  146 + 'sublist' => [
  147 + ['name' => 'example/echarts/index', 'title' => '查看'],
  148 + ]
  149 + ],
  150 + ]
  151 + ]
  152 + ];
  153 + Menu::create($menu);
  154 + return true;
  155 + }
  156 +
  157 + /**
  158 + * 插件卸载方法
  159 + * @return bool
  160 + */
  161 + public function uninstall()
  162 + {
  163 + Menu::delete('example');
  164 + return true;
  165 + }
  166 +
  167 + /**
  168 + * 插件启用方法
  169 + */
  170 + public function enable()
  171 + {
  172 + Menu::enable('example');
  173 + }
  174 +
  175 + /**
  176 + * 插件禁用方法
  177 + */
  178 + public function disable()
  179 + {
  180 + Menu::disable('example');
  181 + }
  182 +
  183 +}
  1 +require.config({
  2 + paths: {
  3 + 'async': '../addons/example/js/async',
  4 + 'BMap': ['//api.map.baidu.com/api?v=2.0&ak=mXijumfojHnAaN2VxpBGoqHM'],
  5 + },
  6 + shim: {
  7 + 'BMap': {
  8 + deps: ['jquery'],
  9 + exports: 'BMap'
  10 + }
  11 + }
  12 +});
  1 +<?php
  2 +
  3 +return [
  4 + [
  5 + 'name' => 'title',
  6 + 'title' => '标题',
  7 + 'type' => 'string',
  8 + 'content' => [
  9 + ],
  10 + 'value' => '示例标题',
  11 + 'rule' => 'required',
  12 + 'msg' => '',
  13 + 'tip' => '',
  14 + 'ok' => '',
  15 + 'extend' => ''
  16 + ],
  17 + [
  18 + //配置唯一标识
  19 + 'name' => 'theme',
  20 + //显示的标题
  21 + 'title' => '皮肤',
  22 + //类型
  23 + 'type' => 'string',
  24 + //数据字典
  25 + 'content' => [
  26 + ],
  27 + //值
  28 + 'value' => 'default',
  29 + //验证规则
  30 + 'rule' => 'required',
  31 + //错误消息
  32 + 'msg' => '',
  33 + //提示消息
  34 + 'tip' => '',
  35 + //成功消息
  36 + 'ok' => '',
  37 + //扩展信息
  38 + 'extend' => ''
  39 + ],
  40 + [
  41 + 'name' => 'domain',
  42 + 'title' => '绑定二级域名前缀',
  43 + 'type' => 'string',
  44 + 'content' => [
  45 + ],
  46 + 'value' => '',
  47 + 'rule' => '',
  48 + 'msg' => '',
  49 + 'tip' => '',
  50 + 'ok' => '',
  51 + 'extend' => ''
  52 + ],
  53 + [
  54 + 'name' => 'rewrite',
  55 + 'title' => '伪静态',
  56 + 'type' => 'array',
  57 + 'content' => [],
  58 + 'value' => [
  59 + 'index/index' => '/example$',
  60 + 'demo/index' => '/example/d/[:name]',
  61 + 'demo/demo1' => '/example/d1/[:name]',
  62 + 'demo/demo2' => '/example/d2/[:name]',
  63 + ],
  64 + 'rule' => 'required',
  65 + 'msg' => '',
  66 + 'tip' => '',
  67 + 'ok' => '',
  68 + 'extend' => ''
  69 + ],
  70 +];
  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.0
  7 +state = 1
  8 +url = /addons/example
  9 +license = regular
  10 +licenseto = 44234
此 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}</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}</p>
  23 + <p class="well">你好!{$user.nickname},<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}</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 + <li data-target="#myCarousel" data-slide-to="1"></li>
  7 + <li data-target="#myCarousel" data-slide-to="2"></li>
  8 + <li data-target="#myCarousel" data-slide-to="3"></li>
  9 + </ol>
  10 +
  11 + <!-- Wrapper for slides -->
  12 + <div class="carousel-inner">
  13 + <div class="item active">
  14 + <a href="https://www.fastadmin.net/store/cms.html" target="_blank">
  15 + <div class="fill" style="background-image:url('https://bg.fastadmin.net?text=random&color=3498db');"></div>
  16 + <div class="carousel-body">
  17 + <div class="container">
  18 + <h1 class="display-1 text-white">CMS内容管理模块</h1>
  19 + <h2 class="display-4 text-white">简单强大的内容管理系统,可自定义内容模型、标签、伪静态、全文搜索、百度推送等功能<br>包含完整的小程序CMS客户端,拥有完善的资讯模块、产品模块、评论模块、会员模块</h2>
  20 + </div>
  21 + </div>
  22 + </a>
  23 + </div>
  24 + <div class="item">
  25 + <a href="https://www.fastadmin.net/store/blog.html" target="_blank">
  26 + <div class="fill" style="background-image:url('https://bg.fastadmin.net?text=random&color=2ecc71');"></div>
  27 + <div class="carousel-body">
  28 + <div class="container">
  29 + <h1 class="display-1 text-white">简单博客模块</h1>
  30 + <h2 class="display-4 text-white">响应式博客插件,包含日志、评论、分类、归档、全文搜索、百度推送等功能<br/>包含完整的小程序博客客户端,拥有博客日志列表、日志详情、评论等功能</h2>
  31 + </div>
  32 + </div>
  33 + </a>
  34 + </div>
  35 + <div class="item">
  36 + <a href="https://www.fastadmin.net/store/vote.html" target="_blank">
  37 + <div class="fill" style="background-image:url('https://bg.fastadmin.net?text=random&color=0082ff');"></div>
  38 + <div class="carousel-body">
  39 + <div class="container">
  40 + <h1 class="display-1 text-white">在线投票系统</h1>
  41 + <h2 class="display-4 text-white">基于FastAdmin+ThinkPHP开发的响应式在线投票系统,支持微信公众号投票和PC端投票<br/>具有高防刷票机制和实时排行榜等诸多特性,提供全部前后台无加密源代码</h2>
  42 + </div>
  43 + </div>
  44 + </a>
  45 + </div>
  46 + <div class="item">
  47 + <a href="https://www.fastadmin.net/store/docs.html" target="_blank">
  48 + <div class="fill" style="background-image:url('https://bg.fastadmin.net?text=random&color=9c88ff');"></div>
  49 + <div class="carousel-body">
  50 + <div class="container">
  51 + <h1 class="display-1 text-white">Markdown文档生成</h1>
  52 + <h2 class="display-4 text-white">将Github或本地Git环境中的Markdown文件解析并生成HTML,可在线浏览或导出为HTML离线浏览</h2>
  53 + </div>
  54 + </div>
  55 + </a>
  56 + </div>
  57 + </div>
  58 +</header>
  59 +
  60 +<!-- Page Content -->
  61 +<div class="container">
  62 +
  63 + <!-- Marketing Icons Section -->
  64 + <div class="row">
  65 + <div class="col-lg-12">
  66 + <h2 class="page-header">
  67 + 基础模块
  68 + </h2>
  69 + </div>
  70 + <div class="col-md-4">
  71 + <div class="panel panel-default">
  72 + <div class="panel-heading">
  73 + <h4><i class="fa fa-fw fa-user"></i> 前台模块</h4>
  74 + </div>
  75 + <div class="panel-body">
  76 + <p>FastAdmin有基础的前台模块,可快速的进行二次开发,前台模块中包含基础的会员模块,前台模块中的会员账号和API模块中的会员账号是同一账号体系</p>
  77 + <a href="{:url('index/index/index')}" target="_blank" class="btn btn-primary">立即访问</a>
  78 + <a href="{:url('index/user/index')}" target="_blank" class="btn btn-default">会员中心</a>
  79 + </div>
  80 + </div>
  81 + </div>
  82 + <div class="col-md-4">
  83 + <div class="panel panel-default">
  84 + <div class="panel-heading">
  85 + <h4><i class="fa fa-fw fa-gift"></i> API模块</h4>
  86 + </div>
  87 + <div class="panel-body">
  88 + <p>FastAdmin有基础的API模块,可快速的进行二次开发,API模块中包含基础的会员模块,初始化模块、短信发送模块、验证模块</p>
  89 + <a href="{:url('api/index/index')}" target="_blank" class="btn btn-primary">立即访问</a>
  90 + <a href="{:url('api/common/init')}?version=1.0.0" target="_blank" class="btn btn-default">初始化接口</a>
  91 + </div>
  92 + </div>
  93 + </div>
  94 + <div class="col-md-4">
  95 + <div class="panel panel-default">
  96 + <div class="panel-heading">
  97 + <h4><i class="fa fa-fw fa-compass"></i> API文档</h4>
  98 + </div>
  99 + <div class="panel-body">
  100 + <p>我们提供了一键生成API文档的功能,当写完API接口以后,可通过执行php think api一键生成我们所需要的API文档,并且可以直接在线测试</p>
  101 + <a href="{:url('/')}api.html" target="_blank" class="btn btn-primary">立即访问</a>
  102 + <a href="https://doc.fastadmin.net/docs/command.html#一键生成API文档" target="_blank" class="btn btn-default">一键生成文档</a>
  103 + </div>
  104 + </div>
  105 + </div>
  106 + </div>
  107 + <div class="row">
  108 + <div class="col-lg-12">
  109 + <h2 class="page-header">
  110 + 功能示例
  111 + </h2>
  112 + </div>
  113 + <div class="col-md-4">
  114 + <div class="panel panel-default">
  115 + <div class="panel-heading">
  116 + <h4><i class="fa fa-fw fa-check"></i> 使用模板标签和变量</h4>
  117 + </div>
  118 + <div class="panel-body">
  119 + <p>在FastAdmin插件的视图中我们可以像前后台开发一样,向视图中渲染我们的自定义变量,然后在视图中进行访问。同时FastAdmin的插件视图中支持所有ThinkPHP5官方的系统模板标签和变量。轻轻松松的开发我们的插件</p>
  120 + <a href="{:addon_url('example/demo/index',[':name'=>'s1'])}" class="btn btn-success">查看示例</a>
  121 + </div>
  122 + </div>
  123 + </div>
  124 + <div class="col-md-4">
  125 + <div class="panel panel-default">
  126 + <div class="panel-heading">
  127 + <h4><i class="fa fa-fw fa-gift"></i> 访问不需要登录的页面</h4>
  128 + </div>
  129 + <div class="panel-body">
  130 + <p>在开发的过程有许多页面是不需要会员登录就可以访问的页面,比如新闻列表、新闻详情、评论列表、产品列表、产品展示、关于我们等等页面。在FastAdmin中可以使用noNeedLogin很方便的控制我们请求方法的访问权限</p>
  131 + <a href="{:addon_url('example/demo/demo1',[':name'=>'s2'])}" class="btn btn-success">立即访问</a>
  132 + </div>
  133 + </div>
  134 + </div>
  135 + <div class="col-md-4">
  136 + <div class="panel panel-default">
  137 + <div class="panel-heading">
  138 + <h4><i class="fa fa-fw fa-compass"></i> 访问需要登录的页面</h4>
  139 + </div>
  140 + <div class="panel-body">
  141 + <p>通常我们在开发中,如果页面与会员信息相关联,则通常需要控制页面在会员登录后才可以访问,FastAdmin中前台的权限控制可以很快捷的在插件中使用。我们可以直接重新定义noNeedLogin排除我们不需要登录的方法即可。</p>
  142 + <a href="{:addon_url('example/demo/demo2',[':name'=>'s3'])}" class="btn btn-success">立即访问</a>
  143 + </div>
  144 + </div>
  145 + </div>
  146 + </div>
  147 + <!-- /.row -->
  148 +
  149 + <div class="row addonlist">
  150 + <div class="col-lg-12">
  151 + <h2 class="page-header">
  152 + 模块&插件
  153 + <span class="pull-right small" style="margin-top:5px;">
  154 + <small>
  155 + <a href="https://www.fastadmin.net/store.html" target="_blank">更多</a>
  156 + </small>
  157 + </span>
  158 + </h2>
  159 + </div>
  160 + <div class="col-md-4 col-sm-6">
  161 + <a href="https://www.fastadmin.net/store/cms.html" target="_blank">
  162 + <img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/cms.png" alt="">
  163 + <p>CMS内容管理模块</p>
  164 + </a>
  165 + </div>
  166 + <div class="col-md-4 col-sm-6">
  167 + <a href="https://www.fastadmin.net/store/blog.html" target="_blank">
  168 + <img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/blog.png" alt="">
  169 + <p>简洁博客模块</p>
  170 + </a>
  171 + </div>
  172 + <div class="col-md-4 col-sm-6">
  173 + <a href="https://www.fastadmin.net/store/ask.html" target="_blank">
  174 + <img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/ask.png" alt="">
  175 + <p>付费问答社区</p>
  176 + </a>
  177 + </div>
  178 + <div class="col-md-4 col-sm-6">
  179 + <a href="https://www.fastadmin.net/store/docs.html" target="_blank">
  180 + <img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/docs.png" alt="">
  181 + <p>文档生成模块</p>
  182 + </a>
  183 + </div>
  184 + <div class="col-md-4 col-sm-6">
  185 + <a href="https://www.fastadmin.net/store/vote.html" target="_blank">
  186 + <img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/vote.png" alt="">
  187 + <p>在线投票系统</p>
  188 + </a>
  189 + </div>
  190 + <div class="col-md-4 col-sm-6">
  191 + <a href="https://www.fastadmin.net/store/qiniu.html" target="_blank">
  192 + <img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/qiniu.png" alt="">
  193 + <p>七牛上传插件</p>
  194 + </a>
  195 + </div>
  196 + <div class="col-md-4 col-sm-6">
  197 + <a href="https://www.fastadmin.net/store/alioss.html" target="_blank">
  198 + <img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/alioss.png" alt="">
  199 + <p>阿里云储存</p>
  200 + </a>
  201 + </div>
  202 + <div class="col-md-4 col-sm-6">
  203 + <a href="https://www.fastadmin.net/store/alisms.html" target="_blank">
  204 + <img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/alisms.png" alt="">
  205 + <p>阿里云短信</p>
  206 + </a>
  207 + </div>
  208 + <div class="col-md-4 col-sm-6">
  209 + <a href="https://www.fastadmin.net/store/nkeditor.html" target="_blank">
  210 + <img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/nkeditor.png" alt="">
  211 + <p>富文本编辑器</p>
  212 + </a>
  213 + </div>
  214 + <div class="col-xs-12 text-center">
  215 + <a href="https://www.fastadmin.net/store.html" class="btn btn-primary" target="_blank">前往插件市场</a>
  216 + </div>
  217 + </div>
  218 + <!-- /.row -->
  219 +
  220 + <hr>
  221 +
  222 + <!-- Call to Action Section -->
  223 + <div class="well">
  224 + <div class="row">
  225 + <div class="col-md-8">
  226 + <p>感谢你对FastAdmin的支持!如果你在使用FastAdmin开发插件的过程中有任何疑问或需要寻求帮助,请前往FastAdmin问答社区与小伙伴们一起交流。</p>
  227 + </div>
  228 + <div class="col-md-4">
  229 + <a class="btn btn-lg btn-default btn-block" href="https://ask.fastadmin.net" target="_blank">前往问答社区</a>
  230 + </div>
  231 + </div>
  232 + </div>
  233 +
  234 + <hr>
  235 +
  236 +</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}</title>
  13 +
  14 + <!-- Bootstrap Core CSS -->
  15 + <link href="https://cdn.bootcss.com/bootstrap/3.3.7/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="https://cdn.bootcss.com/font-awesome/4.6.3/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.bootcss.com/html5shiv/3.7.0/html5shiv.min.js"></script>
  27 + <script src="https://cdn.bootcss.com/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}</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}<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} 2020</p>
  102 + </div>
  103 + </div>
  104 + </footer>
  105 +
  106 + </div>
  107 + <!-- /.container -->
  108 +
  109 + <!-- jQuery -->
  110 + <script src="https://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
  111 +
  112 + <!-- Bootstrap Core JavaScript -->
  113 + <script src="https://cdn.bootcss.com/bootstrap/3.3.7/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 +{"license":"regular","licenseto":"44313","licensekey":"du5NmPJGr8CAhklp lp8HJdQAyDxpIksBLSeNvcEjyVWIq5zimSldyRTaaQM=","menus":["inspection","inspection\/depart","inspection\/depart\/index","inspection\/depart\/add","inspection\/depart\/edit","inspection\/depart\/del","inspection\/depart\/multi","inspection\/staff","inspection\/staff\/index","inspection\/staff\/add","inspection\/staff\/edit","inspection\/staff\/del","inspection\/staff\/multi","inspection\/area","inspection\/area\/index","inspection\/area\/add","inspection\/area\/edit","inspection\/area\/del","inspection\/area\/multi","inspection\/areasite","inspection\/areasite\/index","inspection\/areasite\/add","inspection\/areasite\/edit","inspection\/areasite\/del","inspection\/areasite\/multi","inspection\/areaitem","inspection\/areaitem\/index","inspection\/areaitem\/add","inspection\/areaitem\/edit","inspection\/areaitem\/del","inspection\/areaitem\/multi","inspection\/route","inspection\/route\/index","inspection\/route\/add","inspection\/route\/edit","inspection\/route\/del","inspection\/route\/multi","inspection\/plan","inspection\/plan\/index","inspection\/plan\/add","inspection\/plan\/edit","inspection\/plan\/del","inspection\/plan\/multi","inspection\/project","inspection\/project\/index","inspection\/project\/add","inspection\/project\/edit","inspection\/project\/del","inspection\/project\/multi"],"files":["application\/api\/controller\/inspection\/Route.php","application\/api\/controller\/inspection\/Staff.php","application\/api\/controller\/inspection\/Project.php","application\/admin\/lang\/zh-cn\/inspection\/route.php","application\/admin\/lang\/zh-cn\/inspection\/project.php","application\/admin\/lang\/zh-cn\/inspection\/plan.php","application\/admin\/model\/inspection\/Route.php","application\/admin\/model\/inspection\/Routesite.php","application\/admin\/model\/inspection\/Area.php","application\/admin\/model\/inspection\/Areaitem.php","application\/admin\/model\/inspection\/Plan.php","application\/admin\/model\/inspection\/Areasite.php","application\/admin\/model\/inspection\/Staff.php","application\/admin\/model\/inspection\/Projectitem.php","application\/admin\/model\/inspection\/Depart.php","application\/admin\/model\/inspection\/Project.php","application\/admin\/model\/inspection\/Lnglat.php","application\/admin\/view\/inspection\/route\/sel_area_site.html","application\/admin\/view\/inspection\/route\/edit.html","application\/admin\/view\/inspection\/route\/add.html","application\/admin\/view\/inspection\/route\/index.html","application\/admin\/view\/inspection\/depart\/edit.html","application\/admin\/view\/inspection\/depart\/add.html","application\/admin\/view\/inspection\/depart\/index.html","application\/admin\/view\/inspection\/projectitem\/index.html","application\/admin\/view\/inspection\/area\/edit.html","application\/admin\/view\/inspection\/area\/add.html","application\/admin\/view\/inspection\/area\/index.html","application\/admin\/view\/inspection\/areasite\/ercode.html","application\/admin\/view\/inspection\/areasite\/edit.html","application\/admin\/view\/inspection\/areasite\/add.html","application\/admin\/view\/inspection\/areasite\/index.html","application\/admin\/view\/inspection\/staff\/edit.html","application\/admin\/view\/inspection\/staff\/add.html","application\/admin\/view\/inspection\/staff\/index.html","application\/admin\/view\/inspection\/plan\/sel_staff.html","application\/admin\/view\/inspection\/plan\/edit.html","application\/admin\/view\/inspection\/plan\/add.html","application\/admin\/view\/inspection\/plan\/index.html","application\/admin\/view\/inspection\/areaitem\/edit.html","application\/admin\/view\/inspection\/areaitem\/add.html","application\/admin\/view\/inspection\/project\/edit.html","application\/admin\/view\/inspection\/project\/add.html","application\/admin\/view\/inspection\/project\/index.html","application\/admin\/validate\/inspection\/Route.php","application\/admin\/validate\/inspection\/Plan.php","application\/admin\/validate\/inspection\/Project.php","application\/admin\/controller\/inspection\/Route.php","application\/admin\/controller\/inspection\/Area.php","application\/admin\/controller\/inspection\/Areaitem.php","application\/admin\/controller\/inspection\/Plan.php","application\/admin\/controller\/inspection\/Areasite.php","application\/admin\/controller\/inspection\/Staff.php","application\/admin\/controller\/inspection\/Projectitem.php","application\/admin\/controller\/inspection\/Depart.php","application\/admin\/controller\/inspection\/Project.php","public\/assets\/addons\/inspection\/qrcode\/index.txt","public\/assets\/js\/backend\/inspection\/areasite.js","public\/assets\/js\/backend\/inspection\/projectitem.js","public\/assets\/js\/backend\/inspection\/areaitem.js","public\/assets\/js\/backend\/inspection\/route.js","public\/assets\/js\/backend\/inspection\/area.js备份20231205","public\/assets\/js\/backend\/inspection\/staff.js","public\/assets\/js\/backend\/inspection\/plan.js","public\/assets\/js\/backend\/inspection\/project.js","public\/assets\/js\/backend\/inspection\/depart.js"]}
  1 +<?php
  2 +
  3 +namespace addons\inspection;
  4 +
  5 +use app\common\library\Menu;
  6 +use think\Addons;
  7 +
  8 +/**
  9 + * 插件
  10 + */
  11 +class Inspection extends Addons
  12 +{
  13 +
  14 + /**
  15 + * 插件安装方法
  16 + * @return bool
  17 + */
  18 + public function install()
  19 + {
  20 + $menu = [
  21 + [
  22 + 'name' => 'inspection',
  23 + 'title' => '设备巡检',
  24 + 'icon' => 'fa fa-font-awesome',
  25 + 'sublist' => [
  26 + [
  27 + "name" => "inspection/depart",
  28 + "title" => "部门管理",
  29 + 'icon' => 'fa fa-users',
  30 + 'sublist' => [
  31 + ["name" => "inspection/depart/index", "title" => "查看",],
  32 + ["name" => "inspection/depart/add", "title" => "添加"],
  33 + ["name" => "inspection/depart/edit", "title" => "编辑"],
  34 + ["name" => "inspection/depart/del", "title" => "删除"],
  35 + ["name" => "inspection/depart/multi", "title" => "批量更新"],
  36 + ]
  37 + ],
  38 + [
  39 + "name" => "inspection/staff",
  40 + "title" => "员工管理",
  41 + 'icon' => 'fa fa-user',
  42 + 'sublist' => [
  43 + ["name" => "inspection/staff/index", "title" => "查看",],
  44 + ["name" => "inspection/staff/add", "title" => "添加"],
  45 + ["name" => "inspection/staff/edit", "title" => "编辑"],
  46 + ["name" => "inspection/staff/del", "title" => "删除"],
  47 + ["name" => "inspection/staff/multi", "title" => "批量更新"],
  48 + ]
  49 + ],
  50 + [
  51 + "name" => "inspection/area",
  52 + "title" => "巡检区域管理",
  53 + 'icon' => 'fa fa-braille',
  54 + 'sublist' => [
  55 + ["name" => "inspection/area/index", "title" => "查看",],
  56 + ["name" => "inspection/area/add", "title" => "添加"],
  57 + ["name" => "inspection/area/edit", "title" => "编辑"],
  58 + ["name" => "inspection/area/del", "title" => "删除"],
  59 + ["name" => "inspection/area/multi", "title" => "批量更新"],
  60 + ]
  61 + ],
  62 + [
  63 + "name" => "inspection/areasite",
  64 + "title" => "巡检点管理",
  65 + 'icon' => 'fa fa-anchor',
  66 + 'sublist' => [
  67 + ["name" => "inspection/areasite/index", "title" => "查看",],
  68 + ["name" => "inspection/areasite/add", "title" => "添加"],
  69 + ["name" => "inspection/areasite/edit", "title" => "编辑"],
  70 + ["name" => "inspection/areasite/del", "title" => "删除"],
  71 + ["name" => "inspection/areasite/multi", "title" => "批量更新"],
  72 + ]
  73 + ],
  74 + [
  75 + "name" => "inspection/areaitem",
  76 + "title" => "检查项管理",
  77 + 'ismenu' => 0,
  78 + 'sublist' => [
  79 + ["name" => "inspection/areaitem/index", "title" => "查看",],
  80 + ["name" => "inspection/areaitem/add", "title" => "添加"],
  81 + ["name" => "inspection/areaitem/edit", "title" => "编辑"],
  82 + ["name" => "inspection/areaitem/del", "title" => "删除"],
  83 + ["name" => "inspection/areaitem/multi", "title" => "批量更新"],
  84 + ]
  85 + ],
  86 + [
  87 + "name" => "inspection/route",
  88 + "title" => "巡检路线管理",
  89 + 'icon' => 'fa fa-map',
  90 + 'sublist' => [
  91 + ["name" => "inspection/route/index", "title" => "查看",],
  92 + ["name" => "inspection/route/add", "title" => "添加"],
  93 + ["name" => "inspection/route/edit", "title" => "编辑"],
  94 + ["name" => "inspection/route/del", "title" => "删除"],
  95 + ["name" => "inspection/route/multi", "title" => "批量更新"],
  96 + ]
  97 + ],
  98 + [
  99 + "name" => "inspection/plan",
  100 + "title" => "巡检计划管理",
  101 + 'icon' => 'fa fa-gg',
  102 + 'sublist' => [
  103 + ["name" => "inspection/plan/index", "title" => "查看",],
  104 + ["name" => "inspection/plan/add", "title" => "添加"],
  105 + ["name" => "inspection/plan/edit", "title" => "编辑"],
  106 + ["name" => "inspection/plan/del", "title" => "删除"],
  107 + ["name" => "inspection/plan/multi", "title" => "批量更新"],
  108 + ]
  109 + ],[
  110 + "name" => "inspection/project",
  111 + "title" => "巡检任务管理",
  112 + 'icon' => 'fa fa-bookmark',
  113 + 'sublist' => [
  114 + ["name" => "inspection/project/index", "title" => "查看",],
  115 + ["name" => "inspection/project/add", "title" => "添加"],
  116 + ["name" => "inspection/project/edit", "title" => "编辑"],
  117 + ["name" => "inspection/project/del", "title" => "删除"],
  118 + ["name" => "inspection/project/multi", "title" => "批量更新"],
  119 + ]
  120 + ],
  121 + ]
  122 + ]
  123 + ];
  124 + Menu::create($menu);
  125 + return true;
  126 + }
  127 +
  128 + /**
  129 + * 插件卸载方法
  130 + * @return bool
  131 + */
  132 + public function uninstall()
  133 + {
  134 + Menu::delete("inspection");
  135 + return true;
  136 + }
  137 +
  138 + /**
  139 + * 插件启用方法
  140 + * @return bool
  141 + */
  142 + public function enable()
  143 + {
  144 + Menu::enable("inspection");
  145 + return true;
  146 + }
  147 +
  148 + /**
  149 + * 插件禁用方法
  150 + * @return bool
  151 + */
  152 + public function disable()
  153 + {
  154 + Menu::disable("inspection");
  155 + return true;
  156 + }
  157 +
  158 + public function appInit()
  159 + {
  160 + if(request()->isCli()){
  161 +
  162 + //生成巡检任务
  163 + \think\Console::addDefaultCommands([
  164 + 'addons\inspection\library\GenerateProject'
  165 + ]);
  166 +
  167 + //取消巡检任务
  168 + \think\Console::addDefaultCommands([
  169 + 'addons\inspection\library\CancelProject'
  170 + ]);
  171 + }
  172 +
  173 + }
  174 +
  175 +}
  1 +<?php
  2 +
  3 +return [];
  1 +<?php
  2 +
  3 +namespace addons\inspection\controller;
  4 +
  5 +use app\admin\model\inspection\Lnglat;
  6 +use think\addons\Controller;
  7 +
  8 +class Index extends Controller
  9 +{
  10 +
  11 + public function lnglat()
  12 + {
  13 + $id = $this->request->param("id");
  14 + $this->assign('id',$id);
  15 + $lnglatModel = new Lnglat();
  16 + $lnglatInfo = $lnglatModel->where(['areasite_id'=>$id])->find();
  17 +
  18 + $this->assign('lnglatInfo',$lnglatInfo);
  19 +
  20 + return $this->fetch();
  21 + }
  22 +
  23 +}
  1 +name = inspection
  2 +title = 设备巡检系统
  3 +intro = 基于FastAdmin插件和Uniapp的设备巡检系统,可用在电力、水利等巡检场景
  4 +author = piupiu
  5 +website = https://www.fastadmin.net
  6 +version = 1.0.1
  7 +state = 1
  8 +url = /addons/inspection
  9 +license = regular
  10 +licenseto = 44313
  1 +CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_area` (
  2 + `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  3 + `pid` int(11) NOT NULL COMMENT '上级区域ID',
  4 + `area_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '区域名称',
  5 + `weigh` int(11) NOT NULL COMMENT '排序',
  6 + `createtime` int(11) NOT NULL COMMENT '创建时间',
  7 + `updatetime` int(11) NOT NULL COMMENT '修改时间',
  8 + PRIMARY KEY (`id`) USING BTREE
  9 +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '巡检区域表';
  10 +
  11 +CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_area_item` (
  12 + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  13 + `areasite_id` int(11) NOT NULL DEFAULT 0,
  14 + `item_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
  15 + `type` int(11) NOT NULL,
  16 + `weigh` int(11) NOT NULL DEFAULT 0,
  17 + PRIMARY KEY (`id`) USING BTREE
  18 +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '巡检检查项';
  19 +
  20 +CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_area_site` (
  21 + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  22 + `area_id` int(11) NOT NULL COMMENT '巡检区域ID',
  23 + `site_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '巡检点名称',
  24 + `verify` int(11) NOT NULL COMMENT '验证方式',
  25 + `lnglat` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '经纬度',
  26 + `distance` int(11) NULL DEFAULT NULL COMMENT '距离',
  27 + `weigh` int(11) NOT NULL COMMENT '排序',
  28 + `createtime` int(11) NOT NULL COMMENT '添加时间',
  29 + `updatetime` int(11) NOT NULL COMMENT '更新时间',
  30 + PRIMARY KEY (`id`) USING BTREE
  31 +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '巡检点';
  32 +
  33 +CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_depart` (
  34 + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  35 + `pid` int(11) NOT NULL DEFAULT 0 COMMENT '上级单位',
  36 + `depart_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '单位名称',
  37 + `createtime` int(11) NOT NULL COMMENT '创建时间',
  38 + `weigh` int(11) NOT NULL DEFAULT 0 COMMENT '排序',
  39 + PRIMARY KEY (`id`) USING BTREE
  40 +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '部门表';
  41 +
  42 +CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_plan` (
  43 + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  44 + `plan_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '巡检计划名称',
  45 + `route_id` int(11) NOT NULL COMMENT '路线ID',
  46 + `circle_type` int(11) NOT NULL COMMENT '定期类型 1天 2周 3月',
  47 + `circle_value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '定期周期',
  48 + `num` int(11) NOT NULL COMMENT '每天执行次数',
  49 + `time` int(11) NOT NULL COMMENT '每次间隔时长',
  50 + `begintime` int(11) NOT NULL COMMENT '开始时间',
  51 + `endtime` int(11) NULL DEFAULT NULL COMMENT '结束时间',
  52 + `staff_id` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '员工ID',
  53 + `createtime` int(11) NOT NULL,
  54 + `updatetime` int(11) NOT NULL,
  55 + PRIMARY KEY (`id`) USING BTREE
  56 +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '巡检计划表';
  57 +
  58 +CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_project` (
  59 + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  60 + `plan_id` int(11) NOT NULL COMMENT '计划ID',
  61 + `route_id` int(11) NOT NULL COMMENT '路线ID',
  62 + `area_id` int(11) NOT NULL DEFAULT 0 COMMENT '巡检区域ID',
  63 + `area_site_id` int(11) NOT NULL COMMENT '巡检点ID',
  64 + `createtime` int(11) NOT NULL COMMENT '创建时间',
  65 + `begintime` int(11) NOT NULL COMMENT '开始时间',
  66 + `endtime` int(11) NOT NULL COMMENT '结束时间',
  67 + `staff_id` int(11) NOT NULL DEFAULT 0 COMMENT '员工ID',
  68 + `checktime` int(11) NULL DEFAULT 0 COMMENT '检查时间',
  69 + `jumptime` int(11) NULL DEFAULT NULL COMMENT '跳捡时间',
  70 + `jump_content` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '跳捡原因',
  71 + `images` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图片',
  72 + `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '备注',
  73 + `status` int(11) NOT NULL DEFAULT 0 COMMENT '-1漏检 0进行中 1已巡检 2跳捡',
  74 + `state` int(11) NOT NULL DEFAULT 0 COMMENT '状态 0进行中 1正常 2异常',
  75 + PRIMARY KEY (`id`) USING BTREE
  76 +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '巡检任务表';
  77 +
  78 +CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_project_item` (
  79 + `project_id` int(11) NOT NULL COMMENT '任务ID',
  80 + `item_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '检查项名称',
  81 + `type` int(11) NOT NULL COMMENT '检查项类型',
  82 + `value` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '检查项值'
  83 +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '巡检任务检查项表';
  84 +
  85 +CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_route` (
  86 + `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  87 + `route_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '路线名称',
  88 + `createtime` int(11) NOT NULL COMMENT '创建时间',
  89 + PRIMARY KEY (`id`) USING BTREE
  90 +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '巡检路线表';
  91 +
  92 +CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_route_site` (
  93 + `route_id` int(11) NOT NULL COMMENT '巡检路线ID',
  94 + `area_site_id` int(11) NOT NULL COMMENT '巡检点ID',
  95 + `weigh` int(11) NOT NULL DEFAULT 0 COMMENT '排序',
  96 + `createtime` int(11) NOT NULL COMMENT '创建时间'
  97 +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '巡检路线巡检点表';
  98 +
  99 +CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_staff` (
  100 + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  101 + `user_id` int(11) NOT NULL DEFAULT 0 COMMENT '会员ID',
  102 + `depart_id` int(11) NOT NULL DEFAULT 0 COMMENT '单位id',
  103 + `staff_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '员工编号',
  104 + `staff_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '员工姓名',
  105 + `mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '员工手机号',
  106 + `duty` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '职务',
  107 + `createtime` int(11) NOT NULL COMMENT '创建时间',
  108 + `weigh` int(11) NOT NULL DEFAULT 0 COMMENT '排序',
  109 + PRIMARY KEY (`id`) USING BTREE
  110 +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '员工表';
  111 +
  112 +CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_lnglat` (
  113 + `areasite_id` int(11) NOT NULL COMMENT '巡检点ID',
  114 + `distance` int(11) NOT NULL COMMENT '距离',
  115 + `lng` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '经度',
  116 + `lat` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '纬度',
  117 + `createtime` int(11) NOT NULL,
  118 + `updatetime` int(11) NOT NULL
  119 +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '巡检点定位表';
  1 +<?php
  2 +
  3 +namespace addons\inspection\library;
  4 +
  5 +use think\console\Command;
  6 +use think\console\Input;
  7 +use think\console\Output;
  8 +
  9 +class CancelProject extends Command
  10 +{
  11 +
  12 + protected function configure()
  13 + {
  14 + $this
  15 + ->setName('cancelProject')
  16 + ->setDescription('自动化处理过期的巡检任务');
  17 + }
  18 +
  19 + protected function execute(Input $input, Output $output)
  20 + {
  21 + while (true){
  22 + $projectModel = new \app\admin\model\inspection\Project();
  23 + $projectModel->where(['endtime'=>['lt',time()],'status'=>0])->update(['status'=>-1]);
  24 + sleep(60); //1分钟
  25 + }
  26 +
  27 + }
  28 +
  29 +}
  1 +<?php
  2 +
  3 +namespace addons\inspection\library;
  4 +
  5 +use addons\ygame\service\Order;
  6 +use think\console\Command;
  7 +use think\console\Input;
  8 +use think\console\Output;
  9 +use think\Hook;
  10 +
  11 +class GenerateProject extends Command
  12 +{
  13 +
  14 + protected function configure()
  15 + {
  16 + $this
  17 + ->setName('generateProject')
  18 + ->setDescription('自动化生成巡检任务');
  19 + }
  20 +
  21 + protected function execute(Input $input, Output $output)
  22 + {
  23 + while (true){
  24 + Hook::exec('addons\\inspection\\library\\Project','init',$params);
  25 + sleep(60*60); //1小时
  26 + }
  27 +
  28 + }
  29 +
  30 +}
  1 +<?php
  2 +
  3 +namespace addons\inspection\library;
  4 +
  5 +
  6 +use app\admin\model\inspection\Plan;
  7 +use app\admin\model\inspection\Routesite;
  8 +use think\Db;
  9 +use think\Exception;
  10 +
  11 +class Project
  12 +{
  13 + public function init(&$request){
  14 +
  15 + //在生成任务之前,把昨天以前的数据状态status改为漏检-1
  16 + $projectModel = new \app\admin\model\inspection\Project();
  17 + //当天0点时间
  18 + $datetime = strtotime(date('Y-m-d'));
  19 + $projectModel
  20 + ->save([
  21 + 'status' => -1
  22 + ],[
  23 + 'status' => 0,
  24 + 'state' => 0,
  25 + 'begintime' => ['lt', $datetime]
  26 + ]);
  27 +
  28 + $planModel = new Plan();
  29 + $planList = collection($planModel
  30 + ->alias("plan")
  31 + ->field("plan.id as plan_id,plan.route_id,plan.num,plan.time,plan.circle_type,plan.circle_value,plan.begintime,plan.endtime,plan.exetimes,plan.staff_id")
  32 + ->join("inspection_route route","plan.route_id=route.id")
  33 + ->join("inspection_staff staff","plan.staff_id=staff.id")
  34 + ->where([
  35 + 'plan.begintime'=>['elt',time()],
  36 + 'plan.endtime'=>[['gt',time()],['EXP',Db::raw('is null')],'or'],
  37 + ])
  38 + ->select())->toArray();
  39 +
  40 + foreach($planList as $k=>$v){
  41 +
  42 + //获取计划中路线的巡检点
  43 + $routesiteModel = new Routesite();
  44 + $routsiteList = collection($routesiteModel
  45 + ->alias("routesite")
  46 + ->field("routesite.area_site_id,site.area_id")
  47 + ->join("inspection_area_site site","routesite.area_site_id=site.id")
  48 + ->where(['routesite.route_id'=>$v['route_id']])
  49 + ->select())->toArray();
  50 +
  51 +
  52 + foreach ($routsiteList as $vv){
  53 + $data = $v;
  54 + $data['area_site_id'] = $vv['area_site_id'];
  55 + $data['area_id'] = $vv['area_id'];
  56 +
  57 + switch($v['circle_type']){
  58 + case "1": //日计划
  59 + $this->circle_day($data);
  60 + break;
  61 + case "2": //周计划
  62 + $this->circle_week($data);
  63 + break;
  64 + case "3": //月计划
  65 +
  66 + $this->circle_month($data);
  67 + break;
  68 + }
  69 + }
  70 +
  71 + }
  72 +
  73 + }
  74 +
  75 +
  76 + private function circle_day($data){
  77 +
  78 + //获取巡检点信息
  79 + $begin_time = strtotime(date("Y-m-d",time()));
  80 + $data['begintime'] = $data['begintime']>$begin_time?$data['begintime']:$begin_time;
  81 + $endtime = strtotime("+1 days -1 second",$begin_time);
  82 + $data['endtime'] = empty($data['endtime'])?$endtime:($data['endtime']>$endtime?$endtime:$data['endtime']);
  83 + $this->refresh_area($data);
  84 + }
  85 +
  86 + private function circle_week($data){
  87 + $week_days = $this->get_week();
  88 + $circle_value_arr = explode(",",$data['circle_value']);
  89 + for ($i=0;$i<count($circle_value_arr);$i++){
  90 + if(date("Y-m-d") == $week_days[$circle_value_arr[$i]]){
  91 + //获取巡检点信息
  92 +// $begin_time = strtotime(date("Y-m-d",strtotime($week_days[$circle_value_arr[0]])));
  93 +// $data['begintime'] = $data['begintime']>$begin_time?$data['begintime']:$begin_time;
  94 +// $endtime = strtotime("+1 days -1 second",strtotime($week_days[end($circle_value_arr)]));
  95 +
  96 + //开始时间应该为当天的0点,结束时间应该为当天最后一秒
  97 + $data['begintime'] = strtotime(date("Y-m-d"));
  98 + $endtime = $data['begintime'] + 24*3600 - 1;
  99 +
  100 + $data['endtime'] = empty($data['endtime'])?$endtime:($data['endtime']>$endtime?$endtime:$data['endtime']);
  101 +
  102 + $this->refresh_area($data);
  103 + break;
  104 + }
  105 + }
  106 +
  107 + }
  108 +
  109 + /**
  110 + * 获取本周所有日期
  111 + */
  112 + private function get_week($time = '', $format='Y-m-d'){
  113 + $time = $time != '' ? $time : time();
  114 +
  115 + //获取当前周几
  116 + $week = date('w', $time);
  117 + $week = $week == 0?7:$week;
  118 + $date = [];
  119 + for ($i=1; $i<=7; $i++){
  120 + $date[$i] = date($format ,strtotime( '+' . $i-$week .' days', $time));
  121 + }
  122 + return $date;
  123 + }
  124 +
  125 + /**
  126 + * 获取本月日期
  127 + * @param $date
  128 + * @return array
  129 + */
  130 + private function get_month($time="",$format='Y-m-d'){
  131 + $time = $time != '' ? $time : time();
  132 + //获取当前周几
  133 + $week = date('d', $time);
  134 + $date = [];
  135 + for ($i=1; $i<=date('t'); $i++){
  136 + $date[$i] = date($format ,strtotime( '+' . $i-$week .' days', $time));
  137 + }
  138 + return $date;
  139 + }
  140 +
  141 +
  142 + private function circle_month($data){
  143 + $month_days = $this->get_month();
  144 +
  145 + $circle_value_arr = explode(",",$data['circle_value']);
  146 +
  147 + for ($i=0;$i<count($circle_value_arr);$i++){
  148 +
  149 + if(empty($month_days[$circle_value_arr[$i]])){
  150 + continue;
  151 + }
  152 + if(date("Y-m-d") == $month_days[$circle_value_arr[$i]]){
  153 +
  154 + //获取巡检点信息
  155 +// $begin_time = strtotime(date("Y-m-d",strtotime($month_days[$circle_value_arr[0]])));
  156 +// $data['begintime'] = $data['begintime']>$begin_time?$data['begintime']:$begin_time;
  157 +// if(empty($month_days[end($circle_value_arr)])){
  158 +// $endtime = strtotime("+1 days -1 second",strtotime(end($month_days)));
  159 +// }else{
  160 +// $endtime = strtotime("+1 days -1 second",strtotime($month_days[end($circle_value_arr)]));
  161 +// }
  162 +
  163 + //开始时间应该为当天的0点,结束时间应该为当天最后一秒
  164 + $data['begintime'] = strtotime(date("Y-m-d"));
  165 + $endtime = $data['begintime'] + 24*3600 - 1;
  166 +
  167 + $data['endtime'] = empty($data['endtime'])?$endtime:($data['endtime']>$endtime?$endtime:$data['endtime']);
  168 +
  169 + $this->refresh_area($data);
  170 + break;
  171 + }
  172 + }
  173 +
  174 +
  175 + }
  176 +
  177 + private function refresh_area($data){
  178 + try{
  179 +
  180 + $projectModel = new \app\admin\model\inspection\Project();
  181 +// $project = $projectModel->where(['plan_id'=>$data['plan_id'],'route_id'=>$data['route_id'],'area_id'=>$data['area_id'],'area_site_id'=>$data['area_site_id'],'endtime'=>['egt',$data['endtime']]])->find();
  182 + $project = $projectModel
  183 + ->where([
  184 + 'plan_id'=>$data['plan_id'],
  185 + 'route_id'=>$data['route_id'],
  186 + 'area_id'=>$data['area_id'],
  187 + 'area_site_id'=>$data['area_site_id'],
  188 + 'staff_id'=>$data['staff_id'],
  189 + 'endtime'=>['egt',$data['endtime']]
  190 + ])
  191 + ->find();
  192 +
  193 + if(empty($project)){
  194 + Db::startTrans();
  195 + if (!empty($data['exetimes'])){
  196 + $timeArr = explode(',', $data['exetimes']);
  197 + foreach ($timeArr as $time) {
  198 + $projectModel = new \app\admin\model\inspection\Project();
  199 + $result = $projectModel->save([
  200 + 'plan_id'=>$data['plan_id'],
  201 + 'route_id'=>$data['route_id'],
  202 + 'area_id'=>$data['area_id'],
  203 + 'area_site_id'=>$data['area_site_id'],
  204 + 'staff_id'=>$data['staff_id'],
  205 + 'begintime'=>strtotime(date('Y-m-d',$data['begintime']) . ' ' . $time),
  206 + 'endtime'=>$data['endtime']]);
  207 + if(empty($result)){
  208 + throw new Exception("巡检记录生成失败");
  209 + }
  210 + }
  211 + }
  212 +// for($i=1;$i<=$data['num'];$i++){
  213 +// $projectModel = new \app\admin\model\inspection\Project();
  214 +// $result = $projectModel->save([
  215 +// 'plan_id'=>$data['plan_id'],
  216 +// 'route_id'=>$data['route_id'],
  217 +// 'area_id'=>$data['area_id'],
  218 +// 'area_site_id'=>$data['area_site_id'],
  219 +// 'begintime'=>$data['begintime'],
  220 +// 'endtime'=>$data['endtime']]);
  221 +// if(empty($result)){
  222 +// throw new Exception("巡检记录生成失败");
  223 +// }
  224 +// }
  225 + Db::commit();
  226 + }
  227 +
  228 + }catch (Exception $e){
  229 +
  230 + print_r($e->getMessage());
  231 + Db::rollback();
  232 + }
  233 + }
  234 +
  235 + /**
  236 + * 获取下几个月的当天的日期
  237 + * @param $begin_time
  238 + * @param $month
  239 + * @return false|int
  240 + */
  241 + private function getNextMonthDays($begin_time,$month)
  242 + {
  243 + $firstday = date('Y-m-01', $begin_time);
  244 + $lastday = strtotime("$firstday +".($month+1)." month -1 day");
  245 + $day_lastday = date('d', $lastday); //获取下个月份的最后一天
  246 + $day_benlastday = date('d', strtotime("$firstday +1 month -1 day")); //获取本月份的最后一天
  247 +
  248 + //获取当天日期
  249 + $Same_day = date('d', $begin_time);
  250 + //判断当天是否是最后一天 或 下月最后一天 等于 本月的最后一天
  251 + if ($Same_day == $day_benlastday || $day_lastday == $Same_day) {
  252 + $day = $day_lastday;
  253 + } else {
  254 + $day = $Same_day;
  255 + }
  256 +
  257 + $day = date('Y', $lastday) . '-' . date('m', $lastday) . '-' . $day." ".date("H:i:s",$begin_time);
  258 + return strtotime($day);
  259 + }
  260 +}
此 diff 太大无法显示。
  1 +<?php
  2 +namespace addons\inspection\service;
  3 +
  4 +class Project
  5 +{
  6 +
  7 + public $model;
  8 +
  9 + public function __construct()
  10 + {
  11 +
  12 + }
  13 +
  14 + function checkDistance($lng1, $lat1, $lng2, $lat2) {
  15 + // 将角度转为狐度
  16 + $radLat1 = deg2rad($lat1); //deg2rad()函数将角度转换为弧度
  17 + $radLat2 = deg2rad($lat2);
  18 + $radLng1 = deg2rad($lng1);
  19 + $radLng2 = deg2rad($lng2);
  20 + $a = $radLat1 - $radLat2;
  21 + $b = $radLng1 - $radLng2;
  22 + $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * 6378.137 * 1000;
  23 + return $s;
  24 + }
  25 +
  26 + public function getProjectInfo($where){
  27 + $projectModel = new \app\admin\model\inspection\Project();
  28 + $data = $projectModel
  29 + ->alias("project")
  30 + ->field("project.id,project.plan_id,project.route_id,project.checktime,project.images,project.content,plan.time,site.lnglat,site.verify,site.distance,project.status,project.state,project.begintime,project.endtime,project.area_site_id,site.verify,site.site_name")
  31 + ->join("inspection_plan plan","project.plan_id=plan.id")
  32 + ->join("inspection_area_site site","project.area_site_id=site.id")
  33 + ->where($where)
  34 + ->find();
  35 +
  36 + if($data){
  37 + return $data;
  38 + }
  39 + return false;
  40 +
  41 + }
  42 +
  43 +}
  1 +<script>
  2 + export default {
  3 + onLaunch: function() {
  4 + // #ifdef MP-WEIXIN
  5 + let menuButtonInfo = uni.getMenuButtonBoundingClientRect().top
  6 + this.$lib.$store.commit('setMenuButtonInfo',menuButtonInfo)
  7 + // #endif
  8 + console.log('App Launch')
  9 + },
  10 + onShow: function() {
  11 + console.log('App Show')
  12 + },
  13 + onHide: function() {
  14 + console.log('App Hide')
  15 + }
  16 + }
  17 +</script>
  18 +
  19 +<style>
  20 + /*每个页面公共css */
  21 + @import "./static/font/iconfont.css";
  22 + /*占位符*/
  23 + .lz-status_bar {
  24 + height: var(--status-bar-height);
  25 + width: 100%;
  26 + background-color: #fff;
  27 + }
  28 +
  29 + .lz-top_view {
  30 + height: var(--status-bar-height);
  31 + width: 100%;
  32 + position: fixed;
  33 + background-color: #fff;
  34 + top: 0;
  35 + z-index: 999;
  36 + }
  37 + /*头部*/
  38 + .index-head{
  39 + background: #fff;
  40 + top: var(--status-bar-height);
  41 + z-index: 100;
  42 + height: 32px;
  43 + padding-bottom: 6px;
  44 + }
  45 + .index-head-top{
  46 + display: flex;
  47 + font-size: 16px;
  48 + color: #000;
  49 + align-items: center;
  50 + width: 92%;
  51 + margin: 0 auto;
  52 + line-height: 40px;
  53 + }
  54 + .index-head-top .index-head-l {
  55 + width: 24px;
  56 + display: flex;align-items: center;
  57 + padding-top: 0px;
  58 + }
  59 + .index-head-l .iconfont {
  60 + font-size: 21px;
  61 + transform: rotate(180deg);
  62 + margin-right: 7px;
  63 + }
  64 + .index-head-top .index-head-m{width: 60%;text-align: left;font-size: 16px;}
  65 +</style>
  1 +# 电站巡检
  2 +
  3 +#### Description
  4 +{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
  5 +
  6 +#### Software Architecture
  7 +Software architecture description
  8 +
  9 +#### Installation
  10 +
  11 +1. xxxx
  12 +2. xxxx
  13 +3. xxxx
  14 +
  15 +#### Instructions
  16 +
  17 +1. xxxx
  18 +2. xxxx
  19 +3. xxxx
  20 +
  21 +#### Contribution
  22 +
  23 +1. Fork the repository
  24 +2. Create Feat_xxx branch
  25 +3. Commit your code
  26 +4. Create Pull Request
  27 +
  28 +
  29 +#### Gitee Feature
  30 +
  31 +1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
  32 +2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
  33 +3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
  34 +4. The most valuable open source project [GVP](https://gitee.com/gvp)
  35 +5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
  36 +6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
  1 +# 巡检
  2 +
  3 +#### 介绍
  4 +{**以下是 Gitee 平台说明,您可以替换此简介**
  5 +Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
  6 +无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
  7 +
  8 +#### 软件架构
  9 +软件架构说明
  10 +
  11 +
  12 +#### 安装教程
  13 +
  14 +1. xxxx
  15 +2. xxxx
  16 +3. xxxx
  17 +
  18 +#### 使用说明
  19 +
  20 +1. xxxx
  21 +2. xxxx
  22 +3. xxxx
  23 +
  24 +#### 参与贡献
  25 +
  26 +1. Fork 本仓库
  27 +2. 新建 Feat_xxx 分支
  28 +3. 提交代码
  29 +4. 新建 Pull Request
  30 +
  31 +
  32 +#### 特技
  33 +
  34 +1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
  35 +2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
  36 +3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
  37 +4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
  38 +5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
  39 +6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
  1 +<template>
  2 + <div>
  3 + <div>
  4 + <wuc-tab :tab-list="tabList" :tabCur.sync="TabCur" tab-class="text-center bg-white wuc-tab fixed" :tab-style="CustomBar" select-class="text-blue" @change="tabChange"></wuc-tab>
  5 + <div class="cu-bar bg-white solid-bottom" style="margin-top:100upx">
  6 + <div class="action">
  7 + <text class="cuIcon-titles text-orange"></text>基本使用(tab固定,只支持点击标签切换)
  8 + </div>
  9 + </div>
  10 + <div class="bg-white padding margin text-center text-black">{{tabList[TabCur].name}}</div>
  11 + </div>
  12 +
  13 + <div>
  14 + <div class="cu-bar bg-white margin-top solid-bottom">
  15 + <div class="action">
  16 + <text class="cuIcon-titles text-orange"></text>居中选中放大(外部触发切换)
  17 + </div>
  18 + </div>
  19 + <wuc-tab :tab-list="tabList2" :tabCur="TabCur2" @change="tabChange2" tab-class="text-center text-black bg-white" select-class="text-blue text-xl"></wuc-tab>
  20 + <swiper :current="TabCur2" class="swiper" duration="300" :circular="true" indicator-color="rgba(255,255,255,0)" indicator-active-color="rgba(255,255,255,0)" @change="swiperChange2">
  21 + <swiper-item v-for="(item,index) in tabList2" :key="index">
  22 + <div class="bg-white padding margin text-center text-black">{{item.name}}</div>
  23 + </swiper-item>
  24 + </swiper>
  25 + </div>
  26 +
  27 + <div>
  28 + <div class="cu-bar bg-white margin-top solid-bottom">
  29 + <div class="action">
  30 + <text class="cuIcon-titles text-orange"></text>平分
  31 + </div>
  32 + </div>
  33 + <wuc-tab :tab-list="tabList3" textFlex :tabCur.sync="TabCur3" tab-class="text-center text-black bg-white" select-class="text-orange"></wuc-tab>
  34 + <swiper :current="TabCur3" class="swiper" duration="300" :circular="true" indicator-color="rgba(255,255,255,0)" indicator-active-color="rgba(255,255,255,0)" @change="swiperChange3">
  35 + <swiper-item v-for="(item,index) in tabList3" :key="index">
  36 + <div class="bg-white padding margin text-center text-black">{{item.name}}</div>
  37 + </swiper-item>
  38 + </swiper>
  39 + </div>
  40 +
  41 + <div>
  42 + <div class="cu-bar bg-white margin-top solid-bottom">
  43 + <div class="action">
  44 + <text class="cuIcon-titles text-orange"></text>背景
  45 + </div>
  46 + </div>
  47 + <wuc-tab :tab-list="tabList4" :tabCur.sync="TabCur4" tab-class="text-center text-white bg-blue" select-class="text-white"></wuc-tab>
  48 + <swiper :current="TabCur4" class="swiper row" duration="300" :circular="true" indicator-color="rgba(255,255,255,0)" indicator-active-color="rgba(255,255,255,0)" @change="swiperChange4">
  49 + <swiper-item v-for="(item,index) in tabList4" :key="index">
  50 + <div class="bg-white padding margin text-center text-black">{{item.name}}</div>
  51 + </swiper-item>
  52 + </swiper>
  53 + </div>
  54 +
  55 + <div>
  56 + <div class="cu-bar bg-white margin-top solid-bottom">
  57 + <div class="action">
  58 + <text class="cuIcon-titles text-orange"></text>图标
  59 + </div>
  60 + </div>
  61 + <wuc-tab :tab-list="tabList5" :tabCur.sync="TabCur5" tab-class="text-center text-black bg-white" select-class="text-blue" />
  62 + <swiper :current="TabCur5" class="swiper" duration="300" :circular="true" indicator-color="rgba(255,255,255,0)" indicator-active-color="rgba(255,255,255,0)" @change="swiperChange5">
  63 + <swiper-item v-for="(item,index) in tabList5" :key="index">
  64 + <div class="bg-white padding margin text-center text-black">{{item.name}}</div>
  65 + </swiper-item>
  66 + </swiper>
  67 + </div>
  68 + </div>
  69 +</template>
  70 +
  71 +<script>
  72 +import WucTab from '@/components/wuc-tab/wuc-tab.vue';
  73 +import { obj2style } from '@/utils/index';
  74 +export default {
  75 + data() {
  76 + return {
  77 + tabList: [
  78 + { name: '选项卡一' },
  79 + { name: '选项卡二' },
  80 + { name: '选项卡三' },
  81 + { name: '选项卡四' },
  82 + { name: '选项卡五' },
  83 + { name: '选项卡六' },
  84 + { name: '选项卡七' },
  85 + { name: '选项卡八' }
  86 + ],
  87 + tabList2: [{ name: '精选' }, { name: '订阅' }],
  88 + tabList3: [{ name: '精选' }, { name: '订阅' }],
  89 + tabList4: [
  90 + { name: '推荐' },
  91 + { name: '热点' },
  92 + { name: '视频' },
  93 + { name: '问答' },
  94 + { name: '社会' },
  95 + { name: '娱乐' },
  96 + { name: '科技' },
  97 + { name: '汽车' }
  98 + ],
  99 + tabList5: [
  100 + { name: '短信', icon: 'cuIcon-comment' },
  101 + { name: '电话', icon: 'cuIcon-dianhua' },
  102 + { name: 'wifi', icon: 'cuIcon-wifi' }
  103 + ],
  104 + TabCur: 0,
  105 + TabCur2: 0,
  106 + TabCur3: 0,
  107 + TabCur4: 0,
  108 + TabCur5: 0
  109 + };
  110 + },
  111 +
  112 + components: { WucTab },
  113 +
  114 + computed: {
  115 + CustomBar() {
  116 + let style = {};
  117 + // #ifdef MP-WEIXIN
  118 + const systemInfo = uni.getSystemInfoSync();
  119 + let CustomBar =
  120 + systemInfo.platform === "android"
  121 + ? systemInfo.statusBarHeight + 50
  122 + : systemInfo.statusBarHeight + 45;
  123 + style['top'] = CustomBar + 'px';
  124 + // #endif
  125 + // #ifdef H5
  126 + style['top'] = 0 + 'px';
  127 + // #endif
  128 + return obj2style(style);
  129 + }
  130 + },
  131 +
  132 + methods: {
  133 + tabChange(index) {
  134 + this.TabCur = index;
  135 + },
  136 + tabChange2(index) {
  137 + this.TabCur2 = index;
  138 + },
  139 + swiperChange2(e) {
  140 + let { current } = e.target;
  141 + this.TabCur2 = current;
  142 + },
  143 + swiperChange3(e) {
  144 + let { current } = e.target;
  145 + this.TabCur3 = current;
  146 + },
  147 + swiperChange4(e) {
  148 + let { current } = e.target;
  149 + this.TabCur4 = current;
  150 + },
  151 + swiperChange5(e) {
  152 + this.TabCur5 = e.target.current;
  153 + }
  154 + },
  155 +
  156 + onReady() {}
  157 +};
  158 +</script>
  159 +<style>
  160 +@import "~@/styles/icon.scss";
  161 +div,
  162 +scroll-view,
  163 +swiper {
  164 + box-sizing: border-box;
  165 +}
  166 +div {
  167 + font-size: 28upx;
  168 + background-color: #f1f1f1;
  169 +}
  170 +.swiper {
  171 + height: 140upx;
  172 +}
  173 +
  174 +.cu-bar {
  175 + display: flex;
  176 + position: relative;
  177 + align-items: center;
  178 + min-height: 100upx;
  179 + justify-content: space-between;
  180 +}
  181 +
  182 +.cu-bar .action {
  183 + display: flex;
  184 + align-items: center;
  185 + height: 100%;
  186 + justify-content: center;
  187 + max-width: 100%;
  188 + background-color: #ffffff;
  189 +}
  190 +
  191 +.cu-bar .action:first-child {
  192 + margin-left: 30upx;
  193 + font-size: 30upx;
  194 +}
  195 +
  196 +.solid,
  197 +.solid-bottom {
  198 + position: relative;
  199 +}
  200 +
  201 +.solid::after,
  202 +.solid-bottom::after{
  203 + content: " ";
  204 + width: 200%;
  205 + height: 200%;
  206 + position: absolute;
  207 + top: 0;
  208 + left: 0;
  209 + border-radius: inherit;
  210 + transform: scale(0.5);
  211 + transform-origin: 0 0;
  212 + pointer-events: none;
  213 + box-sizing: border-box;
  214 +}
  215 +
  216 +.solid::after {
  217 + border: 1upx solid rgba(0, 0, 0, 0.1);
  218 +}
  219 +
  220 +.solid-bottom::after {
  221 + border-bottom: 1upx solid rgba(0, 0, 0, 0.1);
  222 +}
  223 +
  224 +.text-orange{
  225 + color:#f37b1d
  226 +}
  227 +.text-black{
  228 + color:#333333;
  229 +}
  230 +.bg-white{
  231 + background-color: #ffffff;
  232 +}
  233 +
  234 +.padding {
  235 + padding: 30upx;
  236 +}
  237 +
  238 +.margin {
  239 + margin: 30upx;
  240 +}
  241 +
  242 +.margin-top {
  243 + margin-top: 30upx;
  244 +}
  245 +.text-center {
  246 + text-align: center;
  247 +}
  248 +</style>