作者 郝子凯

合并分支 '郝子凯' 到 'master'

上传插件



查看合并请求 !3
正在显示 58 个修改的文件 包含 4812 行增加0 行删除

要显示太多修改。

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

{"files":["application\\admin\\controller\\Command.php","application\\admin\\lang\\zh-cn\\command.php","application\\admin\\model\\Command.php","application\\admin\\validate\\Command.php","application\\admin\\view\\command\\add.html","application\\admin\\view\\command\\detail.html","application\\admin\\view\\command\\index.html","public\\assets\\js\\backend\\command.js"],"license":"regular","licenseto":"10789","licensekey":"nUTLWCS6Gjivx0pM \/Qe77lGZWGQWa8IzqinyNA==","domains":["showmerchants.cn"],"licensecodes":[],"validations":["3c36e672cbd8ad7c0b4c2f0562b0c810"],"menus":["command","command\/index","command\/add","command\/detail","command\/execute","command\/del","command\/multi"]}
\ 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 = 10789
... ...
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;
}
}
... ...
{"files":["application\\admin\\controller\\Tablemake.php","application\\admin\\lang\\zh-cn\\tablemake.php","application\\admin\\model\\TableMakeFields.php","application\\admin\\model\\TableMakeTables.php","application\\admin\\view\\tablemake\\add.html","application\\admin\\view\\tablemake\\dictionary.html","application\\admin\\view\\tablemake\\edit.html","application\\admin\\view\\tablemake\\fields.html","application\\admin\\view\\tablemake\\field_add.html","application\\admin\\view\\tablemake\\field_edit.html","application\\admin\\view\\tablemake\\index.html","public\\assets\\js\\backend\\tablemake.js"],"license":"basic","licenseto":"10789","licensekey":"av2DKJLFXrb17iS5 BN9oIbfq5bUhCSUZWJ\/tmXY+OHXwcMPV0hmvE0Qx2WQ=","domains":["showmerchants.cn"],"licensecodes":[],"validations":["3c36e672cbd8ad7c0b4c2f0562b0c810"],"menus":["tablemake","tablemake\/index","tablemake\/add","tablemake\/edit","tablemake\/del","tablemake\/fields","tablemake\/field_add","tablemake\/field_del"]}
\ No newline at end of file
... ...
<?php
namespace addons\tablemake;
use app\common\library\Menu;
use think\Addons;
use think\Config;
use think\Db;
use think\Exception;
/**
* 自建表管理插件
*/
class Tablemake extends Addons {
/**
* 插件安装方法
* @return bool
*/
public function install() {
$menu = [
[
'name' => 'tablemake',
'title' => '自建表管理',
'icon' => 'fa fa-cubes',
'sublist' => [
['name' => 'tablemake/index', 'title' => '查看列表'],
['name' => 'tablemake/add', 'title' => '创建新表'],
['name' => 'tablemake/edit', 'title' => '编辑表'],
['name' => 'tablemake/del', 'title' => '删除模块'],
['name' => 'tablemake/fields', 'title' => '字段管理'],
['name' => 'tablemake/field_add', 'title' => '添加字段'],
['name' => 'tablemake/field_del', 'title' => '删除字段'],
]
]
];
Menu::create($menu);
//$this->doUpgrade();
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall() {
Menu::delete('tablemake');
return true;
}
/**
* 插件启用方法
* @return bool
*/
public function enable() {
Menu::enable('tablemake');
//$this->doUpgrade();
return true;
}
/**
* 插件禁用方法
* @return bool
*/
public function disable() {
Menu::disable('tablemake');
return true;
}
public function doUpgrade() {
$prefix = Config::get('database.prefix');
$haTable = Db::query('SHOW TABLES LIKE '."'{$prefix}tablemake_tables'");
if(!$haTable){
//数据表不存在,表示是安装动作,非升级动作
return;
}
//<editor-fold desc="1.0.7版本更新数据表字段" defaultstate="collapsed">
/**
* 1.检测tablemake_tables表是否需要更新,如果需要则更新tablemake_tables表
*/
$sql = "describe `{$prefix}tablemake_tables` `weigh`;";
$has_weigh = Db::query($sql);
if (!$has_weigh) {//tablemake_tables
Db::startTrans();
try {
//1.新增weigh字段
$sql = "ALTER TABLE `{$prefix}tablemake_tables`
ADD COLUMN `weigh` bigint(11) NOT NULL DEFAULT 0 COMMENT '排序权重' AFTER `desc`;";
Db::execute($sql);
//2.更新weigh字段的值为对应记录的ID值
$sql = "UPDATE `{$prefix}tablemake_tables` SET `weigh`=`id`;";
Db::execute($sql);
//3.原有字段更新
$sql = "ALTER TABLE `{$prefix}tablemake_tables`
MODIFY COLUMN `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID' FIRST ,
MODIFY COLUMN `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '自建表名称' AFTER `id`,
MODIFY COLUMN `table` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '自建表表名' AFTER `name`,
MODIFY COLUMN `desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '自建表简介' AFTER `table`,
MODIFY COLUMN `createtime` bigint(11) NOT NULL DEFAULT 0 COMMENT '创建时间' AFTER `weigh`,
MODIFY COLUMN `updatetime` bigint(11) NOT NULL DEFAULT 0 COMMENT '更新时间' AFTER `createtime`;";
Db::execute($sql);
Db::commit();
} catch (Exception $e) {
\think\Log::write("更新{$prefix}tablemake_tables表字段失败,异常:" . $e->getTraceAsString());
Db::rollback();
}
}
/**
* 2.检测tablemake_fields表是否需要更新,如果需要则更新tablemake_fields表
*/
$sql = "describe `{$prefix}tablemake_fields` `weigh`;";
$has_weigh = Db::query($sql);
if (!$has_weigh) {//tablemake_fields
Db::startTrans();
try {
//1.新增weigh字段
$sql = "ALTER TABLE `{$prefix}tablemake_fields`
ADD COLUMN `desc` varchar(255) NOT NULL DEFAULT '' COMMENT '字段备注' AFTER `comment`,
ADD COLUMN `weigh` bigint(11) NOT NULL DEFAULT 0 COMMENT '排序权重' AFTER `desc`;";
Db::execute($sql);
//2.更新weigh字段的值为对应记录的ID值
$sql = "UPDATE `{$prefix}tablemake_fields` SET `weigh`=`id`;";
Db::execute($sql);
//3.原有字段更新
$sql = "ALTER TABLE `{$prefix}tablemake_fields`
MODIFY COLUMN `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID' FIRST ,
MODIFY COLUMN `mid` bigint(11) NOT NULL DEFAULT 0 COMMENT '所属自建表ID' AFTER `id`,
MODIFY COLUMN `length` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 0 COMMENT '字段长度' AFTER `type`,
MODIFY COLUMN `default` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '默认值' AFTER `length`,
MODIFY COLUMN `comment` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '字段备注' AFTER `default`,
MODIFY COLUMN `createtime` bigint(11) NOT NULL DEFAULT 0 COMMENT '创建时间' AFTER `weigh`,
MODIFY COLUMN `updatetime` bigint(11) NOT NULL DEFAULT 0 COMMENT '更新时间' AFTER `createtime`;";
Db::execute($sql);
Db::commit();
} catch (Exception $e) {
\think\Log::write("更新{$prefix}tablemake_fields表字段失败,异常:" . $e->getTraceAsString());
Db::rollback();
}
}
//</editor-fold>
}
}
... ...
<?php
return [
];
... ...
<?php
namespace addons\tablemake\controller;
/**
* 自建表前台页面,展示数据字典
*/
class Index extends \think\addons\Controller {
public function _initialize() {
parent::_initialize();
}
/**
*展示数据字典信息
*/
public function index() {
$this->error("当前插件暂无前台页面",url());
}
}
... ...
name = tablemake
title = 自建数据表管理
intro = 创建数据表并在线管理表的字段(非本插件创建的表不支持管理),可借助命令行或在线命令工具生成CRUD和菜单
author = 沉醉寒风
website = https://www.fastadmin.net
version = 1.0.7
state = 1
url = /addons/tablemake
license = basic
licenseto = 10789
... ...
--1.0.0--
CREATE TABLE IF NOT EXISTS `__PREFIX__tablemake_tables` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT '模型名称',
`table` varchar(20) NOT NULL COMMENT '表名称',
`desc` varchar(150) DEFAULT 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 = '自建表管理表' ROW_FORMAT = Compact;
CREATE TABLE IF NOT EXISTS `__PREFIX__tablemake_fields` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`mid` int(11) NOT NULL COMMENT '所属模型',
`category` tinyint(2) NOT NULL COMMENT '字段类型',
`title` varchar(50) NOT NULL DEFAULT '' COMMENT '字段标题',
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '字段名称',
`field` varchar(50) NOT NULL DEFAULT '' COMMENT '字段名',
`special` varchar(50) NOT NULL DEFAULT '' COMMENT '特殊字段',
`suffix` varchar(50) NOT NULL DEFAULT '' COMMENT '字段后缀',
`type` varchar(50) NOT NULL DEFAULT '' COMMENT '字段类型',
`length` varchar(10) NOT NULL COMMENT '字段长度',
`default` varchar(255) NOT NULL COMMENT '默认值',
`comment` varchar(2000) 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 = '字段管理表' ROW_FORMAT = Compact;
--1.0.7--
ALTER TABLE `__PREFIX__tablemake_tables` ADD COLUMN `weigh` bigint(11) NOT NULL DEFAULT 0 COMMENT '排序权重' AFTER `desc`;
UPDATE `__PREFIX__tablemake_tables` SET `weigh`=`id`;
ALTER TABLE `__PREFIX__tablemake_tables`
MODIFY COLUMN `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID' FIRST ,
MODIFY COLUMN `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '自建表名称' AFTER `id`,
MODIFY COLUMN `table` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '自建表表名' AFTER `name`,
MODIFY COLUMN `desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '自建表简介' AFTER `table`,
MODIFY COLUMN `createtime` bigint(11) NOT NULL DEFAULT 0 COMMENT '创建时间' AFTER `weigh`,
MODIFY COLUMN `updatetime` bigint(11) NOT NULL DEFAULT 0 COMMENT '更新时间' AFTER `createtime`;
ALTER TABLE `__PREFIX__tablemake_fields` ADD COLUMN `desc` varchar(255) NOT NULL DEFAULT '' COMMENT '字段备注' AFTER `comment`, ADD COLUMN `weigh` bigint(11) NOT NULL DEFAULT 0 COMMENT '排序权重' AFTER `desc`;
UPDATE `__PREFIX__tablemake_fields` SET `weigh`=`id`;
ALTER TABLE `__PREFIX__tablemake_fields`
MODIFY COLUMN `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID' FIRST ,
MODIFY COLUMN `mid` bigint(11) NOT NULL DEFAULT 0 COMMENT '所属自建表ID' AFTER `id`,
MODIFY COLUMN `length` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 0 COMMENT '字段长度' AFTER `type`,
MODIFY COLUMN `default` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '默认值' AFTER `length`,
MODIFY COLUMN `comment` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '字段备注' AFTER `default`,
MODIFY COLUMN `createtime` bigint(11) NOT NULL DEFAULT 0 COMMENT '创建时间' AFTER `weigh`,
MODIFY COLUMN `updatetime` bigint(11) NOT NULL DEFAULT 0 COMMENT '更新时间' AFTER `createtime`;
... ...
{"files":["application\\admin\\controller\\Third.php","application\\admin\\lang\\zh-cn\\third.php","application\\admin\\model\\Third.php","application\\admin\\validate\\Third.php","application\\admin\\view\\third\\index.html","application\\index\\controller\\Third.php","application\\index\\view\\third\\prepare.html","public\\assets\\js\\backend\\third.js"],"license":"regular","licenseto":"10789","licensekey":"qM3GZLWgTv0NRjzV pqjZ8BMpdCeTws\/i\/uhLJA==","domains":["showmerchants.cn"],"licensecodes":[],"validations":["3c36e672cbd8ad7c0b4c2f0562b0c810"],"menus":["third","third\/index","third\/del"]}
\ No newline at end of file
... ...
<?php
namespace addons\third;
use app\common\library\Menu;
use think\Addons;
/**
* 第三方登录
*/
class Third extends Addons
{
/**
* 插件安装方法
* @return bool
*/
public function install()
{
$menu = [
[
'name' => 'third',
'title' => '第三方登录管理',
'icon' => 'fa fa-users',
'sublist' => [
[
"name" => "third/index",
"title" => "查看"
],
[
"name" => "third/del",
"title" => "删除"
]
]
]
];
Menu::create($menu);
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
Menu::delete("third");
return true;
}
/**
* 插件启用方法
* @return bool
*/
public function enable()
{
Menu::enable("third");
return true;
}
/**
* 插件禁用方法
* @return bool
*/
public function disable()
{
Menu::disable("third");
return true;
}
/**
* @param $params
*/
public function configInit(&$params)
{
$config = $this->getConfig();
$params['third'] = ['status' => explode(',', $config['status'])];
}
}
... ...
if (Config.modulename === 'index' && Config.controllername === 'user' && ['login', 'register'].indexOf(Config.actionname) > -1 && $("#register-form,#login-form").size() > 0) {
$('<style>.social-login{display:flex}.social-login a{flex:1;margin:0 2px;}.social-login a:first-child{margin-left:0;}.social-login a:last-child{margin-right:0;}</style>').appendTo("head");
$("#register-form,#login-form").append('<div class="form-group social-login"></div>');
if (Config.third.status.indexOf("wechat") > -1) {
$('<a class="btn btn-success" href="' + Fast.api.fixurl('/third/connect/wechat') + '"><i class="fa fa-wechat"></i> 微信登录</a>').appendTo(".social-login");
}
if (Config.third.status.indexOf("qq") > -1) {
$('<a class="btn btn-info" href="' + Fast.api.fixurl('/third/connect/qq') + '"><i class="fa fa-qq"></i> QQ登录</a>').appendTo(".social-login");
}
if (Config.third.status.indexOf("weibo") > -1) {
$('<a class="btn btn-danger" href="' + Fast.api.fixurl('/third/connect/weibo') + '"><i class="fa fa-weibo"></i> 微博登录</a>').appendTo(".social-login");
}
}
... ...
<?php
return array(
0 =>
array(
'name' => 'qq',
'title' => 'QQ',
'type' => 'array',
'content' =>
array(
'app_id' => '',
'app_secret' => '',
'scope' => 'get_user_info',
),
'value' =>
array(
'app_id' => '100000000',
'app_secret' => '123456',
'scope' => 'get_user_info',
),
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
1 =>
array(
'name' => 'wechat',
'title' => '微信',
'type' => 'array',
'content' =>
array(
'app_id' => '',
'app_secret' => '',
'callback' => '',
'scope' => 'snsapi_base',
),
'value' =>
array(
'app_id' => '100000000',
'app_secret' => '123456',
'scope' => 'snsapi_userinfo',
),
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
2 =>
array(
'name' => 'weibo',
'title' => '微博',
'type' => 'array',
'content' =>
array(
'app_id' => '',
'app_secret' => '',
'scope' => 'get_user_info',
),
'value' =>
array(
'app_id' => '100000000',
'app_secret' => '123456',
'scope' => 'get_user_info',
),
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
3 =>
array(
'name' => 'bindaccount',
'title' => '账号绑定',
'type' => 'radio',
'content' =>
array(
1 => '开启',
0 => '关闭',
),
'value' => '1',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '是否开启账号绑定',
'extend' => '',
),
4 =>
array(
'name' => 'status',
'title' => '前台第三方登录开关',
'type' => 'checkbox',
'content' =>
array(
'qq' => 'QQ',
'wechat' => '微信',
'weibo' => '微博',
),
'value' => 'qq,wechat,weibo',
'rule' => '',
'msg' => '',
'tip' => '',
'ok' => '前台第三方登录的开关',
'extend' => '',
),
5 =>
array(
'name' => 'rewrite',
'title' => '伪静态',
'type' => 'array',
'content' =>
array(),
'value' =>
array(
'index/index' => '/third$',
'index/connect' => '/third/connect/[:platform]',
'index/callback' => '/third/callback/[:platform]',
'index/bind' => '/third/bind/[:platform]',
'index/unbind' => '/third/unbind/[:platform]',
),
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
);
... ...
<?php
namespace addons\third\controller;
use addons\third\library\Application;
use app\common\controller\Api as commonApi;
use addons\third\library\Service;
use addons\third\model\Third;
use app\common\library\Sms;
use fast\Random;
use think\Lang;
use think\Config;
use think\Session;
use think\Validate;
/**
* 第三方登录插件
*/
class Api extends commonApi
{
protected $noNeedLogin = ['getAuthUrl', 'callback', 'account']; // 无需登录即可访问的方法,同时也无需鉴权了
protected $noNeedRight = ['*']; // 无需鉴权即可访问的方法
protected $app = null;
protected $options = [];
protected $config = null;
public function _initialize()
{
//跨域检测
check_cors_request();
//设置session_id
Config::set('session.id', $this->request->server("HTTP_SID"));
parent::_initialize();
$this->config = get_addon_config('third');
$this->app = new Application($this->config);
}
/**
* H5获取授权链接
* @return void
*/
public function getAuthUrl()
{
$url = $this->request->param('url');
$platform = $this->request->param('platform');
if (!$url || !$platform || !isset($this->config[$platform])) {
$this->error('参数错误');
}
$this->config[$platform]['callback'] = $url;
$this->app = new Application($this->config); //
if (!$this->app->{$platform}) {
$this->error(__('Invalid parameters'));
}
$this->success('', $this->app->{$platform}->getAuthorizeUrl());
}
/**
* 公众号:wechat 授权回调的请求【非第三方,自己的前端请求】
* @return void
*/
public function callback()
{
$platform = $this->request->param('platform');
if (!$this->app->{$platform}) {
$this->error(__('Invalid parameters'));
}
$userinfo = $this->app->{$platform}->getUserInfo($this->request->param());
if (!$userinfo) {
$this->error(__('操作失败'));
}
$userinfo['apptype'] = 'mp';
$userinfo['platform'] = $platform;
$third = [
'avatar' => $userinfo['userinfo']['avatar'],
'nickname' => $userinfo['userinfo']['nickname']
];
$user = null;
if ($this->auth->isLogin() || Service::isBindThird($userinfo['platform'], $userinfo['openid'], $userinfo['apptype'], $userinfo['unionid'])) {
Service::connect($userinfo['platform'], $userinfo);
$user = $this->auth->getUserinfo();
} else {
$user = false;
Session::set('third-userinfo', $userinfo);
}
$this->success("授权成功!", ['user' => $user, 'third' => $third]);
}
/**
* 登录或创建账号
*/
public function account()
{
if ($this->request->isPost()) {
$params = Session::get('third-userinfo');
$mobile = $this->request->post('mobile', '');
$code = $this->request->post('code');
$token = $this->request->post('__token__');
$rule = [
'mobile' => 'require|regex:/^1\d{10}$/',
'__token__' => 'require|token',
];
$msg = [
'mobile' => 'Mobile is incorrect',
];
$data = [
'mobile' => $mobile,
'__token__' => $token,
];
$ret = Sms::check($mobile, $code, 'bind');
if (!$ret) {
$this->error(__('验证码错误'));
}
$validate = new Validate($rule, $msg);
$result = $validate->check($data);
if (!$result) {
$this->error(__($validate->getError()), ['__token__' => $this->request->token()]);
}
$userinfo = \app\common\model\User::where('mobile', $mobile)->find();
if ($userinfo) {
$result = $this->auth->direct($userinfo->id);
} else {
$result = $this->auth->register($mobile, Random::alnum(), '', $mobile);
}
if ($result) {
Service::connect($params['platform'], $params);
$this->success(__('绑定账号成功'), ['userinfo' => $this->auth->getUserinfo()]);
} else {
$this->error($this->auth->getError(), ['__token__' => $this->request->token()]);
}
}
}
}
... ...
<?php
namespace addons\third\controller;
use addons\third\library\Application;
use addons\third\library\Service;
use addons\third\model\Third;
use think\addons\Controller;
use think\Config;
use think\Cookie;
use think\Hook;
use think\Lang;
use think\Session;
/**
* 第三方登录插件
*/
class Index extends Controller
{
protected $app = null;
protected $options = [];
public function _initialize()
{
parent::_initialize();
$config = get_addon_config('third');
$this->app = new Application($config);
}
/**
* 插件首页
*/
public function index()
{
if (!\app\admin\library\Auth::instance()->id) {
$this->error('当前插件暂无前台页面');
}
$platformList = [];
if ($this->auth->id) {
$platformList = Third::where('user_id', $this->auth->id)->column('platform');
}
$this->view->assign('platformList', $platformList);
return $this->view->fetch();
}
/**
* 发起授权
*/
public function connect()
{
$platform = $this->request->param('platform');
$url = $this->request->request('url', $this->request->server('HTTP_REFERER', '/'), 'trim');
if (!$this->app->{$platform}) {
$this->error(__('Invalid parameters'));
}
if ($url) {
Session::set("redirecturl", $url);
}
// 跳转到登录授权页面
$this->redirect($this->app->{$platform}->getAuthorizeUrl());
return;
}
/**
* 通知回调
*/
public function callback()
{
$auth = $this->auth;
//监听注册登录注销的事件
Hook::add('user_login_successed', function ($user) use ($auth) {
$expire = input('post.keeplogin') ? 30 * 86400 : 0;
Cookie::set('uid', $user->id, $expire);
Cookie::set('token', $auth->getToken(), $expire);
});
Hook::add('user_register_successed', function ($user) use ($auth) {
Cookie::set('uid', $user->id);
Cookie::set('token', $auth->getToken());
});
Hook::add('user_logout_successed', function ($user) use ($auth) {
Cookie::delete('uid');
Cookie::delete('token');
});
$platform = $this->request->param('platform');
// 成功后返回之前页面
$url = Session::has("redirecturl") ? Session::pull("redirecturl") : url('index/user/index');
// 授权成功后的回调
$userinfo = $this->app->{$platform}->getUserInfo();
if (!$userinfo) {
$this->error(__('操作失败'), $url);
}
Session::set("{$platform}-userinfo", $userinfo);
//判断是否启用账号绑定
$third = Third::get(['platform' => $platform, 'openid' => $userinfo['openid']]);
if (!$third) {
$config = get_addon_config('third');
//要求绑定账号或会员当前是登录状态
if ($config['bindaccount'] || $this->auth->id) {
$this->redirect(url('index/third/prepare') . "?" . http_build_query(['platform' => $platform, 'url' => $url]));
}
}
$loginret = Service::connect($platform, $userinfo);
if ($loginret) {
$this->redirect($url);
}
}
/**
* 绑定账号
*/
public function bind()
{
$platform = $this->request->request('platform', $this->request->param('platform', ''));
$url = $this->request->get('url', $this->request->server('HTTP_REFERER'));
$redirecturl = url("index/third/bind") . "?" . http_build_query(['platform' => $platform, 'url' => $url]);
$this->redirect($redirecturl);
return;
}
/**
* 解绑账号
*/
public function unbind()
{
$platform = $this->request->request('platform', $this->request->param('platform', ''));
$url = $this->request->get('url', $this->request->server('HTTP_REFERER'));
$redirecturl = url("index/third/unbind") . "?" . http_build_query(['platform' => $platform, 'url' => $url]);
$this->redirect($redirecturl);
return;
}
}
... ...
name = third
title = 第三方登录
intro = 使用微信、QQ、微博登录插件
author = FastAdmin
website = https://www.fastadmin.net
version = 1.2.3
state = 1
url = /addons/third
license = regular
licenseto = 10789
... ...
CREATE TABLE IF NOT EXISTS `__PREFIX__third` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` int(10) unsigned DEFAULT '0' COMMENT '会员ID',
`platform` varchar(30) DEFAULT '' COMMENT '第三方应用',
`apptype` varchar(50) DEFAULT '' COMMENT '应用类型',
`unionid` varchar(100) DEFAULT '' COMMENT '第三方UNIONID',
`openid` varchar(100) DEFAULT '' COMMENT '第三方OPENID',
`openname` varchar(100) DEFAULT '' COMMENT '第三方会员昵称',
`access_token` varchar(255) NULL DEFAULT '' COMMENT 'AccessToken',
`refresh_token` varchar(255) DEFAULT 'RefreshToken',
`expires_in` int(10) unsigned DEFAULT '0' COMMENT '有效期',
`createtime` int(10) unsigned DEFAULT NULL COMMENT '创建时间',
`updatetime` int(10) unsigned DEFAULT NULL COMMENT '更新时间',
`logintime` int(10) unsigned DEFAULT NULL COMMENT '登录时间',
`expiretime` int(10) unsigned DEFAULT NULL COMMENT '过期时间',
PRIMARY KEY (`id`),
UNIQUE KEY `platform` (`platform`,`openid`),
KEY `user_id` (`user_id`,`platform`),
KEY `unionid` (`platform`,`unionid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='第三方登录表';
ALTER TABLE `__PREFIX__third` ADD COLUMN `apptype` varchar(50) NULL DEFAULT '' COMMENT '应用类型' AFTER `platform`;
ALTER TABLE `__PREFIX__third` ADD COLUMN `unionid` varchar(100) NULL DEFAULT '' COMMENT '第三方UnionID' AFTER `apptype`;
ALTER TABLE `__PREFIX__third` ADD INDEX `unionid`(`platform`, `unionid`);
ALTER TABLE `__PREFIX__third` CHARACTER SET = utf8mb4, COLLATE = utf8mb4_general_ci;
ALTER TABLE `__PREFIX__third` MODIFY COLUMN `openname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '第三方会员昵称' AFTER `unionid`;
... ...
<?php
namespace addons\third\library;
class Application
{
/**
* 配置信息
* @var array
*/
private $config = [];
/**
* 服务提供者
* @var array
*/
private $providers = [
'qq' => 'Qq',
'weibo' => 'Weibo',
'wechat' => 'Wechat',
];
/**
* 服务对象信息
* @var array
*/
protected $services = [];
public function __construct($options = [])
{
$options = array_intersect_key($options, $this->providers);
$options = array_merge($this->config, is_array($options) ? $options : []);
foreach ($options as $key => &$option) {
$option['app_id'] = isset($option['app_id']) ? $option['app_id'] : '';
$option['app_secret'] = isset($option['app_secret']) ? $option['app_secret'] : '';
// 如果未定义回调地址则自动生成
$option['callback'] = isset($option['callback']) && $option['callback'] ? $option['callback'] : addon_url('third/index/callback', [':platform' => $key], false, true);
}
$this->config = $options;
//注册服务器提供者
$this->registerProviders();
}
/**
* 注册服务提供者
*/
private function registerProviders()
{
foreach ($this->providers as $k => $v) {
$this->services[$k] = function () use ($k, $v) {
$options = $this->config[$k];
$objname = __NAMESPACE__ . "\\{$v}";
return new $objname($options);
};
}
}
public function __set($key, $value)
{
$this->services[$key] = $value;
}
public function __get($key)
{
return isset($this->services[$key]) ? $this->services[$key]($this) : null;
}
}
... ...
<?php
namespace addons\third\library;
use fast\Http;
use think\Config;
use think\Session;
/**
* QQ
*/
class Qq
{
const GET_AUTH_CODE_URL = "https://graph.qq.com/oauth2.0/authorize";
const GET_ACCESS_TOKEN_URL = "https://graph.qq.com/oauth2.0/token";
const GET_USERINFO_URL = "https://graph.qq.com/user/get_user_info";
const GET_OPENID_URL = "https://graph.qq.com/oauth2.0/me";
/**
* 配置信息
* @var array
*/
private $config = [];
public function __construct($options = [])
{
if ($config = Config::get('third.qq')) {
$this->config = array_merge($this->config, $config);
}
$this->config = array_merge($this->config, is_array($options) ? $options : []);
}
/**
* 登陆
*/
public function login()
{
header("Location:" . $this->getAuthorizeUrl());
}
/**
* 获取authorize_url
*/
public function getAuthorizeUrl()
{
$state = md5(uniqid(rand(), true));
Session::set('state', $state);
$queryarr = array(
"response_type" => "code",
"client_id" => $this->config['app_id'],
"redirect_uri" => $this->config['callback'],
"scope" => $this->config['scope'],
"state" => $state,
);
request()->isMobile() && $queryarr['display'] = 'mobile';
$url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr);
return $url;
}
/**
* 获取用户信息
* @param array $params
* @return array
*/
public function getUserInfo($params = [])
{
$params = $params ? $params : $_GET;
if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) {
//获取access_token
$data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params;
$access_token = isset($data['access_token']) ? $data['access_token'] : '';
$refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : '';
$expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0;
if ($access_token) {
$openid = $this->getOpenId($access_token);
//获取用户信息
$queryarr = [
"access_token" => $access_token,
"oauth_consumer_key" => $this->config['app_id'],
"openid" => $openid,
];
$ret = Http::get(self::GET_USERINFO_URL, $queryarr);
$userinfo = (array)json_decode($ret, true);
if (!$userinfo || !isset($userinfo['ret']) || $userinfo['ret'] !== 0) {
return [];
}
$userinfo = $userinfo ? $userinfo : [];
$userinfo['avatar'] = isset($userinfo['figureurl_qq_2']) ? $userinfo['figureurl_qq_2'] : '';
$data = [
'access_token' => $access_token,
'refresh_token' => $refresh_token,
'expires_in' => $expires_in,
'openid' => $openid,
'userinfo' => $userinfo
];
return $data;
}
}
return [];
}
/**
* 获取access_token
* @param string $code
* @return array
*/
public function getAccessToken($code = '')
{
if (!$code) {
return [];
}
$queryarr = array(
"grant_type" => "authorization_code",
"client_id" => $this->config['app_id'],
"client_secret" => $this->config['app_secret'],
"redirect_uri" => $this->config['callback'],
"code" => $code,
);
$ret = Http::get(self::GET_ACCESS_TOKEN_URL, $queryarr);
$params = [];
parse_str($ret, $params);
return $params ? $params : [];
}
/**
* 获取open_id
* @param string $access_token
* @return string
*/
private function getOpenId($access_token = '')
{
$response = Http::get(self::GET_OPENID_URL, ['access_token' => $access_token]);
if (strpos($response, "callback") !== false) {
$lpos = strpos($response, "(");
$rpos = strrpos($response, ")");
$response = substr($response, $lpos + 1, $rpos - $lpos - 1);
}
$user = (array)json_decode($response, true);
return isset($user['openid']) ? $user['openid'] : '';
}
}
... ...
<?php
namespace addons\third\library;
use addons\third\model\Third;
use app\common\model\User;
use fast\Random;
use think\Db;
use think\Exception;
/**
* 第三方登录服务类
*
*/
class Service
{
/**
* 第三方登录
* @param string $platform 平台
* @param array $params 参数
* @param array $extend 会员扩展信息
* @param int $keeptime 有效时长
* @return boolean
*/
public static function connect($platform, $params = [], $extend = [], $keeptime = 0)
{
$time = time();
$nickname = $params['nickname'] ?? ($params['userinfo']['nickname'] ?? '');
$avatar = $params['avatar'] ?? ($params['userinfo']['avatar'] ?? '');
$values = [
'platform' => $platform,
'openid' => $params['openid'],
'openname' => $nickname,
'access_token' => $params['access_token'],
'refresh_token' => $params['refresh_token'],
'expires_in' => $params['expires_in'],
'logintime' => $time,
'expiretime' => $time + $params['expires_in'],
];
$values = array_merge($values, $params);
$auth = \app\common\library\Auth::instance();
$auth->keeptime($keeptime);
//是否有自己的
$third = Third::get(['platform' => $platform, 'openid' => $params['openid']], 'user');
if ($third) {
if (!$third->user) {
$third->delete();
} else {
$third->allowField(true)->save($values);
// 写入登录Cookies和Token
return $auth->direct($third->user_id);
}
}
//存在unionid就需要判断是否需要生成新记录
if (isset($params['unionid']) && !empty($params['unionid'])) {
$third = Third::get(['platform' => $platform, 'unionid' => $params['unionid']], 'user');
if ($third) {
if (!$third->user) {
$third->delete();
} else {
// 保存第三方信息
$values['user_id'] = $third->user_id;
$third = Third::create($values, true);
// 写入登录Cookies和Token
return $auth->direct($third->user_id);
}
}
}
if ($auth->id) {
if (!$third) {
$values['user_id'] = $auth->id;
Third::create($values, true);
}
$user = $auth->getUser();
} else {
// 先随机一个用户名,随后再变更为u+数字id
$username = Random::alnum(20);
$password = Random::alnum(6);
$domain = request()->host();
Db::startTrans();
try {
// 默认注册一个会员
$result = $auth->register($username, $password, $username . '@' . $domain, '', $extend);
if (!$result) {
throw new Exception($auth->getError());
}
$user = $auth->getUser();
$fields = ['username' => 'u' . $user->id, 'email' => 'u' . $user->id . '@' . $domain];
if ($nickname) {
$fields['nickname'] = $nickname;
}
if ($avatar) {
$fields['avatar'] = htmlspecialchars(strip_tags($avatar));
}
// 更新会员资料
$user = User::get($user->id);
$user->save($fields);
// 保存第三方信息
$values['user_id'] = $user->id;
Third::create($values, true);
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$auth->logout();
return false;
}
}
// 写入登录Cookies和Token
return $auth->direct($user->id);
}
public static function isBindThird($platform, $openid, $apptype = '', $unionid = '')
{
$conddtions = [
'platform' => $platform,
'openid' => $openid
];
if ($apptype) {
$conddtions['apptype'] = $apptype;
}
$third = Third::get($conddtions, 'user');
//第三方存在
if ($third) {
//用户失效
if (!$third->user) {
$third->delete();
return false;
}
return true;
}
if ($unionid) {
$third = Third::get(['platform' => $platform, 'unionid' => $unionid], 'user');
if ($third) {
//
if (!$third->user) {
$third->delete();
return false;
}
return true;
}
}
return false;
}
}
... ...
<?php
namespace addons\third\library;
use fast\Http;
use think\Config;
use think\Session;
/**
* 微信
*/
class Wechat
{
const GET_AUTH_CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize";
const GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
const GET_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo";
/**
* 配置信息
* @var array
*/
private $config = [];
public function __construct($options = [])
{
if ($config = Config::get('third.wechat')) {
$this->config = array_merge($this->config, $config);
}
$this->config = array_merge($this->config, is_array($options) ? $options : []);
}
/**
* 登陆
*/
public function login()
{
header("Location:" . $this->getAuthorizeUrl());
}
/**
* 获取authorize_url
*/
public function getAuthorizeUrl()
{
$state = md5(uniqid(rand(), true));
Session::set('state', $state);
$queryarr = array(
"appid" => $this->config['app_id'],
"redirect_uri" => $this->config['callback'],
"response_type" => "code",
"scope" => $this->config['scope'],
"state" => $state,
);
request()->isMobile() && $queryarr['display'] = 'mobile';
$url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr) . '#wechat_redirect';
return $url;
}
/**
* 获取用户信息
* @param array $params
* @return array
*/
public function getUserInfo($params = [])
{
$params = $params ? $params : request()->get();
if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) {
//获取access_token
$data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params;
$access_token = isset($data['access_token']) ? $data['access_token'] : '';
$refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : '';
$expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0;
if ($access_token) {
$openid = isset($data['openid']) ? $data['openid'] : '';
$unionid = isset($data['unionid']) ? $data['unionid'] : '';
if (stripos($this->config['scope'], 'snsapi_userinfo') !== false) {
//获取用户信息
$queryarr = [
"access_token" => $access_token,
"openid" => $openid,
"lang" => 'zh_CN'
];
$ret = Http::get(self::GET_USERINFO_URL, $queryarr);
$userinfo = (array)json_decode($ret, true);
if (!$userinfo || isset($userinfo['errcode'])) {
return [];
}
$userinfo = $userinfo ? $userinfo : [];
$userinfo['avatar'] = isset($userinfo['headimgurl']) ? $userinfo['headimgurl'] : '';
} else {
$userinfo = [];
}
$data = [
'access_token' => $access_token,
'refresh_token' => $refresh_token,
'expires_in' => $expires_in,
'openid' => $openid,
'unionid' => $unionid,
'userinfo' => $userinfo
];
return $data;
}
}
return [];
}
/**
* 获取access_token
* @param string code
* @return array
*/
public function getAccessToken($code = '')
{
if (!$code) {
return [];
}
$queryarr = array(
"appid" => $this->config['app_id'],
"secret" => $this->config['app_secret'],
"code" => $code,
"grant_type" => "authorization_code",
);
$response = Http::get(self::GET_ACCESS_TOKEN_URL, $queryarr);
$ret = (array)json_decode($response, true);
return $ret ? $ret : [];
}
}
... ...
<?php
namespace addons\third\library;
use fast\Http;
use think\Config;
use think\Session;
/**
* 微博
*/
class Weibo
{
const GET_AUTH_CODE_URL = "https://api.weibo.com/oauth2/authorize";
const GET_ACCESS_TOKEN_URL = "https://api.weibo.com/oauth2/access_token";
const GET_USERINFO_URL = "https://api.weibo.com/2/users/show.json";
/**
* 配置信息
* @var array
*/
private $config = [];
public function __construct($options = [])
{
if ($config = Config::get('third.weibo')) {
$this->config = array_merge($this->config, $config);
}
$this->config = array_merge($this->config, is_array($options) ? $options : []);
}
/**
* 登陆
*/
public function login()
{
header("Location:" . $this->getAuthorizeUrl());
}
/**
* 获取authorize_url
*/
public function getAuthorizeUrl()
{
$state = md5(uniqid(rand(), true));
Session::set('state', $state);
$queryarr = array(
"response_type" => "code",
"client_id" => $this->config['app_id'],
"redirect_uri" => $this->config['callback'],
"state" => $state,
);
request()->isMobile() && $queryarr['display'] = 'mobile';
$url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr);
return $url;
}
/**
* 获取用户信息
* @param array $params
* @return array
*/
public function getUserInfo($params = [])
{
$params = $params ? $params : $_GET;
if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) {
//获取access_token
$data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params;
$access_token = isset($data['access_token']) ? $data['access_token'] : '';
$refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : '';
$expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0;
if ($access_token) {
$uid = isset($data['uid']) ? $data['uid'] : '';
//获取用户信息
$queryarr = [
"access_token" => $access_token,
"uid" => $uid,
];
$ret = Http::get(self::GET_USERINFO_URL, $queryarr);
$userinfo = (array)json_decode($ret, true);
if (!$userinfo || isset($userinfo['error_code'])) {
return [];
}
$userinfo = $userinfo ? $userinfo : [];
$userinfo['nickname'] = isset($userinfo['screen_name']) ? $userinfo['screen_name'] : '';
$userinfo['avatar'] = isset($userinfo['profile_image_url']) ? $userinfo['profile_image_url'] : '';
$data = [
'access_token' => $access_token,
'refresh_token' => $refresh_token,
'expires_in' => $expires_in,
'openid' => $uid,
'userinfo' => $userinfo
];
return $data;
}
}
return [];
}
/**
* 获取access_token
* @param string code
* @return array
*/
public function getAccessToken($code = '')
{
if (!$code) {
return '';
}
$queryarr = array(
"grant_type" => "authorization_code",
"client_id" => $this->config['app_id'],
"client_secret" => $this->config['app_secret'],
"redirect_uri" => $this->config['callback'],
"code" => $code,
);
$response = Http::post(self::GET_ACCESS_TOKEN_URL, $queryarr);
$ret = (array)json_decode($response, true);
return $ret ? $ret : [];
}
}
... ...
<?php
namespace addons\third\model;
use think\Model;
/**
* 第三方登录模型
*/
class Third extends Model
{
// 开启自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
// 追加属性
protected $append = [
];
public function user()
{
return $this->belongsTo('\app\common\model\User', 'user_id', 'id', [], 'LEFT');
}
}
... ...
<!DOCTYPE html>
<html>
<head>
<title>第三方登录 - {$site.name}</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="__CDN__/assets/css/frontend.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">
<h2>第三方登录</h2>
<hr>
<div class="well">
<div class="row">
<div class="col-xs-4">
{if $user && in_array('qq', $platformList)}
<a href="{:addon_url('third/index/unbind',[':platform'=>'qq'])}" class="btn btn-block btn-info">
<i class="fa fa-qq"></i> 点击解绑
</a>
{else/}
<a href="{:addon_url('third/index/connect',[':platform'=>'qq'])}" class="btn btn-block btn-info">
<i class="fa fa-qq"></i> QQ登录
</a>
{/if}
</div>
<div class="col-xs-4">
{if $user && in_array('wechat', $platformList)}
<a href="{:addon_url('third/index/unbind',[':platform'=>'wechat'])}" class="btn btn-block btn-success">
<i class="fa fa-wechat"></i> 点击解绑
</a>
{else/}
<a href="{:addon_url('third/index/connect',[':platform'=>'wechat'])}" class="btn btn-block btn-success">
<i class="fa fa-wechat"></i> 微信登录
</a>
{/if}
</div>
<div class="col-xs-4">
{if $user && in_array('weibo', $platformList)}
<a href="{:addon_url('third/index/unbind',[':platform'=>'weibo'])}" class="btn btn-block btn-danger">
<i class="fa fa-weibo"></i> 点击解绑
</a>
{else/}
<a href="{:addon_url('third/index/connect',[':platform'=>'weibo'])}" class="btn btn-block btn-danger">
<i class="fa fa-weibo"></i> 微博登录
</a>
{/if}
</div>
</div>
</div>
<h2>相关链接</h2>
<hr>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>QQ</th>
<th>链接</th>
</tr>
</thead>
<tbody>
<tr>
<td>QQ 连接</td>
<td>{:addon_url('third/index/connect',[':platform'=>'qq'], false, true)}</td>
</tr>
<tr>
<td>QQ 绑定</td>
<td>{:addon_url('third/index/bind',[':platform'=>'qq'], false, true)}</td>
</tr>
<tr>
<td>QQ 解绑</td>
<td>{:addon_url('third/index/unbind',[':platform'=>'qq'], false, true)}</td>
</tr>
</tbody>
</table>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>微信</th>
<th>链接</th>
</tr>
</thead>
<tbody>
<tr>
<td>微信 连接</td>
<td>{:addon_url('third/index/connect',[':platform'=>'wechat'], false, true)}</td>
</tr>
<tr>
<td>微信 绑定</td>
<td>{:addon_url('third/index/bind',[':platform'=>'wechat'], false, true)}</td>
</tr>
<tr>
<td>微信 解绑</td>
<td>{:addon_url('third/index/unbind',[':platform'=>'wechat'], false, true)}</td>
</tr>
</tbody>
</table>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>微博</th>
<th>链接</th>
</tr>
</thead>
<tbody>
<tr>
<td>微博 连接</td>
<td>{:addon_url('third/index/connect',[':platform'=>'weibo'], false, true)}</td>
</tr>
<tr>
<td>微博 绑定</td>
<td>{:addon_url('third/index/bind',[':platform'=>'weibo'], false, true)}</td>
</tr>
<tr>
<td>微博 解绑</td>
<td>{:addon_url('third/index/unbind',[':platform'=>'weibo'], false, true)}</td>
</tr>
</tbody>
</table>
</div>
<!-- jQuery -->
<script src="https://cdn.jsdelivr.net/npm/jquery@2.1.4/dist/jquery.min.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(function () {
});
</script>
</body>
</html>
... ...
{"files":["public\\assets\\addons\\ueditor\\dialogs\\anchor\\anchor.html","public\\assets\\addons\\ueditor\\dialogs\\attachment\\attachment.css","public\\assets\\addons\\ueditor\\dialogs\\attachment\\attachment.html","public\\assets\\addons\\ueditor\\dialogs\\attachment\\attachment.js","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_chm.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_default.png","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_doc.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_exe.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_jpg.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_mp3.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_mv.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_pdf.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_ppt.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_psd.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_rar.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_txt.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\fileTypeImages\\icon_xls.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\images\\alignicon.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\images\\alignicon.png","public\\assets\\addons\\ueditor\\dialogs\\attachment\\images\\bg.png","public\\assets\\addons\\ueditor\\dialogs\\attachment\\images\\file-icons.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\images\\file-icons.png","public\\assets\\addons\\ueditor\\dialogs\\attachment\\images\\icons.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\images\\icons.png","public\\assets\\addons\\ueditor\\dialogs\\attachment\\images\\image.png","public\\assets\\addons\\ueditor\\dialogs\\attachment\\images\\progress.png","public\\assets\\addons\\ueditor\\dialogs\\attachment\\images\\success.gif","public\\assets\\addons\\ueditor\\dialogs\\attachment\\images\\success.png","public\\assets\\addons\\ueditor\\dialogs\\background\\background.css","public\\assets\\addons\\ueditor\\dialogs\\background\\background.html","public\\assets\\addons\\ueditor\\dialogs\\background\\background.js","public\\assets\\addons\\ueditor\\dialogs\\background\\images\\bg.png","public\\assets\\addons\\ueditor\\dialogs\\background\\images\\success.png","public\\assets\\addons\\ueditor\\dialogs\\charts\\chart.config.js","public\\assets\\addons\\ueditor\\dialogs\\charts\\charts.css","public\\assets\\addons\\ueditor\\dialogs\\charts\\charts.html","public\\assets\\addons\\ueditor\\dialogs\\charts\\charts.js","public\\assets\\addons\\ueditor\\dialogs\\charts\\images\\charts0.png","public\\assets\\addons\\ueditor\\dialogs\\charts\\images\\charts1.png","public\\assets\\addons\\ueditor\\dialogs\\charts\\images\\charts2.png","public\\assets\\addons\\ueditor\\dialogs\\charts\\images\\charts3.png","public\\assets\\addons\\ueditor\\dialogs\\charts\\images\\charts4.png","public\\assets\\addons\\ueditor\\dialogs\\charts\\images\\charts5.png","public\\assets\\addons\\ueditor\\dialogs\\emotion\\emotion.css","public\\assets\\addons\\ueditor\\dialogs\\emotion\\emotion.html","public\\assets\\addons\\ueditor\\dialogs\\emotion\\emotion.js","public\\assets\\addons\\ueditor\\dialogs\\emotion\\images\\0.gif","public\\assets\\addons\\ueditor\\dialogs\\emotion\\images\\bface.gif","public\\assets\\addons\\ueditor\\dialogs\\emotion\\images\\cface.gif","public\\assets\\addons\\ueditor\\dialogs\\emotion\\images\\fface.gif","public\\assets\\addons\\ueditor\\dialogs\\emotion\\images\\jxface2.gif","public\\assets\\addons\\ueditor\\dialogs\\emotion\\images\\neweditor-tab-bg.png","public\\assets\\addons\\ueditor\\dialogs\\emotion\\images\\tface.gif","public\\assets\\addons\\ueditor\\dialogs\\emotion\\images\\wface.gif","public\\assets\\addons\\ueditor\\dialogs\\emotion\\images\\yface.gif","public\\assets\\addons\\ueditor\\dialogs\\fonts\\buttoniconex.css","public\\assets\\addons\\ueditor\\dialogs\\fonts\\iconfont.eot","public\\assets\\addons\\ueditor\\dialogs\\fonts\\iconfont.svg","public\\assets\\addons\\ueditor\\dialogs\\fonts\\iconfont.ttf","public\\assets\\addons\\ueditor\\dialogs\\fonts\\iconfont.woff","public\\assets\\addons\\ueditor\\dialogs\\fonts\\images\\addfile.svg","public\\assets\\addons\\ueditor\\dialogs\\fonts\\images\\selected.svg","public\\assets\\addons\\ueditor\\dialogs\\gmap\\gmap.html","public\\assets\\addons\\ueditor\\dialogs\\help\\help.css","public\\assets\\addons\\ueditor\\dialogs\\help\\help.html","public\\assets\\addons\\ueditor\\dialogs\\help\\help.js","public\\assets\\addons\\ueditor\\dialogs\\image\\image.css","public\\assets\\addons\\ueditor\\dialogs\\image\\image.html","public\\assets\\addons\\ueditor\\dialogs\\image\\image.js","public\\assets\\addons\\ueditor\\dialogs\\image\\images\\alignicon.jpg","public\\assets\\addons\\ueditor\\dialogs\\image\\images\\bg.png","public\\assets\\addons\\ueditor\\dialogs\\image\\images\\icons.gif","public\\assets\\addons\\ueditor\\dialogs\\image\\images\\icons.png","public\\assets\\addons\\ueditor\\dialogs\\image\\images\\image.png","public\\assets\\addons\\ueditor\\dialogs\\image\\images\\progress.png","public\\assets\\addons\\ueditor\\dialogs\\image\\images\\success.gif","public\\assets\\addons\\ueditor\\dialogs\\image\\images\\success.png","public\\assets\\addons\\ueditor\\dialogs\\insertframe\\insertframe.html","public\\assets\\addons\\ueditor\\dialogs\\internal.js","public\\assets\\addons\\ueditor\\dialogs\\link\\link.html","public\\assets\\addons\\ueditor\\dialogs\\map\\map.html","public\\assets\\addons\\ueditor\\dialogs\\map\\show.html","public\\assets\\addons\\ueditor\\dialogs\\music\\balls.svg","public\\assets\\addons\\ueditor\\dialogs\\music\\music.css","public\\assets\\addons\\ueditor\\dialogs\\music\\music.html","public\\assets\\addons\\ueditor\\dialogs\\music\\music.js","public\\assets\\addons\\ueditor\\dialogs\\preview\\preview.html","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\addimg.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\brush.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\delimg.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\delimgH.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\empty.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\emptyH.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\eraser.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\redo.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\redoH.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\scale.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\scaleH.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\size.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\undo.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\images\\undoH.png","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\scrawl.css","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\scrawl.html","public\\assets\\addons\\ueditor\\dialogs\\scrawl\\scrawl.js","public\\assets\\addons\\ueditor\\dialogs\\searchreplace\\searchreplace.html","public\\assets\\addons\\ueditor\\dialogs\\searchreplace\\searchreplace.js","public\\assets\\addons\\ueditor\\dialogs\\snapscreen\\snapscreen.html","public\\assets\\addons\\ueditor\\dialogs\\spechars\\spechars.html","public\\assets\\addons\\ueditor\\dialogs\\spechars\\spechars.js","public\\assets\\addons\\ueditor\\dialogs\\table\\dragicon.png","public\\assets\\addons\\ueditor\\dialogs\\table\\edittable.css","public\\assets\\addons\\ueditor\\dialogs\\table\\edittable.html","public\\assets\\addons\\ueditor\\dialogs\\table\\edittable.js","public\\assets\\addons\\ueditor\\dialogs\\table\\edittd.html","public\\assets\\addons\\ueditor\\dialogs\\table\\edittip.html","public\\assets\\addons\\ueditor\\dialogs\\template\\config.js","public\\assets\\addons\\ueditor\\dialogs\\template\\images\\bg.gif","public\\assets\\addons\\ueditor\\dialogs\\template\\images\\pre0.png","public\\assets\\addons\\ueditor\\dialogs\\template\\images\\pre1.png","public\\assets\\addons\\ueditor\\dialogs\\template\\images\\pre2.png","public\\assets\\addons\\ueditor\\dialogs\\template\\images\\pre3.png","public\\assets\\addons\\ueditor\\dialogs\\template\\images\\pre4.png","public\\assets\\addons\\ueditor\\dialogs\\template\\images\\temp.gif","public\\assets\\addons\\ueditor\\dialogs\\template\\template.css","public\\assets\\addons\\ueditor\\dialogs\\template\\template.html","public\\assets\\addons\\ueditor\\dialogs\\template\\template.js","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\bg.png","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\center_focus.jpg","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\file-icons.gif","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\file-icons.png","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\icons.gif","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\icons.png","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\image.png","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\left_focus.jpg","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\none_focus.jpg","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\progress.png","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\right_focus.jpg","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\success.gif","public\\assets\\addons\\ueditor\\dialogs\\video\\images\\success.png","public\\assets\\addons\\ueditor\\dialogs\\video\\video.css","public\\assets\\addons\\ueditor\\dialogs\\video\\video.html","public\\assets\\addons\\ueditor\\dialogs\\video\\video.js","public\\assets\\addons\\ueditor\\dialogs\\webapp\\webapp.html","public\\assets\\addons\\ueditor\\dialogs\\wordimage\\fClipboard_ueditor.swf","public\\assets\\addons\\ueditor\\dialogs\\wordimage\\imageUploader.swf","public\\assets\\addons\\ueditor\\dialogs\\wordimage\\tangram.js","public\\assets\\addons\\ueditor\\dialogs\\wordimage\\wordimage.html","public\\assets\\addons\\ueditor\\dialogs\\wordimage\\wordimage.js","public\\assets\\addons\\ueditor\\i18n\\zh-cn\\images\\copy.png","public\\assets\\addons\\ueditor\\i18n\\zh-cn\\images\\localimage.png","public\\assets\\addons\\ueditor\\i18n\\zh-cn\\images\\music.png","public\\assets\\addons\\ueditor\\i18n\\zh-cn\\images\\upload.png","public\\assets\\addons\\ueditor\\i18n\\zh-cn\\zh-cn.js","public\\assets\\addons\\ueditor\\themes\\default\\css\\ueditor.css","public\\assets\\addons\\ueditor\\themes\\default\\css\\ueditor.min.css","public\\assets\\addons\\ueditor\\themes\\default\\dialogbase.css","public\\assets\\addons\\ueditor\\themes\\default\\images\\anchor.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\arrow.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\arrow_down.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\arrow_up.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\button-bg.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\cancelbutton.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\charts.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\cursor_h.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\cursor_h.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\cursor_v.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\cursor_v.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\dialog-title-bg.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\filescan.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\highlighted.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\icons-all.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\icons.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\icons.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\img-cracked.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\loaderror.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\loading.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\lock.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\neweditor-tab-bg.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\pagebreak.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\scale.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\sortable.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\spacer.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\sparator_v.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\table-cell-align.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\tangram-colorpicker.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\toolbar_bg.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\unhighlighted.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\upload.png","public\\assets\\addons\\ueditor\\themes\\default\\images\\videologo.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\word.gif","public\\assets\\addons\\ueditor\\themes\\default\\images\\wordpaste.png","public\\assets\\addons\\ueditor\\themes\\iframe.css","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\dash.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\dot.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-1.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-10.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-11.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-12.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-13.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-14.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-15.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-16.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-17.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-18.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-19.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-2.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-20.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-21.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-22.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-23.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-24.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-25.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-26.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-27.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-28.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-29.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-3.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-30.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-31.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-32.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-33.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-34.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-35.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-36.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-37.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-38.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-39.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-4.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-40.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-41.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-42.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-43.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-44.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-45.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-46.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-47.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-48.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-49.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-5.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-50.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-51.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-52.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-53.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-54.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-55.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-56.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-57.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-58.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-59.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-6.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-60.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-61.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-62.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-63.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-64.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-65.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-66.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-67.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-68.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-69.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-7.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-70.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-71.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-72.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-73.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-74.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-75.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-76.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-77.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-78.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-79.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-8.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-80.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-81.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-82.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-83.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-84.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-85.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-86.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-87.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-88.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-89.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-9.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-90.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-91.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-92.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-93.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-94.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-95.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-96.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-97.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-1-98.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-1.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-10.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-11.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-12.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-13.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-14.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-15.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-16.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-17.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-18.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-19.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-2.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-20.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-21.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-22.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-23.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-24.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-25.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-26.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-27.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-28.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-29.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-3.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-30.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-31.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-32.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-33.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-34.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-35.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-36.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-37.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-38.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-39.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-4.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-40.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-41.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-42.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-43.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-44.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-45.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-46.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-47.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-48.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-49.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-5.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-50.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-51.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-52.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-53.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-54.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-55.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-56.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-57.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-58.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-59.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-6.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-60.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-61.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-62.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-63.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-64.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-65.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-66.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-67.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-68.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-69.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-7.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-70.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-71.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-72.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-73.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-74.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-75.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-76.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-77.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-78.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-79.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-8.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-80.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-81.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-82.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-83.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-84.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-85.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-86.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-87.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-88.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-89.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-9.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-90.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-91.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-92.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-93.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-94.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-95.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-96.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-97.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-2-98.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-1.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-10.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-11.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-12.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-13.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-14.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-15.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-16.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-17.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-18.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-19.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-2.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-20.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-21.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-22.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-23.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-24.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-25.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-26.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-27.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-28.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-29.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-3.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-30.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-31.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-32.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-33.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-34.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-35.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-36.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-37.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-38.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-39.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-4.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-40.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-41.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-42.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-43.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-44.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-45.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-46.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-47.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-48.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-49.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-5.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-50.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-51.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-52.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-53.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-54.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-55.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-56.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-57.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-58.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-59.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-6.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-60.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-61.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-62.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-63.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-64.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-65.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-66.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-67.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-68.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-69.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-7.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-70.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-71.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-72.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-73.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-74.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-75.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-76.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-77.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-78.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-79.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-8.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-80.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-81.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-82.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-83.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-84.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-85.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-86.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-87.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-88.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-89.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-9.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-90.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-91.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-92.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-93.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-94.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-95.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-96.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-97.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-cn-3-98.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-1.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-10.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-11.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-12.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-13.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-14.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-15.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-16.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-17.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-18.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-19.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-2.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-20.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-21.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-22.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-23.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-24.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-25.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-26.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-27.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-28.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-29.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-3.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-30.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-31.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-32.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-33.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-34.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-35.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-36.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-37.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-38.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-39.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-4.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-40.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-41.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-42.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-43.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-44.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-45.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-46.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-47.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-48.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-49.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-5.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-50.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-51.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-52.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-53.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-54.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-55.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-56.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-57.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-58.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-59.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-6.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-60.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-61.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-62.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-63.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-64.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-65.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-66.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-67.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-68.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-69.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-7.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-70.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-71.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-72.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-73.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-74.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-75.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-76.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-77.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-78.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-79.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-8.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-80.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-81.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-82.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-83.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-84.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-85.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-86.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-87.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-88.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-89.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-9.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-90.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-91.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-92.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-93.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-94.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-95.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-96.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-97.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-1-98.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-1.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-10.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-11.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-12.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-13.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-14.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-15.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-16.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-17.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-18.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-19.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-2.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-20.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-21.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-22.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-23.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-24.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-25.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-26.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-27.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-28.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-29.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-3.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-30.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-31.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-32.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-33.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-34.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-35.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-36.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-37.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-38.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-39.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-4.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-40.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-41.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-42.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-43.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-44.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-45.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-46.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-47.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-48.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-49.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-5.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-50.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-51.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-52.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-53.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-54.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-55.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-56.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-57.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-58.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-59.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-6.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-60.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-61.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-62.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-63.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-64.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-65.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-66.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-67.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-68.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-69.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-7.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-70.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-71.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-72.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-73.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-74.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-75.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-76.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-77.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-78.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-79.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-8.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-80.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-81.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-82.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-83.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-84.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-85.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-86.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-87.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-88.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-89.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-9.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-90.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-91.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-92.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-93.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-94.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-95.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-96.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-97.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-2-98.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-1.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-10.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-11.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-12.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-13.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-14.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-15.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-16.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-17.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-18.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-19.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-2.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-20.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-21.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-22.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-23.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-24.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-25.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-26.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-27.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-28.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-29.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-3.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-30.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-31.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-32.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-33.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-34.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-35.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-36.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-37.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-38.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-39.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-4.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-40.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-41.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-42.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-43.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-44.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-45.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-46.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-47.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-48.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-49.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-5.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-50.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-51.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-52.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-53.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-54.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-55.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-56.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-57.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-58.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-59.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-6.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-60.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-61.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-62.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-63.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-64.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-65.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-66.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-67.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-68.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-69.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-7.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-70.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-71.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-72.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-73.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-74.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-75.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-76.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-77.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-78.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-79.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-8.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-80.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-81.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-82.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-83.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-84.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-85.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-86.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-87.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-88.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-89.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-9.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-90.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-91.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-92.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-93.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-94.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-95.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-96.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-97.gif","public\\assets\\addons\\ueditor\\themes\\ueditor-list\\list-num-3-98.gif","public\\assets\\addons\\ueditor\\third-party\\browser-md5-file.min.js","public\\assets\\addons\\ueditor\\third-party\\codemirror\\codemirror.css","public\\assets\\addons\\ueditor\\third-party\\codemirror\\codemirror.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\adapters\\mootools-adapter.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\adapters\\prototype-adapter.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\adapters\\standalone-framework.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\highcharts-more.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\highcharts.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\modules\\annotations.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\modules\\canvas-tools.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\modules\\data.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\modules\\drilldown.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\modules\\exporting.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\modules\\funnel.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\modules\\heatmap.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\modules\\map.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\modules\\no-data-to-display.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\themes\\dark-blue.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\themes\\dark-green.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\themes\\gray.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\themes\\grid.js","public\\assets\\addons\\ueditor\\third-party\\highcharts\\themes\\skies.js","public\\assets\\addons\\ueditor\\third-party\\jquery-1.10.2.min.js","public\\assets\\addons\\ueditor\\third-party\\jquery-1.10.2.min.map","public\\assets\\addons\\ueditor\\third-party\\snapscreen\\UEditorSnapscreen.exe","public\\assets\\addons\\ueditor\\third-party\\SyntaxHighlighter\\shCore.js","public\\assets\\addons\\ueditor\\third-party\\SyntaxHighlighter\\shCoreDefault.css","public\\assets\\addons\\ueditor\\third-party\\video-js\\font\\vjs.eot","public\\assets\\addons\\ueditor\\third-party\\video-js\\font\\vjs.svg","public\\assets\\addons\\ueditor\\third-party\\video-js\\font\\vjs.ttf","public\\assets\\addons\\ueditor\\third-party\\video-js\\font\\vjs.woff","public\\assets\\addons\\ueditor\\third-party\\video-js\\video-js.css","public\\assets\\addons\\ueditor\\third-party\\video-js\\video-js.min.css","public\\assets\\addons\\ueditor\\third-party\\video-js\\video-js.swf","public\\assets\\addons\\ueditor\\third-party\\video-js\\video.js","public\\assets\\addons\\ueditor\\third-party\\webuploader\\Uploader.swf","public\\assets\\addons\\ueditor\\third-party\\webuploader\\webuploader.css","public\\assets\\addons\\ueditor\\third-party\\webuploader\\webuploader.custom.min.js","public\\assets\\addons\\ueditor\\third-party\\webuploader\\webuploader.flashonly.min.js","public\\assets\\addons\\ueditor\\third-party\\webuploader\\webuploader.html5only.min.js","public\\assets\\addons\\ueditor\\third-party\\webuploader\\webuploader.min.js","public\\assets\\addons\\ueditor\\third-party\\webuploader\\webuploader.withoutimage.min.js","public\\assets\\addons\\ueditor\\third-party\\zeroclipboard\\ZeroClipboard.min.js","public\\assets\\addons\\ueditor\\third-party\\zeroclipboard\\ZeroClipboard.swf","public\\assets\\addons\\ueditor\\ueditor.all.min.js","public\\assets\\addons\\ueditor\\ueditor.config.js","public\\assets\\addons\\ueditor\\ueditor.parse.min.js"],"license":"basic","licenseto":"10789","licensekey":"IeflBpA9nU1FQjDL bLs2GrR0rVi\/foclAXxjZQ==","domains":["showmerchants.cn"],"licensecodes":[],"validations":["3c36e672cbd8ad7c0b4c2f0562b0c810"]}
\ No newline at end of file
... ...
<?php
namespace addons\ueditor;
use think\Addons;
/**
* 百度Ueditor插件
*/
class Ueditor extends Addons
{
/**
* 插件安装方法
* @return bool
*/
public function install()
{
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
return true;
}
/**
* @param $params
*/
public function configInit(&$params)
{
$config = $this->getConfig();
$params['ueditor'] = ['classname' => $config['classname']??'.editor'];
}
}
... ...
window.UEDITOR_HOME_URL = Config.__CDN__ + "/assets/addons/ueditor/";
require.config({
paths: {
'ueditor.config': '../addons/ueditor/ueditor.config',
'ueditor': '../addons/ueditor/ueditor.all.min',
'ueditor.zh': '../addons/ueditor/i18n/zh-cn/zh-cn',
'zeroclipboard': '../addons/ueditor/third-party/zeroclipboard/ZeroClipboard.min',
},
shim: {
'ueditor': {
deps: ['zeroclipboard', 'ueditor.config'],
exports: 'UE',
init: function (ZeroClipboard) {
//导出到全局变量,供ueditor使用
window.ZeroClipboard = ZeroClipboard;
},
},
'ueditor.zh': ['ueditor']
}
});
require(['form', 'upload'], function (Form, Upload) {
var _bindevent = Form.events.bindevent;
Form.events.bindevent = function (form) {
_bindevent.apply(this, [form]);
try {
//绑定editor事件
require(['ueditor', 'ueditor.zh'], function (UE, undefined) {
UE.list = [];
window.UEDITOR_CONFIG['uploadService'] = function (context, editor) {
return {
Upload: () => { return Upload },
Fast: () => { return Fast },
}
};
$(Config.ueditor.classname || '.editor', form).each(function () {
var id = $(this).attr("id");
var name = $(this).attr("name");
$(this).removeClass('form-control');
UE.list[id] = UE.getEditor(id, {
allowDivTransToP: false, //阻止div自动转p标签
initialFrameWidth: '100%',
initialFrameHeight: 320,
autoFloatEnabled: false,
// autoHeightEnabled: true, //自动高度
zIndex: 90,
xssFilterRules: false,
outputXssFilter: false,
inputXssFilter: false,
catchRemoteImageEnable: true
});
UE.list[id].addListener("contentChange", function () {
$('#' + id).val(this.getContent());
$('textarea[name="' + name + '"]').val(this.getContent());
})
});
})
} catch (e) {
console.log('绑定editor事件', e)
}
}
});
\ No newline at end of file
... ...
<?php
return [
[
'name' => 'classname',
'title' => '渲染文本框元素',
'type' => 'string',
'content' => [],
'value' => '.editor',
'rule' => 'required',
'msg' => '',
'tip' => '用于对指定的元素渲染,一般情况下无需修改',
'ok' => '',
'extend' => '',
],
];
... ...
name = ueditor
title = 百度ueditor插件
intro = 基于百度Ueditor的富文本编辑器
author = chance
website = http://it-huai.gitee.io/ueditor-api/
version = 1.0.8
state = 1
url = /addons/ueditor
license = basic
licenseto = 10789
... ...
{"files":["application\\admin\\controller\\wechat\\Autoreply.php","application\\admin\\controller\\wechat\\Config.php","application\\admin\\controller\\wechat\\Menu.php","application\\admin\\controller\\wechat\\Response.php","application\\admin\\lang\\zh-cn\\wechat\\autoreply.php","application\\admin\\lang\\zh-cn\\wechat\\config.php","application\\admin\\lang\\zh-cn\\wechat\\response.php","application\\admin\\model\\WechatAutoreply.php","application\\admin\\model\\WechatCaptcha.php","application\\admin\\model\\WechatConfig.php","application\\admin\\model\\WechatContext.php","application\\admin\\model\\WechatResponse.php","application\\admin\\view\\wechat\\autoreply\\add.html","application\\admin\\view\\wechat\\autoreply\\edit.html","application\\admin\\view\\wechat\\autoreply\\index.html","application\\admin\\view\\wechat\\config\\add.html","application\\admin\\view\\wechat\\config\\edit.html","application\\admin\\view\\wechat\\config\\index.html","application\\admin\\view\\wechat\\menu\\index.html","application\\admin\\view\\wechat\\response\\add.html","application\\admin\\view\\wechat\\response\\edit.html","application\\admin\\view\\wechat\\response\\index.html","application\\admin\\view\\wechat\\response\\select.html","public\\assets\\js\\backend\\wechat\\autoreply.js","public\\assets\\js\\backend\\wechat\\config.js","public\\assets\\js\\backend\\wechat\\menu.js","public\\assets\\js\\backend\\wechat\\response.js","public\\assets\\addons\\wechat\\css\\menu.css","public\\assets\\addons\\wechat\\images\\mobile_footer_bg.png","public\\assets\\addons\\wechat\\images\\mobile_header_bg.png","public\\assets\\addons\\wechat\\images\\mobile_index.png","public\\assets\\addons\\wechat\\images\\weixin_icon.png"],"license":"regular","licenseto":"10789","licensekey":"GeD2qP017ZsyuRth MFI\/PaZgDlLDTiOaCyzNQg==","domains":["showmerchants.cn"],"licensecodes":[],"validations":["3c36e672cbd8ad7c0b4c2f0562b0c810"],"menus":["wechat","wechat\/autoreply","wechat\/autoreply\/index","wechat\/autoreply\/add","wechat\/autoreply\/edit","wechat\/autoreply\/del","wechat\/autoreply\/multi","wechat\/config","wechat\/config\/index","wechat\/config\/add","wechat\/config\/edit","wechat\/config\/del","wechat\/config\/multi","wechat\/menu","wechat\/menu\/index","wechat\/menu\/add","wechat\/menu\/edit","wechat\/menu\/del","wechat\/menu\/remote","wechat\/menu\/sync","wechat\/menu\/multi","wechat\/response","wechat\/response\/index","wechat\/response\/add","wechat\/response\/edit","wechat\/response\/del","wechat\/response\/select","wechat\/response\/multi"]}
\ No newline at end of file
... ...
<?php
namespace addons\wechat;
use app\common\library\Menu;
use think\Addons;
/**
* 微信插件
*/
class Wechat extends Addons
{
/**
* 插件安装方法
* @return bool
*/
public function install()
{
$menu = [
[
'name' => 'wechat',
'title' => '微信管理',
'icon' => 'fa fa-wechat',
'sublist' => [
[
'name' => 'wechat/autoreply',
'title' => '自动回复管理',
'icon' => 'fa fa-reply-all',
'sublist' => [
['name' => 'wechat/autoreply/index', 'title' => '查看'],
['name' => 'wechat/autoreply/add', 'title' => '添加'],
['name' => 'wechat/autoreply/edit', 'title' => '修改'],
['name' => 'wechat/autoreply/del', 'title' => '删除'],
['name' => 'wechat/autoreply/multi', 'title' => '批量更新'],
]
],
[
'name' => 'wechat/config',
'title' => '配置管理',
'icon' => 'fa fa-cog',
'sublist' => [
['name' => 'wechat/config/index', 'title' => '查看'],
['name' => 'wechat/config/add', 'title' => '添加'],
['name' => 'wechat/config/edit', 'title' => '修改'],
['name' => 'wechat/config/del', 'title' => '删除'],
['name' => 'wechat/config/multi', 'title' => '批量更新'],
]
],
[
'name' => 'wechat/menu',
'title' => '菜单管理',
'icon' => 'fa fa-list',
'sublist' => [
['name' => 'wechat/menu/index', 'title' => '查看'],
['name' => 'wechat/menu/add', 'title' => '添加'],
['name' => 'wechat/menu/edit', 'title' => '修改'],
['name' => 'wechat/menu/del', 'title' => '删除'],
['name' => 'wechat/menu/remote', 'title' => '加载远程菜单'],
['name' => 'wechat/menu/sync', 'title' => '同步'],
['name' => 'wechat/menu/multi', 'title' => '批量更新'],
]
],
[
'name' => 'wechat/response',
'title' => '资源管理',
'icon' => 'fa fa-list-alt',
'sublist' => [
['name' => 'wechat/response/index', 'title' => '查看'],
['name' => 'wechat/response/add', 'title' => '添加'],
['name' => 'wechat/response/edit', 'title' => '修改'],
['name' => 'wechat/response/del', 'title' => '删除'],
['name' => 'wechat/response/select', 'title' => '选择'],
['name' => 'wechat/response/multi', 'title' => '批量更新'],
]
]
]
]
];
Menu::create($menu);
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
Menu::delete('wechat');
return true;
}
/**
* 插件启用方法
*/
public function enable()
{
Menu::enable('wechat');
}
/**
* 插件禁用方法
*/
public function disable()
{
Menu::disable('wechat');
}
}
... ...
<?php
return [
[
'name' => 'app_id',
'title' => 'app_id',
'type' => 'string',
'content' => [],
'value' => '',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'secret',
'title' => 'secret',
'type' => 'string',
'content' => [],
'value' => '',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'token',
'title' => 'token',
'type' => 'string',
'content' => [],
'value' => '',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'aes_key',
'title' => 'aes_key',
'type' => 'string',
'content' => [],
'value' => '',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'debug',
'title' => '调试模式',
'type' => 'radio',
'content' => [
'否',
'是',
],
'value' => '0',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'log_level',
'title' => '日志记录等级',
'type' => 'select',
'content' => [
'debug' => 'debug',
'info' => 'info',
'notice' => 'notice',
'warning' => 'warning',
'error' => 'error',
'critical' => 'critical',
'alert' => 'alert',
'emergency' => 'emergency',
],
'value' => 'info',
'rule' => 'required',
'msg' => '',
'tip' => '生产环境日志记录等级',
'ok' => '',
'extend' => '',
],
[
'name' => 'oauth_callback',
'title' => '登录回调',
'type' => 'string',
'content' => [],
'value' => 'http://www.yoursite.com/addons/wechat/index/callback',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
];
... ...
<?php
namespace addons\wechat\controller;
use addons\wechat\library\Wechat;
use addons\wechat\model\WechatCaptcha;
use fast\Http;
/**
* 微信验证码验证接口
*/
class Captcha extends \think\addons\Controller
{
/**
* 验证码检测接口
*/
public function check()
{
$captcha = $this->request->post("captcha");
$event = $this->request->post("event");
$result = WechatCaptcha::check($captcha, $event);
if ($result) {
$this->success("验证码正确");
} else {
$this->error("验证码错误");
}
}
/**
* 验证码发送接口
*/
public function send()
{
$ip = $this->request->ip();
$event = $this->request->post("event");
if (!$event) {
$this->error("参数错误");
}
$captch = WechatCaptcha::where('ip', $ip)
->where('event', $event)
->whereTime('createtime', '-2 minutes')
->find();
if ($captch) {
$this->error("获取频繁,请稍后重试");
}
$token = Wechat::getAccessToken();
if (!$token) {
$this->error("发送失败,请稍后重试");
}
$url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={$token}";
$params = [
'expire_seconds' => 120,
'action_name' => 'QR_STR_SCENE',
'action_info' => [
'scene' => [
'scene_str' => "captcha_" . $event . "_" . $ip,
]
],
];
//获取验证码
$result = Http::sendRequest($url, json_encode($params));
if ($result['ret']) {
$msg = (array)json_decode($result['msg'], true);
if (isset($msg['ticket']) && isset($msg['url'])) {
$this->success("", null, ['image' => "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" . urlencode($msg['ticket']), 'url' => $msg['url']]);
}
}
$this->error("获取失败!请稍后重试");
}
}
... ...
<?php
namespace addons\wechat\controller;
use addons\wechat\library\Config;
use addons\wechat\model\WechatAutoreply;
use addons\wechat\model\WechatCaptcha;
use addons\wechat\model\WechatContext;
use addons\wechat\model\WechatResponse;
use addons\wechat\model\WechatConfig;
use EasyWeChat\Factory;
use addons\wechat\library\Wechat as WechatService;
use addons\wechat\library\Config as ConfigService;
use think\Log;
/**
* 微信接口
*/
class Index extends \think\addons\Controller
{
public $app = null;
public function _initialize()
{
parent::_initialize();
$this->app = Factory::officialAccount(Config::load());
}
/**
*
*/
public function index()
{
$this->error("当前插件暂无前台页面");
}
/**
* 微信API对接接口
*/
public function api()
{
$this->app->server->push(function ($message) {
$wechatService = new WechatService;
$matches = null;
$openid = $message['FromUserName'];
$to_openid = $message['ToUserName'];
$unknownMessage = WechatConfig::getValue('default.unknown.message');
$unknownMessage = $unknownMessage ? $unknownMessage : "";
switch ($message['MsgType']) {
case 'event': //事件消息
$event = $message['Event'];
$eventkey = $message['EventKey'] ? $message['EventKey'] : $message['Event'];
//验证码消息
if (in_array($event, ['subscribe', 'SCAN']) && preg_match("/^captcha_([a-zA-Z0-9]+)_([0-9\.]+)/", $eventkey, $matches)) {
return WechatCaptcha::send($openid, $matches[1], $matches[2]);
}
switch ($event) {
case 'subscribe'://添加关注
$subscribeMessage = WechatConfig::getValue('default.subscribe.message');
$subscribeMessage = $subscribeMessage ? $subscribeMessage : "欢迎关注我们!";
return $subscribeMessage;
case 'unsubscribe'://取消关注
return '';
case 'LOCATION'://获取地理位置
return '';
case 'VIEW': //跳转链接,eventkey为链接
return '';
case 'SCAN': //扫码
return '';
default:
break;
}
$wechatResponse = WechatResponse::where(["eventkey" => $eventkey, 'status' => 'normal'])->find();
if ($wechatResponse) {
$responseContent = (array)json_decode($wechatResponse['content'], true);
$wechatContext = WechatContext::where(['openid' => $openid])->order('id', 'desc')->find();
$data = ['eventkey' => $eventkey, 'command' => '', 'refreshtime' => time(), 'openid' => $openid];
if ($wechatContext) {
$wechatContext->save($data);
} else {
$wechatContext = WechatContext::create($data, true);
}
$result = $wechatService->response($this, $openid, '', $responseContent, $wechatContext);
if ($result) {
return $result;
}
}
return $unknownMessage;
case 'text': //文字消息
case 'image': //图片消息
case 'voice': //语音消息
case 'video': //视频消息
case 'location': //坐标消息
case 'link': //链接消息
default: //其它消息
//自动回复处理
if ($message['MsgType'] == 'text') {
$autoreply = null;
$autoreplyList = WechatAutoreply::where('status', 'normal')->cache(true)->order('weigh DESC,id DESC')->select();
foreach ($autoreplyList as $index => $item) {
//完全匹配和正则匹配
if ($item['text'] == $message['Content'] || (in_array(mb_substr($item['text'], 0, 1), ['#', '~', '/']) && preg_match($item['text'], $message['Content'], $matches))) {
$autoreply = $item;
break;
}
}
if ($autoreply) {
$wechatResponse = WechatResponse::where(["eventkey" => $autoreply['eventkey'], 'status' => 'normal'])->find();
if ($wechatResponse) {
$responseContent = (array)json_decode($wechatResponse['content'], true);
$wechatContext = WechatContext::where(['openid' => $openid])->order('id', 'desc')->find();
$result = $wechatService->response($this, $openid, $message['Content'], $responseContent, $wechatContext, $matches);
if ($result) {
return $result;
}
}
}
}
return $unknownMessage;
}
return ""; //SUCCESS
});
$response = $this->app->server->serve();
// 将响应输出
$response->send();
return;
}
/**
* 登录回调
*/
public function callback()
{
}
/**
* 支付回调
*/
public function notify()
{
Log::record(file_get_contents('php://input'), "notify");
$response = $this->app->handlePaidNotify(function ($message, $fail) {
// 你的逻辑
return true;
// 或者错误消息
$fail('Order not exists.');
});
$response->send();
return;
}
}
... ...
name = wechat
title = 微信管理
intro = 在线管理微信公众号插件
author = FastAdmin
website = https://www.fastadmin.net
version = 1.2.0
state = 1
url = /addons/wechat
license = regular
licenseto = 10789
... ...
CREATE TABLE IF NOT EXISTS `__PREFIX__wechat_autoreply` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL DEFAULT '' COMMENT '标题',
`text` varchar(100) NOT NULL DEFAULT '' COMMENT '触发文本',
`eventkey` varchar(50) NOT NULL DEFAULT '' COMMENT '响应事件',
`remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注',
`weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重',
`createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '添加时间',
`updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
`status` varchar(30) NOT NULL DEFAULT '' COMMENT '状态',
PRIMARY KEY (`id`),
KEY `eventkey` (`eventkey`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='微信自动回复表';
BEGIN;
INSERT INTO `__PREFIX__wechat_autoreply`(`id`, `title`, `text`, `eventkey`, `remark`, `weigh`, `createtime`, `updatetime`, `status`) VALUES (1, '输入hello', 'hello', '58c7d908c4570', '', 1, 1493366855, 1493366855, 'normal');
INSERT INTO `__PREFIX__wechat_autoreply`(`id`, `title`, `text`, `eventkey`, `remark`, `weigh`, `createtime`, `updatetime`, `status`) VALUES (2, '输入你好', '你好', '58fdfaa9e1965', '', 2, 1493704976, 1493704976, 'normal');
COMMIT;
CREATE TABLE IF NOT EXISTS `__PREFIX__wechat_captcha` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`event` varchar(100) DEFAULT '' COMMENT '事件',
`openid` varchar(255) DEFAULT NULL COMMENT '用户openid',
`context` varchar(20) DEFAULT NULL COMMENT '上下文',
`code` varchar(30) DEFAULT NULL COMMENT '验证码',
`times` int(10) unsigned DEFAULT '0' COMMENT '验证次数',
`ip` varchar(50) DEFAULT '' COMMENT 'IP',
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `ip` (`ip`,`event`) USING BTREE,
KEY `openid` (`openid`(191),`event`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='微信公众号验证码';
CREATE TABLE IF NOT EXISTS `__PREFIX__wechat_config` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '配置名称',
`title` varchar(50) NOT NULL DEFAULT '' COMMENT '配置标题',
`value` text NOT NULL COMMENT '配置值',
`createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
`updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='微信配置表';
BEGIN;
INSERT INTO `__PREFIX__wechat_config` VALUES ('1', 'menu', '微信菜单', '[{\"name\":\"FastAdmin\",\"sub_button\":[{\"name\":\"官网\",\"type\":\"view\",\"url\":\"http:\\/\\/www.fastadmin.net\"},{\"name\":\"在线演示\",\"type\":\"click\",\"key\":\"\"},{\"name\":\"文档\",\"type\":\"view\",\"url\":\"http:\\/\\/doc.fastadmin.net\"}]},{\"name\":\"在线客服\",\"type\":\"click\",\"key\":\"58cb852984970\"},{\"name\":\"关于我们\",\"type\":\"click\",\"key\":\"58bf944aa0777\"}]', '1497398820', '1500538185'), ('2', 'service', '客服配置', '{\"onlinetime\":\"09:00-18:00\",\"offlinemsg\":\"请在工作时间联系客服!\",\"nosessionmsg\":\"当前没有客服在线!请稍后重试!\",\"waitformsg\":\"请问有什么可以帮到您?\"}', '1497429674', '1497429674'), ('3', 'signin', '连续登录配置', '{\"s1\":\"100\",\"s2\":\"200\",\"s3\":\"300\",\"sn\":\"500\"}', '1497429711', '1497429711');
COMMIT;
CREATE TABLE IF NOT EXISTS `__PREFIX__wechat_context` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`openid` varchar(64) NOT NULL DEFAULT '',
`type` varchar(30) NOT NULL DEFAULT '' COMMENT '类型',
`eventkey` varchar(64) NOT NULL DEFAULT '',
`command` varchar(64) NOT NULL DEFAULT '',
`message` varchar(255) NOT NULL DEFAULT '' COMMENT '内容',
`refreshtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最后刷新时间',
`createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
`updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `openid` (`openid`,`eventkey`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='微信上下文表';
CREATE TABLE IF NOT EXISTS `__PREFIX__wechat_response` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL DEFAULT '' COMMENT '资源名',
`eventkey` varchar(128) NOT NULL DEFAULT '' COMMENT '事件',
`type` enum('text','image','news','voice','video','music','link','app') NOT NULL DEFAULT 'text' COMMENT '类型',
`content` text NOT NULL COMMENT '内容',
`remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注',
`createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
`updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
`status` varchar(30) NOT NULL DEFAULT '' COMMENT '状态',
PRIMARY KEY (`id`),
UNIQUE KEY `eventkey` (`eventkey`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='微信资源表';
BEGIN;
INSERT INTO `__PREFIX__wechat_response` VALUES ('1', '签到送积分', '58adaf7876aab', 'app', '{\"app\":\"signin\"}', '', '1487777656', '1487777656', 'normal'), ('2', '关于我们', '58bf944aa0777', 'app', '{\"app\":\"page\",\"id\":\"1\"}', '', '1488950346', '1488950346', 'normal'), ('3', '自动回复1', '58c7d908c4570', 'text', '{\"content\":\"world\"}', '', '1489492232', '1489492232', 'normal'), ('5', '自动回复2', '58fdfaa9e1965', 'text', '{\"content\":\"我是FastAdmin!\"}', '', '1493039785', '1493039785', 'normal');
COMMIT;
... ...
<?php
namespace addons\wechat\library;
/**
* 微信配置类
*/
class Config
{
public static function load()
{
$config = get_addon_config('wechat');
return [
/**
* 账号基本信息,请从微信公众平台/开放平台获取
*/
'app_id' => $config['app_id'], // AppID
'secret' => $config['secret'], // AppSecret
'token' => $config['token'], // Token
'aes_key' => $config['aes_key'], // EncodingAESKey,安全模式下请一定要填写!!!
/**
* 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
* 使用自定义类名时,构造函数将会接收一个 `EasyWeChat\Kernel\Http\Response` 实例
*/
'response_type' => 'array',
/**
* 日志配置
*
* level: 日志级别, 可选为:debug/info/notice/warning/error/critical/alert/emergency
* path:日志文件位置(绝对路径!!!),要求可写权限
*/
'log' => [
'default' => 'dev', // 默认使用的 channel,生产环境可以改为下面的 prod
'channels' => [
// 测试环境
'dev' => [
'driver' => 'single',
'path' => ROOT_PATH . '/runtime/log/easywechat.log',
'level' => 'debug',
],
// 生产环境
'prod' => [
'driver' => 'daily',
'path' => ROOT_PATH . '/runtime/log/easywechat.log',
'level' => $config['log_level'],
],
],
],
/**
* 接口请求相关配置,超时时间等,具体可用参数请参考:
* http://docs.guzzlephp.org/en/stable/request-config.html
*
* - retries: 重试次数,默认 1,指定当 http 请求失败时重试的次数。
* - retry_delay: 重试延迟间隔(单位:ms),默认 500
* - log_template: 指定 HTTP 日志模板,请参考:https://github.com/guzzle/guzzle/blob/master/src/MessageFormatter.php
*/
'http' => [
'max_retries' => 1,
'retry_delay' => 500,
'timeout' => 5.0,
// 'base_uri' => 'https://api.weixin.qq.com/', // 如果你在国外想要覆盖默认的 url 的时候才使用,根据不同的模块配置不同的 uri
],
/**
* OAuth 配置
*
* scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login
* callback:OAuth授权完成后的回调页地址
*/
'oauth' => [
'scopes' => ['snsapi_userinfo'],
'callback' => $config['oauth_callback'],
],
];
}
}
... ...
<?php
namespace addons\wechat\library;
use addons\signin\model\Signin;
use addons\third\model\Third;
use app\common\model\User;
use EasyWeChat\Kernel\Messages\News;
use EasyWeChat\Kernel\Messages\NewsItem;
use fast\Date;
use fast\Http;
use fast\Random;
use think\Session;
use think\Config;
/**
* 微信服务类
*/
class Wechat
{
public static function appConfig()
{
return array(
'signin' => array(
'name' => '签到送积分',
'config' => array()
),
'blog' => array(
'name' => '关联博客',
'config' => array(
array(
'type' => 'text',
'caption' => '日志ID',
'field' => 'post_id',
'rule' => '',
'extend' => 'class="form-control selectpage" data-source="blog/post/index" data-field="title"',
'options' => '',
),
array(
'type' => 'radio',
'caption' => '开启搜索日志',
'field' => 'searchpost',
'rule' => '',
'extend' => '',
'options' => [
'1' => '是',
'0' => '否',
],
),
array(
'type' => 'text',
'caption' => '正则搜索匹配索引',
'field' => 'searchregexindex',
'rule' => '',
'defaultvalue' => '1',
'extend' => '',
'options' => [],
)
)
),
'cms' => array(
'name' => '关联CMS',
'config' => array(
array(
'type' => 'text',
'caption' => '文章ID',
'field' => 'archives_id',
'rule' => '',
'extend' => 'class="form-control selectpage" data-source="cms/archives/index" data-field="title"',
'options' => ''
),
array(
'type' => 'text',
'caption' => '单页ID',
'field' => 'page_id',
'rule' => '',
'extend' => 'class="form-control selectpage" data-source="cms/page/index" data-field="title"',
'options' => ''
),
array(
'type' => 'text',
'caption' => '专题ID',
'field' => 'special_id',
'rule' => '',
'extend' => 'class="form-control selectpage" data-source="cms/special/index" data-field="title"',
'options' => ''
),
array(
'type' => 'radio',
'caption' => '开启搜索文章',
'field' => 'searcharchives',
'rule' => '',
'extend' => '',
'options' => [
'1' => '是',
'0' => '否',
],
),
array(
'type' => 'radio',
'caption' => '开启搜索单页',
'field' => 'searchpage',
'rule' => '',
'extend' => '',
'options' => [
'1' => '是',
'0' => '否',
],
),
array(
'type' => 'radio',
'caption' => '开启搜索专题',
'field' => 'searchspecial',
'rule' => '',
'extend' => '',
'options' => [
'1' => '是',
'0' => '否',
],
),
array(
'type' => 'text',
'caption' => '正则搜索匹配索引',
'field' => 'searchregexindex',
'rule' => '',
'defaultvalue' => '1',
'extend' => '',
'options' => [],
)
)
),
'ask' => array(
'name' => '关联问答',
'config' => array(
array(
'type' => 'text',
'caption' => '问题ID',
'field' => 'question_id',
'extend' => 'class="form-control selectpage" data-source="ask/question/index" data-field="title"',
'options' => ''
),
array(
'type' => 'text',
'caption' => '文章ID',
'field' => 'article_id',
'extend' => 'class="form-control selectpage" data-source="ask/article/index" data-field="title"',
'options' => ''
),
array(
'type' => 'radio',
'caption' => '开启搜索问题',
'field' => 'searchquestion',
'rule' => '',
'extend' => '',
'options' => [
'1' => '是',
'0' => '否',
],
),
array(
'type' => 'radio',
'caption' => '开启搜索文章',
'field' => 'searcharticle',
'rule' => '',
'extend' => '',
'options' => [
'1' => '是',
'0' => '否',
],
),
array(
'type' => 'text',
'caption' => '正则搜索匹配索引',
'field' => 'searchregexindex',
'rule' => '',
'defaultvalue' => '1',
'extend' => '',
'options' => [],
)
)
),
'vote' => array(
'name' => '关联投票',
'config' => array(
array(
'type' => 'text',
'caption' => '投票主题ID',
'field' => 'subject_id',
'extend' => 'class="form-control selectpage" data-source="vote/subject/index" data-field="title"',
'rule' => '',
'options' => ''
),
array(
'type' => 'text',
'caption' => '参赛人员ID',
'field' => 'player_id',
'rule' => '',
'extend' => 'class="form-control selectpage" data-source="vote/player/index" data-field="nickname"',
'options' => ''
),
array(
'type' => 'radio',
'caption' => '开启搜索主题',
'field' => 'searchsubject',
'rule' => '',
'extend' => '',
'options' => [
'1' => '是',
'0' => '否',
],
),
array(
'type' => 'radio',
'caption' => '开启搜索参赛人员',
'field' => 'searchplayer',
'rule' => '',
'extend' => '',
'options' => [
'1' => '是',
'0' => '否',
],
),
array(
'type' => 'text',
'caption' => '正则搜索匹配索引',
'field' => 'searchregexindex',
'rule' => '',
'defaultvalue' => '1',
'extend' => '',
'options' => [],
)
)
),
);
}
/**
* 应用交互
* @return array|bool|mixed|string
*/
public function response($obj, $openid, $message, $content, $context, $matches = null)
{
$response = false;
if (isset($content['app'])) {
$entry = null;
$keyword = isset($content['searchregexindex']) && $content['searchregexindex'] > -1 && $matches && isset($matches[$content['searchregexindex']])
? $matches[$content['searchregexindex']] : $message;
switch ($content['app']) {
case 'signin':
$signinInfo = get_addon_info('signin');
if (!$signinInfo || !$signinInfo['state']) {
return "请先在后台管理安装并启用《会员签到》插件";
}
$thirdInfo = get_addon_info('third');
if (!$thirdInfo || !$thirdInfo['state']) {
return "请先在后台管理安装并启用《第三方登录》插件";
}
$user = self::getUserByOpenid($openid);
if (!$user) {
return "请先在会员中心绑定微信登录,<a href='" . addon_url('third/index/connect', [':platform' => 'wechat'], true, true) . "'>点击这里绑定</a>";
}
$config = get_addon_config('signin');
$signdata = $config['signinscore'];
$lastdata = Signin::where('user_id', $user->id)->order('id', 'desc')->find();
$successions = $lastdata && $lastdata['createtime'] > Date::unixtime('day', -1) ? $lastdata['successions'] : 0;
$signin = Signin::where('user_id', $user->id)->whereTime('createtime', 'today')->find();
if ($signin) {
return '今天已签到,请明天再来!';
} else {
$successions++;
Signin::create(['user_id' => $user->id, 'successions' => $successions, 'createtime' => time()]);
$score = isset($signdata['s' . $successions]) ? $signdata['s' . $successions] : $signdata['sn'];
$user->setInc('score', $score);
User::score($score, $user->id, "连续签到{$successions}天");
return '签到成功!连续签到' . $successions . '天!获得' . $score . '积分,';
}
break;
case 'blog':
$blogInfo = get_addon_info('blog');
if (!$blogInfo || !$blogInfo['state']) {
return "请先在后台管理安装并启用《简单博客》插件";
}
$entry = \addons\blog\model\Post::get($content['post_id']);
if ($entry) {
$entry['image'] = $entry['thumb'];
}
if (!$entry && $content['searchpost']) {
$entry = \addons\blog\model\Post::where("title|description", 'like', "%{$keyword}%")->where('status', 'normal')->find();
}
if (!$entry) {
return "未搜索到任何匹配信息$keyword" . json_encode($matches);
}
break;
case 'cms':
$cmsInfo = get_addon_info('cms');
if (!$cmsInfo || !$cmsInfo['state']) {
return "请先在后台管理安装并启用《CMS内容管理系统》插件";
}
if (isset($content['archives_id']) && $content['archives_id']) {
$entry = \addons\cms\model\Archives::get($content['archives_id']);
} elseif (isset($content['page_id']) && $content['page_id']) {
$entry = \addons\cms\model\Page::get($content['page_id']);
} elseif (isset($content['special_id']) && $content['special_id']) {
$entry = \addons\cms\model\Special::get($content['special_id']);
}
if (!$entry && $content['searcharchives']) {
$entry = \addons\cms\model\Archives::where("title|description", 'like', "%{$keyword}%")->where('status', 'normal')->find();
}
if (!$entry && $content['searchpage']) {
$entry = \addons\cms\model\Page::where("title|description", 'like', "%{$keyword}%")->where('status', 'normal')->find();
}
if (!$entry && $content['searchspecial']) {
$entry = \addons\cms\model\Special::where("title|description", 'like', "%{$keyword}%")->where('status', 'normal')->find();
}
if (!$entry) {
return "未搜索到任何匹配信息";
}
break;
case 'ask':
$blogInfo = get_addon_info('ask');
if (!$blogInfo || !$blogInfo['state']) {
return "请先在后台管理安装并启用《知识付费问答》插件";
}
if (isset($content['question_id']) && $content['question_id']) {
$entry = \addons\ask\model\Question::get($content['question_id']);
} elseif (isset($content['article_id']) && $content['article_id']) {
$entry = \addons\ask\model\Article::get($content['article_id']);
}
if (!$entry && $content['searchquestion']) {
$entry = \addons\ask\model\Question::where("title", 'like', "%{$keyword}%")->where('status', 'normal')->find();
}
if (!$entry && $content['searcharticle']) {
$entry = \addons\ask\model\Article::where("title|description", 'like', "%{$keyword}%")->where('status', 'normal')->find();
}
if (!$entry) {
return "未搜索到任何匹配信息";
}
break;
case 'vote':
$blogInfo = get_addon_info('vote');
if (!$blogInfo || !$blogInfo['state']) {
return "请先在后台管理安装并启用《在线投票系统》插件";
}
if (isset($content['subject_id']) && $content['subject_id']) {
$entry = \addons\vote\model\Subject::all($content['subject_id']);
} elseif (isset($content['player_id']) && $content['player_id']) {
$entry = \addons\vote\model\Player::all($content['player_id']);
}
if (!$entry && $content['searchsubject']) {
$entry = \addons\vote\model\Subject::where("title|description", 'like', "%{$keyword}%")->where('status', 'normal')->find();
}
if (!$entry && $content['searchplayer']) {
$entry = \addons\vote\model\Player::where("nickname", 'like', "%{$keyword}%")->where('status', 'normal')->find();
}
if (!$entry) {
return "未搜索到任何匹配信息";
}
break;
default:
break;
}
if (isset($entry) && $entry) {
$items = [
new NewsItem([
'title' => isset($entry['title']) ? $entry['title'] : (isset($entry['nickname']) ? $entry['nickname'] : ''),
'description' => isset($entry['description']) ? $entry['description'] : '',
'url' => $entry['fullurl'],
'image' => cdnurl($entry['image'], true),
]),
];
$news = new News($items);
$response[] = $news;
}
} else {
$response = isset($content['content']) ? $content['content'] : $response;
}
return $response;
}
/**
* 获取Token
*/
public static function getAccessToken()
{
$token = Session::get('wechat_access_token');
if (!$token) {
$config = get_addon_config('wechat');
$params = [
'grant_type' => 'client_credential',
'appid' => $config['app_id'],
'secret' => $config['secret'],
];
$url = "https://api.weixin.qq.com/cgi-bin/token";
$result = Http::sendRequest($url, $params, 'GET');
if ($result['ret']) {
$msg = (array)json_decode($result['msg'], true);
if (isset($msg['access_token'])) {
$token = $msg['access_token'];
Session::set('wechat_access_token', $token, $msg['expires_in'] - 1);
}
}
}
return $token;
}
/**
* 根据Openid获取用户信息
* @param string $openid 微信OpenID
* @return User|null
*/
public static function getUserByOpenid($openid)
{
$third = Third::where('platform', 'wechat')->where('openid', $openid)->find();
if ($third && $third->user_id) {
return User::get($third->user_id);
}
return null;
}
}
... ...
<?php
namespace addons\wechat\model;
use think\Model;
class WechatAutoreply extends Model
{
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
}
... ...
<?php
namespace addons\wechat\model;
use fast\Random;
use think\Model;
class WechatCaptcha extends Model
{
// 表名
protected $name = 'wechat_captcha';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = '';
// 追加属性
protected $append = [
];
/**
* 发送验证码
* @param $openid string 用户OpenID
* @param $event string 事件
* @param $ip string IP地址
* @return string
*/
public static function send($openid, $event, $ip)
{
$captcha = self::where(['openid' => $openid, 'event' => $event])->whereTime('createtime', '-2 minutes')->find();
if ($captcha) {
return "验证码发送速度过快,请稍后重试";
}
$code = Random::alnum(4);
$data = [
'event' => $event,
'openid' => $openid,
'code' => $code,
'ip' => $ip,
];
self::create($data);
return "你的验证码是:{$code},2分钟内输入有效";
}
/**
* 检测验证码
* @param $code string 验证码
* @param $event string 事件
* @param $ip string IP
* @return bool
*/
public static function check($code, $event, $ip = null)
{
$ip = is_null($ip) ? request()->ip() : $ip;
$captcha = self::where(['ip' => $ip, 'event' => $event])->whereTime('createtime', '-2 minutes')->find();
if ($captcha && $captcha->code == $code && $captcha->times < 10) {
$captcha->setInc("times");
return true;
}
//验证大于10次或超时
if ($captcha && ($captcha->times >= 10 || time() - $captcha->createtime > 120)) {
$captcha->delete();
}
return false;
}
}
... ...
<?php
namespace addons\wechat\model;
use think\Model;
class WechatConfig extends Model
{
// 表名,不含前缀
public $name = 'wechat_config';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
// 追加属性
protected $append = [
];
/**
* 读取指定配置名称的值
* @param string $name
* @return string
*/
public static function getValue($name)
{
$item = self::get(['name' => $name]);
return $item ? $item->value : '';
}
}
... ...
<?php
namespace addons\wechat\model;
use think\Model;
class WechatContext extends Model
{
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
}
... ...
<?php
namespace addons\wechat\model;
use think\Model;
class WechatResponse extends Model
{
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
}
... ...
<?php
namespace app\admin\controller;
use app\common\controller\Backend;
use think\Config;
use think\console\Input;
use think\Db;
use think\Exception;
/**
* 在线命令管理
*
* @icon fa fa-circle-o
*/
class Command extends Backend
{
/**
* Command模型对象
*/
protected $model = null;
protected $noNeedRight = ['get_controller_list', 'get_field_list'];
public function _initialize()
{
parent::_initialize();
$this->model = model('Command');
$this->view->assign("statusList", $this->model->getStatusList());
}
/**
* 添加
*/
public function add()
{
$tableList = [];
$list = \think\Db::query("SHOW TABLES");
foreach ($list as $key => $row) {
$tableList[reset($row)] = reset($row);
}
$this->view->assign("tableList", $tableList);
return $this->view->fetch();
}
/**
* 获取字段列表
* @internal
*/
public function get_field_list()
{
$dbname = Config::get('database.database');
$prefix = Config::get('database.prefix');
$table = $this->request->request('table');
//从数据库中获取表字段信息
$sql = "SELECT * FROM `information_schema`.`columns` "
. "WHERE TABLE_SCHEMA = ? AND table_name = ? "
. "ORDER BY ORDINAL_POSITION";
//加载主表的列
$columnList = Db::query($sql, [$dbname, $table]);
$fieldlist = [];
foreach ($columnList as $index => $item) {
$fieldlist[] = $item['COLUMN_NAME'];
}
$this->success("", null, ['fieldlist' => $fieldlist]);
}
/**
* 获取控制器列表
* @internal
*/
public function get_controller_list()
{
//搜索关键词,客户端输入以空格分开,这里接收为数组
$word = (array)$this->request->request("q_word/a");
$word = implode('', $word);
$adminPath = dirname(__DIR__) . DS;
$controllerDir = $adminPath . 'controller' . DS;
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($controllerDir), \RecursiveIteratorIterator::LEAVES_ONLY
);
$list = [];
foreach ($files as $name => $file) {
if (!$file->isDir()) {
$filePath = $file->getRealPath();
$name = str_replace($controllerDir, '', $filePath);
$name = str_replace(DS, "/", $name);
if (!preg_match("/(.*)\.php\$/", $name)) {
continue;
}
if (!$word || stripos($name, $word) !== false) {
$list[] = ['id' => $name, 'name' => $name];
}
}
}
$pageNumber = $this->request->request("pageNumber");
$pageSize = $this->request->request("pageSize");
return json(['list' => array_slice($list, ($pageNumber - 1) * $pageSize, $pageSize), 'total' => count($list)]);
}
/**
* 详情
*/
public function detail($ids)
{
$row = $this->model->get($ids);
if (!$row) {
$this->error(__('No Results were found'));
}
$this->view->assign("row", $row);
return $this->view->fetch();
}
/**
* 执行
*/
public function execute($ids)
{
$row = $this->model->get($ids);
if (!$row) {
$this->error(__('No Results were found'));
}
$result = $this->doexecute($row['type'], json_decode($row['params'], true));
$this->success("", null, ['result' => $result]);
}
/**
* 执行命令
*/
public function command($action = '')
{
$commandtype = $this->request->request("commandtype");
$params = $this->request->request();
$allowfields = [
'crud' => 'table,controller,model,fields,force,local,delete,menu',
'menu' => 'controller,delete',
'min' => 'module,resource,optimize',
'api' => 'url,module,output,template,force,title,author,class,language',
];
$argv = [];
$allowfields = isset($allowfields[$commandtype]) ? explode(',', $allowfields[$commandtype]) : [];
$allowfields = array_filter(array_intersect_key($params, array_flip($allowfields)));
if (isset($params['local']) && !$params['local']) {
$allowfields['local'] = $params['local'];
} else {
unset($allowfields['local']);
}
foreach ($allowfields as $key => $param) {
$argv[] = "--{$key}=" . (is_array($param) ? implode(',', $param) : $param);
}
if ($commandtype == 'crud') {
$extend = 'setcheckboxsuffix,enumradiosuffix,imagefield,filefield,intdatesuffix,switchsuffix,citysuffix,selectpagesuffix,selectpagessuffix,ignorefields,sortfield,editorsuffix,headingfilterfield';
$extendArr = explode(',', $extend);
foreach ($params as $index => $item) {
if (in_array($index, $extendArr)) {
foreach (explode(',', $item) as $key => $value) {
if ($value) {
$argv[] = "--{$index}={$value}";
}
}
}
}
$isrelation = (int)$this->request->request('isrelation');
if ($isrelation && isset($params['relation'])) {
foreach ($params['relation'] as $index => $relation) {
foreach ($relation as $key => $value) {
$argv[] = "--{$key}=" . (is_array($value) ? implode(',', $value) : $value);
}
}
}
} else {
if ($commandtype == 'menu') {
if (isset($params['allcontroller']) && $params['allcontroller']) {
$argv[] = "--controller=all-controller";
} else {
foreach (explode(',', $params['controllerfile']) as $index => $param) {
if ($param) {
$argv[] = "--controller=" . substr($param, 0, -4);
}
}
}
} else {
if ($commandtype == 'min') {
} else {
if ($commandtype == 'api') {
} else {
}
}
}
}
if ($action == 'execute') {
$result = $this->doexecute($commandtype, $argv);
$this->success("", null, ['result' => $result]);
} else {
$this->success("", null, ['command' => "php think {$commandtype} " . implode(' ', $argv)]);
}
return;
}
protected function doexecute($commandtype, $argv)
{
$commandName = "\\app\\admin\\command\\" . ucfirst($commandtype);
$input = new Input($argv);
$output = new \addons\command\library\Output();
$command = new $commandName($commandtype);
$data = [
'type' => $commandtype,
'params' => json_encode($argv),
'command' => "php think {$commandtype} " . implode(' ', $argv),
'executetime' => time(),
];
$this->model->save($data);
try {
$command->run($input, $output);
$result = implode("\n", $output->getMessage());
$this->model->status = 'successed';
} catch (Exception $e) {
$result = implode("\n", $output->getMessage()) . "\n";
$result .= $e->getMessage();
$this->model->status = 'failured';
}
$result = trim($result);
$this->model->content = $result;
$this->model->save();
return $result;
}
}
... ...
<?php
namespace app\admin\controller;
use app\common\controller\Backend;
use think\Db;
use think\Config;
use think\Exception;
//use think\Config;
/**
* 自建表管理
*
* @icon fa fa-circle-o
*/
class Tablemake extends Backend {
/**
* Test模型对象
* @var \app\admin\model\Test
*/
protected $ModelOnline = null;
protected $ModelFields = null;
protected $searchFields = false;//关闭快捷搜索
protected $db_name = '';
protected $db_prefix = '';
public function _initialize() {
parent::_initialize();
$this->ModelOnline = model('TableMakeTables');
$this->ModelFields = model('TableMakeFields');
$dictionary_url = url("tablemake/dictionary", [], true, true);
$this->view->assign("dictionary_url", $dictionary_url);
}
/*
* 数据表列表
*/
public function index() {
$this->searchFields = "name,table,desc";
if ($this->request->isAjax()) {
$prefix = Config::get('database.prefix');
$this->model = $this->ModelOnline;
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$list = $this->model
->where($where)
->order($sort, $order)
->paginate($limit);
$result = array("total" => $list->total(), "rows" => $list->items(), "prefix" => $prefix);
return json($result);
}
return $this->view->fetch();
}
/*
* 创建数据表
*/
public function add() {
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
$params[$this->dataLimitField] = $this->auth->id;
}
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = str_replace("\\model\\", "\\validate\\", get_class($this->ModelOnline));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
$this->ModelOnline->validate($validate);
}
$params['createtime'] = time();
$params['updatetime'] = time();
$result = $this->ModelOnline->allowField(true)->save($params);
$prefix = Config::get('database.prefix');
if ($result !== false) {
//在此执行创建表的操作
$sql = "CREATE TABLE IF NOT EXISTS `{$prefix}" . $params['table'] . "` (
`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='" . $params['name'] . "';";
$res = \think\Db::execute($sql);
//var_export($res);
$this->success();
} else {
$this->error($this->ModelOnline->getError());
}
} catch (\think\exception\PDOException $e) {
$this->error($e->getMessage());
} catch (\think\Exception $e) {
$this->error($e->getMessage());
}
}
$this->error(__('Parameter %s can not be empty', ''));
}
$prefix = Config::get('database.prefix');
$this->view->assign("prefix", $prefix);
return $this->view->fetch();
}
/*
* 编辑数据表
*/
public function edit($ids = NULL) {
$row = $this->ModelOnline->get($ids);
if (!$row)
$this->error(__('No Results were found'));
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds)) {
if (!in_array($row[$this->dataLimitField], $adminIds)) {
$this->error(__('You have no permission'));
}
}
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = basename(str_replace('\\', '/', get_class($this->ModelOnline)));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : true) : $this->modelValidate;
$row->validate($validate);
}
$params['updatetime'] = time();
$result = $row->allowField(true)->save($params);
if ($result !== false) {
$prefix = Config::get('database.prefix');
$sql = "ALTER TABLE `{$prefix}" . $row['table'] . "` COMMENT='" . $row['name'] . "';";
$res = \think\Db::execute($sql);
$this->success();
} else {
$this->error($row->getError());
}
} catch (\think\exception\PDOException $e) {
$this->error($e->getMessage());
} catch (\think\Exception $e) {
$this->error($e->getMessage());
}
}
$this->error(__('Parameter %s can not be empty', ''));
}
$prefix = Config::get('database.prefix');
$this->view->assign("row", $row);
$this->view->assign("prefix", $prefix);
return $this->view->fetch();
}
/*
* 删除模块
*/
public function del($ids = NULL) {
if ($ids) {
$pk = $this->ModelOnline->getPk();
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds)) {
$count = $this->ModelOnline->where($this->dataLimitField, 'in', $adminIds);
}
$list = $this->ModelOnline->where($pk, 'in', $ids)->select();
$prefix = Config::get('database.prefix');
$count = 0;
foreach ($list as $k => $v) {
$sql = "DROP TABLE IF EXISTS `{$prefix}" . $v->table . "`;";
try {
$res = \think\Db::execute($sql);
$this->ModelFields->where("mid", '=', $v->id)->delete();
$count += $v->delete();
if ($count) {
$this->success(__('删除成功!'), null, __('删除成功!'));
} else {
$this->error(__('No rows were deleted'));
}
} catch (Exception $ex) {
$this->error(__('No rows were deleted'));
}
}
}
$this->error(__('Parameter %s can not be empty', 'ids'));
}
/*
* 验证重名
*/
public function check($table = null, $name = null) {
if ($table == null && $name == null) {
if ($this->request->isAjax()) {
$table = $this->request->request('table');
$name = $this->request->request('name');
}
}
if ($table && $name) {
$sql = "describe `{$table}` `{$name}`";
$res = \think\Db::query($sql);
if ($res) {
return true;
} else {
return false;
}
} else {
return false;
}
}
/*
* 字段列表
*/
public function fields($ids = NULL) {
$this->searchFields = "name,title,comment";
if ($ids == NULL) {
$ids = intval($this->request->request('ids'));
}
$model = $this->ModelOnline->get($ids);
if (!$model) {
$this->error(__('No Results were found'));
}
if ($this->request->isAjax()) {
$prefix = Config::get('database.prefix');
$this->model = $this->ModelFields;
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$list = $this->model
->where("mid", '=', $ids)
->where($where)
->order($sort, $order)
->paginate($limit);
$result = array("total" => $list->total(), "rows" => $list->items(), "prefix" => $prefix);
return json($result);
// $list = $this->ModelFields->where("mid", '=', $ids)->order('id desc')->select();
// $total = count($list);
// $prefix = Config::get('database.prefix');
// $result = array("total" => $total, "rows" => $list, "prefix" => $prefix);
// return json($result);
}
$this->view->assign("ids", $ids);
return $this->view->fetch();
}
/*
* 添加字段
*/
public function field_add($mid = NULL) {
$mod_table = $this->ModelOnline->get($mid);
if (!$mod_table)
$this->error(__('No Results were found'));
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = str_replace("\\model\\", "\\validate\\", get_class($this->ModelFields));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
$this->ModelFields->validate($validate);
}
$prefix = Config::get('database.prefix');
$field = array();
$fieldData = array();
switch ($params['category']) {
case "1":
$allow = array(
"text" => array("suffix" => "text", "type" => "varchar", "length" => 200),
"number" => array("suffix" => "number", "type" => "bigint", "length" => 11),
"time" => array("suffix" => "time", "type" => "bigint", "length" => 11),
"image" => array("suffix" => "image", "type" => "varchar", "length" => 255),
"images" => array("suffix" => "images", "type" => "varchar", "length" => 2000),
"file" => array("suffix" => "file", "type" => "varchar", "length" => 255),
"files" => array("suffix" => "files", "type" => "varchar", "length" => 2000),
"avatar" => array("suffix" => "avatar", "type" => "varchar", "length" => 255),
"avatars" => array("suffix" => "avatars", "type" => "varchar", "length" => 2000),
"content" => array("suffix" => "content", "type" => "text", "length" => 0),
"_id" => array("suffix" => "_id", "type" => "bigint", "length" => 11),
"_ids" => array("suffix" => "_ids", "type" => "varchar", "length" => 255),
"list-enum" => array("suffix" => "list", "type" => "enum", "length" => 0),
"list-set" => array("suffix" => "list", "type" => "set", "length" => 0),
"data-enum" => array("suffix" => "data", "type" => "enum", "length" => 0),
"data-set" => array("suffix" => "data", "type" => "set", "length" => 0),
"json" => array("suffix" => "json", "type" => "varchar", "length" => 2000),
"switch" => array("suffix" => "switch", "type" => "tinyint", "length" => 1),
);
if (isset($allow[$params['suffix']]) && is_array($allow[$params['suffix']])) {
$fieldData['special'] = "";
$fieldData['suffix'] = $params['suffix'];
//$field['name'] = $params['name'] . $allow[$params['suffix']]['suffix']; //字段名
$field['name'] = $params['name']; //字段名
$field['field'] = $params['name'] . $allow[$params['suffix']]['suffix']; //字段名
$field['length'] = $field['length2'] = isset($params['length']) && intval($params['length']) ? intval($params['length']) : $allow[$params['suffix']]['length']; //字段长度
$field['type'] = $allow[$params['suffix']]['type']; //字段类型
$field['default'] = isset($params['default']) ? $params['default'] : ""; //默认值
if ($allow[$params['suffix']]['type'] == "enum" || $allow[$params['suffix']]['type'] == "set") {
$comment = \GuzzleHttp\json_decode($params['comment'], true);
$field['comment'] = $params['title'] . ":"; //备注
$field['length2'] = "";
$str = "";
$default_optional = array();
foreach ($comment as $k => $v) {
$default_optional[] = $k;
$field['comment'] .= $str . $k . "=" . $v;
$field['length2'] .= $str . "'" . $k . "'";
$str = ",";
}
if (!in_array($field['default'], $default_optional)) {
$field['default'] = $default_optional[0];
}
} else {
$params['comment'] = "";
$field['comment'] = $params['title']; //备注
}
} else {
$this->error(__('特殊字段类型不正确!'));
}
break;
case "2":
$allow = array(
"varchar" => array("type" => "varchar", "length" => 255),
"int" => array("type" => "bigint", "length" => 11),
"enum" => array("type" => "enum", "length" => 0),
"set" => array("type" => "set", "length" => 0),
"float" => array("type" => "float", "length" => "10,2"),
"text" => array("type" => "text", "length" => 0),
"datetime" => array("type" => "datetime", "length" => 11),
"date" => array("type" => "date", "length" => 11),
"year" => array("type" => "year", "length" => 4),
"timestamp" => array("type" => "timestamp", "length" => 11),
);
if (isset($allow[$params['type']]) && is_array($allow[$params['type']])) {
$fieldData['special'] = "";
$fieldData['suffix'] = "";
$params['suffix'] = "";
$field['name'] = $params['name']; //字段名
$field['field'] = $params['name']; //字段名
if ($params['type'] == "float") {
$field['length'] = $field['length2'] = isset($params['length']) && $params['length'] ? $params['length'] : $allow[$params['type']]['length']; //字段长度
} else {
$field['length'] = $field['length2'] = isset($params['length']) && intval($params['length']) ? intval($params['length']) : $allow[$params['type']]['length']; //字段长度
}
$field['type'] = $allow[$params['type']]['type']; //字段类型
$field['default'] = isset($params['default']) ? $params['default'] : ""; //默认值
if ($allow[$params['type']]['type'] == "enum" || $allow[$params['type']]['type'] == "set") {
$comment = \GuzzleHttp\json_decode($params['comment'], true);
$field['comment'] = $params['title'] . ":"; //备注
$field['length2'] = "";
$str = "";
$default_optional = array();
foreach ($comment as $k => $v) {
$default_optional[] = $k;
$field['comment'] .= $str . $k . "=" . $v;
$field['length2'] .= $str . "'" . $k . "'";
$str = ",";
}
if (!in_array($field['default'], $default_optional)) {
$field['default'] = $default_optional[0];
}
} else {
$params['comment'] = "";
$field['comment'] = $params['title']; //备注
}
} else {
$this->error(__('特殊字段类型不正确!'));
}
break;
case "3":
$allow = array(
"user_id" => array("title" => "会员ID(单选)", "type" => "bigint", "length" => 11),
"category_id" => array("title" => "分类ID(单选)", "type" => "bigint", "length" => 11),
"category_ids" => array("title" => "分类ID(多选)", "type" => "varchar", "length" => 200),
"weigh" => array("title" => "权重", "type" => "bigint", "length" => 11),
"status" => array("title" => "状态", "type" => "enum", "length" => 0),
"createtime" => array("title" => "创建时间", "type" => "bigint", "length" => 11),
"updatetime" => array("title" => "更新时间", "type" => "bigint", "length" => 11),
"deletetime" => array("title" => "删除时间", "type" => "bigint", "length" => 11),
);
if (isset($allow[$params['special']]) && is_array($allow[$params['special']])) {
$fieldData['special'] = $params['special'];
$fieldData['suffix'] = "";
//$params['title'] = $allow[$params['special']]['title'];
// $params['comment'] = $params['suffix'] = "";
$field['name'] = $params['special']; //字段名
$field['field'] = $params['special']; //字段名
$field['length'] = $field['length2'] = $allow[$params['special']]['length']; //字段长度
// $field['comment'] = $params['title']; //备注
$field['type'] = $allow[$params['special']]['type']; //字段类型
$field['default'] = $field['type'] == "varchar" ? "" : "0"; //默认值
if ($params['special'] == "status") {
$comment = \GuzzleHttp\json_decode($params['comment'], true);
$field['comment'] = $params['title'] . ":"; //备注
$field['length2'] = "";
$str = "";
$default_optional = array();
foreach ($comment as $k => $v) {
$default_optional[] = $k;
$field['comment'] .= $str . $k . "=" . $v;
$field['length2'] .= $str . "'" . $k . "'";
$str = ",";
}
if (!in_array($field['default'], $default_optional)) {
$field['default'] = $default_optional[0];
}
} else {
$params['comment'] = "";
$field['comment'] = $params['title']; //备注
}
} else {
$this->error(__('特殊字段类型不正确!'));
}
break;
default :
$this->error(__('No Results were found'));
break;
}
if ($this->check($prefix . $mod_table['table'], $field['name'])) {
$this->error(__('字段已经存在!'));
}
$fieldData['mid'] = $params['mid'];
$fieldData['category'] = $params['category'];
$fieldData['title'] = $params['title'];
$fieldData['name'] = $field['name'];
$fieldData['field'] = $field['field'];
$fieldData['type'] = $field['type'];
$fieldData['length'] = $field['length'];
$fieldData['default'] = $field['default'];
$fieldData['comment'] = $field['comment'];
$fieldData['desc'] = $params['desc'];
$fieldData['createtime'] = time();
$fieldData['updatetime'] = time();
if ($fieldData['type'] == "text") {
$fieldData['default'] = "";
}
if ($field['type'] == "bigint" || $field['type'] == "int") {
$field['default'] = intval($field['default']);
} elseif ($field['type'] == "tinyint") {
$field['default'] = in_array($field['default'], [0, 1]) ? $field['default'] : 0;
} elseif ($field['type'] == "float") {
$field['default'] = is_float($field['default']) ? $field['default'] : 0;
}
\think\Db::startTrans();
try {
$result = $this->ModelFields->allowField(true)->save($fieldData);
if ($result !== false) {
//在此执行添加字段的操作
if (in_array($field['type'], ["text", "datetime", "date", "year", "timestamp"])) {
$sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` ADD COLUMN `{$field['field']}` {$field['type']} NOT NULL COMMENT '{$field['comment']}';";
} else {
$sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` ADD COLUMN `{$field['field']}` {$field['type']}({$field['length2']}) NOT NULL DEFAULT '{$field['default']}' COMMENT '{$field['comment']}';";
}
try {
$res = \think\Db::execute($sql);
} catch (Exception $ex) {
new Exception('参数错误,请检查字段名,字段长度或者默认值等输入参数是否合法');
}
} else {
new Exception($this->ModelFields->getError());
}
\think\Db::commit();
} catch (Exception $e) {
\think\Db::rollback();
$this->error($e->getMessage());
}
$this->success();
} catch (\think\exception\PDOException $e) {
$this->error($e->getMessage());
} catch (\think\Exception $e) {
$this->error($e->getMessage());
}
}
$this->error(__('Parameter %s can not be empty', ''));
}
$prefix = Config::get('database.prefix');
$this->view->assign("prefix", $prefix);
$this->view->assign("mid", $mid);
return $this->view->fetch();
}
/*
* 修改字段
*/
public function field_edit($ids = NULL) {
//$oldField_info = $this->ModelFields->get($ids);
$field_info = $this->ModelFields->get($ids);
$oldField_info = $field_info->toArray();
//var_dump($field_info);
if (!$field_info)
$this->error(__('No Results were found'));
$mod_table = $this->ModelOnline->get($field_info['mid']);
if (!$mod_table)
$this->error(__('No Results were found'));
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = str_replace("\\model\\", "\\validate\\", get_class($this->ModelFields));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : true) : $this->modelValidate;
$this->ModelFields->validate($validate);
}
$prefix = Config::get('database.prefix');
$field = array();
$fieldData = array();
switch ($field_info['category']) {
case "1":
$allow = array(
"text" => array("suffix" => "text", "type" => "varchar", "length" => 200),
"number" => array("suffix" => "number", "type" => "bigint", "length" => 11),
"time" => array("suffix" => "time", "type" => "bigint", "length" => 11),
"image" => array("suffix" => "image", "type" => "varchar", "length" => 255),
"images" => array("suffix" => "images", "type" => "varchar", "length" => 2000),
"file" => array("suffix" => "file", "type" => "varchar", "length" => 255),
"files" => array("suffix" => "files", "type" => "varchar", "length" => 2000),
"avatar" => array("suffix" => "avatar", "type" => "varchar", "length" => 255),
"avatars" => array("suffix" => "avatars", "type" => "varchar", "length" => 2000),
"content" => array("suffix" => "content", "type" => "text", "length" => 0),
"_id" => array("suffix" => "_id", "type" => "bigint", "length" => 11),
"_ids" => array("suffix" => "_ids", "type" => "varchar", "length" => 255),
"list-enum" => array("suffix" => "list", "type" => "enum", "length" => 0),
"list-set" => array("suffix" => "list", "type" => "set", "length" => 0),
"data-enum" => array("suffix" => "data", "type" => "enum", "length" => 0),
"data-set" => array("suffix" => "data", "type" => "set", "length" => 0),
"json" => array("suffix" => "json", "type" => "varchar", "length" => 2000),
"switch" => array("suffix" => "switch", "type" => "tinyint", "length" => 1),
);
if (isset($allow[$params['suffix']]) && is_array($allow[$params['suffix']])) {
$fieldData['special'] = "";
$fieldData['suffix'] = $params['suffix'];
$field['name'] = $params['name']; //字段名
$field['field'] = $params['name'] . $allow[$params['suffix']]['suffix']; //字段名
$field['length'] = $field['length2'] = isset($params['length']) && intval($params['length']) ? intval($params['length']) : $allow[$params['suffix']]['length']; //字段长度
$field['type'] = $allow[$params['suffix']]['type']; //字段类型
$field['default'] = isset($params['default']) ? $params['default'] : ""; //默认值
if ($allow[$params['suffix']]['type'] == "enum" || $allow[$params['suffix']]['type'] == "set") {
$comment = \GuzzleHttp\json_decode($params['comment'], true);
$field['comment'] = $params['title'] . ":"; //备注
$field['length2'] = "";
$str = "";
$default_optional = array();
foreach ($comment as $k => $v) {
$default_optional[] = $k;
$field['comment'] .= $str . $k . "=" . $v;
$field['length2'] .= $str . "'" . $k . "'";
$str = ",";
}
if (!in_array($field['default'], $default_optional)) {
$field['default'] = $default_optional[0];
}
} else {
$params['comment'] = "";
$field['comment'] = $params['title']; //备注
}
} else {
$this->error(__('特殊字段类型不正确!'));
}
break;
case "2":
$allow = array(
"varchar" => array("type" => "varchar", "length" => 255),
"int" => array("type" => "bigint", "length" => 11),
"enum" => array("type" => "enum", "length" => 0),
"set" => array("type" => "set", "length" => 0),
"float" => array("type" => "float", "length" => "10,2"),
"text" => array("type" => "text", "length" => 0),
"datetime" => array("type" => "datetime", "length" => 11),
"date" => array("type" => "date", "length" => 11),
"year" => array("type" => "year", "length" => 4),
"timestamp" => array("type" => "timestamp", "length" => 11),
);
if (isset($allow[$params['type']]) && is_array($allow[$params['type']])) {
$fieldData['special'] = "";
$fieldData['suffix'] = "";
$params['suffix'] = "";
$field['name'] = $params['name']; //字段名
$field['field'] = $params['name']; //字段名
if ($params['type'] == "float") {
$field['length'] = $field['length2'] = isset($params['length']) && $params['length'] ? $params['length'] : $allow[$params['type']]['length']; //字段长度
} else {
$field['length'] = $field['length2'] = isset($params['length']) && intval($params['length']) ? intval($params['length']) : $allow[$params['type']]['length']; //字段长度
}
$field['type'] = $allow[$params['type']]['type']; //字段类型
$field['default'] = isset($params['default']) ? $params['default'] : ""; //默认值
if ($allow[$params['type']]['type'] == "enum" || $allow[$params['type']]['type'] == "set") {
$comment = \GuzzleHttp\json_decode($params['comment'], true);
$field['comment'] = $params['title'] . ":"; //备注
$field['length2'] = "";
$str = "";
$default_optional = array();
foreach ($comment as $k => $v) {
$default_optional[] = $k;
$field['comment'] .= $str . $k . "=" . $v;
$field['length2'] .= $str . "'" . $k . "'";
$str = ",";
}
if (!in_array($field['default'], $default_optional)) {
$field['default'] = $default_optional[0];
}
} else {
$params['comment'] = "";
$field['comment'] = $params['title']; //备注
}
} else {
$this->error(__('特殊字段类型不正确!'));
}
break;
case "3":
$allow = array(
"user_id" => array("title" => "会员ID(单选)", "type" => "bigint", "length" => 11),
"category_id" => array("title" => "分类ID(单选)", "type" => "bigint", "length" => 11),
"category_ids" => array("title" => "分类ID(多选)", "type" => "varchar", "length" => 200),
"weigh" => array("title" => "权重", "type" => "bigint", "length" => 11),
"status" => array("title" => "状态", "type" => "enum", "length" => 0),
"createtime" => array("title" => "创建时间", "type" => "bigint", "length" => 11),
"updatetime" => array("title" => "更新时间", "type" => "bigint", "length" => 11),
"deletetime" => array("title" => "删除时间", "type" => "bigint", "length" => 11),
);
if (isset($allow[$params['special']]) && is_array($allow[$params['special']])) {
$fieldData['special'] = $params['special'];
$fieldData['suffix'] = "";
// $params['title'] = $allow[$params['special']]['title'];
// if ($params['special'] != "status") {
// $params['comment'] = "";
// }
// $params['comment'] =
$params['suffix'] = "";
$field['name'] = $params['special']; //字段名
$field['field'] = $params['special']; //字段名
$field['length'] = $field['length2'] = $allow[$params['special']]['length']; //字段长度
// $field['comment'] = $params['title']; //备注
$field['type'] = $allow[$params['special']]['type']; //字段类型
$field['default'] = $field['type'] == "varchar" ? "" : "0"; //默认值
if ($params['special'] == "status") {
$comment = \GuzzleHttp\json_decode($params['comment'], true);
$field['comment'] = $params['title'] . ":"; //备注
$field['length2'] = "";
$str = "";
$default_optional = array();
foreach ($comment as $k => $v) {
$default_optional[] = $k;
$field['comment'] .= $str . $k . "=" . $v;
$field['length2'] .= $str . "'" . $k . "'";
$str = ",";
}
if (!in_array($field['default'], $default_optional)) {
$field['default'] = $default_optional[0];
}
} else {
$params['comment'] = "";
$field['comment'] = $params['title']; //备注
}
} else {
$this->error(__('特殊字段类型不正确!'));
}
break;
default :
$this->error(__('No Results were found'));
break;
}
/*
if ($this->check($prefix . $mod_table['table'], $field['name'])) {
$this->error(__('字段已经存在!'));
} */
$fieldData['mid'] = $params['mid'];
//$fieldData['category'] = $params['category'];
$fieldData['title'] = $params['title'];
$fieldData['name'] = $field['name'];
$fieldData['field'] = $field['field'];
$fieldData['type'] = $field['type'];
$fieldData['length'] = $field['length'];
$fieldData['default'] = $field['default'];
$fieldData['comment'] = $field['comment'];
$fieldData['desc'] = $params['desc'];
$fieldData['updatetime'] = time();
if ($fieldData['type'] == "text") {
$fieldData['default'] = "";
}
if ($field['type'] == "bigint" || $field['type'] == "int") {
$field['default'] = intval($field['default']);
} elseif ($field['type'] == "tinyint") {
$field['default'] = in_array($field['default'], [0, 1]) ? $field['default'] : 0;
} elseif ($field['type'] == "float") {
$field['default'] = is_float($field['default']) ? $field['default'] : 0;
}
\think\Db::startTrans();
try {
$result = $field_info->save($fieldData);
if ($result !== false) {
//在此执行添加字段的操作
if (in_array($field['type'], ["text", "datetime", "date", "year", "timestamp"])) {
$sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` CHANGE COLUMN `{$oldField_info['field']}` `{$field['field']}` {$field['type']} NOT NULL COMMENT '{$field['comment']}' ;";
} else {
$sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` CHANGE COLUMN `{$oldField_info['field']}` `{$field['field']}` {$field['type']}({$field['length2']}) NOT NULL DEFAULT '{$field['default']}' COMMENT '{$field['comment']}' ;";
}
try {
$res = \think\Db::execute($sql);
} catch (Exception $ex) {
// $field_info->save($oldField_info);
throw new Exception('参数错误,请检查字段名,字段长度或者默认值等输入参数是否合法');
}
} else {
throw new Exception($this->ModelFields->getError());
}
\think\Db::commit();
} catch (Exception $e) {
\think\Db::rollback();
$this->error($e->getMessage());
}
$this->success();
} catch (\think\exception\PDOException $e) {
$field_info->save($oldField_info);
$this->error($e->getMessage());
} catch (\think\Exception $e) {
$field_info->save($oldField_info);
$this->error($e->getMessage());
}
}
$this->error(__('Parameter %s can not be empty', ''));
}
$comment = "";
if ($field_info['type'] == "enum" || $field_info['type'] == "set") {
//echo $field_info['comment'];
$commentStr = substr($field_info['comment'], strpos($field_info['comment'], ":") + 1);
$commentArr = [];
foreach (explode(",", $commentStr) as $k => $v) {
list($key, $val) = explode("=", $v);
$commentArr[$key] = $val;
}
$comment = \json_encode($commentArr);
}
$prefix = Config::get('database.prefix');
$this->view->assign("field_info", $field_info);
$this->view->assign("row", $field_info);
$this->view->assign("prefix", $prefix);
$this->view->assign("comment", $comment);
$this->view->assign("mid", $field_info['mid']);
return $this->view->fetch();
}
public function field_del($ids = NULL) {
if ($ids) {
$pk = $this->ModelFields->getPk();
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds)) {
$count = $this->ModelFields->where($this->dataLimitField, 'in', $adminIds);
}
$list = $this->ModelFields->where($pk, 'in', $ids)->select();
$prefix = Config::get('database.prefix');
$count = 0;
foreach ($list as $k => $v) {
$mod_table = $this->ModelOnline->get($v['mid']);
$sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` DROP `{$v['field']}` ";
try {
$res = \think\Db::execute($sql);
$count += $v->delete();
if ($count) {
$this->success();
} else {
$this->error(__('No rows were deleted'));
}
} catch (Exception $ex) {
$this->error(__('No rows were deleted'));
}
}
}
$this->error(__('Parameter %s can not be empty', 'ids'));
}
public function dictionary() {
$this->db_name = \config("database.database");
$this->db_prefix = \config("database.prefix");
$this->view->assign('db_name', $this->db_name);
$this->view->assign('db_prefix', $this->db_prefix);
$dictionary = [
'make' => [],
'system' => [],
'other' => [],
];
//读取所有表
$tables_res = Db::table("information_schema.TABLES")->field("TABLE_NAME")->where(['TABLE_SCHEMA' => $this->db_name,])->select();
$tables_all = array_column($tables_res, 'TABLE_NAME');
//已经获取到数据字典的表
$tables_isset = [];
//声明系统表 获取系统表的数据字典
$tables_system = ['admin', 'admin_log', 'attachment', 'area', 'auth_group', 'auth_group_access', 'auth_rule', 'category', 'config', 'ems', 'sms', 'user', 'user_group', 'user_money_log', 'user_rule', 'user_score_log', 'user_token', 'version'];
foreach ($tables_system as $k => $v) {
$table_name = $this->db_prefix . $v;
$dictionary['system'][] = $this->getSystemTableInfo($table_name);
$tables_isset[] = $table_name;
}
//读取自建表 获取自建表数据字典
$tables_make = \app\admin\model\TableMakeTables::all(function ($query) {
$query->order("weigh desc,id desc");
});
foreach ($tables_make as $k => $v) {
$table_name = $this->db_prefix . $v['table'];
$dictionary['make'][] = $this->getMakeTableInfo($table_name, $v);
$tables_isset[] = $table_name;
}
//获取其他表数据字典 求差集,计算出其他表
$tables_other = array_diff($tables_all, $tables_isset);
foreach ($tables_other as $k => $v) {
$table_name = $v;
$dictionary['other'][] = $this->getOtherTableInfo($table_name);
$tables_isset[] = $table_name;
}
$this->view->assign('dictionary', $dictionary);
$this->view->engine->layout(false);
return $this->view->fetch();
}
/**
* 根据表名获取系统表的数据字典数据
* @param $table_name 表名
* @return array
*/
protected function getSystemTableInfo($table_name) {
return $this->getOtherTableInfo($table_name);
}
/**
* 根据表名获取非自建表的数据字典信息
* @param $table_name
* @return array
*/
protected function getOtherTableInfo($table_name) {
$table_info = $this->getTableInfo($table_name);
$result = [
'name' => $table_info['table_info']['TABLE_COMMENT'] ? $table_info['table_info']['TABLE_COMMENT'] : $table_name,
'table' => preg_replace('/^(' . $this->db_prefix . ').*?/is', '', $table_name),//表名去前缀
'table_name' => $table_name,
'desc' => $table_info['table_info']['TABLE_COMMENT'],
'engine' => $table_info['table_info']['ENGINE'],
'table_comment' => $table_info['table_info']['TABLE_COMMENT'],
'table_collation' => $table_info['table_info']['TABLE_COLLATION'],
'create_time' => $table_info['table_info']['CREATE_TIME'],
'update_time' => $table_info['table_info']['UPDATE_TIME'],
'fields' => $this->getTableFields($table_info['table_fields']),
];
return $result;
}
/**
* 根据表名、自建表信息数据,获取自建表的数据字典信息
* @param $table_name 表名
* @param $table
* @return array
* @throws \think\exception\DbException
*/
protected function getMakeTableInfo($table_name, $table) {
$model_fields = \app\admin\model\TableMakeFields::all(function ($query) use ($table) {
$query->where(['mid' => $table['id']]);
$query->order("weigh desc,id desc");
});
$result = $this->getOtherTableInfo($table_name);
$result['name'] = $table['name'];
$result['table'] = $table['table'];
$result['desc'] = $table['desc'];
$result['create_time'] = date("Y-m-d H:i:s", $table['createtime']);
$result['update_time'] = date("Y-m-d H:i:s", $table['updatetime']);
$result['fields'] = $this->getTableFieldsByMake($result['fields'], $model_fields);
return $result;
}
/**
* 结合表的字段备注 自建表存储的信息,生成自建表的字段数据字典
* @param $fields
* @param array $make_fields
* @return array
*/
protected function getTableFieldsByMake($fields, $make_fields = []) {
$result = [];
$field_list = [];
foreach ($fields as $k => $v) {
$field_list[$v['field_name']] = $v;
}
$result[] = $field_list['id'];
foreach ($make_fields as $k => $v) {
$result[] = [
"field_title" => $v['title'],
"field_name" => $v['field'],
"character" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['character'] : NULL,
"field_collation" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['field_collation'] : NULL,
"data_type" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['data_type'] : NULL,//字段类型
"column_type" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['column_type'] : NULL,//列类型
"is_nullable" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['is_nullable'] : NULL,//是否能为空
"length" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['length'] : NULL,//字符串长度
"column_comment" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['column_comment'] : NULL,//字段备注
"default" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['default'] : NULL,//字段默认值
"desc" => $v['desc'],
];
}
return $result;
}
/**
* 根据表的字段备注,生成字段数据字典
* @param $fields
* @return array
*/
protected function getTableFields($fields) {
$result = [];
foreach ($fields as $k => $v) {
$column_type = preg_replace('/(unsigned).*?/is', '(无符号)', $v['COLUMN_TYPE']);
list($field_name) = explode(":", $v['COLUMN_COMMENT']);
$result[] = [
"field_title" => $field_name ? $field_name : $v['COLUMN_NAME'],
"field_name" => $v['COLUMN_NAME'],
"character" => $v['CHARACTER_SET_NAME'],
"field_collation" => $v['COLLATION_NAME'],
"data_type" => $v['DATA_TYPE'],//字段类型
"column_type" => $column_type,//列类型
"is_nullable" => $v['IS_NULLABLE'],//是否能为空
"length" => $v['CHARACTER_MAXIMUM_LENGTH'],//字符串长度
"column_comment" => $v['COLUMN_COMMENT'],//字段备注
"default" => $v['COLUMN_DEFAULT'],//字段默认值
"desc" => "",//字段默认值
];
}
return $result;
}
/**
* 获取指定表的基本信息
* @param $table_name
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
protected function getTableInfo($table_name) {
// //读取表信息
// $sql = "SELECT * FROM information_schema.TABLES WHERE table_schema = '{$db_name}' and TABLE_NAME='{$table_name}'";
// $res = Db::query($sql);
// //读取表结构
// $sql = "SELECT * FROM information_schema.COLUMNS where table_schema ='{$db_name}' and TABLE_NAME = '{$table_name}'";
// $res = Db::query($sql);
//读取表信息
$table_info = Db::table("information_schema.TABLES")->field("*")->where(['TABLE_SCHEMA' => $this->db_name, 'TABLE_NAME' => $table_name])->find();
//读取表结构
$table_fields = Db::table("information_schema.COLUMNS")->field("*")->where(['TABLE_SCHEMA' => $this->db_name, 'TABLE_NAME' => $table_name])->select();
return [
'table_info' => $table_info,
'table_fields' => $table_fields,
];
}
}
... ...
<?php
namespace app\admin\controller;
use app\common\controller\Backend;
/**
* 第三方登录管理
*
* @icon fa fa-circle-o
*/
class Third extends Backend
{
/**
* Third模型对象
* @var \app\admin\model\Third
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\Third;
}
/**
* 查看
*/
public function index()
{
$this->relationSearch = true;
//设置过滤方法
$this->request->filter(['strip_tags']);
if ($this->request->isAjax()) {
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField')) {
return $this->selectpage();
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->with(['user'])
->where($where)
->order($sort, $order)
->count();
$list = $this->model
->with(['user'])
->where($where)
->order($sort, $order)
->limit($offset, $limit)
->select();
foreach ($list as $index => $item) {
if ($item->user) {
$item->user->visible(['nickname']);
}
}
$list = collection($list)->toArray();
$result = array("total" => $total, "rows" => $list);
return json($result);
}
return $this->view->fetch();
}
}
... ...
<?php
namespace app\admin\controller\wechat;
use app\common\controller\Backend;
use app\admin\model\WechatResponse;
/**
* 微信自动回复管理
*
* @icon fa fa-circle-o
*/
class Autoreply extends Backend
{
protected $model = null;
protected $noNeedRight = ['check_text_unique'];
public function _initialize()
{
parent::_initialize();
$this->model = model('WechatAutoreply');
}
/**
* 编辑
*/
public function edit($ids = null)
{
$row = $this->model->get(['id' => $ids]);
if (!$row) {
$this->error(__('No Results were found'));
}
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
$row->save($params);
$this->success();
}
$this->error();
}
$response = WechatResponse::get(['eventkey' => $row['eventkey']]);
$this->view->assign("response", $response);
$this->view->assign("row", $row);
return $this->view->fetch();
}
/**
* 判断文本是否唯一
* @internal
*/
public function check_text_unique()
{
$row = $this->request->post("row/a");
$except = $this->request->post("except");
$text = isset($row['text']) ? $row['text'] : '';
if ($this->model->where('text', $text)->where(function ($query) use ($except) {
if ($except) {
$query->where('text', '<>', $except);
}
})->count() == 0) {
$this->success();
} else {
$this->error(__('Text already exists'));
}
}
}
... ...
<?php
namespace app\admin\controller\wechat;
use app\common\controller\Backend;
use think\Controller;
use think\Request;
/**
* 微信配置管理
*
* @icon fa fa-circle-o
*/
class Config extends Backend
{
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = model('WechatConfig');
}
/**
* 添加
*/
public function add()
{
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
foreach ($params as $k => &$v) {
$v = is_array($v) ? implode(',', $v) : $v;
}
if ($params['mode'] == 'json') {
//JSON字段
$fieldarr = $valuearr = [];
$field = $this->request->post('field/a');
$value = $this->request->post('value/a');
foreach ($field as $k => $v) {
if ($v != '') {
$fieldarr[] = $field[$k];
$valuearr[] = $value[$k];
}
}
$params['value'] = json_encode(array_combine($fieldarr, $valuearr), JSON_UNESCAPED_UNICODE);
}
unset($params['mode']);
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = basename(str_replace('\\', '/', get_class($this->model)));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
$this->model->validate($validate);
}
$result = $this->model->save($params);
if ($result !== false) {
$this->success();
} else {
$this->error($this->model->getError());
}
} catch (\think\exception\PDOException $e) {
$this->error($e->getMessage());
}
}
$this->error(__('Parameter %s can not be empty', ''));
}
return $this->view->fetch();
}
/**
* 编辑
*/
public function edit($ids = null)
{
$row = $this->model->get($ids);
if (!$row) {
$this->error(__('No Results were found'));
}
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
foreach ($params as $k => &$v) {
$v = is_array($v) ? implode(',', $v) : $v;
}
if ($params['mode'] == 'json') {
//JSON字段
$fieldarr = $valuearr = [];
$field = $this->request->post('field/a');
$value = $this->request->post('value/a');
foreach ($field as $k => $v) {
if ($v != '') {
$fieldarr[] = $field[$k];
$valuearr[] = $value[$k];
}
}
$params['value'] = json_encode(array_combine($fieldarr, $valuearr), JSON_UNESCAPED_UNICODE);
}
unset($params['mode']);
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = basename(str_replace('\\', '/', get_class($this->model)));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
$row->validate($validate);
}
$result = $row->save($params);
if ($result !== false) {
$this->success();
} else {
$this->error($row->getError());
}
} catch (\think\exception\PDOException $e) {
$this->error($e->getMessage());
}
}
$this->error(__('Parameter %s can not be empty', ''));
}
$this->view->assign("row", $row);
$this->view->assign("value", (array)json_decode($row->value, true));
return $this->view->fetch();
}
}
... ...
<?php
namespace app\admin\controller\wechat;
use addons\wechat\library\Config;
use app\common\controller\Backend;
use app\admin\model\WechatResponse;
use EasyWeChat\Factory;
use think\Exception;
/**
* 菜单管理
*
* @icon fa fa-list-alt
*/
class Menu extends Backend
{
protected $wechatcfg = null;
public function _initialize()
{
parent::_initialize();
$this->wechatcfg = \app\admin\model\WechatConfig::get(['name' => 'menu']);
}
/**
* 查看
*/
public function index()
{
$responselist = array();
$all = WechatResponse::all();
foreach ($all as $k => $v) {
$responselist[$v['eventkey']] = $v['title'];
}
$this->view->assign('responselist', $responselist);
$this->view->assign('menu', (array)json_decode($this->wechatcfg->value, true));
return $this->view->fetch();
}
/**
* 修改
*/
public function edit($ids = null)
{
$menu = $this->request->post("menu");
$menu = (array)json_decode($menu, true);
foreach ($menu as $index => &$item) {
if (isset($item['sub_button'])) {
foreach ($item['sub_button'] as &$subitem) {
if ($subitem['type'] == 'view') {
$allowFields = ['type', 'name', 'url'];
$subitem = ['type' => $subitem['type'], 'name' => $subitem['name'], 'url' => $subitem['url']];
} else {
if ($subitem['type'] == 'miniprogram') {
$allowFields = ['type', 'name', 'url', 'appid', 'pagepath'];
$subitem = ['type' => $subitem['type'], 'name' => $subitem['name'], 'url' => $subitem['url'], 'appid' => $subitem['appid'], 'pagepath' => $subitem['pagepath']];
} else {
$allowFields = ['type', 'name', 'key'];
$subitem = ['type' => $subitem['type'], 'name' => $subitem['name'], 'key' => $subitem['key']];
}
}
$subitem = array_intersect_key($subitem, array_flip($allowFields));
}
} else {
if ($item['type'] == 'view') {
$allowFields = ['type', 'name', 'url'];
} else {
if ($item['type'] == 'miniprogram') {
$allowFields = ['type', 'name', 'url', 'appid', 'pagepath'];
} else {
$allowFields = ['type', 'name', 'key'];
}
}
$item = array_intersect_key($item, array_flip($allowFields));
}
}
$this->wechatcfg->value = json_encode($menu, JSON_UNESCAPED_UNICODE);
$this->wechatcfg->save();
$this->success();
}
/**
* 加载远程菜单
*/
public function remote()
{
$app = Factory::officialAccount(Config::load());
try {
$list = $app->menu->list();
} catch (\Exception $e) {
$this->error($e->getMessage());
}
if (isset($list['menu']['button'])) {
$buttons = $list['menu']['button'];
foreach ($buttons as $index => &$item) {
if (isset($item['sub_button'])) {
if ($item['sub_button']) {
foreach ($item['sub_button'] as $key => &$value) {
if (!isset($value['sub_button']) || !$value['sub_button']) {
unset($value['sub_button']);
}
}
} else {
unset($item['sub_button']);
}
}
}
$this->wechatcfg->value = json_encode($buttons, JSON_UNESCAPED_UNICODE);
$this->wechatcfg->save();
$this->success();
} else {
$this->error("加载菜单失败");
}
}
/**
* 同步到服务器
*/
public function sync($ids = null)
{
$app = Factory::officialAccount(Config::load());
try {
$hasError = false;
$menu = json_decode($this->wechatcfg->value, true);
foreach ($menu as $k => $v) {
if (isset($v['sub_button'])) {
foreach ($v['sub_button'] as $m => $n) {
if ($n['type'] == 'click' && isset($n['key']) && !$n['key']) {
$hasError = true;
break 2;
}
}
} else {
if ($v['type'] == 'click' && isset($v['key']) && !$v['key']) {
$hasError = true;
break;
}
}
}
if (!$hasError) {
try {
$ret = $app->menu->create($menu);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
if ($ret['errcode'] == 0) {
$this->success();
} else {
$this->error($ret['errmsg']);
}
} else {
$this->error(__('Invalid parameters'));
}
} catch (Exception $e) {
$this->error($e->getMessage());
}
}
}
... ...
<?php
namespace app\admin\controller\wechat;
use app\common\controller\Backend;
use addons\wechat\library\Wechat;
/**
* 资源管理
*
* @icon fa fa-list-alt
*/
class Response extends Backend
{
protected $model = null;
protected $searchFields = 'id,title';
public function _initialize()
{
parent::_initialize();
$this->model = model('WechatResponse');
}
/**
* 选择素材
*/
public function select()
{
return $this->view->fetch();
}
/**
* 添加
*/
public function add()
{
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
$params['eventkey'] = isset($params['eventkey']) && $params['eventkey'] ? $params['eventkey'] : uniqid();
$params['content'] = json_encode($params['content']);
$params['createtime'] = time();
if ($params) {
$this->model->save($params);
$this->success();
$this->content = $params;
}
$this->error();
}
$appConfig = Wechat::appConfig();
$this->view->applist = $appConfig;
return $this->view->fetch();
}
/**
* 编辑
*/
public function edit($ids = NULL)
{
$row = $this->model->get($ids);
if (!$row)
$this->error(__('No Results were found'));
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
$params['eventkey'] = isset($params['eventkey']) && $params['eventkey'] ? $params['eventkey'] : uniqid();
$params['content'] = json_encode($params['content']);
if ($params) {
$row->save($params);
$this->success();
}
$this->error();
}
$this->view->assign("row", $row);
$appConfig = Wechat::appConfig();
$this->view->applist = $appConfig;
return $this->view->fetch();
}
}
... ...
<?php
return [
'Id' => 'ID',
'Type' => '类型',
'Params' => '参数',
'Command' => '命令',
'Content' => '返回结果',
'Executetime' => '执行时间',
'Createtime' => '创建时间',
'Updatetime' => '更新时间',
'Execute again' => '再次执行',
'Successed' => '成功',
'Failured' => '失败',
'Status' => '状态'
];
... ...
<?php
return [
'Id' => 'ID',
'mid' => '自建表ID',
'm_name' => '自建表名称',
'm_table' => '自建表表名',
'm_desc' => '自建表描述',
'Admin_id' => '管理员ID',
'Category_id' => '分类ID(单选)',
'Flag' => '标志(多选)',
'Flag hot' => '热门',
'Flag index' => '首页',
'Flag recommend' => '推荐',
'Title' => '标题',
'Content' => '内容',
'Image' => '图片',
'Keywords' => '关键字',
'Description' => '描述',
'Views' => '点击',
'Refreshtime' => '刷新时间(int)',
'Createtime' => '创建时间',
'Updatetime' => '更新时间',
'Weigh' => '权重',
'Status' => '状态',
'State' => '状态值',
'State 0' => '未审核',
'State 1' => '正常',
'State 2' => '推荐'
];
\ No newline at end of file
... ...
<?php
return [
'Id' => 'ID',
'User_id' => '会员ID',
'Platform' => '第三方应用',
'Unionid' => '第三方UnionID',
'Openid' => '第三方OpenID',
'Openname' => '第三方会员昵称',
'Access_token' => 'AccessToken',
'Expires_in' => '有效期',
'Createtime' => '创建时间',
'Updatetime' => '更新时间',
'Logintime' => '登录时间',
'Expiretime' => '过期时间'
];
... ...
<?php
return [
'Text' => '文本',
'Event key' => '响应标识',
'Remark' => '备注',
'Text already exists' => '文本已经存在',
];
... ...