作者 郭文星

123

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

要显示太多修改。

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

{
"directory": "public/assets/libs",
"ignoredDependencies": [
"es6-promise",
"file-saver",
"html2canvas",
"jspdf",
"jspdf-autotable"
]
}
\ No newline at end of file
... ...
[app]
debug = false
trace = false
[database]
hostname = 127.0.0.1
database = fastadmin
username = root
password = root
hostport = 3306
prefix = fa_
... ...
.idea/
.git/
/runtime/*
/application/database.php
/public/uploads/*
/public/1111.log
/public/transfusion_data.txt
/public/haikang.log
/public/kevin_alarm.log
/public/kevin_mng.log
/public/nginx.htaccess
\ No newline at end of file
... ...
\ No newline at end of file
... ...
open_basedir=/www/wwwroot/gjsk.xp.yn.cn/:/tmp/
\ No newline at end of file
... ...
123123
asdsaadsasddds
asdadajshdjh
\ No newline at end of file
... ...
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>404</title>
<style>
body{
background-color:#444;
font-size:14px;
}
h3{
font-size:60px;
color:#eee;
text-align:center;
padding-top:30px;
font-weight:normal;
}
</style>
</head>
<body>
<h3>404,您请求的文件不存在!</h3>
</body>
</html>
... ...
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "{}" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright 2017 Karson
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\ No newline at end of file
... ...
FastAdmin是一款基于ThinkPHP+Bootstrap的极速后台开发框架。
## 主要特性
* 基于`Auth`验证的权限管理系统
* 支持无限级父子级权限继承,父级的管理员可任意增删改子级管理员及权限设置
* 支持单管理员多角色
* 支持管理子级数据或个人数据
* 强大的一键生成功能
* 一键生成CRUD,包括控制器、模型、视图、JS、语言包、菜单、回收站等
* 一键压缩打包JS和CSS文件,一键CDN静态资源部署
* 一键生成控制器菜单和规则
* 一键生成API接口文档
* 完善的前端功能组件开发
* 基于`AdminLTE`二次开发
* 基于`Bootstrap`开发,自适应手机、平板、PC
* 基于`RequireJS`进行JS模块管理,按需加载
* 基于`Less`进行样式开发
* 强大的插件扩展功能,在线安装卸载升级插件
* 通用的会员模块和API模块
* 共用同一账号体系的Web端会员中心权限验证和API接口会员权限验证
* 二级域名部署支持,同时域名支持绑定到应用插件
* 多语言支持,服务端及客户端支持
* 支持大文件分片上传、剪切板粘贴上传、拖拽上传,进度条显示,图片上传前压缩
* 支持表格固定列、固定表头、跨页选择、Excel导出、模板渲染等功能
* 强大的第三方应用模块支持([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))
* 支持CMS、博客、知识付费问答无缝整合[Xunsearch全文搜索](https://www.fastadmin.net/store/xunsearch.html)
* 第三方小程序支持([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))
* 整合第三方短信接口(阿里云、腾讯云短信)
* 无缝整合第三方云存储(七牛云、阿里云OSS、又拍云)功能,支持云储存分片上传
* 第三方富文本编辑器支持(Summernote、Kindeditor、百度编辑器)
* 第三方登录(QQ、微信、微博)整合
* 第三方支付(微信、支付宝)无缝整合,微信支持PC端扫码支付
* 丰富的插件应用市场
## 安装使用
https://doc.fastadmin.net
## 在线演示
https://demo.fastadmin.net
用户名:admin
密 码:123456
提 示:演示站数据无法进行修改,请下载源码安装体验全部功能
## 界面截图
![控制台](https://images.gitee.com/uploads/images/2020/0929/202947_8db2d281_10933.gif "控制台")
## 问题反馈
在使用中有任何问题,请使用以下联系方式联系我们
交流社区: https://ask.fastadmin.net
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群)
Github: https://github.com/karsonzhang/fastadmin
Gitee: https://gitee.com/karson/fastadmin
## 特别鸣谢
感谢以下的项目,排名不分先后
ThinkPHP:http://www.thinkphp.cn
AdminLTE:https://adminlte.io
Bootstrap:http://getbootstrap.com
jQuery:http://jquery.com
Bootstrap-table:https://github.com/wenzhixin/bootstrap-table
Nice-validator: https://validator.niceue.com
SelectPage: https://github.com/TerryZ/SelectPage
Layer: https://layer.layui.com
DropzoneJS: https://www.dropzonejs.com
## 版权信息
FastAdmin遵循Apache2开源协议发布,并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2017-2020 by FastAdmin (https://www.fastadmin.net)
All rights reserved。
... ...
deny from all
\ No newline at end of file
... ...
{"license":"regular","licenseto":"44234","licensekey":"OUQ2e0ygcCnSMFbl TS8vZW767XPDznsqCMpmFQ=="}
\ No newline at end of file
... ...
<?php
namespace addons\address;
use think\Addons;
/**
* 地址选择
* @author [MiniLing] <[laozheyouxiang@163.com]>
*/
class Address extends Addons
{
/**
* 插件安装方法
* @return bool
*/
public function install()
{
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
return true;
}
}
... ...
require([], function () {
//绑定data-toggle=addresspicker属性点击事件
$(document).on('click', "[data-toggle='addresspicker']", function () {
var that = this;
var callback = $(that).data('callback');
var input_id = $(that).data("input-id") ? $(that).data("input-id") : "";
var lat_id = $(that).data("lat-id") ? $(that).data("lat-id") : "";
var lng_id = $(that).data("lng-id") ? $(that).data("lng-id") : "";
var lat = lat_id ? $("#" + lat_id).val() : '';
var lng = lng_id ? $("#" + lng_id).val() : '';
var url = "/addons/address/index/select";
url += (lat && lng) ? '?lat=' + lat + '&lng=' + lng : '';
Fast.api.open(url, '位置选择', {
callback: function (res) {
input_id && $("#" + input_id).val(res.address).trigger("change");
lat_id && $("#" + lat_id).val(res.lat).trigger("change");
lng_id && $("#" + lng_id).val(res.lng).trigger("change");
try {
//执行回调函数
if (typeof callback === 'function') {
callback.call(that, res);
}
} catch (e) {
}
}
});
});
});
... ...
<?php
return [
[
'name' => 'maptype',
'title' => '默认地图类型',
'type' => 'radio',
'content' => [
'baidu' => '百度地图',
'amap' => '高德地图',
'tencent' => '腾讯地图',
],
'value' => 'tencent',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'location',
'title' => '默认检索城市',
'type' => 'string',
'content' => [],
'value' => '蒙自',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'zoom',
'title' => '默认缩放级别',
'type' => 'string',
'content' => [],
'value' => '12',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'lat',
'title' => '默认Lat',
'type' => 'string',
'content' => [],
'value' => '23.375675',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'lng',
'title' => '默认Lng',
'type' => 'string',
'content' => [],
'value' => '103.36941',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'baidukey',
'title' => '百度地图KEY',
'type' => 'string',
'content' => [],
'value' => '7Mt3R8k1PGyB1gOEk60Ksfsg90S1cQTR',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'amapkey',
'title' => '高德地图KEY',
'type' => 'string',
'content' => [],
'value' => '608d75903d29ad471362f8c58c550daf',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'tencentkey',
'title' => '腾讯地图KEY',
'type' => 'string',
'content' => [],
'value' => 'QWNBZ-OV6C2-7UMUS-CSOJB-L3AFT-QTBR5',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => '__tips__',
'title' => '温馨提示',
'type' => '',
'content' => [],
'value' => '请先申请对应地图的Key,配置后再使用',
'rule' => '',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => 'alert-danger-light',
],
];
... ...
<?php
namespace addons\address\controller;
use think\addons\Controller;
use think\Config;
use think\Hook;
class Index extends Controller
{
public function index()
{
// 语言检测
$lang = strip_tags($this->request->langset());
$site = Config::get("site");
// 配置信息
$config = [
'site' => array_intersect_key($site, array_flip(['name', 'cdnurl', 'version', 'timezone', 'languages'])),
'upload' => null,
'modulename' => 'addons',
'controllername' => 'index',
'actionname' => 'index',
'jsname' => 'addons/address',
'moduleurl' => '',
'language' => $lang
];
$config = array_merge($config, Config::get("view_replace_str"));
// 配置信息后
Hook::listen("config_init", $config);
// 加载当前控制器语言包
$this->view->assign('site', $site);
$this->view->assign('config', $config);
return $this->view->fetch();
}
/**
* 选择地址
* @return string
* @throws \think\Exception
*/
public function select()
{
$config = get_addon_config('address');
$lat = $this->request->get('lat', $config['lat']);
$lng = $this->request->get('lng', $config['lng']);
$this->view->assign('lat', $lat);
$this->view->assign('lng', $lng);
$this->view->assign('location', $config['location']);
return $this->view->fetch('index/' . $config['maptype']);
}
}
... ...
name = address
title = 地址选择
intro = 地图位置选择插件,可返回地址和经纬度
author = FastAdmin
website = https://www.fastadmin.net
version = 1.0.5
state = 1
url = /addons/address
license = regular
licenseto = 44234
... ...
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>地址选择器</title>
<link rel="stylesheet" href="__CDN__/assets/css/bootstrap.min.css"/>
<link rel="stylesheet" href="__CDN__/assets/css/fastadmin.min.css"/>
<link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>
<style type="text/css">
body {
margin: 0;
padding: 0;
}
#container {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
.confirm {
position: absolute;
bottom: 30px;
right: 4%;
z-index: 99;
height: 50px;
width: 50px;
line-height: 50px;
font-size: 15px;
text-align: center;
background-color: white;
background: #1ABC9C;
color: white;
border: none;
cursor: pointer;
border-radius: 50%;
}
.search {
position: absolute;
width: 400px;
top: 0;
left: 50%;
padding: 5px;
margin-left: -200px;
}
.amap-marker-label {
border: 0;
background-color: transparent;
}
.info {
padding: .75rem 1.25rem;
margin-bottom: 1rem;
border-radius: .25rem;
position: fixed;
top: 2rem;
background-color: white;
width: auto;
min-width: 22rem;
border-width: 0;
left: 1.8rem;
box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
}
</style>
</head>
<body>
<div class="search">
<div class="input-group">
<input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/>
<span class="input-group-btn">
<button type="submit" name="search" id="search-btn" class="btn btn-success">
<i class="fa fa-search"></i>
</button>
</span>
</div>
</div>
<div class="confirm">确定</div>
<div id="container"></div>
<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>
<!-- UI组件库 1.0 -->
<script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
var as, address, map, lat, lng, geocoder;
var init = function () {
AMapUI.loadUI(['misc/PositionPicker', 'misc/PoiPicker'], function (PositionPicker, PoiPicker) {
//加载PositionPicker,loadUI的路径参数为模块名中 'ui/' 之后的部分
map = new AMap.Map('container', {
zoom: parseInt('{$config.zoom}')
});
geocoder = new AMap.Geocoder({
radius: 1000 //范围,默认:500
});
var positionPicker = new PositionPicker({
mode: 'dragMarker',//设定为拖拽地图模式,可选'dragMap'、'dragMarker',默认为'dragMap'
map: map//依赖地图对象
});
//输入提示
var autoOptions = {
input: "place"
};
var relocation = function (lnglat) {
lng = lnglat.lng;
lat = lnglat.lat;
map.panTo([lng, lat]);
positionPicker.start(lnglat);
geocoder.getAddress(lng + ',' + lat, function (status, result) {
if (status === 'complete' && result.regeocode) {
var address = result.regeocode.formattedAddress;
var label = '<div class="info">地址:' + address + '<br>经度:' + lng + '<br>纬度:' + lat + '</div>';
positionPicker.marker.setLabel({
content: label //显示内容
});
} else {
console.log(JSON.stringify(result));
}
});
};
var auto = new AMap.Autocomplete(autoOptions);
//构造地点查询类
var placeSearch = new AMap.PlaceSearch({
map: map
});
//注册监听,当选中某条记录时会触发
AMap.event.addListener(auto, "select", function (e) {
placeSearch.setCity(e.poi.adcode);
placeSearch.search(e.poi.name); //关键字查询查询
});
AMap.event.addListener(map, 'click', function (e) {
relocation(e.lnglat);
});
//加载工具条
var tool = new AMap.ToolBar();
map.addControl(tool);
var poiPicker = new PoiPicker({
input: 'place',
placeSearchOptions: {
map: map,
pageSize: 6 //关联搜索分页
}
});
poiPicker.on('poiPicked', function (poiResult) {
poiPicker.hideSearchResults();
$('.poi .nearpoi').text(poiResult.item.name);
$('.address .info').text(poiResult.item.address);
$('#address').val(poiResult.item.address);
$("#place").val(poiResult.item.name);
relocation(poiResult.item.location);
});
positionPicker.on('success', function (positionResult) {
as = positionResult.position;
address = positionResult.address;
lat = as.lat;
lng = as.lng;
});
positionPicker.on('fail', function (positionResult) {
address = '';
});
positionPicker.start();
});
};
//点击确定后执行回调赋值
var close = function (data) {
var index = parent.Layer.getFrameIndex(window.name);
var callback = parent.$("#layui-layer" + index).data("callback");
//再执行关闭
parent.Layer.close(index);
//再调用回传函数
if (typeof callback === 'function') {
callback.call(undefined, data);
}
};
//点击搜索按钮
$(document).on('click', '.confirm', function () {
var zoom = map.getZoom();
var data = {lat: lat, lng: lng, zoom: zoom, address: address};
close(data);
});
init();
});
</script>
</body>
</html>
\ No newline at end of file
... ...
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>地址选择器</title>
<link rel="stylesheet" href="__CDN__/assets/css/bootstrap.min.css"/>
<link rel="stylesheet" href="__CDN__/assets/css/fastadmin.min.css"/>
<link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>
<style type="text/css">
body {
margin: 0;
padding: 0;
}
#container {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
.confirm {
position: absolute;
bottom: 30px;
right: 4%;
z-index: 99;
height: 50px;
width: 50px;
line-height: 50px;
font-size: 15px;
text-align: center;
background-color: white;
background: #1ABC9C;
color: white;
border: none;
cursor: pointer;
border-radius: 50%;
}
.search {
position: absolute;
width: 400px;
top: 0;
left: 50%;
padding: 5px;
margin-left: -200px;
}
label.BMapLabel {
max-width: inherit;
padding: .75rem 1.25rem;
margin-bottom: 1rem;
background-color: white;
width: auto;
min-width: 22rem;
border: none;
box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
}
</style>
</head>
<body>
<div class="search">
<div class="input-group">
<input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/>
<div id="searchResultPanel" style="border:1px solid #C0C0C0;width:150px;height:auto; display:none;"></div>
<span class="input-group-btn">
<button type="button" name="search" id="address" class="btn btn-success">
<i class="fa fa-search"></i>
</button>
</span>
</div>
</div>
<div class="confirm">确定</div>
<div id="container"></div>
<script type="text/javascript" src="//api.map.baidu.com/api?v=2.0&ak={$config.baidukey|default=''}"></script>
<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
// 百度地图API功能
function G(id) {
return document.getElementById(id);
}
var map, marker, searchService, address = null, lng, lat;
var init = function () {
map = new BMap.Map("container"); // 创建地图实例
var point = new BMap.Point({$lng}, {$lat}); // 创建点坐标
map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
map.centerAndZoom(point, parseInt("{$config.zoom}")); // 初始化地图,设置中心点坐标和地图级别
var size = new BMap.Size(10, 20);
map.addControl(new BMap.CityListControl({
anchor: BMAP_ANCHOR_TOP_LEFT,
offset: size,
}));
var geoc = new BMap.Geocoder();
var addpoint = function (point) {
//通过点击百度地图,可以获取到对应的point, 由point的lng、lat属性就可以获取对应的经度纬度
var pt = point;
geoc.getLocation(pt, function (rs) {
//对象可以获取到详细的地址信息
address = rs.address;
deletePoint();
var mk = new BMap.Marker(pt);
map.addOverlay(mk);
map.panTo(pt);
var label = new BMap.Label('<div class="info">地址:' + address + '<br>经度:' + pt.lng + '<br>纬度:' + pt.lat + '</div>', {offset: new BMap.Size(16, 20)});
label.setStyle({
border: 'none',
padding: '.75rem 1.25rem'
});
mk.setLabel(label);
//将对应的HTML元素设置值
lng = pt.lng;
lat = pt.lat;
});
};
if ("{$lng}" != '' && "{$lat}" != '') {
addpoint(point);
}
ac = new BMap.Autocomplete({"input": "place", "location": map}); //建立一个自动完成的对象
ac.addEventListener("onhighlight", function (e) { //鼠标放在下拉列表上的事件
var str = "";
var _value = e.fromitem.value;
var value = "";
if (e.fromitem.index > -1) {
value = _value.province + _value.city + _value.district + _value.street + _value.business;
}
str = "FromItem<br />index = " + e.fromitem.index + "<br />value = " + value;
value = "";
if (e.toitem.index > -1) {
_value = e.toitem.value;
value = _value.province + _value.city + _value.district + _value.street + _value.business;
}
str += "<br />ToItem<br />index = " + e.toitem.index + "<br />value = " + value;
G("searchResultPanel").innerHTML = str;
});
ac.addEventListener("onconfirm", function (e) { //鼠标点击下拉列表后的事件
var _value = e.item.value;
myValue = _value.province + _value.city + _value.district + _value.street + _value.business;
G("searchResultPanel").innerHTML = "onconfirm<br />index = " + e.item.index + "<br />myValue = " + myValue;
setPlace();
});
function setPlace() {
map.clearOverlays(); //清除地图上所有覆盖物
function myFun() {
var result = local.getResults().getPoi(0);
var pp = result.point; //获取第一个智能搜索的结果
map.centerAndZoom(pp, 18);
map.addOverlay(new BMap.Marker(pp)); //添加标注
lng = pp.lng;
lat = pp.lat;
address = result.address;
}
var local = new BMap.LocalSearch(map, { //智能搜索
onSearchComplete: myFun
});
local.search(myValue);
}
map.addEventListener("click", function (e) {
//通过点击百度地图,可以获取到对应的point, 由point的lng、lat属性就可以获取对应的经度纬度
var pt = e.point;
addpoint(e.point);
});
/**
* 清除覆盖物
*/
function deletePoint() {
var allOverlay = map.getOverlays();
for (var i = 0; i < allOverlay.length; i++) {
map.removeOverlay(allOverlay[i]);
}
}
};
var close = function (data) {
var index = parent.Layer.getFrameIndex(window.name);
var callback = parent.$("#layui-layer" + index).data("callback");
//再执行关闭
parent.Layer.close(index);
//再调用回传函数
if (typeof callback === 'function') {
callback.call(undefined, data);
}
};
//点击确定后执行回调赋值
$(document).on('click', '.confirm', function () {
var zoom = map.getZoom();
var data = {lat: lat, lng: lng, zoom: zoom, address: address};
close(data);
});
init();
});
</script>
</body>
</html>
\ No newline at end of file
... ...
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<title>地图位置(经纬度)选择插件 - FastAdmin</title>
<!-- Bootstrap Core CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom CSS -->
<link href="https://cdn.demo.fastadmin.net/assets/css/frontend.css" rel="stylesheet">
<!-- Plugin CSS -->
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="bs-docs-section clearfix">
<div class="row">
<div class="col-lg-12">
<div class="page-header">
<h2 id="navbar">地图位置(经纬度)选择示例</h2>
</div>
<div class="bs-component">
<form action="" method="post" role="form">
<div class="form-group">
<label for=""></label>
<input type="text" class="form-control" name="" id="address" placeholder="地址">
</div>
<div class="form-group">
<label for=""></label>
<input type="text" class="form-control" name="" id="lng" placeholder="经度">
</div>
<div class="form-group">
<label for=""></label>
<input type="text" class="form-control" name="" id="lat" placeholder="纬度">
</div>
<button type="button" class="btn btn-primary" data-toggle='addresspicker' data-input-id="address" data-lng-id="lng" data-lat-id="lat">点击选择地址获取经纬度</button>
</form>
</div>
<div class="page-header">
<h2 id="code">调用代码</h2>
</div>
<div class="bs-component">
<textarea class="form-control" rows="17">
<form action="" method="post" role="form">
<div class="form-group">
<label for=""></label>
<input type="text" class="form-control" name="" id="address" placeholder="地址">
</div>
<div class="form-group">
<label for=""></label>
<input type="text" class="form-control" name="" id="lng" placeholder="经度">
</div>
<div class="form-group">
<label for=""></label>
<input type="text" class="form-control" name="" id="lat" placeholder="纬度">
</div>
<button type="button" class="btn btn-primary" data-toggle='addresspicker' data-input-id="address" data-lng-id="lng" data-lat-id="lat">点击选择地址获取经纬度</button>
</form>
</textarea>
</div>
<div class="page-header">
<h2 id="navbar">参数说明</h2>
</div>
<div class="bs-component">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>参数</th>
<th>释义</th>
</tr>
</thead>
<tbody>
<tr>
<td>data-input-id</td>
<td>填充地址的文本框ID</td>
</tr>
<tr>
<td>data-lng-id</td>
<td>填充经度的文本框ID</td>
</tr>
<tr>
<td>data-lat-id</td>
<td>填充纬度的文本框ID</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var require = {
config: {$config | json_encode
}
}
;
</script>
<script>
require.callback = function () {
define('addons/address', ['jquery', 'bootstrap', 'frontend', 'template'], function ($, undefined, Frontend, Template) {
var Controller = {
index: function () {
;
}
};
return Controller;
});
define('lang', function () {
return [];
});
}
</script>
<script src="__CDN__/assets/js/require.min.js" data-main="__CDN__/assets/js/require-frontend.min.js?v={$site.version}"></script>
</body>
</html>
\ No newline at end of file
... ...
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>地址选择器</title>
<link rel="stylesheet" href="__CDN__/assets/css/bootstrap.min.css"/>
<link rel="stylesheet" href="__CDN__/assets/css/fastadmin.min.css"/>
<link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>
<style type="text/css">
body {
margin: 0;
padding: 0;
}
#container {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
.confirm {
position: absolute;
bottom: 30px;
right: 4%;
z-index: 99;
height: 50px;
width: 50px;
line-height: 50px;
font-size: 15px;
text-align: center;
background-color: white;
background: #1ABC9C;
color: white;
border: none;
cursor: pointer;
border-radius: 50%;
}
.search {
position: absolute;
width: 400px;
top: 0;
left: 50%;
padding: 5px;
margin-left: -200px;
}
</style>
</head>
<body>
<div class="search">
<div class="input-group">
<input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/>
<span class="input-group-btn">
<button type="submit" name="search" id="search-btn" class="btn btn-success">
<i class="fa fa-search"></i>
</button>
</span>
</div>
</div>
<div class="confirm">确定</div>
<div id="container"></div>
<script charset="utf-8" src="//map.qq.com/api/js?v=2.exp&libraries=place&key={$config.tencentkey|default=''}"></script>
<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
var map, marker, geocoder, infoWin, searchService, address = null;
var init = function () {
var center = new qq.maps.LatLng({$lat}, {$lng});
map = new qq.maps.Map(document.getElementById('container'), {
center: center,
zoom: parseInt("{$config.zoom}")
});
//初始化marker
initmarker(center);
//实例化信息窗口
infoWin = new qq.maps.InfoWindow({
map: map
});
geocoder = new qq.maps.Geocoder({
complete: function (result) {
infoWin.open();
address = result.detail.addressComponents.province +
result.detail.addressComponents.city +
result.detail.addressComponents.district;
if (result.detail.addressComponents.streetNumber == '') {
address += result.detail.addressComponents.street;
} else {
address += result.detail.addressComponents.streetNumber;
}
infoWin.setContent(address);
infoWin.setPosition(result.detail.location);
}
});
//显示当前marker的位置信息窗口
geocoder.getAddress(center);
var latlngBounds = new qq.maps.LatLngBounds();
//查询poi类信息
searchService = new qq.maps.SearchService({
complete: function (results) {
var pois = results.detail.pois;
for (var i = 0, l = pois.length; i < l; i++) {
var poi = pois[i];
latlngBounds.extend(poi.latLng);
initmarker(poi.latLng);
//显示当前marker的位置信息窗口
geocoder.getAddress(poi.latLng);
}
map.fitBounds(latlngBounds);
}
});
//实例化自动完成
var ap = new qq.maps.place.Autocomplete(document.getElementById('place'));
//添加监听事件
qq.maps.event.addListener(ap, "confirm", function (res) {
searchKeyword();
});
qq.maps.event.addListener(
map,
'click',
function (event) {
try {
infoWin.setContent('<div style="text-align:center;white-space:nowrap;margin:10px;">加载中</div>');
var latLng = event.latLng,
lat = latLng.getLat().toFixed(5),
lng = latLng.getLng().toFixed(5);
var location = new qq.maps.LatLng(lat, lng);
//调用获取位置方法
geocoder.getAddress(location);
infoWin.setPosition(location);
marker.setPosition(location);
} catch (e) {
console.log(e);
}
}
);
};
//实例化marker和监听拖拽结束事件
var initmarker = function (latLng) {
marker = new qq.maps.Marker({
map: map,
position: latLng,
draggable: true,
title: '拖动图标选择位置'
});
//监听拖拽结束
qq.maps.event.addListener(marker, 'dragend', function (event) {
var latLng = event.latLng,
lat = latLng.getLat().toFixed(5),
lng = latLng.getLng().toFixed(5);
var location = new qq.maps.LatLng(lat, lng);
//调用获取位置方法
geocoder.getAddress(location);
});
};
var close = function (data) {
var index = parent.Layer.getFrameIndex(window.name);
var callback = parent.$("#layui-layer" + index).data("callback");
//再执行关闭
parent.Layer.close(index);
//再调用回传函数
if (typeof callback === 'function') {
callback.call(undefined, data);
}
};
//执行搜索方法
var searchKeyword = function () {
searchService.clear();//先清除
marker.setMap(null);
infoWin.close();
var keyword = $("#place").val();
searchService.setLocation("{$location}");//设置默认检索范围(默认为全国),类型可以是坐标或指定的城市名称。
searchService.setPageIndex(0);//设置检索的特定页数。
searchService.setPageCapacity(1);//设置每页返回的结果数量。
searchService.search(keyword);//开始查询
};
//点击确定后执行回调赋值
$(document).on('click', '.confirm', function () {
var as = marker.getPosition();
var x = as.getLat().toFixed(5);
var y = as.getLng().toFixed(5);
var zoom = map.getZoom();
var data = {lat: x, lng: y, zoom: zoom, address: address};
close(data);
});
//点击搜索按钮
$(document).on('click', '#search-btn', function () {
if ($("#place").val() == '')
return;
searchKeyword();
});
init();
});
</script>
</body>
</html>
\ No newline at end of file
... ...
{"license":"regular","licenseto":"44234","licensekey":"82jyXWeYPFpiE1C4 kxxHOwiOqPyuag4dlI\/v3w=="}
\ No newline at end of file
... ...
<?php
namespace addons\alisms;
use think\Addons;
/**
* Alisms
*/
class Alisms extends Addons
{
/**
* 插件安装方法
* @return bool
*/
public function install()
{
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
return true;
}
/**
* 短信发送行为
* @param array $params 必须包含mobile,event,code
* @return boolean
*/
public function smsSend(&$params)
{
$config = get_addon_config('alisms');
$alisms = new \addons\alisms\library\Alisms();
$result = $alisms->mobile($params['mobile'])
->template($config['template'][$params['event']])
->param(['code' => $params['code']])
->send();
return $result;
}
/**
* 短信发送通知
* @param array $params 必须包含 mobile,event,msg
* @return boolean
*/
public function smsNotice(&$params)
{
$config = get_addon_config('alisms');
$alisms = \addons\alisms\library\Alisms::instance();
if (isset($params['msg'])) {
if (is_array($params['msg'])) {
$param = $params['msg'];
} else {
parse_str($params['msg'], $param);
}
} else {
$param = [];
}
$param = $param ? $param : [];
$params['template'] = isset($params['template']) ? $params['template'] : (isset($params['event']) && isset($config['template'][$params['event']]) ? $config['template'][$params['event']] : '');
$result = $alisms->mobile($params['mobile'])
->template($params['template'])
->param($param)
->send();
return $result;
}
/**
* 检测验证是否正确
* @param $params
* @return boolean
*/
public function smsCheck(&$params)
{
return true;
}
}
... ...
<?php
return [
[
'name' => 'key',
'title' => '应用key',
'type' => 'string',
'content' => [],
'value' => 'LTAI4G5vhKpKAdRrJvbpbhXy',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'secret',
'title' => '密钥secret',
'type' => 'string',
'content' => [],
'value' => 'BIXrRKuLb8jELqPKAzYjF9eyW4DjTr',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'sign',
'title' => '签名',
'type' => 'string',
'content' => [],
'value' => '云南智慧水库安全云平台',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'template',
'title' => '短信模板',
'type' => 'array',
'content' => [],
'value' => [
'register' => 'SMS_226785328',
'resetpwd' => 'SMS_114000000',
'changepwd' => 'SMS_114000000',
'changemobile' => 'SMS_114000000',
'profile' => 'SMS_114000000',
'password' => 'SMS_227747048',
],
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => '__tips__',
'title' => '温馨提示',
'type' => 'string',
'content' => [],
'value' => '应用key和密钥你可以通过 https://ak-console.aliyun.com/?spm=a2c4g.11186623.2.13.fd315777PX3tjy#/accesskey 获取',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
];
... ...
<?php
namespace addons\alisms\controller;
use think\addons\Controller;
/**
* 阿里短信
*/
class Index extends Controller
{
protected $model = null;
public function _initialize()
{
// if (!\app\admin\library\Auth::instance()->id) {
// $this->error('暂无权限浏览');
// }
parent::_initialize();
}
public function index()
{
return $this->view->fetch();
}
public function send()
{
$config = get_addon_config('alisms');
$mobile = $this->request->post('mobile');
$template = $this->request->post('template');
$sign = $this->request->post('sign');
if (!$mobile || !$template) {
$this->error('手机号、模板ID不能为空');
}
$sign = $sign ? $sign : $config['sign'];
$param = (array)json_decode($this->request->post('param', '', 'trim'));
$alisms = new \addons\alisms\library\Alisms();
$ret = $alisms->mobile($mobile)
->template($template)
->sign($sign)
->param($param)
->send();
if ($ret) {
$this->success("发送成功");
} else {
$this->error("发送失败!失败原因:" . $alisms->getError());
}
}
//发送短信带参数
public function send_param($mobile,$template,$sign,$param)
{
$config = get_addon_config('alisms');
if (!$mobile || !$template) {
$this->error('手机号、模板ID不能为空');
}
$alisms = new \addons\alisms\library\Alisms();
$ret = $alisms->mobile($mobile)
->template($template)
->sign($sign)
->param($param)
->send();
// if ($ret) {
// $this->success("发送成功");
// } else {
// $this->error("发送失败!失败原因:" . $alisms->getError());
// }
}
}
... ...
<?php
// This file is auto-generated, don't edit it. Thanks.
namespace addons\alisms\controller;
use AlibabaCloud\SDK\Dyvmsapi\V20170525\Dyvmsapi;
use Darabonba\OpenApi\Models\Config;
use AlibabaCloud\SDK\Dyvmsapi\V20170525\Models\SingleCallByTtsRequest;
class Sample {
/**
* 使用AK&SK初始化账号Client
* @param string $accessKeyId
* @param string $accessKeySecret
* @return Dyvmsapi Client
*/
public static function createClient($accessKeyId, $accessKeySecret){
$config = new Config([
// 您的AccessKey ID
"accessKeyId" => $accessKeyId,
// 您的AccessKey Secret
"accessKeySecret" => $accessKeySecret
]);
// 访问的域名
$config->endpoint = "dyvmsapi.aliyuncs.com";
return new Dyvmsapi($config);
}
/**
* @param string[] $args
* @return void
*/
public static function main($mobile='',$template='',$data=[])
{
$client = self::createClient("LTAI4G5vhKpKAdRrJvbpbhXy", "BIXrRKuLb8jELqPKAzYjF9eyW4DjTr");
$singleCallByTtsRequest = new SingleCallByTtsRequest([
"calledNumber" => $mobile,
"ttsCode" => $template,
"ttsParam" => json_encode($data)
//"ttsParam" => json_encode($data,TRUE)
]);
// 复制代码运行请自行打印 API 的返回值
$res = $client->singleCallByTts($singleCallByTtsRequest);
}
public static function sendsms($mobile='',$template='',$data=[])
{
$path = __DIR__ . \DIRECTORY_SEPARATOR . '..' . \DIRECTORY_SEPARATOR . 'vendor' . \DIRECTORY_SEPARATOR . 'autoload.php';
if (file_exists($path)) {
require_once $path;
}
self::main($mobile,$template,$data);
}
}
... ...
name = alisms
title = 阿里云短信发送
intro = 阿里云短信发送插件
author = FastAdmin
website = https://www.fastadmin.net
version = 1.0.9
state = 1
url = /addons/alisms
license = regular
licenseto = 44234
... ...
<?php
namespace addons\alisms\library;
/**
* 阿里大于SMS短信发送
*/
class Alisms
{
private $_params = [];
public $error = '';
protected $config = [];
protected static $instance;
public function __construct($options = [])
{
if ($config = get_addon_config('alisms')) {
$this->config = array_merge($this->config, $config);
}
$this->config = array_merge($this->config, is_array($options) ? $options : []);
}
/**
* 单例
* @param array $options 参数
* @return Alisms
*/
public static function instance($options = [])
{
if (is_null(self::$instance)) {
self::$instance = new static($options);
}
return self::$instance;
}
/**
* 设置签名
* @param string $sign
* @return Alisms
*/
public function sign($sign = '')
{
$this->_params['SignName'] = $sign;
return $this;
}
/**
* 设置参数
* @param array $param
* @return Alisms
*/
public function param(array $param = [])
{
foreach ($param as $k => &$v) {
$v = (string)$v;
}
unset($v);
$param = array_filter($param);
$this->_params['TemplateParam'] = $param ? json_encode($param) : '{}';
return $this;
}
/**
* 设置模板
* @param string $code 短信模板
* @return Alisms
*/
public function template($code = '')
{
$this->_params['TemplateCode'] = $code;
return $this;
}
/**
* 接收手机
* @param string $mobile 手机号码
* @return Alisms
*/
public function mobile($mobile = '')
{
$this->_params['PhoneNumbers'] = $mobile;
return $this;
}
/**
* 立即发送
* @return boolean
*/
public function send()
{
$this->error = '';
$params = $this->_params();
$params['Signature'] = $this->_signed($params);
$response = $this->_curl($params);
if ($response !== false) {
$res = (array)json_decode($response, true);
if (isset($res['Code']) && $res['Code'] == 'OK') {
return true;
}
$this->error = isset($res['Message']) ? $res['Message'] : 'InvalidResult';
} else {
$this->error = 'InvalidResult';
}
return false;
}
/**
* 获取错误信息
* @return string
*/
public function getError()
{
return $this->error;
}
private function _params()
{
return array_merge([
'AccessKeyId' => $this->config['key'],
'SignName' => isset($this->config['sign']) ? $this->config['sign'] : '',
'Action' => 'SendSms',
'Format' => 'JSON',
'Version' => '2017-05-25',
'SignatureVersion' => '1.0',
'SignatureMethod' => 'HMAC-SHA1',
'SignatureNonce' => uniqid(),
'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
], $this->_params);
}
private function percentEncode($string)
{
$string = urlencode($string);
$string = preg_replace('/\+/', '%20', $string);
$string = preg_replace('/\*/', '%2A', $string);
$string = preg_replace('/%7E/', '~', $string);
return $string;
}
private function _signed($params)
{
$sign = $this->config['secret'];
ksort($params);
$canonicalizedQueryString = '';
foreach ($params as $key => $value) {
$canonicalizedQueryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
}
$stringToSign = 'GET&%2F&' . $this->percentencode(substr($canonicalizedQueryString, 1));
$signature = base64_encode(hash_hmac('sha1', $stringToSign, $sign . '&', true));
return $signature;
}
private function _curl($params)
{
$uri = 'http://dysmsapi.aliyuncs.com/?' . http_build_query($params);
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_URL, $uri);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
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");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$reponse = curl_exec($ch);
curl_close($ch);
return $reponse;
}
}
... ...
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<title>阿里云通信短信发送示例 - FastAdmin</title>
<!-- Bootstrap Core CSS -->
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom CSS -->
<link href="__CDN__/assets/css/frontend.css" rel="stylesheet">
<!-- Plugin CSS -->
<link href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link href="https://cdn.staticfile.org/simple-line-icons/2.4.1/css/simple-line-icons.min.css" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://cdn.staticfile.org/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="well" style="margin-top:30px;">
<form class="form-horizontal" action="{:addon_url('alisms/index/send')}" method="POST">
<fieldset>
<legend>阿里云通信短信发送</legend>
<div class="form-group">
<label class="col-lg-2 control-label">手机号</label>
<div class="col-lg-10">
<input type="text" class="form-control" name="mobile" placeholder="手机号">
</div>
</div>
<div class="form-group">
<label class="col-lg-2 control-label">消息模板ID</label>
<div class="col-lg-10">
<input type="text" class="form-control" name="template" placeholder="消息模板ID,从阿里云通信获得,通常是:SMS_114000000这种格式">
</div>
</div>
<div class="form-group">
<label class="col-lg-2 control-label">签名</label>
<div class="col-lg-10">
<input type="text" class="form-control" name="sign" placeholder="消息模板(可以留空,留空使用后台插件管理中的配置)">
</div>
</div>
<div class="form-group">
<label class="col-lg-2 control-label">模板变量参数</label>
<div class="col-lg-10">
<textarea name="param" class="form-control" cols="30" rows="10" placeholder='必须是JSON字符串,如{"name":"李明"}'></textarea>
</div>
</div>
<div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<button type="submit" class="btn btn-primary">发送</button>
<button type="reset" class="btn btn-default">重置</button>
</div>
</div>
</fieldset>
</form>
</div>
</div>
<!-- jQuery -->
<script src="https://cdn.staticfile.org/jquery/2.1.4/jquery.min.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(function () {
});
</script>
</body>
</html>
\ No newline at end of file
... ...
{"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"]}
\ No newline at end of file
... ...
<?php
namespace addons\command;
use app\common\library\Menu;
use think\Addons;
/**
* 在线命令插件
*/
class Command extends Addons
{
/**
* 插件安装方法
* @return bool
*/
public function install()
{
$menu = [
[
'name' => 'command',
'title' => '在线命令管理',
'icon' => 'fa fa-terminal',
'sublist' => [
['name' => 'command/index', 'title' => '查看'],
['name' => 'command/add', 'title' => '添加'],
['name' => 'command/detail', 'title' => '详情'],
['name' => 'command/execute', 'title' => '运行'],
['name' => 'command/del', 'title' => '删除'],
['name' => 'command/multi', 'title' => '批量更新'],
]
]
];
Menu::create($menu);
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
Menu::delete('command');
return true;
}
/**
* 插件启用方法
* @return bool
*/
public function enable()
{
Menu::enable('command');
return true;
}
/**
* 插件禁用方法
* @return bool
*/
public function disable()
{
Menu::disable('command');
return true;
}
}
... ...
<?php
return [
];
... ...
<?php
namespace addons\command\controller;
use think\addons\Controller;
class Index extends Controller
{
public function index()
{
$this->error("当前插件暂无前台页面");
}
}
... ...
name = command
title = 在线命令
intro = 可在线执行FastAdmin的命令行相关命令
author = Karson
website = https://www.fastadmin.net
version = 1.0.6
state = 1
url = /addons/command
license = regular
licenseto = 44234
... ...
CREATE TABLE IF NOT EXISTS `__PREFIX__command` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',
`type` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '类型',
`params` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '参数',
`command` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '命令',
`content` text COMMENT '返回结果',
`executetime` int(10) UNSIGNED DEFAULT NULL COMMENT '执行时间',
`createtime` int(10) UNSIGNED DEFAULT NULL COMMENT '创建时间',
`updatetime` int(10) UNSIGNED DEFAULT NULL COMMENT '更新时间',
`status` enum('successed','failured') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'failured' COMMENT '状态',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '在线命令表';
... ...
<?php
namespace addons\command\library;
/**
* Class Output
*/
class Output extends \think\console\Output
{
protected $message = [];
public function __construct($driver = 'console')
{
parent::__construct($driver);
}
protected function block($style, $message)
{
$this->message[] = $message;
}
public function getMessage()
{
return $this->message;
}
}
... ...
{"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"]}
\ No newline at end of file
... ...
<?php
namespace addons\dinghorn;
use addons\dinghorn\library\DinghornLib;
use app\common\library\Menu;
use think\Addons;
use think\Db;
/**
* 钉钉小喇叭
*/
class Dinghorn extends Addons
{
/**
* 通过模板发送通知消息
* @param string $template 消息模板Id或Code
* @param array $tpl_data 要覆盖的模板数据 (参见:\application\admin\controller\dinghorn\Example.php 的 example2 方法)
* @param array $tpl_variable 模板变量键值对,若模板变量已预先定义,则会自动获取值,无需在此传递
* @return array 发送结果
*/
public static function msgNotice($template, $tpl_data = array(), $tpl_variable = array())
{
$now_time = time();
$dinghorn_config = get_addon_config('dinghorn');
$template = Db::name('dinghorn_template')
->where('id = :tpl OR code = :tpl_code', ['tpl' => $template, 'tpl_code' => $template])
->where('deletetime', null)
->find();
if (!$template || !$template['openswitch']) {
if ($dinghorn_config['error_log']) {
$log_arr = array(
'robot_id' => 0,
'template_id' => isset($template['id']) ? $template['id'] : 0,
'template_data' => json_encode($tpl_data),
'errmsg' => '消息模板未找到或已禁用!(-1)',
'status' => '0',
'createtime' => $now_time
);
Db::name('dinghorn_msglog')->insert($log_arr);
}
return ['errcode' => -1, 'errmsg' => '消息模板未找到或已禁用!'];
}
$DinghornLib = new DinghornLib($template, $tpl_data, $tpl_variable);
// 获取模板内的机器人
$robot_ids = isset($tpl_data['robot_ids']) ? $tpl_data['robot_ids'] : $template['robot_ids'];
$robots = Db::name('dinghorn_robot')
->whereIn('id', $robot_ids)
->where('openswitch', 1)
->where('deletetime', null)
->select();
// 组装消息数据
$msg_data = $DinghornLib->deal_with_msg();
$log_arr = [];//要插入的日志
$is_err = false;//是否有错误,用于判定本次操作的返回值
// 循环所有要发送的机器人
foreach ($robots as $key => $value) {
$res = $DinghornLib->msgSend($value['access_token'], $msg_data, $value['sign']);
if ($res['errcode'] == 0 && $dinghorn_config['success_log']) {
$log_arr[] = array(
'robot_id' => $value['id'],
'template_id' => $template['id'],
'template_data' => json_encode($msg_data),
'errmsg' => '',
'status' => '1',
'createtime' => $now_time
);
} else if ($res['errcode'] != 0) {
$is_err = true;
$errmsg = $res['errmsg'] . '(' . $res['errcode'] . ')';
if ($dinghorn_config['error_log']) {
$log_arr[] = array(
'robot_id' => $value['id'],
'template_id' => $template['id'],
'template_data' => json_encode($msg_data),
'errmsg' => $errmsg,
'status' => '0',
'createtime' => $now_time
);
}
}
}
if ($log_arr) {
Db::startTrans();
try {
Db::name('dinghorn_msglog')->insertAll($log_arr);
Db::commit();
} catch (\Exception $e) {
Db::rollback();
}
}
return $is_err ? ['errcode' => -2, 'errmsg' => '消息发送失败:' . $errmsg] : ['errcode' => 0];
}
/**
* 插件安装方法
* @return bool
*/
public function install()
{
$menu = [
[
'name' => 'dinghorn',
'title' => '钉钉小喇叭',
'icon' => 'fa fa-volume-up',
'sublist' => [
[
'name' => 'dinghorn/robot',
'title' => '机器人管理',
'icon' => 'fa fa-circle-o',
'sublist' => [
['name' => 'dinghorn/robot/index', 'title' => '查看'],
['name' => 'dinghorn/robot/add', 'title' => '添加'],
['name' => 'dinghorn/robot/edit', 'title' => '编辑'],
['name' => 'dinghorn/robot/del', 'title' => '删除'],
['name' => 'dinghorn/robot/multi', 'title' => '批量更新'],
['name' => 'dinghorn/robot/recyclebin', 'title' => '回收站'],
['name' => 'dinghorn/robot/destroy', 'title' => '真实删除'],
['name' => 'dinghorn/robot/restore', 'title' => '还原'],
]
],
[
'name' => 'dinghorn/variable',
'title' => '模板变量管理',
'icon' => 'fa fa-circle-o',
'remark' => '在此处设置变量,随后可在模板通知内使用变量,变量值可来源于方法返回值或SQL查询结果',
'sublist' => [
['name' => 'dinghorn/variable/index', 'title' => '查看'],
['name' => 'dinghorn/variable/add', 'title' => '添加'],
['name' => 'dinghorn/variable/edit', 'title' => '编辑'],
['name' => 'dinghorn/variable/del', 'title' => '删除'],
['name' => 'dinghorn/variable/multi', 'title' => '批量更新'],
['name' => 'dinghorn/variable/recyclebin', 'title' => '回收站'],
['name' => 'dinghorn/variable/destroy', 'title' => '真实删除'],
['name' => 'dinghorn/variable/restore', 'title' => '还原'],
['name' => 'dinghorn/variable/view_variable', 'title' => '计算变量值'],
]
],
[
'name' => 'dinghorn/template',
'title' => '通知模板管理',
'icon' => 'fa fa-circle-o',
'sublist' => [
['name' => 'dinghorn/template/index', 'title' => '查看'],
['name' => 'dinghorn/template/add', 'title' => '添加'],
['name' => 'dinghorn/template/edit', 'title' => '编辑'],
['name' => 'dinghorn/template/del', 'title' => '删除'],
['name' => 'dinghorn/template/multi', 'title' => '批量更新'],
['name' => 'dinghorn/template/recyclebin', 'title' => '回收站'],
['name' => 'dinghorn/template/destroy', 'title' => '真实删除'],
['name' => 'dinghorn/template/restore', 'title' => '还原'],
]
],
[
'name' => 'dinghorn/msglog',
'title' => '通知发送日志管理',
'icon' => 'fa fa-circle-o',
'sublist' => [
['name' => 'dinghorn/msglog/index', 'title' => '查看'],
['name' => 'dinghorn/msglog/edit', 'title' => '编辑'],
['name' => 'dinghorn/msglog/del', 'title' => '删除'],
['name' => 'dinghorn/msglog/multi', 'title' => '批量更新'],
['name' => 'dinghorn/msglog/recyclebin', 'title' => '回收站'],
['name' => 'dinghorn/msglog/destroy', 'title' => '真实删除'],
['name' => 'dinghorn/msglog/restore', 'title' => '还原'],
]
],
]
]
];
Menu::create($menu);
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
Menu::delete('dinghorn');
return true;
}
/**
* 插件启用方法
* @return bool
*/
public function enable()
{
Menu::enable('dinghorn');
return true;
}
/**
* 插件禁用方法
* @return bool
*/
public function disable()
{
Menu::disable('dinghorn');
return true;
}
}
... ...
<?php
return [
[
'name' => 'success_log',
'title' => '成功日志',
'type' => 'radio',
'options' => [
'1' => '记录',
'0' => '不记录'
],
'content' => array(
'1' => '记录',
'0' => '不记录'
),
'value' => '0',
'rule' => 'required',
'msg' => '',
'tip' => '机器人发送消息成功后,记录日志',
'ok' => '',
'extend' => ''
],
[
'name' => 'error_log',
'title' => '失败日志',
'type' => 'radio',
'options' => [
'1' => '记录',
'0' => '不记录'
],
'content' => array(
'1' => '记录',
'0' => '不记录'
),
'value' => '1',
'rule' => 'required',
'msg' => '',
'tip' => '机器人发送消息失败时,记录日志',
'ok' => '',
'extend' => ''
],
];
\ No newline at end of file
... ...
<?php
namespace addons\dinghorn\controller;
use think\addons\Controller;
class Index extends Controller
{
public function index()
{
$update_log = <<<html
<h4>V1.0.1更新内容</h4>
<p>1. 后台增加模板变量测试功能</p>
<p>2. 模板内现已可使用未定义的模板变量,在调用时传递变量值</p>
<p>3. 模板增加Code,业务代码中调用时比ID更易识别</p>
<p>4. 后台发送模板消息失败提示成功的问题</p>
<p>5. 模板不存在或禁用时,无失败日志的问题</p>
<p>6. 模板变量名重复检测</p>
<p>7. 优化多处代码逻辑</p>
html;
echo $update_log;
}
}
... ...
name = dinghorn
title = 钉钉小喇叭
intro = 利用钉钉机器人,实时接受业务提醒,快速接入、使用方便、免费无限制的通知服务,支持发送文本、链接、 markdown、ActionCard、FeedCard消息类型
author = 白衣素袖
website = https://www.fastadmin.net
version = 1.0.2
state = 1
url = /addons/dinghorn
license = regular
licenseto = 44234
... ...
-- ---------------------------
-- 机器人表
-- ---------------------------
CREATE TABLE IF NOT EXISTS `__PREFIX__dinghorn_robot` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '机器人名称',
`logo_image` varchar(100) NOT NULL DEFAULT '' COMMENT '机器人logo',
`access_token` varchar(100) NOT NULL DEFAULT '' COMMENT 'Hook地址',
`sign` varchar(100) NOT NULL DEFAULT '' COMMENT '签名密匙',
`keywords` varchar(100) NOT NULL DEFAULT '' COMMENT '自定义关键词',
`weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重',
`openswitch` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否开启:0=否,1=是',
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
`deletetime` int(10) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='钉钉机器人表';
-- ----------------------------
-- 插入机器人
-- ----------------------------
BEGIN;
INSERT IGNORE INTO `__PREFIX__dinghorn_robot` VALUES ('1', '测试机器人', '', '1f81037666a7f9255827b916e0bdd7d4be382afc774d893be82d977bb926286a6','' , '', '1', '1', '1561962387', '1561962247', null);
COMMIT;
-- ----------------------------
-- 通知发送日志表
-- ----------------------------
CREATE TABLE IF NOT EXISTS `__PREFIX__dinghorn_msglog` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`robot_id` int(10) NOT NULL DEFAULT '0' COMMENT '发送机器人',
`template_id` int(10) NOT NULL DEFAULT '0' COMMENT '通知模板',
`template_data` text COMMENT '发送的数据',
`errmsg` varchar(255) NOT NULL DEFAULT '' COMMENT '错误消息',
`status` enum('1','0') NOT NULL DEFAULT '0' COMMENT '状态:0=失败,1=成功',
`createtime` int(10) DEFAULT NULL COMMENT '发送时间',
`deletetime` int(10) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='通知发送日志表';
-- ----------------------------
-- 通知消息模板表
-- ----------------------------
CREATE TABLE IF NOT EXISTS `__PREFIX__dinghorn_template` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`code` varchar(50) NOT NULL DEFAULT '' COMMENT '模板Code',
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '模板名称',
`robot_ids` varchar(100) NOT NULL DEFAULT '0' COMMENT '发送机器人',
`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',
`content` text DEFAULT NULL COMMENT '默认消息内容',
`title` varchar(100) NOT NULL DEFAULT '' COMMENT '默认消息标题',
`msg_url` varchar(255) NOT NULL DEFAULT '' COMMENT '默认链接URL',
`picurl_image` varchar(255) NOT NULL DEFAULT '' COMMENT '默认图片URL',
`single_title` varchar(100) NOT NULL DEFAULT '' COMMENT '按钮文字',
`btn_orientation` tinyint(1) NOT NULL DEFAULT '0' COMMENT '按钮排列方式:0=竖直排列,1=横向排列',
`hide_avatar` tinyint(1) NOT NULL DEFAULT '0' COMMENT '隐藏机器人头像:0=否,1=是',
`btns` text COMMENT '按钮组',
`links` text COMMENT '默认链接组',
`at_mobiles` varchar(100) NOT NULL DEFAULT '' COMMENT '被AT人的手机号',
`is_atall` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'AT所有人:0=否,1=是',
`openswitch` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否开启:0=否,1=是',
`updatetime` int(10) DEFAULT NULL COMMENT '修改时间',
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
`deletetime` int(10) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='通知消息模板表';
-- ----------------------------
-- 插入一个初始模板
-- ----------------------------
BEGIN;
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);
COMMIT;
-- ----------------------------
-- 模板变量表
-- ----------------------------
CREATE TABLE IF NOT EXISTS `__PREFIX__dinghorn_variable` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '变量名',
`value_source` tinyint(1) NOT NULL DEFAULT '0' COMMENT '变量值来源:0=SQL查询结果,1=方法返回值',
`sql` varchar(255) NOT NULL DEFAULT '' COMMENT 'SQL',
`namespace` varchar(200) NOT NULL DEFAULT '' COMMENT '命名空间',
`class` varchar(50) NOT NULL DEFAULT '' COMMENT '类',
`function` varchar(50) NOT NULL DEFAULT '' COMMENT '方法',
`params` varchar(100) NOT NULL DEFAULT '' COMMENT '参数',
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
`deletetime` int(10) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='模板变量表';
-- ----------------------------
-- 插入两个初始变量
-- ----------------------------
BEGIN;
INSERT IGNORE INTO `__PREFIX__dinghorn_variable` VALUES ('1', 'user_count', '0', 'SELECT count(id) as id FROM __PREFIX__user', '', '', '', '', '1562132190', '1562123868', null);
INSERT IGNORE INTO `__PREFIX__dinghorn_variable` VALUES ('2', 'test', '1', '', 'app\\admin\\controller\\dinghorn', 'Example', 'test', '我是传递过来的参数', '1562132323', '1562124050', null);
COMMIT;
-- ----------------------------
-- 旧版本增加字段处理
-- ----------------------------
BEGIN;
ALTER TABLE `__PREFIX__dinghorn_robot` ADD COLUMN `keywords` varchar(100) NOT NULL DEFAULT '' COMMENT '自定义关键词' AFTER `access_token`;
ALTER TABLE `__PREFIX__dinghorn_robot` ADD COLUMN `sign` varchar(100) NOT NULL DEFAULT '' COMMENT '签名密匙' AFTER `access_token`;
COMMIT;
BEGIN;
ALTER TABLE `__PREFIX__dinghorn_template` ADD COLUMN `code` varchar(50) NOT NULL DEFAULT '' COMMENT '模板Code' AFTER `id`;
COMMIT;
-- ----------------------------
-- 旧版本修改字段处理
-- ----------------------------
BEGIN;
ALTER TABLE `__PREFIX__dinghorn_template` MODIFY COLUMN `content` text DEFAULT NULL COMMENT '默认消息内容' AFTER `typelist`;
ALTER TABLE `__PREFIX__dinghorn_template` MODIFY COLUMN `msg_url` varchar(255) NOT NULL DEFAULT '' COMMENT '默认图片URL' AFTER `title`;
ALTER TABLE `__PREFIX__dinghorn_template` MODIFY COLUMN `picurl_image` varchar(255) NOT NULL DEFAULT '' COMMENT '默认图片URL' AFTER `msg_url`;
COMMIT;
BEGIN;
ALTER TABLE `__PREFIX__dinghorn_msglog` MODIFY COLUMN `errmsg` varchar(255) NOT NULL DEFAULT '' COMMENT '错误消息' AFTER `template_data`;
ALTER TABLE `__PREFIX__dinghorn_variable` MODIFY COLUMN `sql` varchar(255) NOT NULL DEFAULT '' COMMENT 'SQL' AFTER `value_source`;
COMMIT;
\ No newline at end of file
... ...
<?php
namespace addons\dinghorn\library;
/**
*
*/
class DinghornLib
{
// 模板数据
public $template;
// 要覆盖的模板数据 (参见:\application\admin\controller\dinghorn\Example.php 的 example2 方法)
public $tpl_data;
// 模板变量键值对,若模板变量已预先定义,则会自动获取值,无需在此传递
public $tpl_variable;
/**
* 构造方法
* @param array $template 模板数据
* @param array $tpl_data 要覆盖的模板数据
* @param array $tpl_variable 模板变量键值对
*/
public function __construct($template = array(), $tpl_data = array(), $tpl_variable = array())
{
$this->template = $template;
$this->tpl_data = $tpl_data;
$this->tpl_variable = $tpl_variable;
}
/**
* 发起请求
* @param string $access_token 机器人的 access_token
* @param array $post_data 请求数据
* @return array 请求结果
*/
public function msgSend($access_token, $post_data, $sign = false)
{
$remote_server = 'https://oapi.dingtalk.com/robot/send?access_token=' . $access_token;
if ($sign) {
$millisecond = $this->getMillisecond();
$sign_str = $millisecond . "\n" . $sign;
$sign_str = hash_hmac('sha256', $sign_str, $sign, true);
$sign_str = urlencode(base64_encode($sign_str));
$remote_server .= '&timestamp=' . $millisecond . '&sign=' . $sign_str;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $remote_server);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json;charset=utf-8'));
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$ret = curl_exec($ch);
if (false == $ret) {
// curl_exec failed
$result = ['errcode' => -2, 'errmsg' => curl_error($ch)];
} else {
$rsp = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (200 != $rsp) {
$result = ['errcode' => -1, 'errmsg' => $rsp . ' ' . curl_error($ch)];
} else {
$result = json_decode($ret, true);
if (!$result) {
$result = ['errcode' => -3, 'errmsg' => '转换请求结果数据失败!'];
}
}
}
curl_close($ch);
return $result;
}
public function getMillisecond()
{
list($microsecond, $time) = explode(' ', microtime()); //' '中间是一个空格
return (float)sprintf('%.0f', (floatval($microsecond) + floatval($time)) * 1000);
}
/**
* 组装消息数据
* @return array 组装结果
*/
public function deal_with_msg()
{
$msg_data = array();
$msgtype = $msg_data['msgtype'] = $this->template['typelist'];
if (isset($this->tpl_data['content'])) {
$content = $this->analysis_variable($this->tpl_data['content']);
} else {
$content = $this->analysis_variable($this->template['content']);
}
if (isset($this->tpl_data['title'])) {
$title = $this->analysis_variable($this->tpl_data['title']);
} else {
$title = $this->analysis_variable($this->template['title']);
}
if ($msgtype == 'text') {
$msg_data['text'] = [
'content' => $content
];
$msg_data['at'] = $this->deal_with_at();
} elseif ($msgtype == 'link') {
$msg_data['link'] = [
'title' => $title,
'text' => $content,
'picUrl' => request()->domain() . (isset($this->tpl_data['picurl_image']) ? $this->tpl_data['picurl_image'] : cdnurl($this->template['picurl_image'])),
'messageUrl' => isset($this->tpl_data['msg_url']) ? $this->tpl_data['msg_url'] : $this->template['msg_url'],
];
} elseif ($msgtype == 'markdown') {
$msg_data['markdown'] = [
'title' => $title,
'text' => $content
];
$msg_data['at'] = $this->deal_with_at();
} elseif ($msgtype == 'actionCard_whole') {
$msg_data['msgtype'] = 'actionCard';
$msg_data['actionCard'] = [
'title' => $title,
'text' => $content,
'hideAvatar' => isset($this->tpl_data['hide_avatar']) ? $this->tpl_data['hide_avatar'] : $this->template['hide_avatar'],
'btnOrientation' => 1,
'singleTitle' => isset($this->tpl_data['single_title']) ? $this->analysis_variable($this->tpl_data['single_title']) : $this->analysis_variable($this->template['single_title']),
'singleURL' => isset($this->tpl_data['msg_url']) ? $this->tpl_data['msg_url'] : $this->template['msg_url']
];
} elseif ($msgtype == 'actionCard') {
$btns = isset($this->tpl_data['btns']) ? $this->tpl_data['btns'] : json_decode($this->template['btns'], true);
$btns_temp = [];
foreach ($btns as $key => $value) {
$btns_temp[] = array(
'title' => $this->analysis_variable($key),
'actionURL' => $value
);
}
$msg_data['actionCard'] = [
'title' => $title,
'text' => $content,
'hideAvatar' => isset($this->tpl_data['hide_avatar']) ? $this->tpl_data['hide_avatar'] : $this->template['hide_avatar'],
'btnOrientation' => isset($this->tpl_data['btn_orientation']) ? $this->tpl_data['btn_orientation'] : $this->template['btn_orientation'],
'btns' => $btns_temp
];
} elseif ($msgtype == 'feedCard') {
$links = isset($this->tpl_data['links']) ? $this->tpl_data['links'] : json_decode($this->template['links'], true);
foreach ($links as $key => $value) {
$links[$key]['title'] = $this->analysis_variable($links[$key]['title']);
}
$msg_data['feedCard'] = array(
'links' => $links
);
}
return $msg_data;
}
/**
* 分析字符串中的自定义变量
* @param string $str 要分析的字符串
* @return string 解析过变量的字符串
*/
public function analysis_variable($str)
{
if (!$str) {
return '';
}
$variables = array();
$match = array();
preg_match_all('/\${(.*?)}/', $str, $match);// 匹配到所有变量
// 读取数据库中的模板变量
$variable_tmp = \think\Db::name('dinghorn_variable')->where('deletetime', null)->select();
foreach ($variable_tmp as $key => $value) {
$value['variable_type'] = 'predefined';// 标记为预定义
$variable_arr[$value['name']] = $value;
}
unset($variable_tmp);
// 准备传递过来的模板变量
foreach ($this->tpl_variable as $key => $value) {
$variable_arr[$key] = [
'variable_type' => 'definition_now',// 标记为现在定义
'variable_value' => $value,
];
}
foreach ($match[1] as $key => $value) {
if (array_key_exists($value, $variable_arr)) {
if ($variable_arr[$value]['variable_type'] == 'definition_now') {
$str = str_replace($match[0][$key], $variable_arr[$value]['variable_value'], $str);
} else if ($variable_arr[$value]['variable_type'] == 'predefined') {
$variable_value = $this->get_variable_value($variable_arr[$value]);
$str = str_replace($match[0][$key], $variable_value, $str);
}
}
}
return $str;
}
/**
* 获取数据库中的模板变量的值
* @param string $var 变量数据
* @return string 变量值
*/
public function get_variable_value($var)
{
if ($var['value_source'] == 0) {
$var['sql'] = str_replace('__PREFIX__', config('database.prefix'), $var['sql']);
$res = \think\Db::query($var['sql']);
if ($res) {
if (is_array($res[0])) {
foreach ($res[0] as $key => $value) {
return $value;
}
} else {
return $res[0];
}
} else {
return false;
}
} else if ($var['value_source'] == 1) {
return \think\Hook::exec($var['namespace'] . '\\' . $var['class'], $var['function'], $var['params']);
}
}
/**
* 组装at数据
* @return array 组装结果
*/
public function deal_with_at()
{
// 数据覆盖
if (isset($this->tpl_data['is_atall']) || isset($this->tpl_data['at_mobiles'])) {
$this->template['is_atall'] = $this->tpl_data['is_atall'];
$this->template['at_mobiles'] = $this->tpl_data['at_mobiles'];
}
if ($this->template['is_atall']) {
return [
'atMobiles' => [],
'isAtAll' => true
];
} else {
$at_mobiles = explode(',', rtrim($this->template['at_mobiles'], ','));
return [
'atMobiles' => $at_mobiles,
'isAtAll' => false
];
}
}
}
... ...
{"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"]}
\ No newline at end of file
... ...
<?php
namespace addons\example;
use app\common\library\Menu;
use think\Addons;
/**
* Example
*/
class Example extends Addons
{
/**
* 插件安装方法
* @return bool
*/
public function install()
{
$menu = [
[
'name' => 'example',
'title' => '开发示例管理',
'icon' => 'fa fa-magic',
'sublist' => [
[
'name' => 'example/bootstraptable',
'title' => '表格完整示例',
'icon' => 'fa fa-table',
'sublist' => [
['name' => 'example/bootstraptable/index', 'title' => '查看'],
['name' => 'example/bootstraptable/detail', 'title' => '详情'],
['name' => 'example/bootstraptable/change', 'title' => '变更'],
['name' => 'example/bootstraptable/del', 'title' => '删除'],
['name' => 'example/bootstraptable/multi', 'title' => '批量更新'],
]
],
[
'name' => 'example/customsearch',
'title' => '自定义搜索',
'icon' => 'fa fa-table',
'sublist' => [
['name' => 'example/customsearch/index', 'title' => '查看'],
['name' => 'example/customsearch/del', 'title' => '删除'],
['name' => 'example/customsearch/multi', 'title' => '批量更新'],
]
],
[
'name' => 'example/customform',
'title' => '自定义表单示例',
'icon' => 'fa fa-edit',
'sublist' => [
['name' => 'example/customform/index', 'title' => '查看'],
]
],
[
'name' => 'example/tablelink',
'title' => '表格联动示例',
'icon' => 'fa fa-table',
'remark' => '点击左侧日志列表,右侧的表格数据会显示指定管理员的日志列表',
'sublist' => [
['name' => 'example/tablelink/index', 'title' => '查看'],
]
],
[
'name' => 'example/colorbadge',
'title' => '彩色角标',
'icon' => 'fa fa-table',
'remark' => '左侧彩色的角标会根据当前数据量的大小进行更新',
'sublist' => [
['name' => 'example/colorbadge/index', 'title' => '查看'],
['name' => 'example/colorbadge/del', 'title' => '删除'],
['name' => 'example/colorbadge/multi', 'title' => '批量更新'],
]
],
[
'name' => 'example/controllerjump',
'title' => '控制器间跳转',
'icon' => 'fa fa-table',
'remark' => '点击IP地址可以跳转到新的选项卡中查看指定IP的数据',
'sublist' => [
['name' => 'example/controllerjump/index', 'title' => '查看'],
['name' => 'example/controllerjump/del', 'title' => '删除'],
['name' => 'example/controllerjump/multi', 'title' => '批量更新'],
]
],
[
'name' => 'example/cxselect',
'title' => '多级联动',
'icon' => 'fa fa-table',
'remark' => '基于jquery.cxselect实现的多级联动',
'sublist' => [
['name' => 'example/cxselect/index', 'title' => '查看'],
['name' => 'example/cxselect/del', 'title' => '删除'],
['name' => 'example/cxselect/multi', 'title' => '批量更新'],
]
],
[
'name' => 'example/multitable',
'title' => '多表格示例',
'icon' => 'fa fa-table',
'remark' => '展示在一个页面显示多个Bootstrap-table表格',
'sublist' => [
['name' => 'example/multitable/index', 'title' => '查看'],
['name' => 'example/multitable/del', 'title' => '删除'],
['name' => 'example/multitable/multi', 'title' => '批量更新'],
]
],
[
'name' => 'example/relationmodel',
'title' => '关联模型示例',
'icon' => 'fa fa-table',
'remark' => '列表中的头像、用户名和昵称字段均从关联表中取出',
'sublist' => [
['name' => 'example/relationmodel/index', 'title' => '查看'],
['name' => 'example/relationmodel/del', 'title' => '删除'],
['name' => 'example/relationmodel/multi', 'title' => '批量更新'],
]
],
[
'name' => 'example/tabletemplate',
'title' => '表格模板示例',
'icon' => 'fa fa-table',
'remark' => '',
'sublist' => [
['name' => 'example/tabletemplate/index', 'title' => '查看'],
['name' => 'example/tabletemplate/detail', 'title' => '详情'],
['name' => 'example/tabletemplate/del', 'title' => '删除'],
['name' => 'example/tabletemplate/multi', 'title' => '批量更新'],
]
],
[
'name' => 'example/baidumap',
'title' => '百度地图示例',
'icon' => 'fa fa-map-pin',
'sublist' => [
['name' => 'example/baidumap/index', 'title' => '查看'],
['name' => 'example/baidumap/map', 'title' => '详情'],
['name' => 'example/baidumap/del', 'title' => '删除'],
]
],
[
'name' => 'example/echarts',
'title' => '统计图表示例',
'icon' => 'fa fa-bar-chart',
'sublist' => [
['name' => 'example/echarts/index', 'title' => '查看'],
]
],
]
]
];
Menu::create($menu);
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
Menu::delete('example');
return true;
}
/**
* 插件启用方法
*/
public function enable()
{
Menu::enable('example');
}
/**
* 插件禁用方法
*/
public function disable()
{
Menu::disable('example');
}
}
... ...
require.config({
paths: {
'async': '../addons/example/js/async',
'BMap': ['//api.map.baidu.com/api?v=2.0&ak=mXijumfojHnAaN2VxpBGoqHM'],
},
shim: {
'BMap': {
deps: ['jquery'],
exports: 'BMap'
}
}
});
... ...
<?php
return [
[
'name' => 'title',
'title' => '标题',
'type' => 'string',
'content' => [
],
'value' => '示例标题',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => ''
],
[
//配置唯一标识
'name' => 'theme',
//显示的标题
'title' => '皮肤',
//类型
'type' => 'string',
//数据字典
'content' => [
],
//值
'value' => 'default',
//验证规则
'rule' => 'required',
//错误消息
'msg' => '',
//提示消息
'tip' => '',
//成功消息
'ok' => '',
//扩展信息
'extend' => ''
],
[
'name' => 'domain',
'title' => '绑定二级域名前缀',
'type' => 'string',
'content' => [
],
'value' => '',
'rule' => '',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => ''
],
[
'name' => 'rewrite',
'title' => '伪静态',
'type' => 'array',
'content' => [],
'value' => [
'index/index' => '/example$',
'demo/index' => '/example/d/[:name]',
'demo/demo1' => '/example/d1/[:name]',
'demo/demo2' => '/example/d2/[:name]',
],
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => ''
],
];
... ...
<?php
namespace addons\example\controller;
use think\addons\Controller;
/**
* 测试控制器
*/
class Demo extends Controller
{
protected $layout = 'default';
protected $noNeedLogin = ['index', 'demo1'];
protected $noNeedRight = ['*'];
public function index()
{
return $this->view->fetch();
}
public function demo1()
{
return $this->view->fetch();
}
public function demo2()
{
return $this->view->fetch();
}
}
... ...
<?php
namespace addons\example\controller;
use think\addons\Controller;
class Index extends Controller
{
protected $layout = 'default';
public function index()
{
return $this->view->fetch();
}
}
... ...
name = example
title = 开发示例
intro = FastAdmin多个开发示例
author = FastAdmin
website = https://www.fastadmin.net
version = 1.1.0
state = 1
url = /addons/example
license = regular
licenseto = 44234
... ...
此 diff 太大无法显示。
<!-- Page Content -->
<div class="container">
<!-- Page Heading/Breadcrumbs -->
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">无需登录页面
<small>开发者示例</small>
</h1>
<ol class="breadcrumb">
<li><a href="{:addon_url('example/index/index')}">插件首页</a>
</li>
<li class="active">无需登录页面</li>
</ol>
</div>
</div>
<!-- /.row -->
<!-- Content Row -->
<div class="row">
<div class="col-lg-12">
<p class="well">当前登录页面无需登录即可查看,当前请求的name值为:{$Request.param.name}</p>
{if $user}
<p class="well text-danger">但是如果你登录后可以浏览到这段隐藏的信息</p>
{/if}
</div>
</div>
<!-- /.row -->
<hr>
</div>
<!-- /.container -->
\ No newline at end of file
... ...
<!-- Page Content -->
<div class="container">
<!-- Page Heading/Breadcrumbs -->
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">需登录页面
<small>开发者示例</small>
</h1>
<ol class="breadcrumb">
<li><a href="{:addon_url('example/index/index')}">插件首页</a>
</li>
<li class="active">需登录页面</li>
</ol>
</div>
</div>
<!-- /.row -->
<!-- Content Row -->
<div class="row">
<div class="col-lg-12">
<p class="well">当前登录页面需要登录后才可以查看,你可以退出后再访问此页面,会提醒登录,当前请求的name值为:{$Request.param.name}</p>
<p class="well">你好!{$user.nickname},<a href="{:url('index/user/logout')}">注销登录</a></p>
</div>
</div>
<!-- /.row -->
<hr>
</div>
<!-- /.container -->
\ No newline at end of file
... ...
<!-- Page Content -->
<div class="container">
<!-- Page Heading/Breadcrumbs -->
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">使用模板标签和变量
<small>开发者示例</small>
</h1>
<ol class="breadcrumb">
<li><a href="{:addon_url('example/index/index')}">插件首页</a>
</li>
<li class="active">使用模板标签和变量</li>
</ol>
</div>
</div>
<!-- /.row -->
<!-- Content Row -->
<div class="row">
<div class="col-lg-12">
<p class="well">当前请求的name值为:{$Request.param.name}</p>
{literal}
<pre>
在插件视图中可以使用所有ThinkPHP5内支持的模板标签和变量,如
{$Think.server.script_name} // 输出$_SERVER['SCRIPT_NAME']变量
{$Think.session.user_id} // 输出$_SESSION['user_id']变量
{$Think.get.pageNumber} // 输出$_GET['pageNumber']变量
{$Think.cookie.name} // 输出$_COOKIE['name']变量
// 调用Request对象的get方法 传入参数为id
{$Request.get.id}
// 调用Request对象的param方法 传入参数为name
{$Request.param.name}
// 调用Request对象的param方法 传入参数为user.nickname
{$Request.param.user.nickname}
// 调用Request对象的root方法
{$Request.root}
// 调用Request对象的root方法,并且传入参数true
{$Request.root.true}
// 调用Request对象的path方法
{$Request.path}
// 调用Request对象的module方法
{$Request.module}
// 调用Request对象的controller方法
{$Request.controller}
// 调用Request对象的action方法
{$Request.action}
// 调用Request对象的ext方法
{$Request.ext}
// 调用Request对象的host方法
{$Request.host}
// 调用Request对象的ip方法
{$Request.ip}
// 调用Request对象的header方法
{$Request.header.accept-encoding}
</pre>
{/literal}
</div>
</div>
<!-- /.row -->
<hr>
</div>
<!-- /.container -->
\ No newline at end of file
... ...
<!-- Header Carousel -->
<header id="myCarousel" class="carousel slide">
<!-- Indicators -->
<ol class="carousel-indicators">
<li data-target="#myCarousel" data-slide-to="0" class="active"></li>
<li data-target="#myCarousel" data-slide-to="1"></li>
<li data-target="#myCarousel" data-slide-to="2"></li>
<li data-target="#myCarousel" data-slide-to="3"></li>
</ol>
<!-- Wrapper for slides -->
<div class="carousel-inner">
<div class="item active">
<a href="https://www.fastadmin.net/store/cms.html" target="_blank">
<div class="fill" style="background-image:url('https://bg.fastadmin.net?text=random&color=3498db');"></div>
<div class="carousel-body">
<div class="container">
<h1 class="display-1 text-white">CMS内容管理模块</h1>
<h2 class="display-4 text-white">简单强大的内容管理系统,可自定义内容模型、标签、伪静态、全文搜索、百度推送等功能<br>包含完整的小程序CMS客户端,拥有完善的资讯模块、产品模块、评论模块、会员模块</h2>
</div>
</div>
</a>
</div>
<div class="item">
<a href="https://www.fastadmin.net/store/blog.html" target="_blank">
<div class="fill" style="background-image:url('https://bg.fastadmin.net?text=random&color=2ecc71');"></div>
<div class="carousel-body">
<div class="container">
<h1 class="display-1 text-white">简单博客模块</h1>
<h2 class="display-4 text-white">响应式博客插件,包含日志、评论、分类、归档、全文搜索、百度推送等功能<br/>包含完整的小程序博客客户端,拥有博客日志列表、日志详情、评论等功能</h2>
</div>
</div>
</a>
</div>
<div class="item">
<a href="https://www.fastadmin.net/store/vote.html" target="_blank">
<div class="fill" style="background-image:url('https://bg.fastadmin.net?text=random&color=0082ff');"></div>
<div class="carousel-body">
<div class="container">
<h1 class="display-1 text-white">在线投票系统</h1>
<h2 class="display-4 text-white">基于FastAdmin+ThinkPHP开发的响应式在线投票系统,支持微信公众号投票和PC端投票<br/>具有高防刷票机制和实时排行榜等诸多特性,提供全部前后台无加密源代码</h2>
</div>
</div>
</a>
</div>
<div class="item">
<a href="https://www.fastadmin.net/store/docs.html" target="_blank">
<div class="fill" style="background-image:url('https://bg.fastadmin.net?text=random&color=9c88ff');"></div>
<div class="carousel-body">
<div class="container">
<h1 class="display-1 text-white">Markdown文档生成</h1>
<h2 class="display-4 text-white">将Github或本地Git环境中的Markdown文件解析并生成HTML,可在线浏览或导出为HTML离线浏览</h2>
</div>
</div>
</a>
</div>
</div>
</header>
<!-- Page Content -->
<div class="container">
<!-- Marketing Icons Section -->
<div class="row">
<div class="col-lg-12">
<h2 class="page-header">
基础模块
</h2>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h4><i class="fa fa-fw fa-user"></i> 前台模块</h4>
</div>
<div class="panel-body">
<p>FastAdmin有基础的前台模块,可快速的进行二次开发,前台模块中包含基础的会员模块,前台模块中的会员账号和API模块中的会员账号是同一账号体系</p>
<a href="{:url('index/index/index')}" target="_blank" class="btn btn-primary">立即访问</a>
<a href="{:url('index/user/index')}" target="_blank" class="btn btn-default">会员中心</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h4><i class="fa fa-fw fa-gift"></i> API模块</h4>
</div>
<div class="panel-body">
<p>FastAdmin有基础的API模块,可快速的进行二次开发,API模块中包含基础的会员模块,初始化模块、短信发送模块、验证模块</p>
<a href="{:url('api/index/index')}" target="_blank" class="btn btn-primary">立即访问</a>
<a href="{:url('api/common/init')}?version=1.0.0" target="_blank" class="btn btn-default">初始化接口</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h4><i class="fa fa-fw fa-compass"></i> API文档</h4>
</div>
<div class="panel-body">
<p>我们提供了一键生成API文档的功能,当写完API接口以后,可通过执行php think api一键生成我们所需要的API文档,并且可以直接在线测试</p>
<a href="{:url('/')}api.html" target="_blank" class="btn btn-primary">立即访问</a>
<a href="https://doc.fastadmin.net/docs/command.html#一键生成API文档" target="_blank" class="btn btn-default">一键生成文档</a>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<h2 class="page-header">
功能示例
</h2>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h4><i class="fa fa-fw fa-check"></i> 使用模板标签和变量</h4>
</div>
<div class="panel-body">
<p>在FastAdmin插件的视图中我们可以像前后台开发一样,向视图中渲染我们的自定义变量,然后在视图中进行访问。同时FastAdmin的插件视图中支持所有ThinkPHP5官方的系统模板标签和变量。轻轻松松的开发我们的插件</p>
<a href="{:addon_url('example/demo/index',[':name'=>'s1'])}" class="btn btn-success">查看示例</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h4><i class="fa fa-fw fa-gift"></i> 访问不需要登录的页面</h4>
</div>
<div class="panel-body">
<p>在开发的过程有许多页面是不需要会员登录就可以访问的页面,比如新闻列表、新闻详情、评论列表、产品列表、产品展示、关于我们等等页面。在FastAdmin中可以使用noNeedLogin很方便的控制我们请求方法的访问权限</p>
<a href="{:addon_url('example/demo/demo1',[':name'=>'s2'])}" class="btn btn-success">立即访问</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h4><i class="fa fa-fw fa-compass"></i> 访问需要登录的页面</h4>
</div>
<div class="panel-body">
<p>通常我们在开发中,如果页面与会员信息相关联,则通常需要控制页面在会员登录后才可以访问,FastAdmin中前台的权限控制可以很快捷的在插件中使用。我们可以直接重新定义noNeedLogin排除我们不需要登录的方法即可。</p>
<a href="{:addon_url('example/demo/demo2',[':name'=>'s3'])}" class="btn btn-success">立即访问</a>
</div>
</div>
</div>
</div>
<!-- /.row -->
<div class="row addonlist">
<div class="col-lg-12">
<h2 class="page-header">
模块&插件
<span class="pull-right small" style="margin-top:5px;">
<small>
<a href="https://www.fastadmin.net/store.html" target="_blank">更多</a>
</small>
</span>
</h2>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/cms.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/cms.png" alt="">
<p>CMS内容管理模块</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/blog.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/blog.png" alt="">
<p>简洁博客模块</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/ask.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/ask.png" alt="">
<p>付费问答社区</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/docs.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/docs.png" alt="">
<p>文档生成模块</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/vote.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/vote.png" alt="">
<p>在线投票系统</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/qiniu.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/qiniu.png" alt="">
<p>七牛上传插件</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/alioss.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/alioss.png" alt="">
<p>阿里云储存</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/alisms.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/alisms.png" alt="">
<p>阿里云短信</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/nkeditor.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/nkeditor.png" alt="">
<p>富文本编辑器</p>
</a>
</div>
<div class="col-xs-12 text-center">
<a href="https://www.fastadmin.net/store.html" class="btn btn-primary" target="_blank">前往插件市场</a>
</div>
</div>
<!-- /.row -->
<hr>
<!-- Call to Action Section -->
<div class="well">
<div class="row">
<div class="col-md-8">
<p>感谢你对FastAdmin的支持!如果你在使用FastAdmin开发插件的过程中有任何疑问或需要寻求帮助,请前往FastAdmin问答社区与小伙伴们一起交流。</p>
</div>
<div class="col-md-4">
<a class="btn btn-lg btn-default btn-block" href="https://ask.fastadmin.net" target="_blank">前往问答社区</a>
</div>
</div>
</div>
<hr>
</div>
... ...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>开发者示例 - {$site.name}</title>
<!-- Bootstrap Core CSS -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom CSS -->
<link href="__ADDON__/css/common.css" rel="stylesheet">
<!-- Custom Fonts -->
<link href="https://cdn.bootcss.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://cdn.bootcss.com/html5shiv/3.7.0/html5shiv.min.js"></script>
<script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{:addon_url('example/index/index')}">{$site.name}</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li>
<a href="{:addon_url('example/index/index')}">插件首页</a>
</li>
<li>
<a href="{:addon_url('example/demo/demo1', [':name'=>'s1'])}">无需登录页面</a>
</li>
<li>
<a href="{:addon_url('example/demo/demo2', [':name'=>'s2'])}">需登录页面</a>
</li>
{if $user}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">欢迎你! {$user.nickname}<b class="caret"></b></a>
<ul class="dropdown-menu">
<li>
<a href="{:url('index/user/index')}">会员中心</a>
</li>
<li>
<a href="{:url('index/user/profile')}">个人资料</a>
</li>
<li>
<a href="{:url('index/user/logout')}">退出登录</a>
</li>
</ul>
</li>
{else /}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">会员中心 <b class="caret"></b></a>
<ul class="dropdown-menu">
<li>
<a href="{:url('index/user/login')}">登录</a>
</li>
<li>
<a href="{:url('index/user/register')}">注册</a>
</li>
</ul>
</li>
{/if}
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
{__CONTENT__}
<div class="container">
<!-- Footer -->
<footer>
<div class="row">
<div class="col-lg-12">
<p>Copyright &copy; {$site.name} 2020</p>
</div>
</div>
</footer>
</div>
<!-- /.container -->
<!-- jQuery -->
<script src="https://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- Script to Activate the Carousel -->
<script>
$('.carousel').carousel({
interval: 5000 //changes the speed
})
</script>
</body>
</html>
... ...
{"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"]}
\ No newline at end of file
... ...
<?php
namespace addons\inspection;
use app\common\library\Menu;
use think\Addons;
/**
* 插件
*/
class Inspection extends Addons
{
/**
* 插件安装方法
* @return bool
*/
public function install()
{
$menu = [
[
'name' => 'inspection',
'title' => '设备巡检',
'icon' => 'fa fa-font-awesome',
'sublist' => [
[
"name" => "inspection/depart",
"title" => "部门管理",
'icon' => 'fa fa-users',
'sublist' => [
["name" => "inspection/depart/index", "title" => "查看",],
["name" => "inspection/depart/add", "title" => "添加"],
["name" => "inspection/depart/edit", "title" => "编辑"],
["name" => "inspection/depart/del", "title" => "删除"],
["name" => "inspection/depart/multi", "title" => "批量更新"],
]
],
[
"name" => "inspection/staff",
"title" => "员工管理",
'icon' => 'fa fa-user',
'sublist' => [
["name" => "inspection/staff/index", "title" => "查看",],
["name" => "inspection/staff/add", "title" => "添加"],
["name" => "inspection/staff/edit", "title" => "编辑"],
["name" => "inspection/staff/del", "title" => "删除"],
["name" => "inspection/staff/multi", "title" => "批量更新"],
]
],
[
"name" => "inspection/area",
"title" => "巡检区域管理",
'icon' => 'fa fa-braille',
'sublist' => [
["name" => "inspection/area/index", "title" => "查看",],
["name" => "inspection/area/add", "title" => "添加"],
["name" => "inspection/area/edit", "title" => "编辑"],
["name" => "inspection/area/del", "title" => "删除"],
["name" => "inspection/area/multi", "title" => "批量更新"],
]
],
[
"name" => "inspection/areasite",
"title" => "巡检点管理",
'icon' => 'fa fa-anchor',
'sublist' => [
["name" => "inspection/areasite/index", "title" => "查看",],
["name" => "inspection/areasite/add", "title" => "添加"],
["name" => "inspection/areasite/edit", "title" => "编辑"],
["name" => "inspection/areasite/del", "title" => "删除"],
["name" => "inspection/areasite/multi", "title" => "批量更新"],
]
],
[
"name" => "inspection/areaitem",
"title" => "检查项管理",
'ismenu' => 0,
'sublist' => [
["name" => "inspection/areaitem/index", "title" => "查看",],
["name" => "inspection/areaitem/add", "title" => "添加"],
["name" => "inspection/areaitem/edit", "title" => "编辑"],
["name" => "inspection/areaitem/del", "title" => "删除"],
["name" => "inspection/areaitem/multi", "title" => "批量更新"],
]
],
[
"name" => "inspection/route",
"title" => "巡检路线管理",
'icon' => 'fa fa-map',
'sublist' => [
["name" => "inspection/route/index", "title" => "查看",],
["name" => "inspection/route/add", "title" => "添加"],
["name" => "inspection/route/edit", "title" => "编辑"],
["name" => "inspection/route/del", "title" => "删除"],
["name" => "inspection/route/multi", "title" => "批量更新"],
]
],
[
"name" => "inspection/plan",
"title" => "巡检计划管理",
'icon' => 'fa fa-gg',
'sublist' => [
["name" => "inspection/plan/index", "title" => "查看",],
["name" => "inspection/plan/add", "title" => "添加"],
["name" => "inspection/plan/edit", "title" => "编辑"],
["name" => "inspection/plan/del", "title" => "删除"],
["name" => "inspection/plan/multi", "title" => "批量更新"],
]
],[
"name" => "inspection/project",
"title" => "巡检任务管理",
'icon' => 'fa fa-bookmark',
'sublist' => [
["name" => "inspection/project/index", "title" => "查看",],
["name" => "inspection/project/add", "title" => "添加"],
["name" => "inspection/project/edit", "title" => "编辑"],
["name" => "inspection/project/del", "title" => "删除"],
["name" => "inspection/project/multi", "title" => "批量更新"],
]
],
]
]
];
Menu::create($menu);
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
Menu::delete("inspection");
return true;
}
/**
* 插件启用方法
* @return bool
*/
public function enable()
{
Menu::enable("inspection");
return true;
}
/**
* 插件禁用方法
* @return bool
*/
public function disable()
{
Menu::disable("inspection");
return true;
}
public function appInit()
{
if(request()->isCli()){
//生成巡检任务
\think\Console::addDefaultCommands([
'addons\inspection\library\GenerateProject'
]);
//取消巡检任务
\think\Console::addDefaultCommands([
'addons\inspection\library\CancelProject'
]);
}
}
}
... ...
<?php
return [];
... ...
<?php
namespace addons\inspection\controller;
use app\admin\model\inspection\Lnglat;
use think\addons\Controller;
class Index extends Controller
{
public function lnglat()
{
$id = $this->request->param("id");
$this->assign('id',$id);
$lnglatModel = new Lnglat();
$lnglatInfo = $lnglatModel->where(['areasite_id'=>$id])->find();
$this->assign('lnglatInfo',$lnglatInfo);
return $this->fetch();
}
}
... ...
name = inspection
title = 设备巡检系统
intro = 基于FastAdmin插件和Uniapp的设备巡检系统,可用在电力、水利等巡检场景
author = piupiu
website = https://www.fastadmin.net
version = 1.0.1
state = 1
url = /addons/inspection
license = regular
licenseto = 44313
... ...
CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_area` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`pid` int(11) NOT NULL COMMENT '上级区域ID',
`area_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '区域名称',
`weigh` int(11) NOT NULL COMMENT '排序',
`createtime` int(11) NOT NULL COMMENT '创建时间',
`updatetime` int(11) NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '巡检区域表';
CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_area_item` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`areasite_id` int(11) NOT NULL DEFAULT 0,
`item_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`type` int(11) NOT NULL,
`weigh` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '巡检检查项';
CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_area_site` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`area_id` int(11) NOT NULL COMMENT '巡检区域ID',
`site_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '巡检点名称',
`verify` int(11) NOT NULL COMMENT '验证方式',
`lnglat` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '经纬度',
`distance` int(11) NULL DEFAULT NULL COMMENT '距离',
`weigh` int(11) NOT NULL COMMENT '排序',
`createtime` int(11) NOT NULL COMMENT '添加时间',
`updatetime` int(11) NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '巡检点';
CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_depart` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`pid` int(11) NOT NULL DEFAULT 0 COMMENT '上级单位',
`depart_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '单位名称',
`createtime` int(11) NOT NULL COMMENT '创建时间',
`weigh` int(11) NOT NULL DEFAULT 0 COMMENT '排序',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '部门表';
CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_plan` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`plan_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '巡检计划名称',
`route_id` int(11) NOT NULL COMMENT '路线ID',
`circle_type` int(11) NOT NULL COMMENT '定期类型 1天 2周 3月',
`circle_value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '定期周期',
`num` int(11) NOT NULL COMMENT '每天执行次数',
`time` int(11) NOT NULL COMMENT '每次间隔时长',
`begintime` int(11) NOT NULL COMMENT '开始时间',
`endtime` int(11) NULL DEFAULT NULL COMMENT '结束时间',
`staff_id` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '员工ID',
`createtime` int(11) NOT NULL,
`updatetime` int(11) NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '巡检计划表';
CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_project` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`plan_id` int(11) NOT NULL COMMENT '计划ID',
`route_id` int(11) NOT NULL COMMENT '路线ID',
`area_id` int(11) NOT NULL DEFAULT 0 COMMENT '巡检区域ID',
`area_site_id` int(11) NOT NULL COMMENT '巡检点ID',
`createtime` int(11) NOT NULL COMMENT '创建时间',
`begintime` int(11) NOT NULL COMMENT '开始时间',
`endtime` int(11) NOT NULL COMMENT '结束时间',
`staff_id` int(11) NOT NULL DEFAULT 0 COMMENT '员工ID',
`checktime` int(11) NULL DEFAULT 0 COMMENT '检查时间',
`jumptime` int(11) NULL DEFAULT NULL COMMENT '跳捡时间',
`jump_content` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '跳捡原因',
`images` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图片',
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '备注',
`status` int(11) NOT NULL DEFAULT 0 COMMENT '-1漏检 0进行中 1已巡检 2跳捡',
`state` int(11) NOT NULL DEFAULT 0 COMMENT '状态 0进行中 1正常 2异常',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '巡检任务表';
CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_project_item` (
`project_id` int(11) NOT NULL COMMENT '任务ID',
`item_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '检查项名称',
`type` int(11) NOT NULL COMMENT '检查项类型',
`value` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '检查项值'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '巡检任务检查项表';
CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_route` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`route_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '路线名称',
`createtime` int(11) NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '巡检路线表';
CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_route_site` (
`route_id` int(11) NOT NULL COMMENT '巡检路线ID',
`area_site_id` int(11) NOT NULL COMMENT '巡检点ID',
`weigh` int(11) NOT NULL DEFAULT 0 COMMENT '排序',
`createtime` int(11) NOT NULL COMMENT '创建时间'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '巡检路线巡检点表';
CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_staff` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL DEFAULT 0 COMMENT '会员ID',
`depart_id` int(11) NOT NULL DEFAULT 0 COMMENT '单位id',
`staff_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '员工编号',
`staff_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '员工姓名',
`mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '员工手机号',
`duty` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '职务',
`createtime` int(11) NOT NULL COMMENT '创建时间',
`weigh` int(11) NOT NULL DEFAULT 0 COMMENT '排序',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '员工表';
CREATE TABLE IF NOT EXISTS `__PREFIX__inspection_lnglat` (
`areasite_id` int(11) NOT NULL COMMENT '巡检点ID',
`distance` int(11) NOT NULL COMMENT '距离',
`lng` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '经度',
`lat` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '纬度',
`createtime` int(11) NOT NULL,
`updatetime` int(11) NOT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '巡检点定位表';
\ No newline at end of file
... ...
<?php
namespace addons\inspection\library;
use think\console\Command;
use think\console\Input;
use think\console\Output;
class CancelProject extends Command
{
protected function configure()
{
$this
->setName('cancelProject')
->setDescription('自动化处理过期的巡检任务');
}
protected function execute(Input $input, Output $output)
{
while (true){
$projectModel = new \app\admin\model\inspection\Project();
$projectModel->where(['endtime'=>['lt',time()],'status'=>0])->update(['status'=>-1]);
sleep(60); //1分钟
}
}
}
... ...
<?php
namespace addons\inspection\library;
use addons\ygame\service\Order;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Hook;
class GenerateProject extends Command
{
protected function configure()
{
$this
->setName('generateProject')
->setDescription('自动化生成巡检任务');
}
protected function execute(Input $input, Output $output)
{
while (true){
Hook::exec('addons\\inspection\\library\\Project','init',$params);
sleep(60*60); //1小时
}
}
}
... ...
<?php
namespace addons\inspection\library;
use app\admin\model\inspection\Plan;
use app\admin\model\inspection\Routesite;
use think\Db;
use think\Exception;
class Project
{
public function init(&$request){
$planModel = new Plan();
$planList = collection($planModel
->alias("plan")
->field("plan.id as plan_id,plan.route_id,plan.num,plan.time,plan.circle_type,plan.circle_value,plan.begintime,plan.endtime")
->join("inspection_route route","plan.route_id=route.id")
->join("inspection_staff staff","plan.staff_id=staff.id")
->where([
'plan.begintime'=>['elt',time()],
'plan.endtime'=>[['gt',time()],['EXP',Db::raw('is null')],'or'],
])
->select())->toArray();
foreach($planList as $k=>$v){
//获取计划中路线的巡检点
$routesiteModel = new Routesite();
$routsiteList = collection($routesiteModel
->alias("routesite")
->field("routesite.area_site_id,site.area_id")
->join("inspection_area_site site","routesite.area_site_id=site.id")
->where(['routesite.route_id'=>$v['route_id']])
->select())->toArray();
foreach ($routsiteList as $vv){
$data = $v;
$data['area_site_id'] = $vv['area_site_id'];
$data['area_id'] = $vv['area_id'];
switch($v['circle_type']){
case "1": //日计划
$this->circle_day($data);
break;
case "2": //周计划
$this->circle_week($data);
break;
case "3": //月计划
$this->circle_month($data);
break;
}
}
}
}
private function circle_day($data){
//获取巡检点信息
$begin_time = strtotime(date("Y-m-d",time()));
$data['begintime'] = $data['begintime']>$begin_time?$data['begintime']:$begin_time;
$endtime = strtotime("+1 days -1 second",$begin_time);
$data['endtime'] = empty($data['endtime'])?$endtime:($data['endtime']>$endtime?$endtime:$data['endtime']);
$this->refresh_area($data);
}
private function circle_week($data){
$week_days = $this->get_week();
$circle_value_arr = explode(",",$data['circle_value']);
for ($i=0;$i<count($circle_value_arr);$i++){
if(date("Y-m-d") == $week_days[$circle_value_arr[$i]]){
//获取巡检点信息
$begin_time = strtotime(date("Y-m-d",strtotime($week_days[$circle_value_arr[0]])));
$data['begintime'] = $data['begintime']>$begin_time?$data['begintime']:$begin_time;
$endtime = strtotime("+1 days -1 second",strtotime($week_days[end($circle_value_arr)]));
$data['endtime'] = empty($data['endtime'])?$endtime:($data['endtime']>$endtime?$endtime:$data['endtime']);
$this->refresh_area($data);
break;
}
}
}
/**
* 获取本周所有日期
*/
private function get_week($time = '', $format='Y-m-d'){
$time = $time != '' ? $time : time();
//获取当前周几
$week = date('w', $time);
$week = $week == 0?7:$week;
$date = [];
for ($i=1; $i<=7; $i++){
$date[$i] = date($format ,strtotime( '+' . $i-$week .' days', $time));
}
return $date;
}
/**
* 获取本月日期
* @param $date
* @return array
*/
private function get_month($time="",$format='Y-m-d'){
$time = $time != '' ? $time : time();
//获取当前周几
$week = date('d', $time);
$date = [];
for ($i=1; $i<=date('t'); $i++){
$date[$i] = date($format ,strtotime( '+' . $i-$week .' days', $time));
}
return $date;
}
private function circle_month($data){
$month_days = $this->get_month();
$circle_value_arr = explode(",",$data['circle_value']);
for ($i=0;$i<count($circle_value_arr);$i++){
if(empty($month_days[$circle_value_arr[$i]])){
continue;
}
if(date("Y-m-d") == $month_days[$circle_value_arr[$i]]){
//获取巡检点信息
$begin_time = strtotime(date("Y-m-d",strtotime($month_days[$circle_value_arr[0]])));
$data['begintime'] = $data['begintime']>$begin_time?$data['begintime']:$begin_time;
if(empty($month_days[end($circle_value_arr)])){
$endtime = strtotime("+1 days -1 second",strtotime(end($month_days)));
}else{
$endtime = strtotime("+1 days -1 second",strtotime($month_days[end($circle_value_arr)]));
}
$data['endtime'] = empty($data['endtime'])?$endtime:($data['endtime']>$endtime?$endtime:$data['endtime']);
$this->refresh_area($data);
break;
}
}
}
private function refresh_area($data){
try{
$projectModel = new \app\admin\model\inspection\Project();
$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();
if(empty($project)){
Db::startTrans();
for($i=1;$i<=$data['num'];$i++){
$projectModel = new \app\admin\model\inspection\Project();
$result = $projectModel->save([
'plan_id'=>$data['plan_id'],
'route_id'=>$data['route_id'],
'area_id'=>$data['area_id'],
'area_site_id'=>$data['area_site_id'],
'begintime'=>$data['begintime'],
'endtime'=>$data['endtime']]);
if(empty($result)){
throw new Exception("巡检记录生成失败");
}
}
Db::commit();
}
}catch (Exception $e){
print_r($e->getMessage());
Db::rollback();
}
}
/**
* 获取下几个月的当天的日期
* @param $begin_time
* @param $month
* @return false|int
*/
private function getNextMonthDays($begin_time,$month)
{
$firstday = date('Y-m-01', $begin_time);
$lastday = strtotime("$firstday +".($month+1)." month -1 day");
$day_lastday = date('d', $lastday); //获取下个月份的最后一天
$day_benlastday = date('d', strtotime("$firstday +1 month -1 day")); //获取本月份的最后一天
//获取当天日期
$Same_day = date('d', $begin_time);
//判断当天是否是最后一天 或 下月最后一天 等于 本月的最后一天
if ($Same_day == $day_benlastday || $day_lastday == $Same_day) {
$day = $day_lastday;
} else {
$day = $Same_day;
}
$day = date('Y', $lastday) . '-' . date('m', $lastday) . '-' . $day." ".date("H:i:s",$begin_time);
return strtotime($day);
}
}
... ...
此 diff 太大无法显示。
<?php
namespace addons\inspection\service;
class Project
{
public $model;
public function __construct()
{
}
function checkDistance($lng1, $lat1, $lng2, $lat2) {
// 将角度转为狐度
$radLat1 = deg2rad($lat1); //deg2rad()函数将角度转换为弧度
$radLat2 = deg2rad($lat2);
$radLng1 = deg2rad($lng1);
$radLng2 = deg2rad($lng2);
$a = $radLat1 - $radLat2;
$b = $radLng1 - $radLng2;
$s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * 6378.137 * 1000;
return $s;
}
public function getProjectInfo($where){
$projectModel = new \app\admin\model\inspection\Project();
$data = $projectModel
->alias("project")
->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")
->join("inspection_plan plan","project.plan_id=plan.id")
->join("inspection_area_site site","project.area_site_id=site.id")
->where($where)
->find();
if($data){
return $data;
}
return false;
}
}
\ No newline at end of file
... ...
<script>
export default {
onLaunch: function() {
// #ifdef MP-WEIXIN
let menuButtonInfo = uni.getMenuButtonBoundingClientRect().top
this.$lib.$store.commit('setMenuButtonInfo',menuButtonInfo)
// #endif
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style>
/*每个页面公共css */
@import "./static/font/iconfont.css";
/*占位符*/
.lz-status_bar {
height: var(--status-bar-height);
width: 100%;
background-color: #fff;
}
.lz-top_view {
height: var(--status-bar-height);
width: 100%;
position: fixed;
background-color: #fff;
top: 0;
z-index: 999;
}
/*头部*/
.index-head{
background: #fff;
top: var(--status-bar-height);
z-index: 100;
height: 32px;
padding-bottom: 6px;
}
.index-head-top{
display: flex;
font-size: 16px;
color: #000;
align-items: center;
width: 92%;
margin: 0 auto;
line-height: 40px;
}
.index-head-top .index-head-l {
width: 24px;
display: flex;align-items: center;
padding-top: 0px;
}
.index-head-l .iconfont {
font-size: 21px;
transform: rotate(180deg);
margin-right: 7px;
}
.index-head-top .index-head-m{width: 60%;text-align: left;font-size: 16px;}
</style>
... ...
# 电站巡检
#### Description
{**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**}
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
... ...
# 巡检
#### 介绍
{**以下是 Gitee 平台说明,您可以替换此简介**
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
... ...
<template>
<div>
<div>
<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>
<div class="cu-bar bg-white solid-bottom" style="margin-top:100upx">
<div class="action">
<text class="cuIcon-titles text-orange"></text>基本使用(tab固定,只支持点击标签切换)
</div>
</div>
<div class="bg-white padding margin text-center text-black">{{tabList[TabCur].name}}</div>
</div>
<div>
<div class="cu-bar bg-white margin-top solid-bottom">
<div class="action">
<text class="cuIcon-titles text-orange"></text>居中选中放大(外部触发切换)
</div>
</div>
<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>
<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">
<swiper-item v-for="(item,index) in tabList2" :key="index">
<div class="bg-white padding margin text-center text-black">{{item.name}}</div>
</swiper-item>
</swiper>
</div>
<div>
<div class="cu-bar bg-white margin-top solid-bottom">
<div class="action">
<text class="cuIcon-titles text-orange"></text>平分
</div>
</div>
<wuc-tab :tab-list="tabList3" textFlex :tabCur.sync="TabCur3" tab-class="text-center text-black bg-white" select-class="text-orange"></wuc-tab>
<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">
<swiper-item v-for="(item,index) in tabList3" :key="index">
<div class="bg-white padding margin text-center text-black">{{item.name}}</div>
</swiper-item>
</swiper>
</div>
<div>
<div class="cu-bar bg-white margin-top solid-bottom">
<div class="action">
<text class="cuIcon-titles text-orange"></text>背景
</div>
</div>
<wuc-tab :tab-list="tabList4" :tabCur.sync="TabCur4" tab-class="text-center text-white bg-blue" select-class="text-white"></wuc-tab>
<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">
<swiper-item v-for="(item,index) in tabList4" :key="index">
<div class="bg-white padding margin text-center text-black">{{item.name}}</div>
</swiper-item>
</swiper>
</div>
<div>
<div class="cu-bar bg-white margin-top solid-bottom">
<div class="action">
<text class="cuIcon-titles text-orange"></text>图标
</div>
</div>
<wuc-tab :tab-list="tabList5" :tabCur.sync="TabCur5" tab-class="text-center text-black bg-white" select-class="text-blue" />
<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">
<swiper-item v-for="(item,index) in tabList5" :key="index">
<div class="bg-white padding margin text-center text-black">{{item.name}}</div>
</swiper-item>
</swiper>
</div>
</div>
</template>
<script>
import WucTab from '@/components/wuc-tab/wuc-tab.vue';
import { obj2style } from '@/utils/index';
export default {
data() {
return {
tabList: [
{ name: '选项卡一' },
{ name: '选项卡二' },
{ name: '选项卡三' },
{ name: '选项卡四' },
{ name: '选项卡五' },
{ name: '选项卡六' },
{ name: '选项卡七' },
{ name: '选项卡八' }
],
tabList2: [{ name: '精选' }, { name: '订阅' }],
tabList3: [{ name: '精选' }, { name: '订阅' }],
tabList4: [
{ name: '推荐' },
{ name: '热点' },
{ name: '视频' },
{ name: '问答' },
{ name: '社会' },
{ name: '娱乐' },
{ name: '科技' },
{ name: '汽车' }
],
tabList5: [
{ name: '短信', icon: 'cuIcon-comment' },
{ name: '电话', icon: 'cuIcon-dianhua' },
{ name: 'wifi', icon: 'cuIcon-wifi' }
],
TabCur: 0,
TabCur2: 0,
TabCur3: 0,
TabCur4: 0,
TabCur5: 0
};
},
components: { WucTab },
computed: {
CustomBar() {
let style = {};
// #ifdef MP-WEIXIN
const systemInfo = uni.getSystemInfoSync();
let CustomBar =
systemInfo.platform === "android"
? systemInfo.statusBarHeight + 50
: systemInfo.statusBarHeight + 45;
style['top'] = CustomBar + 'px';
// #endif
// #ifdef H5
style['top'] = 0 + 'px';
// #endif
return obj2style(style);
}
},
methods: {
tabChange(index) {
this.TabCur = index;
},
tabChange2(index) {
this.TabCur2 = index;
},
swiperChange2(e) {
let { current } = e.target;
this.TabCur2 = current;
},
swiperChange3(e) {
let { current } = e.target;
this.TabCur3 = current;
},
swiperChange4(e) {
let { current } = e.target;
this.TabCur4 = current;
},
swiperChange5(e) {
this.TabCur5 = e.target.current;
}
},
onReady() {}
};
</script>
<style>
@import "~@/styles/icon.scss";
div,
scroll-view,
swiper {
box-sizing: border-box;
}
div {
font-size: 28upx;
background-color: #f1f1f1;
}
.swiper {
height: 140upx;
}
.cu-bar {
display: flex;
position: relative;
align-items: center;
min-height: 100upx;
justify-content: space-between;
}
.cu-bar .action {
display: flex;
align-items: center;
height: 100%;
justify-content: center;
max-width: 100%;
background-color: #ffffff;
}
.cu-bar .action:first-child {
margin-left: 30upx;
font-size: 30upx;
}
.solid,
.solid-bottom {
position: relative;
}
.solid::after,
.solid-bottom::after{
content: " ";
width: 200%;
height: 200%;
position: absolute;
top: 0;
left: 0;
border-radius: inherit;
transform: scale(0.5);
transform-origin: 0 0;
pointer-events: none;
box-sizing: border-box;
}
.solid::after {
border: 1upx solid rgba(0, 0, 0, 0.1);
}
.solid-bottom::after {
border-bottom: 1upx solid rgba(0, 0, 0, 0.1);
}
.text-orange{
color:#f37b1d
}
.text-black{
color:#333333;
}
.bg-white{
background-color: #ffffff;
}
.padding {
padding: 30upx;
}
.margin {
margin: 30upx;
}
.margin-top {
margin-top: 30upx;
}
.text-center {
text-align: center;
}
</style>
... ...