正在显示
71 个修改的文件
包含
4570 行增加
和
0 行删除
.bowerrc
0 → 100644
.env.sample
0 → 100644
.gitignore
0 → 100644
404.html
0 → 100644
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> |
LICENSE
0 → 100644
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. |
README.md
0 → 100644
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 | + | ||
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。 |
addons/.gitkeep
0 → 100644
1 | + |
addons/.htaccess
0 → 100644
1 | +deny from all |
addons/address/.addonrc
0 → 100644
1 | +{"license":"regular","licenseto":"44234","licensekey":"OUQ2e0ygcCnSMFbl TS8vZW767XPDznsqCMpmFQ=="} |
addons/address/Address.php
0 → 100644
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 | +} |
addons/address/bootstrap.js
0 → 100644
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 | +}); |
addons/address/config.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +return [ | ||
4 | + [ | ||
5 | + 'name' => 'maptype', | ||
6 | + 'title' => '默认地图类型', | ||
7 | + 'type' => 'radio', | ||
8 | + 'content' => [ | ||
9 | + 'baidu' => '百度地图', | ||
10 | + 'amap' => '高德地图', | ||
11 | + 'tencent' => '腾讯地图', | ||
12 | + ], | ||
13 | + 'value' => 'tencent', | ||
14 | + 'rule' => 'required', | ||
15 | + 'msg' => '', | ||
16 | + 'tip' => '', | ||
17 | + 'ok' => '', | ||
18 | + 'extend' => '', | ||
19 | + ], | ||
20 | + [ | ||
21 | + 'name' => 'location', | ||
22 | + 'title' => '默认检索城市', | ||
23 | + 'type' => 'string', | ||
24 | + 'content' => [], | ||
25 | + 'value' => '蒙自', | ||
26 | + 'rule' => 'required', | ||
27 | + 'msg' => '', | ||
28 | + 'tip' => '', | ||
29 | + 'ok' => '', | ||
30 | + 'extend' => '', | ||
31 | + ], | ||
32 | + [ | ||
33 | + 'name' => 'zoom', | ||
34 | + 'title' => '默认缩放级别', | ||
35 | + 'type' => 'string', | ||
36 | + 'content' => [], | ||
37 | + 'value' => '12', | ||
38 | + 'rule' => 'required', | ||
39 | + 'msg' => '', | ||
40 | + 'tip' => '', | ||
41 | + 'ok' => '', | ||
42 | + 'extend' => '', | ||
43 | + ], | ||
44 | + [ | ||
45 | + 'name' => 'lat', | ||
46 | + 'title' => '默认Lat', | ||
47 | + 'type' => 'string', | ||
48 | + 'content' => [], | ||
49 | + 'value' => '23.375675', | ||
50 | + 'rule' => 'required', | ||
51 | + 'msg' => '', | ||
52 | + 'tip' => '', | ||
53 | + 'ok' => '', | ||
54 | + 'extend' => '', | ||
55 | + ], | ||
56 | + [ | ||
57 | + 'name' => 'lng', | ||
58 | + 'title' => '默认Lng', | ||
59 | + 'type' => 'string', | ||
60 | + 'content' => [], | ||
61 | + 'value' => '103.36941', | ||
62 | + 'rule' => 'required', | ||
63 | + 'msg' => '', | ||
64 | + 'tip' => '', | ||
65 | + 'ok' => '', | ||
66 | + 'extend' => '', | ||
67 | + ], | ||
68 | + [ | ||
69 | + 'name' => 'baidukey', | ||
70 | + 'title' => '百度地图KEY', | ||
71 | + 'type' => 'string', | ||
72 | + 'content' => [], | ||
73 | + 'value' => '7Mt3R8k1PGyB1gOEk60Ksfsg90S1cQTR', | ||
74 | + 'rule' => 'required', | ||
75 | + 'msg' => '', | ||
76 | + 'tip' => '', | ||
77 | + 'ok' => '', | ||
78 | + 'extend' => '', | ||
79 | + ], | ||
80 | + [ | ||
81 | + 'name' => 'amapkey', | ||
82 | + 'title' => '高德地图KEY', | ||
83 | + 'type' => 'string', | ||
84 | + 'content' => [], | ||
85 | + 'value' => '608d75903d29ad471362f8c58c550daf', | ||
86 | + 'rule' => 'required', | ||
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' => 'required', | ||
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 | +]; |
addons/address/controller/Index.php
0 → 100644
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 | + public function index() | ||
13 | + { | ||
14 | + // 语言检测 | ||
15 | + $lang = strip_tags($this->request->langset()); | ||
16 | + | ||
17 | + $site = Config::get("site"); | ||
18 | + | ||
19 | + // 配置信息 | ||
20 | + $config = [ | ||
21 | + 'site' => array_intersect_key($site, array_flip(['name', 'cdnurl', 'version', 'timezone', 'languages'])), | ||
22 | + 'upload' => null, | ||
23 | + 'modulename' => 'addons', | ||
24 | + 'controllername' => 'index', | ||
25 | + 'actionname' => 'index', | ||
26 | + 'jsname' => 'addons/address', | ||
27 | + 'moduleurl' => '', | ||
28 | + 'language' => $lang | ||
29 | + ]; | ||
30 | + $config = array_merge($config, Config::get("view_replace_str")); | ||
31 | + | ||
32 | + // 配置信息后 | ||
33 | + Hook::listen("config_init", $config); | ||
34 | + // 加载当前控制器语言包 | ||
35 | + $this->view->assign('site', $site); | ||
36 | + $this->view->assign('config', $config); | ||
37 | + | ||
38 | + return $this->view->fetch(); | ||
39 | + } | ||
40 | + | ||
41 | + /** | ||
42 | + * 选择地址 | ||
43 | + * @return string | ||
44 | + * @throws \think\Exception | ||
45 | + */ | ||
46 | + public function select() | ||
47 | + { | ||
48 | + $config = get_addon_config('address'); | ||
49 | + $lat = $this->request->get('lat', $config['lat']); | ||
50 | + $lng = $this->request->get('lng', $config['lng']); | ||
51 | + $this->view->assign('lat', $lat); | ||
52 | + $this->view->assign('lng', $lng); | ||
53 | + $this->view->assign('location', $config['location']); | ||
54 | + return $this->view->fetch('index/' . $config['maptype']); | ||
55 | + } | ||
56 | + | ||
57 | +} |
addons/address/info.ini
0 → 100644
addons/address/view/index/amap.html
0 → 100644
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/bootstrap.min.css"/> | ||
7 | + <link rel="stylesheet" href="__CDN__/assets/css/fastadmin.min.css"/> | ||
8 | + <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/> | ||
9 | + <style type="text/css"> | ||
10 | + body { | ||
11 | + margin: 0; | ||
12 | + padding: 0; | ||
13 | + } | ||
14 | + | ||
15 | + #container { | ||
16 | + position: absolute; | ||
17 | + left: 0; | ||
18 | + top: 0; | ||
19 | + right: 0; | ||
20 | + bottom: 0; | ||
21 | + } | ||
22 | + | ||
23 | + .confirm { | ||
24 | + position: absolute; | ||
25 | + bottom: 30px; | ||
26 | + right: 4%; | ||
27 | + z-index: 99; | ||
28 | + height: 50px; | ||
29 | + width: 50px; | ||
30 | + line-height: 50px; | ||
31 | + font-size: 15px; | ||
32 | + text-align: center; | ||
33 | + background-color: white; | ||
34 | + background: #1ABC9C; | ||
35 | + color: white; | ||
36 | + border: none; | ||
37 | + cursor: pointer; | ||
38 | + border-radius: 50%; | ||
39 | + } | ||
40 | + | ||
41 | + .search { | ||
42 | + position: absolute; | ||
43 | + width: 400px; | ||
44 | + top: 0; | ||
45 | + left: 50%; | ||
46 | + padding: 5px; | ||
47 | + margin-left: -200px; | ||
48 | + } | ||
49 | + | ||
50 | + .amap-marker-label { | ||
51 | + border: 0; | ||
52 | + background-color: transparent; | ||
53 | + } | ||
54 | + | ||
55 | + .info { | ||
56 | + padding: .75rem 1.25rem; | ||
57 | + margin-bottom: 1rem; | ||
58 | + border-radius: .25rem; | ||
59 | + position: fixed; | ||
60 | + top: 2rem; | ||
61 | + background-color: white; | ||
62 | + width: auto; | ||
63 | + min-width: 22rem; | ||
64 | + border-width: 0; | ||
65 | + left: 1.8rem; | ||
66 | + box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5); | ||
67 | + } | ||
68 | + </style> | ||
69 | +</head> | ||
70 | +<body> | ||
71 | +<div class="search"> | ||
72 | + <div class="input-group"> | ||
73 | + <input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/> | ||
74 | + <span class="input-group-btn"> | ||
75 | + <button type="submit" name="search" id="search-btn" class="btn btn-success"> | ||
76 | + <i class="fa fa-search"></i> | ||
77 | + </button> | ||
78 | + </span> | ||
79 | + </div> | ||
80 | +</div> | ||
81 | +<div class="confirm">确定</div> | ||
82 | +<div id="container"></div> | ||
83 | +<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> | ||
84 | +<!-- UI组件库 1.0 --> | ||
85 | +<script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script> | ||
86 | +<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script> | ||
87 | +<script type="text/javascript"> | ||
88 | + $(function () { | ||
89 | + var as, address, map, lat, lng, geocoder; | ||
90 | + var init = function () { | ||
91 | + AMapUI.loadUI(['misc/PositionPicker', 'misc/PoiPicker'], function (PositionPicker, PoiPicker) { | ||
92 | + //加载PositionPicker,loadUI的路径参数为模块名中 'ui/' 之后的部分 | ||
93 | + map = new AMap.Map('container', { | ||
94 | + zoom: parseInt('{$config.zoom}') | ||
95 | + }); | ||
96 | + geocoder = new AMap.Geocoder({ | ||
97 | + radius: 1000 //范围,默认:500 | ||
98 | + }); | ||
99 | + var positionPicker = new PositionPicker({ | ||
100 | + mode: 'dragMarker',//设定为拖拽地图模式,可选'dragMap'、'dragMarker',默认为'dragMap' | ||
101 | + map: map//依赖地图对象 | ||
102 | + }); | ||
103 | + //输入提示 | ||
104 | + var autoOptions = { | ||
105 | + input: "place" | ||
106 | + }; | ||
107 | + | ||
108 | + var relocation = function (lnglat) { | ||
109 | + lng = lnglat.lng; | ||
110 | + lat = lnglat.lat; | ||
111 | + map.panTo([lng, lat]); | ||
112 | + positionPicker.start(lnglat); | ||
113 | + geocoder.getAddress(lng + ',' + lat, function (status, result) { | ||
114 | + if (status === 'complete' && result.regeocode) { | ||
115 | + var address = result.regeocode.formattedAddress; | ||
116 | + var label = '<div class="info">地址:' + address + '<br>经度:' + lng + '<br>纬度:' + lat + '</div>'; | ||
117 | + positionPicker.marker.setLabel({ | ||
118 | + content: label //显示内容 | ||
119 | + }); | ||
120 | + } else { | ||
121 | + console.log(JSON.stringify(result)); | ||
122 | + } | ||
123 | + }); | ||
124 | + }; | ||
125 | + var auto = new AMap.Autocomplete(autoOptions); | ||
126 | + | ||
127 | + //构造地点查询类 | ||
128 | + var placeSearch = new AMap.PlaceSearch({ | ||
129 | + map: map | ||
130 | + }); | ||
131 | + //注册监听,当选中某条记录时会触发 | ||
132 | + AMap.event.addListener(auto, "select", function (e) { | ||
133 | + placeSearch.setCity(e.poi.adcode); | ||
134 | + placeSearch.search(e.poi.name); //关键字查询查询 | ||
135 | + }); | ||
136 | + AMap.event.addListener(map, 'click', function (e) { | ||
137 | + relocation(e.lnglat); | ||
138 | + }); | ||
139 | + | ||
140 | + //加载工具条 | ||
141 | + var tool = new AMap.ToolBar(); | ||
142 | + map.addControl(tool); | ||
143 | + | ||
144 | + var poiPicker = new PoiPicker({ | ||
145 | + input: 'place', | ||
146 | + placeSearchOptions: { | ||
147 | + map: map, | ||
148 | + pageSize: 6 //关联搜索分页 | ||
149 | + } | ||
150 | + }); | ||
151 | + poiPicker.on('poiPicked', function (poiResult) { | ||
152 | + poiPicker.hideSearchResults(); | ||
153 | + $('.poi .nearpoi').text(poiResult.item.name); | ||
154 | + $('.address .info').text(poiResult.item.address); | ||
155 | + $('#address').val(poiResult.item.address); | ||
156 | + $("#place").val(poiResult.item.name); | ||
157 | + | ||
158 | + relocation(poiResult.item.location); | ||
159 | + }); | ||
160 | + | ||
161 | + positionPicker.on('success', function (positionResult) { | ||
162 | + as = positionResult.position; | ||
163 | + address = positionResult.address; | ||
164 | + lat = as.lat; | ||
165 | + lng = as.lng; | ||
166 | + }); | ||
167 | + positionPicker.on('fail', function (positionResult) { | ||
168 | + address = ''; | ||
169 | + }); | ||
170 | + positionPicker.start(); | ||
171 | + }); | ||
172 | + }; | ||
173 | + | ||
174 | + //点击确定后执行回调赋值 | ||
175 | + var close = function (data) { | ||
176 | + var index = parent.Layer.getFrameIndex(window.name); | ||
177 | + var callback = parent.$("#layui-layer" + index).data("callback"); | ||
178 | + //再执行关闭 | ||
179 | + parent.Layer.close(index); | ||
180 | + //再调用回传函数 | ||
181 | + if (typeof callback === 'function') { | ||
182 | + callback.call(undefined, data); | ||
183 | + } | ||
184 | + }; | ||
185 | + | ||
186 | + //点击搜索按钮 | ||
187 | + $(document).on('click', '.confirm', function () { | ||
188 | + var zoom = map.getZoom(); | ||
189 | + var data = {lat: lat, lng: lng, zoom: zoom, address: address}; | ||
190 | + close(data); | ||
191 | + }); | ||
192 | + init(); | ||
193 | + }); | ||
194 | +</script> | ||
195 | +</body> | ||
196 | +</html> |
addons/address/view/index/baidu.html
0 → 100644
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/bootstrap.min.css"/> | ||
7 | + <link rel="stylesheet" href="__CDN__/assets/css/fastadmin.min.css"/> | ||
8 | + <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/> | ||
9 | + <style type="text/css"> | ||
10 | + body { | ||
11 | + margin: 0; | ||
12 | + padding: 0; | ||
13 | + } | ||
14 | + | ||
15 | + #container { | ||
16 | + position: absolute; | ||
17 | + left: 0; | ||
18 | + top: 0; | ||
19 | + right: 0; | ||
20 | + bottom: 0; | ||
21 | + } | ||
22 | + | ||
23 | + .confirm { | ||
24 | + position: absolute; | ||
25 | + bottom: 30px; | ||
26 | + right: 4%; | ||
27 | + z-index: 99; | ||
28 | + height: 50px; | ||
29 | + width: 50px; | ||
30 | + line-height: 50px; | ||
31 | + font-size: 15px; | ||
32 | + text-align: center; | ||
33 | + background-color: white; | ||
34 | + background: #1ABC9C; | ||
35 | + color: white; | ||
36 | + border: none; | ||
37 | + cursor: pointer; | ||
38 | + border-radius: 50%; | ||
39 | + } | ||
40 | + | ||
41 | + .search { | ||
42 | + position: absolute; | ||
43 | + width: 400px; | ||
44 | + top: 0; | ||
45 | + left: 50%; | ||
46 | + padding: 5px; | ||
47 | + margin-left: -200px; | ||
48 | + } | ||
49 | + | ||
50 | + label.BMapLabel { | ||
51 | + max-width: inherit; | ||
52 | + padding: .75rem 1.25rem; | ||
53 | + margin-bottom: 1rem; | ||
54 | + background-color: white; | ||
55 | + width: auto; | ||
56 | + min-width: 22rem; | ||
57 | + border: none; | ||
58 | + box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5); | ||
59 | + } | ||
60 | + | ||
61 | + </style> | ||
62 | +</head> | ||
63 | +<body> | ||
64 | +<div class="search"> | ||
65 | + <div class="input-group"> | ||
66 | + <input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/> | ||
67 | + <div id="searchResultPanel" style="border:1px solid #C0C0C0;width:150px;height:auto; display:none;"></div> | ||
68 | + <span class="input-group-btn"> | ||
69 | + <button type="button" name="search" id="address" class="btn btn-success"> | ||
70 | + <i class="fa fa-search"></i> | ||
71 | + </button> | ||
72 | + </span> | ||
73 | + </div> | ||
74 | +</div> | ||
75 | +<div class="confirm">确定</div> | ||
76 | +<div id="container"></div> | ||
77 | +<script type="text/javascript" src="//api.map.baidu.com/api?v=2.0&ak={$config.baidukey|default=''}"></script> | ||
78 | +<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script> | ||
79 | +<script type="text/javascript"> | ||
80 | + $(function () { | ||
81 | + // 百度地图API功能 | ||
82 | + function G(id) { | ||
83 | + return document.getElementById(id); | ||
84 | + } | ||
85 | + | ||
86 | + var map, marker, searchService, address = null, lng, lat; | ||
87 | + | ||
88 | + var init = function () { | ||
89 | + map = new BMap.Map("container"); // 创建地图实例 | ||
90 | + var point = new BMap.Point({$lng}, {$lat}); // 创建点坐标 | ||
91 | + map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放 | ||
92 | + map.centerAndZoom(point, parseInt("{$config.zoom}")); // 初始化地图,设置中心点坐标和地图级别 | ||
93 | + | ||
94 | + var size = new BMap.Size(10, 20); | ||
95 | + map.addControl(new BMap.CityListControl({ | ||
96 | + anchor: BMAP_ANCHOR_TOP_LEFT, | ||
97 | + offset: size, | ||
98 | + })); | ||
99 | + | ||
100 | + var geoc = new BMap.Geocoder(); | ||
101 | + | ||
102 | + var addpoint = function (point) { | ||
103 | + //通过点击百度地图,可以获取到对应的point, 由point的lng、lat属性就可以获取对应的经度纬度 | ||
104 | + var pt = point; | ||
105 | + geoc.getLocation(pt, function (rs) { | ||
106 | + //对象可以获取到详细的地址信息 | ||
107 | + address = rs.address; | ||
108 | + deletePoint(); | ||
109 | + var mk = new BMap.Marker(pt); | ||
110 | + map.addOverlay(mk); | ||
111 | + map.panTo(pt); | ||
112 | + var label = new BMap.Label('<div class="info">地址:' + address + '<br>经度:' + pt.lng + '<br>纬度:' + pt.lat + '</div>', {offset: new BMap.Size(16, 20)}); | ||
113 | + label.setStyle({ | ||
114 | + border: 'none', | ||
115 | + padding: '.75rem 1.25rem' | ||
116 | + }); | ||
117 | + mk.setLabel(label); | ||
118 | + //将对应的HTML元素设置值 | ||
119 | + lng = pt.lng; | ||
120 | + lat = pt.lat; | ||
121 | + }); | ||
122 | + }; | ||
123 | + | ||
124 | + if ("{$lng}" != '' && "{$lat}" != '') { | ||
125 | + addpoint(point); | ||
126 | + } | ||
127 | + | ||
128 | + ac = new BMap.Autocomplete({"input": "place", "location": map}); //建立一个自动完成的对象 | ||
129 | + ac.addEventListener("onhighlight", function (e) { //鼠标放在下拉列表上的事件 | ||
130 | + var str = ""; | ||
131 | + var _value = e.fromitem.value; | ||
132 | + var value = ""; | ||
133 | + if (e.fromitem.index > -1) { | ||
134 | + value = _value.province + _value.city + _value.district + _value.street + _value.business; | ||
135 | + } | ||
136 | + str = "FromItem<br />index = " + e.fromitem.index + "<br />value = " + value; | ||
137 | + | ||
138 | + value = ""; | ||
139 | + if (e.toitem.index > -1) { | ||
140 | + _value = e.toitem.value; | ||
141 | + value = _value.province + _value.city + _value.district + _value.street + _value.business; | ||
142 | + } | ||
143 | + str += "<br />ToItem<br />index = " + e.toitem.index + "<br />value = " + value; | ||
144 | + G("searchResultPanel").innerHTML = str; | ||
145 | + }); | ||
146 | + ac.addEventListener("onconfirm", function (e) { //鼠标点击下拉列表后的事件 | ||
147 | + var _value = e.item.value; | ||
148 | + myValue = _value.province + _value.city + _value.district + _value.street + _value.business; | ||
149 | + G("searchResultPanel").innerHTML = "onconfirm<br />index = " + e.item.index + "<br />myValue = " + myValue; | ||
150 | + setPlace(); | ||
151 | + }); | ||
152 | + | ||
153 | + function setPlace() { | ||
154 | + map.clearOverlays(); //清除地图上所有覆盖物 | ||
155 | + function myFun() { | ||
156 | + var result = local.getResults().getPoi(0); | ||
157 | + var pp = result.point; //获取第一个智能搜索的结果 | ||
158 | + map.centerAndZoom(pp, 18); | ||
159 | + map.addOverlay(new BMap.Marker(pp)); //添加标注 | ||
160 | + lng = pp.lng; | ||
161 | + lat = pp.lat; | ||
162 | + address = result.address; | ||
163 | + } | ||
164 | + | ||
165 | + var local = new BMap.LocalSearch(map, { //智能搜索 | ||
166 | + onSearchComplete: myFun | ||
167 | + }); | ||
168 | + local.search(myValue); | ||
169 | + } | ||
170 | + | ||
171 | + map.addEventListener("click", function (e) { | ||
172 | + //通过点击百度地图,可以获取到对应的point, 由point的lng、lat属性就可以获取对应的经度纬度 | ||
173 | + var pt = e.point; | ||
174 | + addpoint(e.point); | ||
175 | + }); | ||
176 | + | ||
177 | + /** | ||
178 | + * 清除覆盖物 | ||
179 | + */ | ||
180 | + function deletePoint() { | ||
181 | + var allOverlay = map.getOverlays(); | ||
182 | + for (var i = 0; i < allOverlay.length; i++) { | ||
183 | + map.removeOverlay(allOverlay[i]); | ||
184 | + } | ||
185 | + } | ||
186 | + }; | ||
187 | + | ||
188 | + var close = function (data) { | ||
189 | + var index = parent.Layer.getFrameIndex(window.name); | ||
190 | + var callback = parent.$("#layui-layer" + index).data("callback"); | ||
191 | + //再执行关闭 | ||
192 | + parent.Layer.close(index); | ||
193 | + //再调用回传函数 | ||
194 | + if (typeof callback === 'function') { | ||
195 | + callback.call(undefined, data); | ||
196 | + } | ||
197 | + }; | ||
198 | + | ||
199 | + //点击确定后执行回调赋值 | ||
200 | + $(document).on('click', '.confirm', function () { | ||
201 | + var zoom = map.getZoom(); | ||
202 | + var data = {lat: lat, lng: lng, zoom: zoom, address: address}; | ||
203 | + close(data); | ||
204 | + }); | ||
205 | + | ||
206 | + init(); | ||
207 | + }); | ||
208 | +</script> | ||
209 | +</body> | ||
210 | +</html> |
addons/address/view/index/index.html
0 → 100644
1 | +<!DOCTYPE html> | ||
2 | +<html> | ||
3 | +<head> | ||
4 | + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> | ||
5 | + | ||
6 | + <title>地图位置(经纬度)选择插件 - FastAdmin</title> | ||
7 | + | ||
8 | + <!-- Bootstrap Core CSS --> | ||
9 | + <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet"> | ||
10 | + | ||
11 | + <!-- Custom CSS --> | ||
12 | + <link href="https://cdn.demo.fastadmin.net/assets/css/frontend.css" rel="stylesheet"> | ||
13 | + | ||
14 | + <!-- Plugin CSS --> | ||
15 | + <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.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.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script> | ||
20 | + <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script> | ||
21 | + <![endif]--> | ||
22 | +</head> | ||
23 | +<body> | ||
24 | +<div class="container"> | ||
25 | + | ||
26 | + <div class="bs-docs-section clearfix"> | ||
27 | + <div class="row"> | ||
28 | + <div class="col-lg-12"> | ||
29 | + <div class="page-header"> | ||
30 | + <h2 id="navbar">地图位置(经纬度)选择示例</h2> | ||
31 | + </div> | ||
32 | + | ||
33 | + <div class="bs-component"> | ||
34 | + <form action="" method="post" role="form"> | ||
35 | + <div class="form-group"> | ||
36 | + <label for=""></label> | ||
37 | + <input type="text" class="form-control" name="" id="address" placeholder="地址"> | ||
38 | + </div> | ||
39 | + <div class="form-group"> | ||
40 | + <label for=""></label> | ||
41 | + <input type="text" class="form-control" name="" id="lng" placeholder="经度"> | ||
42 | + </div> | ||
43 | + <div class="form-group"> | ||
44 | + <label for=""></label> | ||
45 | + <input type="text" class="form-control" name="" id="lat" placeholder="纬度"> | ||
46 | + </div> | ||
47 | + | ||
48 | + <button type="button" class="btn btn-primary" data-toggle='addresspicker' data-input-id="address" data-lng-id="lng" data-lat-id="lat">点击选择地址获取经纬度</button> | ||
49 | + </form> | ||
50 | + </div> | ||
51 | + | ||
52 | + <div class="page-header"> | ||
53 | + <h2 id="code">调用代码</h2> | ||
54 | + </div> | ||
55 | + <div class="bs-component"> | ||
56 | + <textarea class="form-control" rows="17"> | ||
57 | +<form action="" method="post" role="form"> | ||
58 | + <div class="form-group"> | ||
59 | + <label for=""></label> | ||
60 | + <input type="text" class="form-control" name="" id="address" placeholder="地址"> | ||
61 | + </div> | ||
62 | + <div class="form-group"> | ||
63 | + <label for=""></label> | ||
64 | + <input type="text" class="form-control" name="" id="lng" placeholder="经度"> | ||
65 | + </div> | ||
66 | + <div class="form-group"> | ||
67 | + <label for=""></label> | ||
68 | + <input type="text" class="form-control" name="" id="lat" placeholder="纬度"> | ||
69 | + </div> | ||
70 | + | ||
71 | + <button type="button" class="btn btn-primary" data-toggle='addresspicker' data-input-id="address" data-lng-id="lng" data-lat-id="lat">点击选择地址获取经纬度</button> | ||
72 | +</form> | ||
73 | + </textarea> | ||
74 | + </div> | ||
75 | + <div class="page-header"> | ||
76 | + <h2 id="navbar">参数说明</h2> | ||
77 | + </div> | ||
78 | + | ||
79 | + <div class="bs-component"> | ||
80 | + <table class="table table-condensed table-hover"> | ||
81 | + <thead> | ||
82 | + <tr> | ||
83 | + <th>参数</th> | ||
84 | + <th>释义</th> | ||
85 | + </tr> | ||
86 | + </thead> | ||
87 | + <tbody> | ||
88 | + <tr> | ||
89 | + <td>data-input-id</td> | ||
90 | + <td>填充地址的文本框ID</td> | ||
91 | + </tr> | ||
92 | + <tr> | ||
93 | + <td>data-lng-id</td> | ||
94 | + <td>填充经度的文本框ID</td> | ||
95 | + </tr> | ||
96 | + <tr> | ||
97 | + <td>data-lat-id</td> | ||
98 | + <td>填充纬度的文本框ID</td> | ||
99 | + </tr> | ||
100 | + </tbody> | ||
101 | + </table> | ||
102 | + </div> | ||
103 | + | ||
104 | + </div> | ||
105 | + </div> | ||
106 | + </div> | ||
107 | + | ||
108 | +</div> | ||
109 | +<script type="text/javascript"> | ||
110 | + var require = { | ||
111 | + config: {$config | json_encode | ||
112 | + } | ||
113 | + } | ||
114 | + ; | ||
115 | +</script> | ||
116 | + | ||
117 | +<script> | ||
118 | + require.callback = function () { | ||
119 | + define('addons/address', ['jquery', 'bootstrap', 'frontend', 'template'], function ($, undefined, Frontend, Template) { | ||
120 | + var Controller = { | ||
121 | + index: function () { | ||
122 | + ; | ||
123 | + } | ||
124 | + }; | ||
125 | + return Controller; | ||
126 | + }); | ||
127 | + define('lang', function () { | ||
128 | + return []; | ||
129 | + }); | ||
130 | + } | ||
131 | +</script> | ||
132 | + | ||
133 | + | ||
134 | +<script src="__CDN__/assets/js/require.min.js" data-main="__CDN__/assets/js/require-frontend.min.js?v={$site.version}"></script> | ||
135 | +</body> | ||
136 | +</html> |
addons/address/view/index/tencent.html
0 → 100644
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/bootstrap.min.css"/> | ||
7 | + <link rel="stylesheet" href="__CDN__/assets/css/fastadmin.min.css"/> | ||
8 | + <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/> | ||
9 | + <style type="text/css"> | ||
10 | + body { | ||
11 | + margin: 0; | ||
12 | + padding: 0; | ||
13 | + } | ||
14 | + | ||
15 | + #container { | ||
16 | + position: absolute; | ||
17 | + left: 0; | ||
18 | + top: 0; | ||
19 | + right: 0; | ||
20 | + bottom: 0; | ||
21 | + } | ||
22 | + | ||
23 | + .confirm { | ||
24 | + position: absolute; | ||
25 | + bottom: 30px; | ||
26 | + right: 4%; | ||
27 | + z-index: 99; | ||
28 | + height: 50px; | ||
29 | + width: 50px; | ||
30 | + line-height: 50px; | ||
31 | + font-size: 15px; | ||
32 | + text-align: center; | ||
33 | + background-color: white; | ||
34 | + background: #1ABC9C; | ||
35 | + color: white; | ||
36 | + border: none; | ||
37 | + cursor: pointer; | ||
38 | + border-radius: 50%; | ||
39 | + } | ||
40 | + | ||
41 | + .search { | ||
42 | + position: absolute; | ||
43 | + width: 400px; | ||
44 | + top: 0; | ||
45 | + left: 50%; | ||
46 | + padding: 5px; | ||
47 | + margin-left: -200px; | ||
48 | + } | ||
49 | + </style> | ||
50 | +</head> | ||
51 | +<body> | ||
52 | +<div class="search"> | ||
53 | + <div class="input-group"> | ||
54 | + <input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/> | ||
55 | + <span class="input-group-btn"> | ||
56 | + <button type="submit" name="search" id="search-btn" class="btn btn-success"> | ||
57 | + <i class="fa fa-search"></i> | ||
58 | + </button> | ||
59 | + </span> | ||
60 | + </div> | ||
61 | +</div> | ||
62 | +<div class="confirm">确定</div> | ||
63 | +<div id="container"></div> | ||
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 | +<script type="text/javascript"> | ||
67 | + $(function () { | ||
68 | + var map, marker, geocoder, infoWin, searchService, address = null; | ||
69 | + var init = function () { | ||
70 | + var center = new qq.maps.LatLng({$lat}, {$lng}); | ||
71 | + map = new qq.maps.Map(document.getElementById('container'), { | ||
72 | + center: center, | ||
73 | + zoom: parseInt("{$config.zoom}") | ||
74 | + }); | ||
75 | + //初始化marker | ||
76 | + initmarker(center); | ||
77 | + | ||
78 | + //实例化信息窗口 | ||
79 | + infoWin = new qq.maps.InfoWindow({ | ||
80 | + map: map | ||
81 | + }); | ||
82 | + geocoder = new qq.maps.Geocoder({ | ||
83 | + complete: function (result) { | ||
84 | + infoWin.open(); | ||
85 | + address = result.detail.addressComponents.province + | ||
86 | + result.detail.addressComponents.city + | ||
87 | + result.detail.addressComponents.district; | ||
88 | + if (result.detail.addressComponents.streetNumber == '') { | ||
89 | + address += result.detail.addressComponents.street; | ||
90 | + } else { | ||
91 | + address += result.detail.addressComponents.streetNumber; | ||
92 | + } | ||
93 | + infoWin.setContent(address); | ||
94 | + infoWin.setPosition(result.detail.location); | ||
95 | + } | ||
96 | + }); | ||
97 | + //显示当前marker的位置信息窗口 | ||
98 | + geocoder.getAddress(center); | ||
99 | + | ||
100 | + var latlngBounds = new qq.maps.LatLngBounds(); | ||
101 | + //查询poi类信息 | ||
102 | + searchService = new qq.maps.SearchService({ | ||
103 | + complete: function (results) { | ||
104 | + var pois = results.detail.pois; | ||
105 | + for (var i = 0, l = pois.length; i < l; i++) { | ||
106 | + var poi = pois[i]; | ||
107 | + latlngBounds.extend(poi.latLng); | ||
108 | + initmarker(poi.latLng); | ||
109 | + //显示当前marker的位置信息窗口 | ||
110 | + geocoder.getAddress(poi.latLng); | ||
111 | + } | ||
112 | + map.fitBounds(latlngBounds); | ||
113 | + } | ||
114 | + }); | ||
115 | + //实例化自动完成 | ||
116 | + var ap = new qq.maps.place.Autocomplete(document.getElementById('place')); | ||
117 | + //添加监听事件 | ||
118 | + qq.maps.event.addListener(ap, "confirm", function (res) { | ||
119 | + searchKeyword(); | ||
120 | + }); | ||
121 | + qq.maps.event.addListener( | ||
122 | + map, | ||
123 | + 'click', | ||
124 | + function (event) { | ||
125 | + try { | ||
126 | + infoWin.setContent('<div style="text-align:center;white-space:nowrap;margin:10px;">加载中</div>'); | ||
127 | + var latLng = event.latLng, | ||
128 | + lat = latLng.getLat().toFixed(5), | ||
129 | + lng = latLng.getLng().toFixed(5); | ||
130 | + var location = new qq.maps.LatLng(lat, lng); | ||
131 | + //调用获取位置方法 | ||
132 | + geocoder.getAddress(location); | ||
133 | + infoWin.setPosition(location); | ||
134 | + marker.setPosition(location); | ||
135 | + } catch (e) { | ||
136 | + console.log(e); | ||
137 | + } | ||
138 | + } | ||
139 | + ); | ||
140 | + }; | ||
141 | + | ||
142 | + //实例化marker和监听拖拽结束事件 | ||
143 | + var initmarker = function (latLng) { | ||
144 | + marker = new qq.maps.Marker({ | ||
145 | + map: map, | ||
146 | + position: latLng, | ||
147 | + draggable: true, | ||
148 | + title: '拖动图标选择位置' | ||
149 | + }); | ||
150 | + //监听拖拽结束 | ||
151 | + qq.maps.event.addListener(marker, 'dragend', function (event) { | ||
152 | + var latLng = event.latLng, | ||
153 | + lat = latLng.getLat().toFixed(5), | ||
154 | + lng = latLng.getLng().toFixed(5); | ||
155 | + var location = new qq.maps.LatLng(lat, lng); | ||
156 | + //调用获取位置方法 | ||
157 | + geocoder.getAddress(location); | ||
158 | + }); | ||
159 | + }; | ||
160 | + var close = function (data) { | ||
161 | + var index = parent.Layer.getFrameIndex(window.name); | ||
162 | + var callback = parent.$("#layui-layer" + index).data("callback"); | ||
163 | + //再执行关闭 | ||
164 | + parent.Layer.close(index); | ||
165 | + //再调用回传函数 | ||
166 | + if (typeof callback === 'function') { | ||
167 | + callback.call(undefined, data); | ||
168 | + } | ||
169 | + }; | ||
170 | + | ||
171 | + //执行搜索方法 | ||
172 | + var searchKeyword = function () { | ||
173 | + searchService.clear();//先清除 | ||
174 | + marker.setMap(null); | ||
175 | + infoWin.close(); | ||
176 | + var keyword = $("#place").val(); | ||
177 | + searchService.setLocation("{$location}");//设置默认检索范围(默认为全国),类型可以是坐标或指定的城市名称。 | ||
178 | + searchService.setPageIndex(0);//设置检索的特定页数。 | ||
179 | + searchService.setPageCapacity(1);//设置每页返回的结果数量。 | ||
180 | + searchService.search(keyword);//开始查询 | ||
181 | + }; | ||
182 | + | ||
183 | + //点击确定后执行回调赋值 | ||
184 | + $(document).on('click', '.confirm', function () { | ||
185 | + var as = marker.getPosition(); | ||
186 | + var x = as.getLat().toFixed(5); | ||
187 | + var y = as.getLng().toFixed(5); | ||
188 | + var zoom = map.getZoom(); | ||
189 | + var data = {lat: x, lng: y, zoom: zoom, address: address}; | ||
190 | + close(data); | ||
191 | + }); | ||
192 | + | ||
193 | + //点击搜索按钮 | ||
194 | + $(document).on('click', '#search-btn', function () { | ||
195 | + if ($("#place").val() == '') | ||
196 | + return; | ||
197 | + searchKeyword(); | ||
198 | + }); | ||
199 | + | ||
200 | + init(); | ||
201 | + }); | ||
202 | +</script> | ||
203 | +</body> | ||
204 | +</html> |
addons/alisms/.addonrc
0 → 100644
1 | +{"license":"regular","licenseto":"44234","licensekey":"82jyXWeYPFpiE1C4 kxxHOwiOqPyuag4dlI\/v3w=="} |
addons/alisms/Alisms.php
0 → 100644
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 | +} |
addons/alisms/config.php
0 → 100644
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 | +]; |
addons/alisms/controller/Index.php
0 → 100644
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 | +} |
addons/alisms/controller/Sample.php
0 → 100644
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 | +} |
addons/alisms/info.ini
0 → 100644
addons/alisms/library/Alisms.php
0 → 100644
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 | +} |
addons/alisms/view/index/index.html
0 → 100644
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> |
addons/command/.addonrc
0 → 100644
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"]} |
addons/command/Command.php
0 → 100644
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 | +} |
addons/command/config.php
0 → 100644
addons/command/controller/Index.php
0 → 100644
addons/command/info.ini
0 → 100644
addons/command/install.sql
0 → 100644
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 = '在线命令表'; |
addons/command/library/Output.php
0 → 100644
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 | +} |
addons/dinghorn/.addonrc
0 → 100644
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"]} |
addons/dinghorn/Dinghorn.php
0 → 100644
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 | +} |
addons/dinghorn/config.php
0 → 100644
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 | +]; |
addons/dinghorn/controller/Index.php
0 → 100644
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 | +} |
addons/dinghorn/info.ini
0 → 100644
addons/dinghorn/install.sql
0 → 100644
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; |
addons/dinghorn/library/DinghornLib.php
0 → 100644
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 .= '×tamp=' . $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 | +} |
addons/example/.addonrc
0 → 100644
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"]} |
addons/example/Example.php
0 → 100644
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 | +} |
addons/example/bootstrap.js
0 → 100644
addons/example/config.php
0 → 100644
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 | +]; |
addons/example/controller/Demo.php
0 → 100644
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 | +} |
addons/example/controller/Index.php
0 → 100644
addons/example/info.ini
0 → 100644
addons/example/install.sql
0 → 100644
此 diff 太大无法显示。
addons/example/view/demo/demo1.html
0 → 100644
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 --> |
addons/example/view/demo/demo2.html
0 → 100644
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 --> |
addons/example/view/demo/index.html
0 → 100644
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 --> |
addons/example/view/index/index.html
0 → 100644
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> |
addons/example/view/layout/default.html
0 → 100644
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 © {$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> |
addons/inspection/.addonrc
0 → 100644
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","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"]} |
addons/inspection/Inspection.php
0 → 100644
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 | +} |
addons/inspection/config.php
0 → 100644
addons/inspection/controller/Index.php
0 → 100644
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 | +} |
addons/inspection/info.ini
0 → 100644
addons/inspection/install.sql
0 → 100644
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 = '巡检点定位表'; |
addons/inspection/library/CancelProject.php
0 → 100644
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 | +} |
addons/inspection/library/Project.php
0 → 100644
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 | + $planModel = new Plan(); | ||
16 | + $planList = collection($planModel | ||
17 | + ->alias("plan") | ||
18 | + ->field("plan.id as plan_id,plan.route_id,plan.num,plan.time,plan.circle_type,plan.circle_value,plan.begintime,plan.endtime") | ||
19 | + ->join("inspection_route route","plan.route_id=route.id") | ||
20 | + ->join("inspection_staff staff","plan.staff_id=staff.id") | ||
21 | + ->where([ | ||
22 | + 'plan.begintime'=>['elt',time()], | ||
23 | + 'plan.endtime'=>[['gt',time()],['EXP',Db::raw('is null')],'or'], | ||
24 | + ]) | ||
25 | + ->select())->toArray(); | ||
26 | + | ||
27 | + foreach($planList as $k=>$v){ | ||
28 | + | ||
29 | + //获取计划中路线的巡检点 | ||
30 | + $routesiteModel = new Routesite(); | ||
31 | + $routsiteList = collection($routesiteModel | ||
32 | + ->alias("routesite") | ||
33 | + ->field("routesite.area_site_id,site.area_id") | ||
34 | + ->join("inspection_area_site site","routesite.area_site_id=site.id") | ||
35 | + ->where(['routesite.route_id'=>$v['route_id']]) | ||
36 | + ->select())->toArray(); | ||
37 | + | ||
38 | + | ||
39 | + foreach ($routsiteList as $vv){ | ||
40 | + $data = $v; | ||
41 | + $data['area_site_id'] = $vv['area_site_id']; | ||
42 | + $data['area_id'] = $vv['area_id']; | ||
43 | + | ||
44 | + | ||
45 | + switch($v['circle_type']){ | ||
46 | + case "1": //日计划 | ||
47 | + $this->circle_day($data); | ||
48 | + break; | ||
49 | + case "2": //周计划 | ||
50 | + $this->circle_week($data); | ||
51 | + break; | ||
52 | + case "3": //月计划 | ||
53 | + | ||
54 | + $this->circle_month($data); | ||
55 | + break; | ||
56 | + } | ||
57 | + } | ||
58 | + | ||
59 | + } | ||
60 | + | ||
61 | + } | ||
62 | + | ||
63 | + | ||
64 | + private function circle_day($data){ | ||
65 | + | ||
66 | + //获取巡检点信息 | ||
67 | + $begin_time = strtotime(date("Y-m-d",time())); | ||
68 | + $data['begintime'] = $data['begintime']>$begin_time?$data['begintime']:$begin_time; | ||
69 | + $endtime = strtotime("+1 days -1 second",$begin_time); | ||
70 | + $data['endtime'] = empty($data['endtime'])?$endtime:($data['endtime']>$endtime?$endtime:$data['endtime']); | ||
71 | + $this->refresh_area($data); | ||
72 | + } | ||
73 | + | ||
74 | + private function circle_week($data){ | ||
75 | + $week_days = $this->get_week(); | ||
76 | + $circle_value_arr = explode(",",$data['circle_value']); | ||
77 | + for ($i=0;$i<count($circle_value_arr);$i++){ | ||
78 | + if(date("Y-m-d") == $week_days[$circle_value_arr[$i]]){ | ||
79 | + //获取巡检点信息 | ||
80 | + $begin_time = strtotime(date("Y-m-d",strtotime($week_days[$circle_value_arr[0]]))); | ||
81 | + $data['begintime'] = $data['begintime']>$begin_time?$data['begintime']:$begin_time; | ||
82 | + $endtime = strtotime("+1 days -1 second",strtotime($week_days[end($circle_value_arr)])); | ||
83 | + $data['endtime'] = empty($data['endtime'])?$endtime:($data['endtime']>$endtime?$endtime:$data['endtime']); | ||
84 | + | ||
85 | + $this->refresh_area($data); | ||
86 | + break; | ||
87 | + } | ||
88 | + } | ||
89 | + | ||
90 | + } | ||
91 | + | ||
92 | + /** | ||
93 | + * 获取本周所有日期 | ||
94 | + */ | ||
95 | + private function get_week($time = '', $format='Y-m-d'){ | ||
96 | + $time = $time != '' ? $time : time(); | ||
97 | + | ||
98 | + //获取当前周几 | ||
99 | + $week = date('w', $time); | ||
100 | + $week = $week == 0?7:$week; | ||
101 | + $date = []; | ||
102 | + for ($i=1; $i<=7; $i++){ | ||
103 | + $date[$i] = date($format ,strtotime( '+' . $i-$week .' days', $time)); | ||
104 | + } | ||
105 | + return $date; | ||
106 | + } | ||
107 | + | ||
108 | + /** | ||
109 | + * 获取本月日期 | ||
110 | + * @param $date | ||
111 | + * @return array | ||
112 | + */ | ||
113 | + private function get_month($time="",$format='Y-m-d'){ | ||
114 | + $time = $time != '' ? $time : time(); | ||
115 | + //获取当前周几 | ||
116 | + $week = date('d', $time); | ||
117 | + $date = []; | ||
118 | + for ($i=1; $i<=date('t'); $i++){ | ||
119 | + $date[$i] = date($format ,strtotime( '+' . $i-$week .' days', $time)); | ||
120 | + } | ||
121 | + return $date; | ||
122 | + } | ||
123 | + | ||
124 | + | ||
125 | + private function circle_month($data){ | ||
126 | + $month_days = $this->get_month(); | ||
127 | + | ||
128 | + $circle_value_arr = explode(",",$data['circle_value']); | ||
129 | + | ||
130 | + for ($i=0;$i<count($circle_value_arr);$i++){ | ||
131 | + | ||
132 | + if(empty($month_days[$circle_value_arr[$i]])){ | ||
133 | + continue; | ||
134 | + } | ||
135 | + if(date("Y-m-d") == $month_days[$circle_value_arr[$i]]){ | ||
136 | + | ||
137 | + //获取巡检点信息 | ||
138 | + $begin_time = strtotime(date("Y-m-d",strtotime($month_days[$circle_value_arr[0]]))); | ||
139 | + $data['begintime'] = $data['begintime']>$begin_time?$data['begintime']:$begin_time; | ||
140 | + if(empty($month_days[end($circle_value_arr)])){ | ||
141 | + $endtime = strtotime("+1 days -1 second",strtotime(end($month_days))); | ||
142 | + }else{ | ||
143 | + $endtime = strtotime("+1 days -1 second",strtotime($month_days[end($circle_value_arr)])); | ||
144 | + } | ||
145 | + | ||
146 | + | ||
147 | + $data['endtime'] = empty($data['endtime'])?$endtime:($data['endtime']>$endtime?$endtime:$data['endtime']); | ||
148 | + | ||
149 | + $this->refresh_area($data); | ||
150 | + break; | ||
151 | + } | ||
152 | + } | ||
153 | + | ||
154 | + | ||
155 | + } | ||
156 | + | ||
157 | + private function refresh_area($data){ | ||
158 | + try{ | ||
159 | + | ||
160 | + $projectModel = new \app\admin\model\inspection\Project(); | ||
161 | + $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(); | ||
162 | + | ||
163 | + if(empty($project)){ | ||
164 | + Db::startTrans(); | ||
165 | + for($i=1;$i<=$data['num'];$i++){ | ||
166 | + $projectModel = new \app\admin\model\inspection\Project(); | ||
167 | + $result = $projectModel->save([ | ||
168 | + 'plan_id'=>$data['plan_id'], | ||
169 | + 'route_id'=>$data['route_id'], | ||
170 | + 'area_id'=>$data['area_id'], | ||
171 | + 'area_site_id'=>$data['area_site_id'], | ||
172 | + 'begintime'=>$data['begintime'], | ||
173 | + 'endtime'=>$data['endtime']]); | ||
174 | + if(empty($result)){ | ||
175 | + throw new Exception("巡检记录生成失败"); | ||
176 | + } | ||
177 | + } | ||
178 | + | ||
179 | + | ||
180 | + Db::commit(); | ||
181 | + } | ||
182 | + | ||
183 | + }catch (Exception $e){ | ||
184 | + | ||
185 | + print_r($e->getMessage()); | ||
186 | + Db::rollback(); | ||
187 | + } | ||
188 | + } | ||
189 | + | ||
190 | + /** | ||
191 | + * 获取下几个月的当天的日期 | ||
192 | + * @param $begin_time | ||
193 | + * @param $month | ||
194 | + * @return false|int | ||
195 | + */ | ||
196 | + private function getNextMonthDays($begin_time,$month) | ||
197 | + { | ||
198 | + $firstday = date('Y-m-01', $begin_time); | ||
199 | + $lastday = strtotime("$firstday +".($month+1)." month -1 day"); | ||
200 | + $day_lastday = date('d', $lastday); //获取下个月份的最后一天 | ||
201 | + $day_benlastday = date('d', strtotime("$firstday +1 month -1 day")); //获取本月份的最后一天 | ||
202 | + | ||
203 | + //获取当天日期 | ||
204 | + $Same_day = date('d', $begin_time); | ||
205 | + //判断当天是否是最后一天 或 下月最后一天 等于 本月的最后一天 | ||
206 | + if ($Same_day == $day_benlastday || $day_lastday == $Same_day) { | ||
207 | + $day = $day_lastday; | ||
208 | + } else { | ||
209 | + $day = $Same_day; | ||
210 | + } | ||
211 | + | ||
212 | + $day = date('Y', $lastday) . '-' . date('m', $lastday) . '-' . $day." ".date("H:i:s",$begin_time); | ||
213 | + return strtotime($day); | ||
214 | + } | ||
215 | +} |
addons/inspection/library/QRcode.php
0 → 100644
此 diff 太大无法显示。
addons/inspection/service/Project.php
0 → 100644
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 | +} |
addons/inspection/uniapp/App.vue
0 → 100644
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> |
addons/inspection/uniapp/README.en.md
0 → 100644
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/) |
addons/inspection/uniapp/README.md
0 → 100644
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> |
-
请 注册 或 登录 后发表评论