合并分支 '郝子凯' 到 'master'
上传插件 查看合并请求 !3
正在显示
58 个修改的文件
包含
4812 行增加
和
0 行删除
addons/command/.addonrc
0 → 100644
1 | +{"files":["application\\admin\\controller\\Command.php","application\\admin\\lang\\zh-cn\\command.php","application\\admin\\model\\Command.php","application\\admin\\validate\\Command.php","application\\admin\\view\\command\\add.html","application\\admin\\view\\command\\detail.html","application\\admin\\view\\command\\index.html","public\\assets\\js\\backend\\command.js"],"license":"regular","licenseto":"10789","licensekey":"nUTLWCS6Gjivx0pM \/Qe77lGZWGQWa8IzqinyNA==","domains":["showmerchants.cn"],"licensecodes":[],"validations":["3c36e672cbd8ad7c0b4c2f0562b0c810"],"menus":["command","command\/index","command\/add","command\/detail","command\/execute","command\/del","command\/multi"]} |
addons/command/Command.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\command; | ||
4 | + | ||
5 | +use app\common\library\Menu; | ||
6 | +use think\Addons; | ||
7 | + | ||
8 | +/** | ||
9 | + * 在线命令插件 | ||
10 | + */ | ||
11 | +class Command extends Addons | ||
12 | +{ | ||
13 | + | ||
14 | + /** | ||
15 | + * 插件安装方法 | ||
16 | + * @return bool | ||
17 | + */ | ||
18 | + public function install() | ||
19 | + { | ||
20 | + $menu = [ | ||
21 | + [ | ||
22 | + 'name' => 'command', | ||
23 | + 'title' => '在线命令管理', | ||
24 | + 'icon' => 'fa fa-terminal', | ||
25 | + 'sublist' => [ | ||
26 | + ['name' => 'command/index', 'title' => '查看'], | ||
27 | + ['name' => 'command/add', 'title' => '添加'], | ||
28 | + ['name' => 'command/detail', 'title' => '详情'], | ||
29 | + ['name' => 'command/execute', 'title' => '运行'], | ||
30 | + ['name' => 'command/del', 'title' => '删除'], | ||
31 | + ['name' => 'command/multi', 'title' => '批量更新'], | ||
32 | + ] | ||
33 | + ] | ||
34 | + ]; | ||
35 | + Menu::create($menu); | ||
36 | + return true; | ||
37 | + } | ||
38 | + | ||
39 | + /** | ||
40 | + * 插件卸载方法 | ||
41 | + * @return bool | ||
42 | + */ | ||
43 | + public function uninstall() | ||
44 | + { | ||
45 | + Menu::delete('command'); | ||
46 | + return true; | ||
47 | + } | ||
48 | + | ||
49 | + /** | ||
50 | + * 插件启用方法 | ||
51 | + * @return bool | ||
52 | + */ | ||
53 | + public function enable() | ||
54 | + { | ||
55 | + Menu::enable('command'); | ||
56 | + return true; | ||
57 | + } | ||
58 | + | ||
59 | + /** | ||
60 | + * 插件禁用方法 | ||
61 | + * @return bool | ||
62 | + */ | ||
63 | + public function disable() | ||
64 | + { | ||
65 | + Menu::disable('command'); | ||
66 | + return true; | ||
67 | + } | ||
68 | + | ||
69 | +} |
addons/command/config.php
0 → 100644
addons/command/controller/Index.php
0 → 100644
addons/command/info.ini
0 → 100644
addons/command/install.sql
0 → 100644
1 | +CREATE TABLE IF NOT EXISTS `__PREFIX__command` ( | ||
2 | + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID', | ||
3 | + `type` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '类型', | ||
4 | + `params` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '参数', | ||
5 | + `command` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '命令', | ||
6 | + `content` text COMMENT '返回结果', | ||
7 | + `executetime` int(10) UNSIGNED DEFAULT NULL COMMENT '执行时间', | ||
8 | + `createtime` int(10) UNSIGNED DEFAULT NULL COMMENT '创建时间', | ||
9 | + `updatetime` int(10) UNSIGNED DEFAULT NULL COMMENT '更新时间', | ||
10 | + `status` enum('successed','failured') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'failured' COMMENT '状态', | ||
11 | + PRIMARY KEY (`id`) USING BTREE | ||
12 | +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '在线命令表'; |
addons/command/library/Output.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\command\library; | ||
4 | + | ||
5 | +/** | ||
6 | + * Class Output | ||
7 | + */ | ||
8 | +class Output extends \think\console\Output | ||
9 | +{ | ||
10 | + | ||
11 | + protected $message = []; | ||
12 | + | ||
13 | + public function __construct($driver = 'console') | ||
14 | + { | ||
15 | + parent::__construct($driver); | ||
16 | + } | ||
17 | + | ||
18 | + protected function block($style, $message) | ||
19 | + { | ||
20 | + $this->message[] = $message; | ||
21 | + } | ||
22 | + | ||
23 | + public function getMessage() | ||
24 | + { | ||
25 | + return $this->message; | ||
26 | + } | ||
27 | + | ||
28 | +} |
addons/tablemake/.addonrc
0 → 100644
1 | +{"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"]} |
addons/tablemake/Tablemake.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\tablemake; | ||
4 | + | ||
5 | +use app\common\library\Menu; | ||
6 | +use think\Addons; | ||
7 | +use think\Config; | ||
8 | +use think\Db; | ||
9 | +use think\Exception; | ||
10 | + | ||
11 | +/** | ||
12 | + * 自建表管理插件 | ||
13 | + */ | ||
14 | +class Tablemake extends Addons { | ||
15 | + | ||
16 | + /** | ||
17 | + * 插件安装方法 | ||
18 | + * @return bool | ||
19 | + */ | ||
20 | + public function install() { | ||
21 | + $menu = [ | ||
22 | + [ | ||
23 | + 'name' => 'tablemake', | ||
24 | + 'title' => '自建表管理', | ||
25 | + 'icon' => 'fa fa-cubes', | ||
26 | + 'sublist' => [ | ||
27 | + ['name' => 'tablemake/index', 'title' => '查看列表'], | ||
28 | + ['name' => 'tablemake/add', 'title' => '创建新表'], | ||
29 | + ['name' => 'tablemake/edit', 'title' => '编辑表'], | ||
30 | + ['name' => 'tablemake/del', 'title' => '删除模块'], | ||
31 | + ['name' => 'tablemake/fields', 'title' => '字段管理'], | ||
32 | + ['name' => 'tablemake/field_add', 'title' => '添加字段'], | ||
33 | + ['name' => 'tablemake/field_del', 'title' => '删除字段'], | ||
34 | + ] | ||
35 | + ] | ||
36 | + ]; | ||
37 | + Menu::create($menu); | ||
38 | + //$this->doUpgrade(); | ||
39 | + return true; | ||
40 | + } | ||
41 | + | ||
42 | + /** | ||
43 | + * 插件卸载方法 | ||
44 | + * @return bool | ||
45 | + */ | ||
46 | + public function uninstall() { | ||
47 | + Menu::delete('tablemake'); | ||
48 | + return true; | ||
49 | + } | ||
50 | + | ||
51 | + /** | ||
52 | + * 插件启用方法 | ||
53 | + * @return bool | ||
54 | + */ | ||
55 | + public function enable() { | ||
56 | + Menu::enable('tablemake'); | ||
57 | + //$this->doUpgrade(); | ||
58 | + return true; | ||
59 | + } | ||
60 | + | ||
61 | + /** | ||
62 | + * 插件禁用方法 | ||
63 | + * @return bool | ||
64 | + */ | ||
65 | + public function disable() { | ||
66 | + Menu::disable('tablemake'); | ||
67 | + return true; | ||
68 | + } | ||
69 | + | ||
70 | + public function doUpgrade() { | ||
71 | + $prefix = Config::get('database.prefix'); | ||
72 | + | ||
73 | + $haTable = Db::query('SHOW TABLES LIKE '."'{$prefix}tablemake_tables'"); | ||
74 | + if(!$haTable){ | ||
75 | + //数据表不存在,表示是安装动作,非升级动作 | ||
76 | + return; | ||
77 | + } | ||
78 | + | ||
79 | + //<editor-fold desc="1.0.7版本更新数据表字段" defaultstate="collapsed"> | ||
80 | + /** | ||
81 | + * 1.检测tablemake_tables表是否需要更新,如果需要则更新tablemake_tables表 | ||
82 | + */ | ||
83 | + $sql = "describe `{$prefix}tablemake_tables` `weigh`;"; | ||
84 | + $has_weigh = Db::query($sql); | ||
85 | + if (!$has_weigh) {//tablemake_tables | ||
86 | + Db::startTrans(); | ||
87 | + try { | ||
88 | + //1.新增weigh字段 | ||
89 | + $sql = "ALTER TABLE `{$prefix}tablemake_tables` | ||
90 | + ADD COLUMN `weigh` bigint(11) NOT NULL DEFAULT 0 COMMENT '排序权重' AFTER `desc`;"; | ||
91 | + Db::execute($sql); | ||
92 | + //2.更新weigh字段的值为对应记录的ID值 | ||
93 | + $sql = "UPDATE `{$prefix}tablemake_tables` SET `weigh`=`id`;"; | ||
94 | + Db::execute($sql); | ||
95 | + //3.原有字段更新 | ||
96 | + $sql = "ALTER TABLE `{$prefix}tablemake_tables` | ||
97 | + MODIFY COLUMN `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID' FIRST , | ||
98 | + MODIFY COLUMN `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '自建表名称' AFTER `id`, | ||
99 | + MODIFY COLUMN `table` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '自建表表名' AFTER `name`, | ||
100 | + MODIFY COLUMN `desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '自建表简介' AFTER `table`, | ||
101 | + MODIFY COLUMN `createtime` bigint(11) NOT NULL DEFAULT 0 COMMENT '创建时间' AFTER `weigh`, | ||
102 | + MODIFY COLUMN `updatetime` bigint(11) NOT NULL DEFAULT 0 COMMENT '更新时间' AFTER `createtime`;"; | ||
103 | + Db::execute($sql); | ||
104 | + Db::commit(); | ||
105 | + } catch (Exception $e) { | ||
106 | + \think\Log::write("更新{$prefix}tablemake_tables表字段失败,异常:" . $e->getTraceAsString()); | ||
107 | + Db::rollback(); | ||
108 | + } | ||
109 | + } | ||
110 | + /** | ||
111 | + * 2.检测tablemake_fields表是否需要更新,如果需要则更新tablemake_fields表 | ||
112 | + */ | ||
113 | + $sql = "describe `{$prefix}tablemake_fields` `weigh`;"; | ||
114 | + $has_weigh = Db::query($sql); | ||
115 | + if (!$has_weigh) {//tablemake_fields | ||
116 | + Db::startTrans(); | ||
117 | + try { | ||
118 | + //1.新增weigh字段 | ||
119 | + $sql = "ALTER TABLE `{$prefix}tablemake_fields` | ||
120 | + ADD COLUMN `desc` varchar(255) NOT NULL DEFAULT '' COMMENT '字段备注' AFTER `comment`, | ||
121 | + ADD COLUMN `weigh` bigint(11) NOT NULL DEFAULT 0 COMMENT '排序权重' AFTER `desc`;"; | ||
122 | + Db::execute($sql); | ||
123 | + //2.更新weigh字段的值为对应记录的ID值 | ||
124 | + $sql = "UPDATE `{$prefix}tablemake_fields` SET `weigh`=`id`;"; | ||
125 | + Db::execute($sql); | ||
126 | + //3.原有字段更新 | ||
127 | + $sql = "ALTER TABLE `{$prefix}tablemake_fields` | ||
128 | + MODIFY COLUMN `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID' FIRST , | ||
129 | + MODIFY COLUMN `mid` bigint(11) NOT NULL DEFAULT 0 COMMENT '所属自建表ID' AFTER `id`, | ||
130 | + MODIFY COLUMN `length` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 0 COMMENT '字段长度' AFTER `type`, | ||
131 | + MODIFY COLUMN `default` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '默认值' AFTER `length`, | ||
132 | + MODIFY COLUMN `comment` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '字段备注' AFTER `default`, | ||
133 | + MODIFY COLUMN `createtime` bigint(11) NOT NULL DEFAULT 0 COMMENT '创建时间' AFTER `weigh`, | ||
134 | + MODIFY COLUMN `updatetime` bigint(11) NOT NULL DEFAULT 0 COMMENT '更新时间' AFTER `createtime`;"; | ||
135 | + Db::execute($sql); | ||
136 | + Db::commit(); | ||
137 | + } catch (Exception $e) { | ||
138 | + \think\Log::write("更新{$prefix}tablemake_fields表字段失败,异常:" . $e->getTraceAsString()); | ||
139 | + Db::rollback(); | ||
140 | + } | ||
141 | + } | ||
142 | + //</editor-fold> | ||
143 | + } | ||
144 | + | ||
145 | +} |
addons/tablemake/controller/Index.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\tablemake\controller; | ||
4 | + | ||
5 | + | ||
6 | + | ||
7 | +/** | ||
8 | + * 自建表前台页面,展示数据字典 | ||
9 | + */ | ||
10 | +class Index extends \think\addons\Controller { | ||
11 | + | ||
12 | + | ||
13 | + | ||
14 | + public function _initialize() { | ||
15 | + parent::_initialize(); | ||
16 | + } | ||
17 | + | ||
18 | + /** | ||
19 | + *展示数据字典信息 | ||
20 | + */ | ||
21 | + public function index() { | ||
22 | + $this->error("当前插件暂无前台页面",url()); | ||
23 | + | ||
24 | + } | ||
25 | + | ||
26 | +} |
addons/tablemake/info.ini
0 → 100644
addons/tablemake/install.sql
0 → 100644
1 | +--1.0.0-- | ||
2 | +CREATE TABLE IF NOT EXISTS `__PREFIX__tablemake_tables` ( | ||
3 | + `id` int(11) NOT NULL AUTO_INCREMENT, | ||
4 | + `name` varchar(50) NOT NULL COMMENT '模型名称', | ||
5 | + `table` varchar(20) NOT NULL COMMENT '表名称', | ||
6 | + `desc` varchar(150) DEFAULT NULL COMMENT '简介', | ||
7 | + `createtime` int(11) NOT NULL COMMENT '创建时间', | ||
8 | + `updatetime` int(11) NOT NULL COMMENT '更新时间', | ||
9 | + PRIMARY KEY (`id`) USING BTREE | ||
10 | +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '自建表管理表' ROW_FORMAT = Compact; | ||
11 | + | ||
12 | +CREATE TABLE IF NOT EXISTS `__PREFIX__tablemake_fields` ( | ||
13 | + `id` int(11) NOT NULL AUTO_INCREMENT, | ||
14 | + `mid` int(11) NOT NULL COMMENT '所属模型', | ||
15 | + `category` tinyint(2) NOT NULL COMMENT '字段类型', | ||
16 | + `title` varchar(50) NOT NULL DEFAULT '' COMMENT '字段标题', | ||
17 | + `name` varchar(50) NOT NULL DEFAULT '' COMMENT '字段名称', | ||
18 | + `field` varchar(50) NOT NULL DEFAULT '' COMMENT '字段名', | ||
19 | + `special` varchar(50) NOT NULL DEFAULT '' COMMENT '特殊字段', | ||
20 | + `suffix` varchar(50) NOT NULL DEFAULT '' COMMENT '字段后缀', | ||
21 | + `type` varchar(50) NOT NULL DEFAULT '' COMMENT '字段类型', | ||
22 | + `length` varchar(10) NOT NULL COMMENT '字段长度', | ||
23 | + `default` varchar(255) NOT NULL COMMENT '默认值', | ||
24 | + `comment` varchar(2000) NOT NULL COMMENT '字段备注', | ||
25 | + `createtime` int(11) NOT NULL COMMENT '创建时间', | ||
26 | + `updatetime` int(11) NOT NULL COMMENT '更新时间', | ||
27 | + PRIMARY KEY (`id`) USING BTREE | ||
28 | +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '字段管理表' ROW_FORMAT = Compact; | ||
29 | + | ||
30 | + | ||
31 | + | ||
32 | + | ||
33 | +--1.0.7-- | ||
34 | +ALTER TABLE `__PREFIX__tablemake_tables` ADD COLUMN `weigh` bigint(11) NOT NULL DEFAULT 0 COMMENT '排序权重' AFTER `desc`; | ||
35 | +UPDATE `__PREFIX__tablemake_tables` SET `weigh`=`id`; | ||
36 | +ALTER TABLE `__PREFIX__tablemake_tables` | ||
37 | + MODIFY COLUMN `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID' FIRST , | ||
38 | + MODIFY COLUMN `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '自建表名称' AFTER `id`, | ||
39 | + MODIFY COLUMN `table` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '自建表表名' AFTER `name`, | ||
40 | + MODIFY COLUMN `desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '自建表简介' AFTER `table`, | ||
41 | + MODIFY COLUMN `createtime` bigint(11) NOT NULL DEFAULT 0 COMMENT '创建时间' AFTER `weigh`, | ||
42 | + MODIFY COLUMN `updatetime` bigint(11) NOT NULL DEFAULT 0 COMMENT '更新时间' AFTER `createtime`; | ||
43 | + | ||
44 | + | ||
45 | +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`; | ||
46 | +UPDATE `__PREFIX__tablemake_fields` SET `weigh`=`id`; | ||
47 | +ALTER TABLE `__PREFIX__tablemake_fields` | ||
48 | + MODIFY COLUMN `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID' FIRST , | ||
49 | + MODIFY COLUMN `mid` bigint(11) NOT NULL DEFAULT 0 COMMENT '所属自建表ID' AFTER `id`, | ||
50 | + MODIFY COLUMN `length` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 0 COMMENT '字段长度' AFTER `type`, | ||
51 | + MODIFY COLUMN `default` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '默认值' AFTER `length`, | ||
52 | + MODIFY COLUMN `comment` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '字段备注' AFTER `default`, | ||
53 | + MODIFY COLUMN `createtime` bigint(11) NOT NULL DEFAULT 0 COMMENT '创建时间' AFTER `weigh`, | ||
54 | + MODIFY COLUMN `updatetime` bigint(11) NOT NULL DEFAULT 0 COMMENT '更新时间' AFTER `createtime`; | ||
55 | + | ||
56 | + | ||
57 | + |
addons/third/.addonrc
0 → 100644
1 | +{"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"]} |
addons/third/Third.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\third; | ||
4 | + | ||
5 | +use app\common\library\Menu; | ||
6 | +use think\Addons; | ||
7 | + | ||
8 | +/** | ||
9 | + * 第三方登录 | ||
10 | + */ | ||
11 | +class Third extends Addons | ||
12 | +{ | ||
13 | + | ||
14 | + /** | ||
15 | + * 插件安装方法 | ||
16 | + * @return bool | ||
17 | + */ | ||
18 | + public function install() | ||
19 | + { | ||
20 | + $menu = [ | ||
21 | + [ | ||
22 | + 'name' => 'third', | ||
23 | + 'title' => '第三方登录管理', | ||
24 | + 'icon' => 'fa fa-users', | ||
25 | + 'sublist' => [ | ||
26 | + [ | ||
27 | + "name" => "third/index", | ||
28 | + "title" => "查看" | ||
29 | + ], | ||
30 | + [ | ||
31 | + "name" => "third/del", | ||
32 | + "title" => "删除" | ||
33 | + ] | ||
34 | + ] | ||
35 | + ] | ||
36 | + ]; | ||
37 | + Menu::create($menu); | ||
38 | + return true; | ||
39 | + } | ||
40 | + | ||
41 | + /** | ||
42 | + * 插件卸载方法 | ||
43 | + * @return bool | ||
44 | + */ | ||
45 | + public function uninstall() | ||
46 | + { | ||
47 | + Menu::delete("third"); | ||
48 | + return true; | ||
49 | + } | ||
50 | + | ||
51 | + /** | ||
52 | + * 插件启用方法 | ||
53 | + * @return bool | ||
54 | + */ | ||
55 | + public function enable() | ||
56 | + { | ||
57 | + Menu::enable("third"); | ||
58 | + return true; | ||
59 | + } | ||
60 | + | ||
61 | + /** | ||
62 | + * 插件禁用方法 | ||
63 | + * @return bool | ||
64 | + */ | ||
65 | + public function disable() | ||
66 | + { | ||
67 | + Menu::disable("third"); | ||
68 | + return true; | ||
69 | + } | ||
70 | + | ||
71 | + /** | ||
72 | + * @param $params | ||
73 | + */ | ||
74 | + public function configInit(&$params) | ||
75 | + { | ||
76 | + $config = $this->getConfig(); | ||
77 | + $params['third'] = ['status' => explode(',', $config['status'])]; | ||
78 | + } | ||
79 | +} |
addons/third/bootstrap.js
0 → 100644
1 | +if (Config.modulename === 'index' && Config.controllername === 'user' && ['login', 'register'].indexOf(Config.actionname) > -1 && $("#register-form,#login-form").size() > 0) { | ||
2 | + $('<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"); | ||
3 | + $("#register-form,#login-form").append('<div class="form-group social-login"></div>'); | ||
4 | + if (Config.third.status.indexOf("wechat") > -1) { | ||
5 | + $('<a class="btn btn-success" href="' + Fast.api.fixurl('/third/connect/wechat') + '"><i class="fa fa-wechat"></i> 微信登录</a>').appendTo(".social-login"); | ||
6 | + } | ||
7 | + if (Config.third.status.indexOf("qq") > -1) { | ||
8 | + $('<a class="btn btn-info" href="' + Fast.api.fixurl('/third/connect/qq') + '"><i class="fa fa-qq"></i> QQ登录</a>').appendTo(".social-login"); | ||
9 | + } | ||
10 | + if (Config.third.status.indexOf("weibo") > -1) { | ||
11 | + $('<a class="btn btn-danger" href="' + Fast.api.fixurl('/third/connect/weibo') + '"><i class="fa fa-weibo"></i> 微博登录</a>').appendTo(".social-login"); | ||
12 | + } | ||
13 | +} |
addons/third/config.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +return array( | ||
4 | + 0 => | ||
5 | + array( | ||
6 | + 'name' => 'qq', | ||
7 | + 'title' => 'QQ', | ||
8 | + 'type' => 'array', | ||
9 | + 'content' => | ||
10 | + array( | ||
11 | + 'app_id' => '', | ||
12 | + 'app_secret' => '', | ||
13 | + 'scope' => 'get_user_info', | ||
14 | + ), | ||
15 | + 'value' => | ||
16 | + array( | ||
17 | + 'app_id' => '100000000', | ||
18 | + 'app_secret' => '123456', | ||
19 | + 'scope' => 'get_user_info', | ||
20 | + ), | ||
21 | + 'rule' => 'required', | ||
22 | + 'msg' => '', | ||
23 | + 'tip' => '', | ||
24 | + 'ok' => '', | ||
25 | + 'extend' => '', | ||
26 | + ), | ||
27 | + 1 => | ||
28 | + array( | ||
29 | + 'name' => 'wechat', | ||
30 | + 'title' => '微信', | ||
31 | + 'type' => 'array', | ||
32 | + 'content' => | ||
33 | + array( | ||
34 | + 'app_id' => '', | ||
35 | + 'app_secret' => '', | ||
36 | + 'callback' => '', | ||
37 | + 'scope' => 'snsapi_base', | ||
38 | + ), | ||
39 | + 'value' => | ||
40 | + array( | ||
41 | + 'app_id' => '100000000', | ||
42 | + 'app_secret' => '123456', | ||
43 | + 'scope' => 'snsapi_userinfo', | ||
44 | + ), | ||
45 | + 'rule' => 'required', | ||
46 | + 'msg' => '', | ||
47 | + 'tip' => '', | ||
48 | + 'ok' => '', | ||
49 | + 'extend' => '', | ||
50 | + ), | ||
51 | + 2 => | ||
52 | + array( | ||
53 | + 'name' => 'weibo', | ||
54 | + 'title' => '微博', | ||
55 | + 'type' => 'array', | ||
56 | + 'content' => | ||
57 | + array( | ||
58 | + 'app_id' => '', | ||
59 | + 'app_secret' => '', | ||
60 | + 'scope' => 'get_user_info', | ||
61 | + ), | ||
62 | + 'value' => | ||
63 | + array( | ||
64 | + 'app_id' => '100000000', | ||
65 | + 'app_secret' => '123456', | ||
66 | + 'scope' => 'get_user_info', | ||
67 | + ), | ||
68 | + 'rule' => 'required', | ||
69 | + 'msg' => '', | ||
70 | + 'tip' => '', | ||
71 | + 'ok' => '', | ||
72 | + 'extend' => '', | ||
73 | + ), | ||
74 | + 3 => | ||
75 | + array( | ||
76 | + 'name' => 'bindaccount', | ||
77 | + 'title' => '账号绑定', | ||
78 | + 'type' => 'radio', | ||
79 | + 'content' => | ||
80 | + array( | ||
81 | + 1 => '开启', | ||
82 | + 0 => '关闭', | ||
83 | + ), | ||
84 | + 'value' => '1', | ||
85 | + 'rule' => 'required', | ||
86 | + 'msg' => '', | ||
87 | + 'tip' => '', | ||
88 | + 'ok' => '是否开启账号绑定', | ||
89 | + 'extend' => '', | ||
90 | + ), | ||
91 | + 4 => | ||
92 | + array( | ||
93 | + 'name' => 'status', | ||
94 | + 'title' => '前台第三方登录开关', | ||
95 | + 'type' => 'checkbox', | ||
96 | + 'content' => | ||
97 | + array( | ||
98 | + 'qq' => 'QQ', | ||
99 | + 'wechat' => '微信', | ||
100 | + 'weibo' => '微博', | ||
101 | + ), | ||
102 | + 'value' => 'qq,wechat,weibo', | ||
103 | + 'rule' => '', | ||
104 | + 'msg' => '', | ||
105 | + 'tip' => '', | ||
106 | + 'ok' => '前台第三方登录的开关', | ||
107 | + 'extend' => '', | ||
108 | + ), | ||
109 | + 5 => | ||
110 | + array( | ||
111 | + 'name' => 'rewrite', | ||
112 | + 'title' => '伪静态', | ||
113 | + 'type' => 'array', | ||
114 | + 'content' => | ||
115 | + array(), | ||
116 | + 'value' => | ||
117 | + array( | ||
118 | + 'index/index' => '/third$', | ||
119 | + 'index/connect' => '/third/connect/[:platform]', | ||
120 | + 'index/callback' => '/third/callback/[:platform]', | ||
121 | + 'index/bind' => '/third/bind/[:platform]', | ||
122 | + 'index/unbind' => '/third/unbind/[:platform]', | ||
123 | + ), | ||
124 | + 'rule' => 'required', | ||
125 | + 'msg' => '', | ||
126 | + 'tip' => '', | ||
127 | + 'ok' => '', | ||
128 | + 'extend' => '', | ||
129 | + ), | ||
130 | +); |
addons/third/controller/Api.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\third\controller; | ||
4 | + | ||
5 | +use addons\third\library\Application; | ||
6 | +use app\common\controller\Api as commonApi; | ||
7 | +use addons\third\library\Service; | ||
8 | +use addons\third\model\Third; | ||
9 | +use app\common\library\Sms; | ||
10 | +use fast\Random; | ||
11 | +use think\Lang; | ||
12 | +use think\Config; | ||
13 | +use think\Session; | ||
14 | +use think\Validate; | ||
15 | + | ||
16 | +/** | ||
17 | + * 第三方登录插件 | ||
18 | + */ | ||
19 | +class Api extends commonApi | ||
20 | +{ | ||
21 | + protected $noNeedLogin = ['getAuthUrl', 'callback', 'account']; // 无需登录即可访问的方法,同时也无需鉴权了 | ||
22 | + protected $noNeedRight = ['*']; // 无需鉴权即可访问的方法 | ||
23 | + | ||
24 | + protected $app = null; | ||
25 | + protected $options = []; | ||
26 | + protected $config = null; | ||
27 | + | ||
28 | + public function _initialize() | ||
29 | + { | ||
30 | + //跨域检测 | ||
31 | + check_cors_request(); | ||
32 | + //设置session_id | ||
33 | + Config::set('session.id', $this->request->server("HTTP_SID")); | ||
34 | + | ||
35 | + parent::_initialize(); | ||
36 | + $this->config = get_addon_config('third'); | ||
37 | + $this->app = new Application($this->config); | ||
38 | + } | ||
39 | + | ||
40 | + /** | ||
41 | + * H5获取授权链接 | ||
42 | + * @return void | ||
43 | + */ | ||
44 | + public function getAuthUrl() | ||
45 | + { | ||
46 | + $url = $this->request->param('url'); | ||
47 | + $platform = $this->request->param('platform'); | ||
48 | + if (!$url || !$platform || !isset($this->config[$platform])) { | ||
49 | + $this->error('参数错误'); | ||
50 | + } | ||
51 | + $this->config[$platform]['callback'] = $url; | ||
52 | + $this->app = new Application($this->config); // | ||
53 | + if (!$this->app->{$platform}) { | ||
54 | + $this->error(__('Invalid parameters')); | ||
55 | + } | ||
56 | + $this->success('', $this->app->{$platform}->getAuthorizeUrl()); | ||
57 | + } | ||
58 | + | ||
59 | + /** | ||
60 | + * 公众号:wechat 授权回调的请求【非第三方,自己的前端请求】 | ||
61 | + * @return void | ||
62 | + */ | ||
63 | + public function callback() | ||
64 | + { | ||
65 | + | ||
66 | + $platform = $this->request->param('platform'); | ||
67 | + if (!$this->app->{$platform}) { | ||
68 | + $this->error(__('Invalid parameters')); | ||
69 | + } | ||
70 | + $userinfo = $this->app->{$platform}->getUserInfo($this->request->param()); | ||
71 | + if (!$userinfo) { | ||
72 | + $this->error(__('操作失败')); | ||
73 | + } | ||
74 | + $userinfo['apptype'] = 'mp'; | ||
75 | + $userinfo['platform'] = $platform; | ||
76 | + | ||
77 | + $third = [ | ||
78 | + 'avatar' => $userinfo['userinfo']['avatar'], | ||
79 | + 'nickname' => $userinfo['userinfo']['nickname'] | ||
80 | + ]; | ||
81 | + | ||
82 | + $user = null; | ||
83 | + if ($this->auth->isLogin() || Service::isBindThird($userinfo['platform'], $userinfo['openid'], $userinfo['apptype'], $userinfo['unionid'])) { | ||
84 | + Service::connect($userinfo['platform'], $userinfo); | ||
85 | + $user = $this->auth->getUserinfo(); | ||
86 | + } else { | ||
87 | + $user = false; | ||
88 | + Session::set('third-userinfo', $userinfo); | ||
89 | + } | ||
90 | + $this->success("授权成功!", ['user' => $user, 'third' => $third]); | ||
91 | + } | ||
92 | + | ||
93 | + /** | ||
94 | + * 登录或创建账号 | ||
95 | + */ | ||
96 | + public function account() | ||
97 | + { | ||
98 | + | ||
99 | + if ($this->request->isPost()) { | ||
100 | + $params = Session::get('third-userinfo'); | ||
101 | + $mobile = $this->request->post('mobile', ''); | ||
102 | + $code = $this->request->post('code'); | ||
103 | + $token = $this->request->post('__token__'); | ||
104 | + $rule = [ | ||
105 | + 'mobile' => 'require|regex:/^1\d{10}$/', | ||
106 | + '__token__' => 'require|token', | ||
107 | + ]; | ||
108 | + $msg = [ | ||
109 | + 'mobile' => 'Mobile is incorrect', | ||
110 | + ]; | ||
111 | + $data = [ | ||
112 | + 'mobile' => $mobile, | ||
113 | + '__token__' => $token, | ||
114 | + ]; | ||
115 | + $ret = Sms::check($mobile, $code, 'bind'); | ||
116 | + if (!$ret) { | ||
117 | + $this->error(__('验证码错误')); | ||
118 | + } | ||
119 | + $validate = new Validate($rule, $msg); | ||
120 | + $result = $validate->check($data); | ||
121 | + if (!$result) { | ||
122 | + $this->error(__($validate->getError()), ['__token__' => $this->request->token()]); | ||
123 | + } | ||
124 | + | ||
125 | + $userinfo = \app\common\model\User::where('mobile', $mobile)->find(); | ||
126 | + if ($userinfo) { | ||
127 | + $result = $this->auth->direct($userinfo->id); | ||
128 | + } else { | ||
129 | + $result = $this->auth->register($mobile, Random::alnum(), '', $mobile); | ||
130 | + } | ||
131 | + | ||
132 | + if ($result) { | ||
133 | + Service::connect($params['platform'], $params); | ||
134 | + $this->success(__('绑定账号成功'), ['userinfo' => $this->auth->getUserinfo()]); | ||
135 | + } else { | ||
136 | + $this->error($this->auth->getError(), ['__token__' => $this->request->token()]); | ||
137 | + } | ||
138 | + } | ||
139 | + } | ||
140 | + | ||
141 | + | ||
142 | +} |
addons/third/controller/Index.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\third\controller; | ||
4 | + | ||
5 | +use addons\third\library\Application; | ||
6 | +use addons\third\library\Service; | ||
7 | +use addons\third\model\Third; | ||
8 | +use think\addons\Controller; | ||
9 | +use think\Config; | ||
10 | +use think\Cookie; | ||
11 | +use think\Hook; | ||
12 | +use think\Lang; | ||
13 | +use think\Session; | ||
14 | + | ||
15 | +/** | ||
16 | + * 第三方登录插件 | ||
17 | + */ | ||
18 | +class Index extends Controller | ||
19 | +{ | ||
20 | + protected $app = null; | ||
21 | + protected $options = []; | ||
22 | + | ||
23 | + public function _initialize() | ||
24 | + { | ||
25 | + parent::_initialize(); | ||
26 | + $config = get_addon_config('third'); | ||
27 | + $this->app = new Application($config); | ||
28 | + } | ||
29 | + | ||
30 | + /** | ||
31 | + * 插件首页 | ||
32 | + */ | ||
33 | + public function index() | ||
34 | + { | ||
35 | + if (!\app\admin\library\Auth::instance()->id) { | ||
36 | + $this->error('当前插件暂无前台页面'); | ||
37 | + } | ||
38 | + $platformList = []; | ||
39 | + if ($this->auth->id) { | ||
40 | + $platformList = Third::where('user_id', $this->auth->id)->column('platform'); | ||
41 | + } | ||
42 | + $this->view->assign('platformList', $platformList); | ||
43 | + return $this->view->fetch(); | ||
44 | + } | ||
45 | + | ||
46 | + /** | ||
47 | + * 发起授权 | ||
48 | + */ | ||
49 | + public function connect() | ||
50 | + { | ||
51 | + $platform = $this->request->param('platform'); | ||
52 | + $url = $this->request->request('url', $this->request->server('HTTP_REFERER', '/'), 'trim'); | ||
53 | + if (!$this->app->{$platform}) { | ||
54 | + $this->error(__('Invalid parameters')); | ||
55 | + } | ||
56 | + if ($url) { | ||
57 | + Session::set("redirecturl", $url); | ||
58 | + } | ||
59 | + // 跳转到登录授权页面 | ||
60 | + $this->redirect($this->app->{$platform}->getAuthorizeUrl()); | ||
61 | + return; | ||
62 | + } | ||
63 | + | ||
64 | + /** | ||
65 | + * 通知回调 | ||
66 | + */ | ||
67 | + public function callback() | ||
68 | + { | ||
69 | + $auth = $this->auth; | ||
70 | + | ||
71 | + //监听注册登录注销的事件 | ||
72 | + Hook::add('user_login_successed', function ($user) use ($auth) { | ||
73 | + $expire = input('post.keeplogin') ? 30 * 86400 : 0; | ||
74 | + Cookie::set('uid', $user->id, $expire); | ||
75 | + Cookie::set('token', $auth->getToken(), $expire); | ||
76 | + }); | ||
77 | + Hook::add('user_register_successed', function ($user) use ($auth) { | ||
78 | + Cookie::set('uid', $user->id); | ||
79 | + Cookie::set('token', $auth->getToken()); | ||
80 | + }); | ||
81 | + Hook::add('user_logout_successed', function ($user) use ($auth) { | ||
82 | + Cookie::delete('uid'); | ||
83 | + Cookie::delete('token'); | ||
84 | + }); | ||
85 | + $platform = $this->request->param('platform'); | ||
86 | + | ||
87 | + // 成功后返回之前页面 | ||
88 | + $url = Session::has("redirecturl") ? Session::pull("redirecturl") : url('index/user/index'); | ||
89 | + | ||
90 | + // 授权成功后的回调 | ||
91 | + $userinfo = $this->app->{$platform}->getUserInfo(); | ||
92 | + if (!$userinfo) { | ||
93 | + $this->error(__('操作失败'), $url); | ||
94 | + } | ||
95 | + | ||
96 | + Session::set("{$platform}-userinfo", $userinfo); | ||
97 | + //判断是否启用账号绑定 | ||
98 | + $third = Third::get(['platform' => $platform, 'openid' => $userinfo['openid']]); | ||
99 | + if (!$third) { | ||
100 | + $config = get_addon_config('third'); | ||
101 | + //要求绑定账号或会员当前是登录状态 | ||
102 | + if ($config['bindaccount'] || $this->auth->id) { | ||
103 | + $this->redirect(url('index/third/prepare') . "?" . http_build_query(['platform' => $platform, 'url' => $url])); | ||
104 | + } | ||
105 | + } | ||
106 | + | ||
107 | + $loginret = Service::connect($platform, $userinfo); | ||
108 | + if ($loginret) { | ||
109 | + $this->redirect($url); | ||
110 | + } | ||
111 | + } | ||
112 | + | ||
113 | + /** | ||
114 | + * 绑定账号 | ||
115 | + */ | ||
116 | + public function bind() | ||
117 | + { | ||
118 | + $platform = $this->request->request('platform', $this->request->param('platform', '')); | ||
119 | + $url = $this->request->get('url', $this->request->server('HTTP_REFERER')); | ||
120 | + $redirecturl = url("index/third/bind") . "?" . http_build_query(['platform' => $platform, 'url' => $url]); | ||
121 | + $this->redirect($redirecturl); | ||
122 | + return; | ||
123 | + } | ||
124 | + | ||
125 | + /** | ||
126 | + * 解绑账号 | ||
127 | + */ | ||
128 | + public function unbind() | ||
129 | + { | ||
130 | + $platform = $this->request->request('platform', $this->request->param('platform', '')); | ||
131 | + $url = $this->request->get('url', $this->request->server('HTTP_REFERER')); | ||
132 | + $redirecturl = url("index/third/unbind") . "?" . http_build_query(['platform' => $platform, 'url' => $url]); | ||
133 | + $this->redirect($redirecturl); | ||
134 | + return; | ||
135 | + } | ||
136 | + | ||
137 | +} |
addons/third/info.ini
0 → 100644
addons/third/install.sql
0 → 100644
1 | + | ||
2 | +CREATE TABLE IF NOT EXISTS `__PREFIX__third` ( | ||
3 | + `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', | ||
4 | + `user_id` int(10) unsigned DEFAULT '0' COMMENT '会员ID', | ||
5 | + `platform` varchar(30) DEFAULT '' COMMENT '第三方应用', | ||
6 | + `apptype` varchar(50) DEFAULT '' COMMENT '应用类型', | ||
7 | + `unionid` varchar(100) DEFAULT '' COMMENT '第三方UNIONID', | ||
8 | + `openid` varchar(100) DEFAULT '' COMMENT '第三方OPENID', | ||
9 | + `openname` varchar(100) DEFAULT '' COMMENT '第三方会员昵称', | ||
10 | + `access_token` varchar(255) NULL DEFAULT '' COMMENT 'AccessToken', | ||
11 | + `refresh_token` varchar(255) DEFAULT 'RefreshToken', | ||
12 | + `expires_in` int(10) unsigned DEFAULT '0' COMMENT '有效期', | ||
13 | + `createtime` int(10) unsigned DEFAULT NULL COMMENT '创建时间', | ||
14 | + `updatetime` int(10) unsigned DEFAULT NULL COMMENT '更新时间', | ||
15 | + `logintime` int(10) unsigned DEFAULT NULL COMMENT '登录时间', | ||
16 | + `expiretime` int(10) unsigned DEFAULT NULL COMMENT '过期时间', | ||
17 | + PRIMARY KEY (`id`), | ||
18 | + UNIQUE KEY `platform` (`platform`,`openid`), | ||
19 | + KEY `user_id` (`user_id`,`platform`), | ||
20 | + KEY `unionid` (`platform`,`unionid`) | ||
21 | +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='第三方登录表'; | ||
22 | + | ||
23 | +ALTER TABLE `__PREFIX__third` ADD COLUMN `apptype` varchar(50) NULL DEFAULT '' COMMENT '应用类型' AFTER `platform`; | ||
24 | + | ||
25 | +ALTER TABLE `__PREFIX__third` ADD COLUMN `unionid` varchar(100) NULL DEFAULT '' COMMENT '第三方UnionID' AFTER `apptype`; | ||
26 | +ALTER TABLE `__PREFIX__third` ADD INDEX `unionid`(`platform`, `unionid`); | ||
27 | + | ||
28 | +ALTER TABLE `__PREFIX__third` CHARACTER SET = utf8mb4, COLLATE = utf8mb4_general_ci; | ||
29 | +ALTER TABLE `__PREFIX__third` MODIFY COLUMN `openname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '第三方会员昵称' AFTER `unionid`; | ||
30 | + |
addons/third/library/Application.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\third\library; | ||
4 | + | ||
5 | +class Application | ||
6 | +{ | ||
7 | + | ||
8 | + /** | ||
9 | + * 配置信息 | ||
10 | + * @var array | ||
11 | + */ | ||
12 | + private $config = []; | ||
13 | + | ||
14 | + /** | ||
15 | + * 服务提供者 | ||
16 | + * @var array | ||
17 | + */ | ||
18 | + private $providers = [ | ||
19 | + 'qq' => 'Qq', | ||
20 | + 'weibo' => 'Weibo', | ||
21 | + 'wechat' => 'Wechat', | ||
22 | + ]; | ||
23 | + | ||
24 | + /** | ||
25 | + * 服务对象信息 | ||
26 | + * @var array | ||
27 | + */ | ||
28 | + protected $services = []; | ||
29 | + | ||
30 | + public function __construct($options = []) | ||
31 | + { | ||
32 | + $options = array_intersect_key($options, $this->providers); | ||
33 | + $options = array_merge($this->config, is_array($options) ? $options : []); | ||
34 | + foreach ($options as $key => &$option) { | ||
35 | + $option['app_id'] = isset($option['app_id']) ? $option['app_id'] : ''; | ||
36 | + $option['app_secret'] = isset($option['app_secret']) ? $option['app_secret'] : ''; | ||
37 | + // 如果未定义回调地址则自动生成 | ||
38 | + $option['callback'] = isset($option['callback']) && $option['callback'] ? $option['callback'] : addon_url('third/index/callback', [':platform' => $key], false, true); | ||
39 | + } | ||
40 | + $this->config = $options; | ||
41 | + //注册服务器提供者 | ||
42 | + $this->registerProviders(); | ||
43 | + } | ||
44 | + | ||
45 | + /** | ||
46 | + * 注册服务提供者 | ||
47 | + */ | ||
48 | + private function registerProviders() | ||
49 | + { | ||
50 | + foreach ($this->providers as $k => $v) { | ||
51 | + $this->services[$k] = function () use ($k, $v) { | ||
52 | + $options = $this->config[$k]; | ||
53 | + $objname = __NAMESPACE__ . "\\{$v}"; | ||
54 | + return new $objname($options); | ||
55 | + }; | ||
56 | + } | ||
57 | + } | ||
58 | + | ||
59 | + public function __set($key, $value) | ||
60 | + { | ||
61 | + $this->services[$key] = $value; | ||
62 | + } | ||
63 | + | ||
64 | + public function __get($key) | ||
65 | + { | ||
66 | + return isset($this->services[$key]) ? $this->services[$key]($this) : null; | ||
67 | + } | ||
68 | +} |
addons/third/library/Qq.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\third\library; | ||
4 | + | ||
5 | +use fast\Http; | ||
6 | +use think\Config; | ||
7 | +use think\Session; | ||
8 | + | ||
9 | +/** | ||
10 | |||
11 | + */ | ||
12 | +class Qq | ||
13 | +{ | ||
14 | + const GET_AUTH_CODE_URL = "https://graph.qq.com/oauth2.0/authorize"; | ||
15 | + const GET_ACCESS_TOKEN_URL = "https://graph.qq.com/oauth2.0/token"; | ||
16 | + const GET_USERINFO_URL = "https://graph.qq.com/user/get_user_info"; | ||
17 | + const GET_OPENID_URL = "https://graph.qq.com/oauth2.0/me"; | ||
18 | + | ||
19 | + /** | ||
20 | + * 配置信息 | ||
21 | + * @var array | ||
22 | + */ | ||
23 | + private $config = []; | ||
24 | + | ||
25 | + public function __construct($options = []) | ||
26 | + { | ||
27 | + if ($config = Config::get('third.qq')) { | ||
28 | + $this->config = array_merge($this->config, $config); | ||
29 | + } | ||
30 | + $this->config = array_merge($this->config, is_array($options) ? $options : []); | ||
31 | + } | ||
32 | + | ||
33 | + /** | ||
34 | + * 登陆 | ||
35 | + */ | ||
36 | + public function login() | ||
37 | + { | ||
38 | + header("Location:" . $this->getAuthorizeUrl()); | ||
39 | + } | ||
40 | + | ||
41 | + /** | ||
42 | + * 获取authorize_url | ||
43 | + */ | ||
44 | + public function getAuthorizeUrl() | ||
45 | + { | ||
46 | + $state = md5(uniqid(rand(), true)); | ||
47 | + Session::set('state', $state); | ||
48 | + $queryarr = array( | ||
49 | + "response_type" => "code", | ||
50 | + "client_id" => $this->config['app_id'], | ||
51 | + "redirect_uri" => $this->config['callback'], | ||
52 | + "scope" => $this->config['scope'], | ||
53 | + "state" => $state, | ||
54 | + ); | ||
55 | + request()->isMobile() && $queryarr['display'] = 'mobile'; | ||
56 | + $url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr); | ||
57 | + return $url; | ||
58 | + } | ||
59 | + | ||
60 | + /** | ||
61 | + * 获取用户信息 | ||
62 | + * @param array $params | ||
63 | + * @return array | ||
64 | + */ | ||
65 | + public function getUserInfo($params = []) | ||
66 | + { | ||
67 | + $params = $params ? $params : $_GET; | ||
68 | + if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) { | ||
69 | + //获取access_token | ||
70 | + $data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params; | ||
71 | + $access_token = isset($data['access_token']) ? $data['access_token'] : ''; | ||
72 | + $refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : ''; | ||
73 | + $expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0; | ||
74 | + if ($access_token) { | ||
75 | + $openid = $this->getOpenId($access_token); | ||
76 | + //获取用户信息 | ||
77 | + $queryarr = [ | ||
78 | + "access_token" => $access_token, | ||
79 | + "oauth_consumer_key" => $this->config['app_id'], | ||
80 | + "openid" => $openid, | ||
81 | + ]; | ||
82 | + $ret = Http::get(self::GET_USERINFO_URL, $queryarr); | ||
83 | + $userinfo = (array)json_decode($ret, true); | ||
84 | + if (!$userinfo || !isset($userinfo['ret']) || $userinfo['ret'] !== 0) { | ||
85 | + return []; | ||
86 | + } | ||
87 | + $userinfo = $userinfo ? $userinfo : []; | ||
88 | + $userinfo['avatar'] = isset($userinfo['figureurl_qq_2']) ? $userinfo['figureurl_qq_2'] : ''; | ||
89 | + $data = [ | ||
90 | + 'access_token' => $access_token, | ||
91 | + 'refresh_token' => $refresh_token, | ||
92 | + 'expires_in' => $expires_in, | ||
93 | + 'openid' => $openid, | ||
94 | + 'userinfo' => $userinfo | ||
95 | + ]; | ||
96 | + return $data; | ||
97 | + } | ||
98 | + } | ||
99 | + return []; | ||
100 | + } | ||
101 | + | ||
102 | + /** | ||
103 | + * 获取access_token | ||
104 | + * @param string $code | ||
105 | + * @return array | ||
106 | + */ | ||
107 | + public function getAccessToken($code = '') | ||
108 | + { | ||
109 | + if (!$code) { | ||
110 | + return []; | ||
111 | + } | ||
112 | + $queryarr = array( | ||
113 | + "grant_type" => "authorization_code", | ||
114 | + "client_id" => $this->config['app_id'], | ||
115 | + "client_secret" => $this->config['app_secret'], | ||
116 | + "redirect_uri" => $this->config['callback'], | ||
117 | + "code" => $code, | ||
118 | + ); | ||
119 | + $ret = Http::get(self::GET_ACCESS_TOKEN_URL, $queryarr); | ||
120 | + $params = []; | ||
121 | + parse_str($ret, $params); | ||
122 | + return $params ? $params : []; | ||
123 | + } | ||
124 | + | ||
125 | + /** | ||
126 | + * 获取open_id | ||
127 | + * @param string $access_token | ||
128 | + * @return string | ||
129 | + */ | ||
130 | + private function getOpenId($access_token = '') | ||
131 | + { | ||
132 | + $response = Http::get(self::GET_OPENID_URL, ['access_token' => $access_token]); | ||
133 | + if (strpos($response, "callback") !== false) { | ||
134 | + $lpos = strpos($response, "("); | ||
135 | + $rpos = strrpos($response, ")"); | ||
136 | + $response = substr($response, $lpos + 1, $rpos - $lpos - 1); | ||
137 | + } | ||
138 | + $user = (array)json_decode($response, true); | ||
139 | + return isset($user['openid']) ? $user['openid'] : ''; | ||
140 | + } | ||
141 | +} |
addons/third/library/Service.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\third\library; | ||
4 | + | ||
5 | +use addons\third\model\Third; | ||
6 | +use app\common\model\User; | ||
7 | +use fast\Random; | ||
8 | +use think\Db; | ||
9 | +use think\Exception; | ||
10 | + | ||
11 | +/** | ||
12 | + * 第三方登录服务类 | ||
13 | + * | ||
14 | + */ | ||
15 | +class Service | ||
16 | +{ | ||
17 | + | ||
18 | + /** | ||
19 | + * 第三方登录 | ||
20 | + * @param string $platform 平台 | ||
21 | + * @param array $params 参数 | ||
22 | + * @param array $extend 会员扩展信息 | ||
23 | + * @param int $keeptime 有效时长 | ||
24 | + * @return boolean | ||
25 | + */ | ||
26 | + public static function connect($platform, $params = [], $extend = [], $keeptime = 0) | ||
27 | + { | ||
28 | + | ||
29 | + $time = time(); | ||
30 | + $nickname = $params['nickname'] ?? ($params['userinfo']['nickname'] ?? ''); | ||
31 | + $avatar = $params['avatar'] ?? ($params['userinfo']['avatar'] ?? ''); | ||
32 | + $values = [ | ||
33 | + 'platform' => $platform, | ||
34 | + 'openid' => $params['openid'], | ||
35 | + 'openname' => $nickname, | ||
36 | + 'access_token' => $params['access_token'], | ||
37 | + 'refresh_token' => $params['refresh_token'], | ||
38 | + 'expires_in' => $params['expires_in'], | ||
39 | + 'logintime' => $time, | ||
40 | + 'expiretime' => $time + $params['expires_in'], | ||
41 | + ]; | ||
42 | + $values = array_merge($values, $params); | ||
43 | + | ||
44 | + $auth = \app\common\library\Auth::instance(); | ||
45 | + | ||
46 | + $auth->keeptime($keeptime); | ||
47 | + //是否有自己的 | ||
48 | + $third = Third::get(['platform' => $platform, 'openid' => $params['openid']], 'user'); | ||
49 | + if ($third) { | ||
50 | + if (!$third->user) { | ||
51 | + $third->delete(); | ||
52 | + } else { | ||
53 | + $third->allowField(true)->save($values); | ||
54 | + // 写入登录Cookies和Token | ||
55 | + return $auth->direct($third->user_id); | ||
56 | + } | ||
57 | + } | ||
58 | + | ||
59 | + //存在unionid就需要判断是否需要生成新记录 | ||
60 | + if (isset($params['unionid']) && !empty($params['unionid'])) { | ||
61 | + $third = Third::get(['platform' => $platform, 'unionid' => $params['unionid']], 'user'); | ||
62 | + if ($third) { | ||
63 | + if (!$third->user) { | ||
64 | + $third->delete(); | ||
65 | + } else { | ||
66 | + // 保存第三方信息 | ||
67 | + $values['user_id'] = $third->user_id; | ||
68 | + $third = Third::create($values, true); | ||
69 | + // 写入登录Cookies和Token | ||
70 | + return $auth->direct($third->user_id); | ||
71 | + } | ||
72 | + } | ||
73 | + } | ||
74 | + | ||
75 | + if ($auth->id) { | ||
76 | + if (!$third) { | ||
77 | + $values['user_id'] = $auth->id; | ||
78 | + Third::create($values, true); | ||
79 | + } | ||
80 | + $user = $auth->getUser(); | ||
81 | + } else { | ||
82 | + // 先随机一个用户名,随后再变更为u+数字id | ||
83 | + $username = Random::alnum(20); | ||
84 | + $password = Random::alnum(6); | ||
85 | + $domain = request()->host(); | ||
86 | + | ||
87 | + Db::startTrans(); | ||
88 | + try { | ||
89 | + // 默认注册一个会员 | ||
90 | + $result = $auth->register($username, $password, $username . '@' . $domain, '', $extend); | ||
91 | + if (!$result) { | ||
92 | + throw new Exception($auth->getError()); | ||
93 | + } | ||
94 | + $user = $auth->getUser(); | ||
95 | + $fields = ['username' => 'u' . $user->id, 'email' => 'u' . $user->id . '@' . $domain]; | ||
96 | + if ($nickname) { | ||
97 | + $fields['nickname'] = $nickname; | ||
98 | + } | ||
99 | + if ($avatar) { | ||
100 | + $fields['avatar'] = htmlspecialchars(strip_tags($avatar)); | ||
101 | + } | ||
102 | + | ||
103 | + // 更新会员资料 | ||
104 | + $user = User::get($user->id); | ||
105 | + $user->save($fields); | ||
106 | + | ||
107 | + // 保存第三方信息 | ||
108 | + $values['user_id'] = $user->id; | ||
109 | + Third::create($values, true); | ||
110 | + Db::commit(); | ||
111 | + } catch (\Exception $e) { | ||
112 | + Db::rollback(); | ||
113 | + $auth->logout(); | ||
114 | + return false; | ||
115 | + } | ||
116 | + } | ||
117 | + // 写入登录Cookies和Token | ||
118 | + return $auth->direct($user->id); | ||
119 | + } | ||
120 | + | ||
121 | + | ||
122 | + public static function isBindThird($platform, $openid, $apptype = '', $unionid = '') | ||
123 | + { | ||
124 | + $conddtions = [ | ||
125 | + 'platform' => $platform, | ||
126 | + 'openid' => $openid | ||
127 | + ]; | ||
128 | + if ($apptype) { | ||
129 | + $conddtions['apptype'] = $apptype; | ||
130 | + } | ||
131 | + $third = Third::get($conddtions, 'user'); | ||
132 | + //第三方存在 | ||
133 | + if ($third) { | ||
134 | + //用户失效 | ||
135 | + if (!$third->user) { | ||
136 | + $third->delete(); | ||
137 | + return false; | ||
138 | + } | ||
139 | + return true; | ||
140 | + } | ||
141 | + if ($unionid) { | ||
142 | + $third = Third::get(['platform' => $platform, 'unionid' => $unionid], 'user'); | ||
143 | + if ($third) { | ||
144 | + // | ||
145 | + if (!$third->user) { | ||
146 | + $third->delete(); | ||
147 | + return false; | ||
148 | + } | ||
149 | + return true; | ||
150 | + } | ||
151 | + } | ||
152 | + | ||
153 | + return false; | ||
154 | + } | ||
155 | +} |
addons/third/library/Wechat.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\third\library; | ||
4 | + | ||
5 | +use fast\Http; | ||
6 | +use think\Config; | ||
7 | +use think\Session; | ||
8 | + | ||
9 | +/** | ||
10 | + * 微信 | ||
11 | + */ | ||
12 | +class Wechat | ||
13 | +{ | ||
14 | + const GET_AUTH_CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize"; | ||
15 | + const GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token"; | ||
16 | + const GET_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo"; | ||
17 | + | ||
18 | + /** | ||
19 | + * 配置信息 | ||
20 | + * @var array | ||
21 | + */ | ||
22 | + private $config = []; | ||
23 | + | ||
24 | + public function __construct($options = []) | ||
25 | + { | ||
26 | + if ($config = Config::get('third.wechat')) { | ||
27 | + $this->config = array_merge($this->config, $config); | ||
28 | + } | ||
29 | + $this->config = array_merge($this->config, is_array($options) ? $options : []); | ||
30 | + } | ||
31 | + | ||
32 | + /** | ||
33 | + * 登陆 | ||
34 | + */ | ||
35 | + public function login() | ||
36 | + { | ||
37 | + header("Location:" . $this->getAuthorizeUrl()); | ||
38 | + } | ||
39 | + | ||
40 | + /** | ||
41 | + * 获取authorize_url | ||
42 | + */ | ||
43 | + public function getAuthorizeUrl() | ||
44 | + { | ||
45 | + $state = md5(uniqid(rand(), true)); | ||
46 | + Session::set('state', $state); | ||
47 | + $queryarr = array( | ||
48 | + "appid" => $this->config['app_id'], | ||
49 | + "redirect_uri" => $this->config['callback'], | ||
50 | + "response_type" => "code", | ||
51 | + "scope" => $this->config['scope'], | ||
52 | + "state" => $state, | ||
53 | + ); | ||
54 | + request()->isMobile() && $queryarr['display'] = 'mobile'; | ||
55 | + $url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr) . '#wechat_redirect'; | ||
56 | + return $url; | ||
57 | + } | ||
58 | + | ||
59 | + /** | ||
60 | + * 获取用户信息 | ||
61 | + * @param array $params | ||
62 | + * @return array | ||
63 | + */ | ||
64 | + public function getUserInfo($params = []) | ||
65 | + { | ||
66 | + $params = $params ? $params : request()->get(); | ||
67 | + if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) { | ||
68 | + //获取access_token | ||
69 | + $data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params; | ||
70 | + $access_token = isset($data['access_token']) ? $data['access_token'] : ''; | ||
71 | + $refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : ''; | ||
72 | + $expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0; | ||
73 | + if ($access_token) { | ||
74 | + $openid = isset($data['openid']) ? $data['openid'] : ''; | ||
75 | + $unionid = isset($data['unionid']) ? $data['unionid'] : ''; | ||
76 | + if (stripos($this->config['scope'], 'snsapi_userinfo') !== false) { | ||
77 | + //获取用户信息 | ||
78 | + $queryarr = [ | ||
79 | + "access_token" => $access_token, | ||
80 | + "openid" => $openid, | ||
81 | + "lang" => 'zh_CN' | ||
82 | + ]; | ||
83 | + $ret = Http::get(self::GET_USERINFO_URL, $queryarr); | ||
84 | + $userinfo = (array)json_decode($ret, true); | ||
85 | + if (!$userinfo || isset($userinfo['errcode'])) { | ||
86 | + return []; | ||
87 | + } | ||
88 | + $userinfo = $userinfo ? $userinfo : []; | ||
89 | + $userinfo['avatar'] = isset($userinfo['headimgurl']) ? $userinfo['headimgurl'] : ''; | ||
90 | + } else { | ||
91 | + $userinfo = []; | ||
92 | + } | ||
93 | + $data = [ | ||
94 | + 'access_token' => $access_token, | ||
95 | + 'refresh_token' => $refresh_token, | ||
96 | + 'expires_in' => $expires_in, | ||
97 | + 'openid' => $openid, | ||
98 | + 'unionid' => $unionid, | ||
99 | + 'userinfo' => $userinfo | ||
100 | + ]; | ||
101 | + return $data; | ||
102 | + } | ||
103 | + } | ||
104 | + return []; | ||
105 | + } | ||
106 | + | ||
107 | + /** | ||
108 | + * 获取access_token | ||
109 | + * @param string code | ||
110 | + * @return array | ||
111 | + */ | ||
112 | + public function getAccessToken($code = '') | ||
113 | + { | ||
114 | + if (!$code) { | ||
115 | + return []; | ||
116 | + } | ||
117 | + $queryarr = array( | ||
118 | + "appid" => $this->config['app_id'], | ||
119 | + "secret" => $this->config['app_secret'], | ||
120 | + "code" => $code, | ||
121 | + "grant_type" => "authorization_code", | ||
122 | + ); | ||
123 | + $response = Http::get(self::GET_ACCESS_TOKEN_URL, $queryarr); | ||
124 | + $ret = (array)json_decode($response, true); | ||
125 | + return $ret ? $ret : []; | ||
126 | + } | ||
127 | +} |
addons/third/library/Weibo.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\third\library; | ||
4 | + | ||
5 | +use fast\Http; | ||
6 | +use think\Config; | ||
7 | +use think\Session; | ||
8 | + | ||
9 | +/** | ||
10 | + * 微博 | ||
11 | + */ | ||
12 | +class Weibo | ||
13 | +{ | ||
14 | + const GET_AUTH_CODE_URL = "https://api.weibo.com/oauth2/authorize"; | ||
15 | + const GET_ACCESS_TOKEN_URL = "https://api.weibo.com/oauth2/access_token"; | ||
16 | + const GET_USERINFO_URL = "https://api.weibo.com/2/users/show.json"; | ||
17 | + | ||
18 | + /** | ||
19 | + * 配置信息 | ||
20 | + * @var array | ||
21 | + */ | ||
22 | + private $config = []; | ||
23 | + | ||
24 | + public function __construct($options = []) | ||
25 | + { | ||
26 | + if ($config = Config::get('third.weibo')) { | ||
27 | + $this->config = array_merge($this->config, $config); | ||
28 | + } | ||
29 | + $this->config = array_merge($this->config, is_array($options) ? $options : []); | ||
30 | + } | ||
31 | + | ||
32 | + /** | ||
33 | + * 登陆 | ||
34 | + */ | ||
35 | + public function login() | ||
36 | + { | ||
37 | + header("Location:" . $this->getAuthorizeUrl()); | ||
38 | + } | ||
39 | + | ||
40 | + /** | ||
41 | + * 获取authorize_url | ||
42 | + */ | ||
43 | + public function getAuthorizeUrl() | ||
44 | + { | ||
45 | + $state = md5(uniqid(rand(), true)); | ||
46 | + Session::set('state', $state); | ||
47 | + $queryarr = array( | ||
48 | + "response_type" => "code", | ||
49 | + "client_id" => $this->config['app_id'], | ||
50 | + "redirect_uri" => $this->config['callback'], | ||
51 | + "state" => $state, | ||
52 | + ); | ||
53 | + request()->isMobile() && $queryarr['display'] = 'mobile'; | ||
54 | + $url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr); | ||
55 | + return $url; | ||
56 | + } | ||
57 | + | ||
58 | + /** | ||
59 | + * 获取用户信息 | ||
60 | + * @param array $params | ||
61 | + * @return array | ||
62 | + */ | ||
63 | + public function getUserInfo($params = []) | ||
64 | + { | ||
65 | + $params = $params ? $params : $_GET; | ||
66 | + if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) { | ||
67 | + //获取access_token | ||
68 | + $data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params; | ||
69 | + $access_token = isset($data['access_token']) ? $data['access_token'] : ''; | ||
70 | + $refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : ''; | ||
71 | + $expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0; | ||
72 | + if ($access_token) { | ||
73 | + $uid = isset($data['uid']) ? $data['uid'] : ''; | ||
74 | + //获取用户信息 | ||
75 | + $queryarr = [ | ||
76 | + "access_token" => $access_token, | ||
77 | + "uid" => $uid, | ||
78 | + ]; | ||
79 | + $ret = Http::get(self::GET_USERINFO_URL, $queryarr); | ||
80 | + $userinfo = (array)json_decode($ret, true); | ||
81 | + if (!$userinfo || isset($userinfo['error_code'])) { | ||
82 | + return []; | ||
83 | + } | ||
84 | + $userinfo = $userinfo ? $userinfo : []; | ||
85 | + $userinfo['nickname'] = isset($userinfo['screen_name']) ? $userinfo['screen_name'] : ''; | ||
86 | + $userinfo['avatar'] = isset($userinfo['profile_image_url']) ? $userinfo['profile_image_url'] : ''; | ||
87 | + $data = [ | ||
88 | + 'access_token' => $access_token, | ||
89 | + 'refresh_token' => $refresh_token, | ||
90 | + 'expires_in' => $expires_in, | ||
91 | + 'openid' => $uid, | ||
92 | + 'userinfo' => $userinfo | ||
93 | + ]; | ||
94 | + return $data; | ||
95 | + } | ||
96 | + } | ||
97 | + return []; | ||
98 | + } | ||
99 | + | ||
100 | + /** | ||
101 | + * 获取access_token | ||
102 | + * @param string code | ||
103 | + * @return array | ||
104 | + */ | ||
105 | + public function getAccessToken($code = '') | ||
106 | + { | ||
107 | + if (!$code) { | ||
108 | + return ''; | ||
109 | + } | ||
110 | + $queryarr = array( | ||
111 | + "grant_type" => "authorization_code", | ||
112 | + "client_id" => $this->config['app_id'], | ||
113 | + "client_secret" => $this->config['app_secret'], | ||
114 | + "redirect_uri" => $this->config['callback'], | ||
115 | + "code" => $code, | ||
116 | + ); | ||
117 | + $response = Http::post(self::GET_ACCESS_TOKEN_URL, $queryarr); | ||
118 | + $ret = (array)json_decode($response, true); | ||
119 | + return $ret ? $ret : []; | ||
120 | + } | ||
121 | +} |
addons/third/model/Third.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\third\model; | ||
4 | + | ||
5 | +use think\Model; | ||
6 | + | ||
7 | +/** | ||
8 | + * 第三方登录模型 | ||
9 | + */ | ||
10 | +class Third extends Model | ||
11 | +{ | ||
12 | + | ||
13 | + // 开启自动写入时间戳字段 | ||
14 | + protected $autoWriteTimestamp = 'int'; | ||
15 | + // 定义时间戳字段名 | ||
16 | + protected $createTime = 'createtime'; | ||
17 | + protected $updateTime = 'updatetime'; | ||
18 | + // 追加属性 | ||
19 | + protected $append = [ | ||
20 | + ]; | ||
21 | + | ||
22 | + public function user() | ||
23 | + { | ||
24 | + return $this->belongsTo('\app\common\model\User', 'user_id', 'id', [], 'LEFT'); | ||
25 | + } | ||
26 | +} |
addons/third/view/index/index.html
0 → 100644
1 | +<!DOCTYPE html> | ||
2 | +<html> | ||
3 | +<head> | ||
4 | + <title>第三方登录 - {$site.name}</title> | ||
5 | + <meta charset="UTF-8"> | ||
6 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
7 | + | ||
8 | + <link href="__CDN__/assets/css/frontend.min.css" rel="stylesheet"> | ||
9 | + | ||
10 | + <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> | ||
11 | + <!--[if lt IE 9]> | ||
12 | + <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script> | ||
13 | + <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script> | ||
14 | + <![endif]--> | ||
15 | + | ||
16 | +</head> | ||
17 | +<body> | ||
18 | +<div class="container"> | ||
19 | + <h2>第三方登录</h2> | ||
20 | + <hr> | ||
21 | + <div class="well"> | ||
22 | + <div class="row"> | ||
23 | + <div class="col-xs-4"> | ||
24 | + {if $user && in_array('qq', $platformList)} | ||
25 | + <a href="{:addon_url('third/index/unbind',[':platform'=>'qq'])}" class="btn btn-block btn-info"> | ||
26 | + <i class="fa fa-qq"></i> 点击解绑 | ||
27 | + </a> | ||
28 | + {else/} | ||
29 | + <a href="{:addon_url('third/index/connect',[':platform'=>'qq'])}" class="btn btn-block btn-info"> | ||
30 | + <i class="fa fa-qq"></i> QQ登录 | ||
31 | + </a> | ||
32 | + {/if} | ||
33 | + </div> | ||
34 | + <div class="col-xs-4"> | ||
35 | + {if $user && in_array('wechat', $platformList)} | ||
36 | + <a href="{:addon_url('third/index/unbind',[':platform'=>'wechat'])}" class="btn btn-block btn-success"> | ||
37 | + <i class="fa fa-wechat"></i> 点击解绑 | ||
38 | + </a> | ||
39 | + {else/} | ||
40 | + <a href="{:addon_url('third/index/connect',[':platform'=>'wechat'])}" class="btn btn-block btn-success"> | ||
41 | + <i class="fa fa-wechat"></i> 微信登录 | ||
42 | + </a> | ||
43 | + {/if} | ||
44 | + </div> | ||
45 | + <div class="col-xs-4"> | ||
46 | + {if $user && in_array('weibo', $platformList)} | ||
47 | + <a href="{:addon_url('third/index/unbind',[':platform'=>'weibo'])}" class="btn btn-block btn-danger"> | ||
48 | + <i class="fa fa-weibo"></i> 点击解绑 | ||
49 | + </a> | ||
50 | + {else/} | ||
51 | + <a href="{:addon_url('third/index/connect',[':platform'=>'weibo'])}" class="btn btn-block btn-danger"> | ||
52 | + <i class="fa fa-weibo"></i> 微博登录 | ||
53 | + </a> | ||
54 | + {/if} | ||
55 | + </div> | ||
56 | + </div> | ||
57 | + </div> | ||
58 | + <h2>相关链接</h2> | ||
59 | + <hr> | ||
60 | + <table class="table table-striped table-hover"> | ||
61 | + <thead> | ||
62 | + <tr> | ||
63 | + <th>QQ</th> | ||
64 | + <th>链接</th> | ||
65 | + </tr> | ||
66 | + </thead> | ||
67 | + <tbody> | ||
68 | + <tr> | ||
69 | + <td>QQ 连接</td> | ||
70 | + <td>{:addon_url('third/index/connect',[':platform'=>'qq'], false, true)}</td> | ||
71 | + </tr> | ||
72 | + <tr> | ||
73 | + <td>QQ 绑定</td> | ||
74 | + <td>{:addon_url('third/index/bind',[':platform'=>'qq'], false, true)}</td> | ||
75 | + </tr> | ||
76 | + <tr> | ||
77 | + <td>QQ 解绑</td> | ||
78 | + <td>{:addon_url('third/index/unbind',[':platform'=>'qq'], false, true)}</td> | ||
79 | + </tr> | ||
80 | + </tbody> | ||
81 | + </table> | ||
82 | + <table class="table table-striped table-hover"> | ||
83 | + <thead> | ||
84 | + <tr> | ||
85 | + <th>微信</th> | ||
86 | + <th>链接</th> | ||
87 | + </tr> | ||
88 | + </thead> | ||
89 | + <tbody> | ||
90 | + <tr> | ||
91 | + <td>微信 连接</td> | ||
92 | + <td>{:addon_url('third/index/connect',[':platform'=>'wechat'], false, true)}</td> | ||
93 | + </tr> | ||
94 | + <tr> | ||
95 | + <td>微信 绑定</td> | ||
96 | + <td>{:addon_url('third/index/bind',[':platform'=>'wechat'], false, true)}</td> | ||
97 | + </tr> | ||
98 | + <tr> | ||
99 | + <td>微信 解绑</td> | ||
100 | + <td>{:addon_url('third/index/unbind',[':platform'=>'wechat'], false, true)}</td> | ||
101 | + </tr> | ||
102 | + </tbody> | ||
103 | + </table> | ||
104 | + <table class="table table-striped table-hover"> | ||
105 | + <thead> | ||
106 | + <tr> | ||
107 | + <th>微博</th> | ||
108 | + <th>链接</th> | ||
109 | + </tr> | ||
110 | + </thead> | ||
111 | + <tbody> | ||
112 | + <tr> | ||
113 | + <td>微博 连接</td> | ||
114 | + <td>{:addon_url('third/index/connect',[':platform'=>'weibo'], false, true)}</td> | ||
115 | + </tr> | ||
116 | + <tr> | ||
117 | + <td>微博 绑定</td> | ||
118 | + <td>{:addon_url('third/index/bind',[':platform'=>'weibo'], false, true)}</td> | ||
119 | + </tr> | ||
120 | + <tr> | ||
121 | + <td>微博 解绑</td> | ||
122 | + <td>{:addon_url('third/index/unbind',[':platform'=>'weibo'], false, true)}</td> | ||
123 | + </tr> | ||
124 | + </tbody> | ||
125 | + </table> | ||
126 | +</div> | ||
127 | +<!-- jQuery --> | ||
128 | +<script src="https://cdn.jsdelivr.net/npm/jquery@2.1.4/dist/jquery.min.js"></script> | ||
129 | + | ||
130 | +<!-- Bootstrap Core JavaScript --> | ||
131 | +<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script> | ||
132 | + | ||
133 | +<script type="text/javascript"> | ||
134 | + $(function () { | ||
135 | + | ||
136 | + }); | ||
137 | +</script> | ||
138 | +</body> | ||
139 | +</html> |
addons/ueditor/.addonrc
0 → 100644
1 | +{"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"]} |
addons/ueditor/Ueditor.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\ueditor; | ||
4 | + | ||
5 | +use think\Addons; | ||
6 | + | ||
7 | +/** | ||
8 | + * 百度Ueditor插件 | ||
9 | + */ | ||
10 | +class Ueditor extends Addons | ||
11 | +{ | ||
12 | + | ||
13 | + /** | ||
14 | + * 插件安装方法 | ||
15 | + * @return bool | ||
16 | + */ | ||
17 | + public function install() | ||
18 | + { | ||
19 | + return true; | ||
20 | + } | ||
21 | + | ||
22 | + /** | ||
23 | + * 插件卸载方法 | ||
24 | + * @return bool | ||
25 | + */ | ||
26 | + public function uninstall() | ||
27 | + { | ||
28 | + return true; | ||
29 | + } | ||
30 | + | ||
31 | + /** | ||
32 | + * @param $params | ||
33 | + */ | ||
34 | + public function configInit(&$params) | ||
35 | + { | ||
36 | + $config = $this->getConfig(); | ||
37 | + $params['ueditor'] = ['classname' => $config['classname']??'.editor']; | ||
38 | + } | ||
39 | +} |
addons/ueditor/bootstrap.js
0 → 100644
1 | +window.UEDITOR_HOME_URL = Config.__CDN__ + "/assets/addons/ueditor/"; | ||
2 | +require.config({ | ||
3 | + paths: { | ||
4 | + 'ueditor.config': '../addons/ueditor/ueditor.config', | ||
5 | + 'ueditor': '../addons/ueditor/ueditor.all.min', | ||
6 | + 'ueditor.zh': '../addons/ueditor/i18n/zh-cn/zh-cn', | ||
7 | + 'zeroclipboard': '../addons/ueditor/third-party/zeroclipboard/ZeroClipboard.min', | ||
8 | + }, | ||
9 | + shim: { | ||
10 | + 'ueditor': { | ||
11 | + deps: ['zeroclipboard', 'ueditor.config'], | ||
12 | + exports: 'UE', | ||
13 | + init: function (ZeroClipboard) { | ||
14 | + //导出到全局变量,供ueditor使用 | ||
15 | + window.ZeroClipboard = ZeroClipboard; | ||
16 | + }, | ||
17 | + }, | ||
18 | + 'ueditor.zh': ['ueditor'] | ||
19 | + } | ||
20 | +}); | ||
21 | +require(['form', 'upload'], function (Form, Upload) { | ||
22 | + var _bindevent = Form.events.bindevent; | ||
23 | + Form.events.bindevent = function (form) { | ||
24 | + _bindevent.apply(this, [form]); | ||
25 | + try { | ||
26 | + //绑定editor事件 | ||
27 | + require(['ueditor', 'ueditor.zh'], function (UE, undefined) { | ||
28 | + UE.list = []; | ||
29 | + window.UEDITOR_CONFIG['uploadService'] = function (context, editor) { | ||
30 | + return { | ||
31 | + Upload: () => { return Upload }, | ||
32 | + Fast: () => { return Fast }, | ||
33 | + } | ||
34 | + }; | ||
35 | + $(Config.ueditor.classname || '.editor', form).each(function () { | ||
36 | + var id = $(this).attr("id"); | ||
37 | + var name = $(this).attr("name"); | ||
38 | + $(this).removeClass('form-control'); | ||
39 | + UE.list[id] = UE.getEditor(id, { | ||
40 | + allowDivTransToP: false, //阻止div自动转p标签 | ||
41 | + initialFrameWidth: '100%', | ||
42 | + initialFrameHeight: 320, | ||
43 | + autoFloatEnabled: false, | ||
44 | + // autoHeightEnabled: true, //自动高度 | ||
45 | + zIndex: 90, | ||
46 | + xssFilterRules: false, | ||
47 | + outputXssFilter: false, | ||
48 | + inputXssFilter: false, | ||
49 | + catchRemoteImageEnable: true | ||
50 | + }); | ||
51 | + UE.list[id].addListener("contentChange", function () { | ||
52 | + $('#' + id).val(this.getContent()); | ||
53 | + $('textarea[name="' + name + '"]').val(this.getContent()); | ||
54 | + }) | ||
55 | + }); | ||
56 | + }) | ||
57 | + } catch (e) { | ||
58 | + console.log('绑定editor事件', e) | ||
59 | + } | ||
60 | + } | ||
61 | +}); |
addons/ueditor/config.php
0 → 100644
addons/ueditor/info.ini
0 → 100644
addons/wechat/.addonrc
0 → 100644
1 | +{"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"]} |
addons/wechat/Wechat.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\wechat; | ||
4 | + | ||
5 | +use app\common\library\Menu; | ||
6 | +use think\Addons; | ||
7 | + | ||
8 | +/** | ||
9 | + * 微信插件 | ||
10 | + */ | ||
11 | +class Wechat extends Addons | ||
12 | +{ | ||
13 | + | ||
14 | + /** | ||
15 | + * 插件安装方法 | ||
16 | + * @return bool | ||
17 | + */ | ||
18 | + public function install() | ||
19 | + { | ||
20 | + $menu = [ | ||
21 | + [ | ||
22 | + 'name' => 'wechat', | ||
23 | + 'title' => '微信管理', | ||
24 | + 'icon' => 'fa fa-wechat', | ||
25 | + 'sublist' => [ | ||
26 | + [ | ||
27 | + 'name' => 'wechat/autoreply', | ||
28 | + 'title' => '自动回复管理', | ||
29 | + 'icon' => 'fa fa-reply-all', | ||
30 | + 'sublist' => [ | ||
31 | + ['name' => 'wechat/autoreply/index', 'title' => '查看'], | ||
32 | + ['name' => 'wechat/autoreply/add', 'title' => '添加'], | ||
33 | + ['name' => 'wechat/autoreply/edit', 'title' => '修改'], | ||
34 | + ['name' => 'wechat/autoreply/del', 'title' => '删除'], | ||
35 | + ['name' => 'wechat/autoreply/multi', 'title' => '批量更新'], | ||
36 | + ] | ||
37 | + ], | ||
38 | + [ | ||
39 | + 'name' => 'wechat/config', | ||
40 | + 'title' => '配置管理', | ||
41 | + 'icon' => 'fa fa-cog', | ||
42 | + 'sublist' => [ | ||
43 | + ['name' => 'wechat/config/index', 'title' => '查看'], | ||
44 | + ['name' => 'wechat/config/add', 'title' => '添加'], | ||
45 | + ['name' => 'wechat/config/edit', 'title' => '修改'], | ||
46 | + ['name' => 'wechat/config/del', 'title' => '删除'], | ||
47 | + ['name' => 'wechat/config/multi', 'title' => '批量更新'], | ||
48 | + ] | ||
49 | + ], | ||
50 | + [ | ||
51 | + 'name' => 'wechat/menu', | ||
52 | + 'title' => '菜单管理', | ||
53 | + 'icon' => 'fa fa-list', | ||
54 | + 'sublist' => [ | ||
55 | + ['name' => 'wechat/menu/index', 'title' => '查看'], | ||
56 | + ['name' => 'wechat/menu/add', 'title' => '添加'], | ||
57 | + ['name' => 'wechat/menu/edit', 'title' => '修改'], | ||
58 | + ['name' => 'wechat/menu/del', 'title' => '删除'], | ||
59 | + ['name' => 'wechat/menu/remote', 'title' => '加载远程菜单'], | ||
60 | + ['name' => 'wechat/menu/sync', 'title' => '同步'], | ||
61 | + ['name' => 'wechat/menu/multi', 'title' => '批量更新'], | ||
62 | + ] | ||
63 | + ], | ||
64 | + [ | ||
65 | + 'name' => 'wechat/response', | ||
66 | + 'title' => '资源管理', | ||
67 | + 'icon' => 'fa fa-list-alt', | ||
68 | + 'sublist' => [ | ||
69 | + ['name' => 'wechat/response/index', 'title' => '查看'], | ||
70 | + ['name' => 'wechat/response/add', 'title' => '添加'], | ||
71 | + ['name' => 'wechat/response/edit', 'title' => '修改'], | ||
72 | + ['name' => 'wechat/response/del', 'title' => '删除'], | ||
73 | + ['name' => 'wechat/response/select', 'title' => '选择'], | ||
74 | + ['name' => 'wechat/response/multi', 'title' => '批量更新'], | ||
75 | + ] | ||
76 | + ] | ||
77 | + ] | ||
78 | + ] | ||
79 | + ]; | ||
80 | + Menu::create($menu); | ||
81 | + return true; | ||
82 | + } | ||
83 | + | ||
84 | + /** | ||
85 | + * 插件卸载方法 | ||
86 | + * @return bool | ||
87 | + */ | ||
88 | + public function uninstall() | ||
89 | + { | ||
90 | + Menu::delete('wechat'); | ||
91 | + return true; | ||
92 | + } | ||
93 | + | ||
94 | + /** | ||
95 | + * 插件启用方法 | ||
96 | + */ | ||
97 | + public function enable() | ||
98 | + { | ||
99 | + Menu::enable('wechat'); | ||
100 | + } | ||
101 | + | ||
102 | + /** | ||
103 | + * 插件禁用方法 | ||
104 | + */ | ||
105 | + public function disable() | ||
106 | + { | ||
107 | + Menu::disable('wechat'); | ||
108 | + } | ||
109 | + | ||
110 | +} |
addons/wechat/config.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +return [ | ||
4 | + [ | ||
5 | + 'name' => 'app_id', | ||
6 | + 'title' => 'app_id', | ||
7 | + 'type' => 'string', | ||
8 | + 'content' => [], | ||
9 | + 'value' => '', | ||
10 | + 'rule' => 'required', | ||
11 | + 'msg' => '', | ||
12 | + 'tip' => '', | ||
13 | + 'ok' => '', | ||
14 | + 'extend' => '', | ||
15 | + ], | ||
16 | + [ | ||
17 | + 'name' => 'secret', | ||
18 | + 'title' => 'secret', | ||
19 | + 'type' => 'string', | ||
20 | + 'content' => [], | ||
21 | + 'value' => '', | ||
22 | + 'rule' => 'required', | ||
23 | + 'msg' => '', | ||
24 | + 'tip' => '', | ||
25 | + 'ok' => '', | ||
26 | + 'extend' => '', | ||
27 | + ], | ||
28 | + [ | ||
29 | + 'name' => 'token', | ||
30 | + 'title' => 'token', | ||
31 | + 'type' => 'string', | ||
32 | + 'content' => [], | ||
33 | + 'value' => '', | ||
34 | + 'rule' => 'required', | ||
35 | + 'msg' => '', | ||
36 | + 'tip' => '', | ||
37 | + 'ok' => '', | ||
38 | + 'extend' => '', | ||
39 | + ], | ||
40 | + [ | ||
41 | + 'name' => 'aes_key', | ||
42 | + 'title' => 'aes_key', | ||
43 | + 'type' => 'string', | ||
44 | + 'content' => [], | ||
45 | + 'value' => '', | ||
46 | + 'rule' => 'required', | ||
47 | + 'msg' => '', | ||
48 | + 'tip' => '', | ||
49 | + 'ok' => '', | ||
50 | + 'extend' => '', | ||
51 | + ], | ||
52 | + [ | ||
53 | + 'name' => 'debug', | ||
54 | + 'title' => '调试模式', | ||
55 | + 'type' => 'radio', | ||
56 | + 'content' => [ | ||
57 | + '否', | ||
58 | + '是', | ||
59 | + ], | ||
60 | + 'value' => '0', | ||
61 | + 'rule' => 'required', | ||
62 | + 'msg' => '', | ||
63 | + 'tip' => '', | ||
64 | + 'ok' => '', | ||
65 | + 'extend' => '', | ||
66 | + ], | ||
67 | + [ | ||
68 | + 'name' => 'log_level', | ||
69 | + 'title' => '日志记录等级', | ||
70 | + 'type' => 'select', | ||
71 | + 'content' => [ | ||
72 | + 'debug' => 'debug', | ||
73 | + 'info' => 'info', | ||
74 | + 'notice' => 'notice', | ||
75 | + 'warning' => 'warning', | ||
76 | + 'error' => 'error', | ||
77 | + 'critical' => 'critical', | ||
78 | + 'alert' => 'alert', | ||
79 | + 'emergency' => 'emergency', | ||
80 | + ], | ||
81 | + 'value' => 'info', | ||
82 | + 'rule' => 'required', | ||
83 | + 'msg' => '', | ||
84 | + 'tip' => '生产环境日志记录等级', | ||
85 | + 'ok' => '', | ||
86 | + 'extend' => '', | ||
87 | + ], | ||
88 | + [ | ||
89 | + 'name' => 'oauth_callback', | ||
90 | + 'title' => '登录回调', | ||
91 | + 'type' => 'string', | ||
92 | + 'content' => [], | ||
93 | + 'value' => 'http://www.yoursite.com/addons/wechat/index/callback', | ||
94 | + 'rule' => 'required', | ||
95 | + 'msg' => '', | ||
96 | + 'tip' => '', | ||
97 | + 'ok' => '', | ||
98 | + 'extend' => '', | ||
99 | + ], | ||
100 | +]; |
addons/wechat/controller/Captcha.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\wechat\controller; | ||
4 | + | ||
5 | +use addons\wechat\library\Wechat; | ||
6 | +use addons\wechat\model\WechatCaptcha; | ||
7 | +use fast\Http; | ||
8 | + | ||
9 | +/** | ||
10 | + * 微信验证码验证接口 | ||
11 | + */ | ||
12 | +class Captcha extends \think\addons\Controller | ||
13 | +{ | ||
14 | + | ||
15 | + /** | ||
16 | + * 验证码检测接口 | ||
17 | + */ | ||
18 | + public function check() | ||
19 | + { | ||
20 | + $captcha = $this->request->post("captcha"); | ||
21 | + $event = $this->request->post("event"); | ||
22 | + $result = WechatCaptcha::check($captcha, $event); | ||
23 | + if ($result) { | ||
24 | + $this->success("验证码正确"); | ||
25 | + } else { | ||
26 | + $this->error("验证码错误"); | ||
27 | + } | ||
28 | + } | ||
29 | + | ||
30 | + /** | ||
31 | + * 验证码发送接口 | ||
32 | + */ | ||
33 | + public function send() | ||
34 | + { | ||
35 | + $ip = $this->request->ip(); | ||
36 | + $event = $this->request->post("event"); | ||
37 | + if (!$event) { | ||
38 | + $this->error("参数错误"); | ||
39 | + } | ||
40 | + $captch = WechatCaptcha::where('ip', $ip) | ||
41 | + ->where('event', $event) | ||
42 | + ->whereTime('createtime', '-2 minutes') | ||
43 | + ->find(); | ||
44 | + if ($captch) { | ||
45 | + $this->error("获取频繁,请稍后重试"); | ||
46 | + } | ||
47 | + $token = Wechat::getAccessToken(); | ||
48 | + if (!$token) { | ||
49 | + $this->error("发送失败,请稍后重试"); | ||
50 | + } | ||
51 | + $url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={$token}"; | ||
52 | + $params = [ | ||
53 | + 'expire_seconds' => 120, | ||
54 | + 'action_name' => 'QR_STR_SCENE', | ||
55 | + 'action_info' => [ | ||
56 | + 'scene' => [ | ||
57 | + 'scene_str' => "captcha_" . $event . "_" . $ip, | ||
58 | + ] | ||
59 | + ], | ||
60 | + ]; | ||
61 | + //获取验证码 | ||
62 | + $result = Http::sendRequest($url, json_encode($params)); | ||
63 | + if ($result['ret']) { | ||
64 | + $msg = (array)json_decode($result['msg'], true); | ||
65 | + if (isset($msg['ticket']) && isset($msg['url'])) { | ||
66 | + $this->success("", null, ['image' => "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" . urlencode($msg['ticket']), 'url' => $msg['url']]); | ||
67 | + } | ||
68 | + } | ||
69 | + $this->error("获取失败!请稍后重试"); | ||
70 | + } | ||
71 | + | ||
72 | +} |
addons/wechat/controller/Index.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\wechat\controller; | ||
4 | + | ||
5 | +use addons\wechat\library\Config; | ||
6 | +use addons\wechat\model\WechatAutoreply; | ||
7 | +use addons\wechat\model\WechatCaptcha; | ||
8 | +use addons\wechat\model\WechatContext; | ||
9 | +use addons\wechat\model\WechatResponse; | ||
10 | +use addons\wechat\model\WechatConfig; | ||
11 | + | ||
12 | +use EasyWeChat\Factory; | ||
13 | +use addons\wechat\library\Wechat as WechatService; | ||
14 | +use addons\wechat\library\Config as ConfigService; | ||
15 | +use think\Log; | ||
16 | + | ||
17 | +/** | ||
18 | + * 微信接口 | ||
19 | + */ | ||
20 | +class Index extends \think\addons\Controller | ||
21 | +{ | ||
22 | + | ||
23 | + public $app = null; | ||
24 | + | ||
25 | + public function _initialize() | ||
26 | + { | ||
27 | + parent::_initialize(); | ||
28 | + $this->app = Factory::officialAccount(Config::load()); | ||
29 | + } | ||
30 | + | ||
31 | + /** | ||
32 | + * | ||
33 | + */ | ||
34 | + public function index() | ||
35 | + { | ||
36 | + $this->error("当前插件暂无前台页面"); | ||
37 | + } | ||
38 | + | ||
39 | + /** | ||
40 | + * 微信API对接接口 | ||
41 | + */ | ||
42 | + public function api() | ||
43 | + { | ||
44 | + $this->app->server->push(function ($message) { | ||
45 | + $wechatService = new WechatService; | ||
46 | + | ||
47 | + $matches = null; | ||
48 | + $openid = $message['FromUserName']; | ||
49 | + $to_openid = $message['ToUserName']; | ||
50 | + | ||
51 | + $unknownMessage = WechatConfig::getValue('default.unknown.message'); | ||
52 | + $unknownMessage = $unknownMessage ? $unknownMessage : ""; | ||
53 | + | ||
54 | + switch ($message['MsgType']) { | ||
55 | + case 'event': //事件消息 | ||
56 | + $event = $message['Event']; | ||
57 | + $eventkey = $message['EventKey'] ? $message['EventKey'] : $message['Event']; | ||
58 | + //验证码消息 | ||
59 | + if (in_array($event, ['subscribe', 'SCAN']) && preg_match("/^captcha_([a-zA-Z0-9]+)_([0-9\.]+)/", $eventkey, $matches)) { | ||
60 | + return WechatCaptcha::send($openid, $matches[1], $matches[2]); | ||
61 | + } | ||
62 | + switch ($event) { | ||
63 | + case 'subscribe'://添加关注 | ||
64 | + $subscribeMessage = WechatConfig::getValue('default.subscribe.message'); | ||
65 | + $subscribeMessage = $subscribeMessage ? $subscribeMessage : "欢迎关注我们!"; | ||
66 | + return $subscribeMessage; | ||
67 | + case 'unsubscribe'://取消关注 | ||
68 | + return ''; | ||
69 | + case 'LOCATION'://获取地理位置 | ||
70 | + return ''; | ||
71 | + case 'VIEW': //跳转链接,eventkey为链接 | ||
72 | + return ''; | ||
73 | + case 'SCAN': //扫码 | ||
74 | + return ''; | ||
75 | + default: | ||
76 | + break; | ||
77 | + } | ||
78 | + | ||
79 | + $wechatResponse = WechatResponse::where(["eventkey" => $eventkey, 'status' => 'normal'])->find(); | ||
80 | + if ($wechatResponse) { | ||
81 | + $responseContent = (array)json_decode($wechatResponse['content'], true); | ||
82 | + $wechatContext = WechatContext::where(['openid' => $openid])->order('id', 'desc')->find(); | ||
83 | + $data = ['eventkey' => $eventkey, 'command' => '', 'refreshtime' => time(), 'openid' => $openid]; | ||
84 | + if ($wechatContext) { | ||
85 | + $wechatContext->save($data); | ||
86 | + } else { | ||
87 | + $wechatContext = WechatContext::create($data, true); | ||
88 | + } | ||
89 | + $result = $wechatService->response($this, $openid, '', $responseContent, $wechatContext); | ||
90 | + if ($result) { | ||
91 | + return $result; | ||
92 | + } | ||
93 | + } | ||
94 | + return $unknownMessage; | ||
95 | + case 'text': //文字消息 | ||
96 | + case 'image': //图片消息 | ||
97 | + case 'voice': //语音消息 | ||
98 | + case 'video': //视频消息 | ||
99 | + case 'location': //坐标消息 | ||
100 | + case 'link': //链接消息 | ||
101 | + default: //其它消息 | ||
102 | + //自动回复处理 | ||
103 | + if ($message['MsgType'] == 'text') { | ||
104 | + $autoreply = null; | ||
105 | + $autoreplyList = WechatAutoreply::where('status', 'normal')->cache(true)->order('weigh DESC,id DESC')->select(); | ||
106 | + foreach ($autoreplyList as $index => $item) { | ||
107 | + //完全匹配和正则匹配 | ||
108 | + if ($item['text'] == $message['Content'] || (in_array(mb_substr($item['text'], 0, 1), ['#', '~', '/']) && preg_match($item['text'], $message['Content'], $matches))) { | ||
109 | + $autoreply = $item; | ||
110 | + break; | ||
111 | + } | ||
112 | + } | ||
113 | + | ||
114 | + if ($autoreply) { | ||
115 | + $wechatResponse = WechatResponse::where(["eventkey" => $autoreply['eventkey'], 'status' => 'normal'])->find(); | ||
116 | + if ($wechatResponse) { | ||
117 | + $responseContent = (array)json_decode($wechatResponse['content'], true); | ||
118 | + $wechatContext = WechatContext::where(['openid' => $openid])->order('id', 'desc')->find(); | ||
119 | + $result = $wechatService->response($this, $openid, $message['Content'], $responseContent, $wechatContext, $matches); | ||
120 | + if ($result) { | ||
121 | + return $result; | ||
122 | + } | ||
123 | + } | ||
124 | + } | ||
125 | + } | ||
126 | + return $unknownMessage; | ||
127 | + } | ||
128 | + return ""; //SUCCESS | ||
129 | + }); | ||
130 | + | ||
131 | + $response = $this->app->server->serve(); | ||
132 | + // 将响应输出 | ||
133 | + $response->send(); | ||
134 | + return; | ||
135 | + } | ||
136 | + | ||
137 | + /** | ||
138 | + * 登录回调 | ||
139 | + */ | ||
140 | + public function callback() | ||
141 | + { | ||
142 | + | ||
143 | + } | ||
144 | + | ||
145 | + /** | ||
146 | + * 支付回调 | ||
147 | + */ | ||
148 | + public function notify() | ||
149 | + { | ||
150 | + Log::record(file_get_contents('php://input'), "notify"); | ||
151 | + $response = $this->app->handlePaidNotify(function ($message, $fail) { | ||
152 | + // 你的逻辑 | ||
153 | + return true; | ||
154 | + // 或者错误消息 | ||
155 | + $fail('Order not exists.'); | ||
156 | + }); | ||
157 | + | ||
158 | + $response->send(); | ||
159 | + return; | ||
160 | + } | ||
161 | + | ||
162 | +} |
addons/wechat/info.ini
0 → 100644
addons/wechat/install.sql
0 → 100644
1 | + | ||
2 | +CREATE TABLE IF NOT EXISTS `__PREFIX__wechat_autoreply` ( | ||
3 | + `id` int(10) NOT NULL AUTO_INCREMENT, | ||
4 | + `title` varchar(100) NOT NULL DEFAULT '' COMMENT '标题', | ||
5 | + `text` varchar(100) NOT NULL DEFAULT '' COMMENT '触发文本', | ||
6 | + `eventkey` varchar(50) NOT NULL DEFAULT '' COMMENT '响应事件', | ||
7 | + `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注', | ||
8 | + `weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重', | ||
9 | + `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '添加时间', | ||
10 | + `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', | ||
11 | + `status` varchar(30) NOT NULL DEFAULT '' COMMENT '状态', | ||
12 | + PRIMARY KEY (`id`), | ||
13 | + KEY `eventkey` (`eventkey`) | ||
14 | +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='微信自动回复表'; | ||
15 | + | ||
16 | +BEGIN; | ||
17 | +INSERT INTO `__PREFIX__wechat_autoreply`(`id`, `title`, `text`, `eventkey`, `remark`, `weigh`, `createtime`, `updatetime`, `status`) VALUES (1, '输入hello', 'hello', '58c7d908c4570', '', 1, 1493366855, 1493366855, 'normal'); | ||
18 | +INSERT INTO `__PREFIX__wechat_autoreply`(`id`, `title`, `text`, `eventkey`, `remark`, `weigh`, `createtime`, `updatetime`, `status`) VALUES (2, '输入你好', '你好', '58fdfaa9e1965', '', 2, 1493704976, 1493704976, 'normal'); | ||
19 | +COMMIT; | ||
20 | + | ||
21 | +CREATE TABLE IF NOT EXISTS `__PREFIX__wechat_captcha` ( | ||
22 | + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||
23 | + `event` varchar(100) DEFAULT '' COMMENT '事件', | ||
24 | + `openid` varchar(255) DEFAULT NULL COMMENT '用户openid', | ||
25 | + `context` varchar(20) DEFAULT NULL COMMENT '上下文', | ||
26 | + `code` varchar(30) DEFAULT NULL COMMENT '验证码', | ||
27 | + `times` int(10) unsigned DEFAULT '0' COMMENT '验证次数', | ||
28 | + `ip` varchar(50) DEFAULT '' COMMENT 'IP', | ||
29 | + `createtime` int(10) DEFAULT NULL COMMENT '创建时间', | ||
30 | + PRIMARY KEY (`id`), | ||
31 | + KEY `ip` (`ip`,`event`) USING BTREE, | ||
32 | + KEY `openid` (`openid`(191),`event`) | ||
33 | +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='微信公众号验证码'; | ||
34 | + | ||
35 | +CREATE TABLE IF NOT EXISTS `__PREFIX__wechat_config` ( | ||
36 | + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||
37 | + `name` varchar(50) NOT NULL DEFAULT '' COMMENT '配置名称', | ||
38 | + `title` varchar(50) NOT NULL DEFAULT '' COMMENT '配置标题', | ||
39 | + `value` text NOT NULL COMMENT '配置值', | ||
40 | + `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', | ||
41 | + `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', | ||
42 | + PRIMARY KEY (`id`), | ||
43 | + UNIQUE KEY `name` (`name`) USING BTREE | ||
44 | +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='微信配置表'; | ||
45 | + | ||
46 | +BEGIN; | ||
47 | +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'); | ||
48 | +COMMIT; | ||
49 | + | ||
50 | +CREATE TABLE IF NOT EXISTS `__PREFIX__wechat_context` ( | ||
51 | + `id` int(10) NOT NULL AUTO_INCREMENT, | ||
52 | + `openid` varchar(64) NOT NULL DEFAULT '', | ||
53 | + `type` varchar(30) NOT NULL DEFAULT '' COMMENT '类型', | ||
54 | + `eventkey` varchar(64) NOT NULL DEFAULT '', | ||
55 | + `command` varchar(64) NOT NULL DEFAULT '', | ||
56 | + `message` varchar(255) NOT NULL DEFAULT '' COMMENT '内容', | ||
57 | + `refreshtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最后刷新时间', | ||
58 | + `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', | ||
59 | + `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', | ||
60 | + PRIMARY KEY (`id`), | ||
61 | + KEY `openid` (`openid`,`eventkey`) USING BTREE | ||
62 | +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='微信上下文表'; | ||
63 | + | ||
64 | +CREATE TABLE IF NOT EXISTS `__PREFIX__wechat_response` ( | ||
65 | + `id` int(10) NOT NULL AUTO_INCREMENT, | ||
66 | + `title` varchar(100) NOT NULL DEFAULT '' COMMENT '资源名', | ||
67 | + `eventkey` varchar(128) NOT NULL DEFAULT '' COMMENT '事件', | ||
68 | + `type` enum('text','image','news','voice','video','music','link','app') NOT NULL DEFAULT 'text' COMMENT '类型', | ||
69 | + `content` text NOT NULL COMMENT '内容', | ||
70 | + `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注', | ||
71 | + `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', | ||
72 | + `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', | ||
73 | + `status` varchar(30) NOT NULL DEFAULT '' COMMENT '状态', | ||
74 | + PRIMARY KEY (`id`), | ||
75 | + UNIQUE KEY `eventkey` (`eventkey`) USING BTREE | ||
76 | +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='微信资源表'; | ||
77 | + | ||
78 | +BEGIN; | ||
79 | +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'); | ||
80 | +COMMIT; | ||
81 | + |
addons/wechat/library/Config.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\wechat\library; | ||
4 | + | ||
5 | +/** | ||
6 | + * 微信配置类 | ||
7 | + */ | ||
8 | +class Config | ||
9 | +{ | ||
10 | + | ||
11 | + public static function load() | ||
12 | + { | ||
13 | + $config = get_addon_config('wechat'); | ||
14 | + | ||
15 | + return [ | ||
16 | + /** | ||
17 | + * 账号基本信息,请从微信公众平台/开放平台获取 | ||
18 | + */ | ||
19 | + 'app_id' => $config['app_id'], // AppID | ||
20 | + 'secret' => $config['secret'], // AppSecret | ||
21 | + 'token' => $config['token'], // Token | ||
22 | + 'aes_key' => $config['aes_key'], // EncodingAESKey,安全模式下请一定要填写!!! | ||
23 | + | ||
24 | + /** | ||
25 | + * 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名 | ||
26 | + * 使用自定义类名时,构造函数将会接收一个 `EasyWeChat\Kernel\Http\Response` 实例 | ||
27 | + */ | ||
28 | + 'response_type' => 'array', | ||
29 | + | ||
30 | + /** | ||
31 | + * 日志配置 | ||
32 | + * | ||
33 | + * level: 日志级别, 可选为:debug/info/notice/warning/error/critical/alert/emergency | ||
34 | + * path:日志文件位置(绝对路径!!!),要求可写权限 | ||
35 | + */ | ||
36 | + 'log' => [ | ||
37 | + 'default' => 'dev', // 默认使用的 channel,生产环境可以改为下面的 prod | ||
38 | + 'channels' => [ | ||
39 | + // 测试环境 | ||
40 | + 'dev' => [ | ||
41 | + 'driver' => 'single', | ||
42 | + 'path' => ROOT_PATH . '/runtime/log/easywechat.log', | ||
43 | + 'level' => 'debug', | ||
44 | + ], | ||
45 | + // 生产环境 | ||
46 | + 'prod' => [ | ||
47 | + 'driver' => 'daily', | ||
48 | + 'path' => ROOT_PATH . '/runtime/log/easywechat.log', | ||
49 | + 'level' => $config['log_level'], | ||
50 | + ], | ||
51 | + ], | ||
52 | + ], | ||
53 | + | ||
54 | + /** | ||
55 | + * 接口请求相关配置,超时时间等,具体可用参数请参考: | ||
56 | + * http://docs.guzzlephp.org/en/stable/request-config.html | ||
57 | + * | ||
58 | + * - retries: 重试次数,默认 1,指定当 http 请求失败时重试的次数。 | ||
59 | + * - retry_delay: 重试延迟间隔(单位:ms),默认 500 | ||
60 | + * - log_template: 指定 HTTP 日志模板,请参考:https://github.com/guzzle/guzzle/blob/master/src/MessageFormatter.php | ||
61 | + */ | ||
62 | + 'http' => [ | ||
63 | + 'max_retries' => 1, | ||
64 | + 'retry_delay' => 500, | ||
65 | + 'timeout' => 5.0, | ||
66 | + // 'base_uri' => 'https://api.weixin.qq.com/', // 如果你在国外想要覆盖默认的 url 的时候才使用,根据不同的模块配置不同的 uri | ||
67 | + ], | ||
68 | + | ||
69 | + /** | ||
70 | + * OAuth 配置 | ||
71 | + * | ||
72 | + * scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login | ||
73 | + * callback:OAuth授权完成后的回调页地址 | ||
74 | + */ | ||
75 | + 'oauth' => [ | ||
76 | + 'scopes' => ['snsapi_userinfo'], | ||
77 | + 'callback' => $config['oauth_callback'], | ||
78 | + ], | ||
79 | + ]; | ||
80 | + } | ||
81 | + | ||
82 | +} |
addons/wechat/library/Wechat.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\wechat\library; | ||
4 | + | ||
5 | +use addons\signin\model\Signin; | ||
6 | +use addons\third\model\Third; | ||
7 | +use app\common\model\User; | ||
8 | +use EasyWeChat\Kernel\Messages\News; | ||
9 | +use EasyWeChat\Kernel\Messages\NewsItem; | ||
10 | +use fast\Date; | ||
11 | +use fast\Http; | ||
12 | +use fast\Random; | ||
13 | +use think\Session; | ||
14 | +use think\Config; | ||
15 | + | ||
16 | +/** | ||
17 | + * 微信服务类 | ||
18 | + */ | ||
19 | +class Wechat | ||
20 | +{ | ||
21 | + public static function appConfig() | ||
22 | + { | ||
23 | + return array( | ||
24 | + 'signin' => array( | ||
25 | + 'name' => '签到送积分', | ||
26 | + 'config' => array() | ||
27 | + ), | ||
28 | + 'blog' => array( | ||
29 | + 'name' => '关联博客', | ||
30 | + 'config' => array( | ||
31 | + array( | ||
32 | + 'type' => 'text', | ||
33 | + 'caption' => '日志ID', | ||
34 | + 'field' => 'post_id', | ||
35 | + 'rule' => '', | ||
36 | + 'extend' => 'class="form-control selectpage" data-source="blog/post/index" data-field="title"', | ||
37 | + 'options' => '', | ||
38 | + ), | ||
39 | + array( | ||
40 | + 'type' => 'radio', | ||
41 | + 'caption' => '开启搜索日志', | ||
42 | + 'field' => 'searchpost', | ||
43 | + 'rule' => '', | ||
44 | + 'extend' => '', | ||
45 | + 'options' => [ | ||
46 | + '1' => '是', | ||
47 | + '0' => '否', | ||
48 | + ], | ||
49 | + ), | ||
50 | + array( | ||
51 | + 'type' => 'text', | ||
52 | + 'caption' => '正则搜索匹配索引', | ||
53 | + 'field' => 'searchregexindex', | ||
54 | + 'rule' => '', | ||
55 | + 'defaultvalue' => '1', | ||
56 | + 'extend' => '', | ||
57 | + 'options' => [], | ||
58 | + ) | ||
59 | + ) | ||
60 | + ), | ||
61 | + 'cms' => array( | ||
62 | + 'name' => '关联CMS', | ||
63 | + 'config' => array( | ||
64 | + array( | ||
65 | + 'type' => 'text', | ||
66 | + 'caption' => '文章ID', | ||
67 | + 'field' => 'archives_id', | ||
68 | + 'rule' => '', | ||
69 | + 'extend' => 'class="form-control selectpage" data-source="cms/archives/index" data-field="title"', | ||
70 | + 'options' => '' | ||
71 | + ), | ||
72 | + array( | ||
73 | + 'type' => 'text', | ||
74 | + 'caption' => '单页ID', | ||
75 | + 'field' => 'page_id', | ||
76 | + 'rule' => '', | ||
77 | + 'extend' => 'class="form-control selectpage" data-source="cms/page/index" data-field="title"', | ||
78 | + 'options' => '' | ||
79 | + ), | ||
80 | + array( | ||
81 | + 'type' => 'text', | ||
82 | + 'caption' => '专题ID', | ||
83 | + 'field' => 'special_id', | ||
84 | + 'rule' => '', | ||
85 | + 'extend' => 'class="form-control selectpage" data-source="cms/special/index" data-field="title"', | ||
86 | + 'options' => '' | ||
87 | + ), | ||
88 | + array( | ||
89 | + 'type' => 'radio', | ||
90 | + 'caption' => '开启搜索文章', | ||
91 | + 'field' => 'searcharchives', | ||
92 | + 'rule' => '', | ||
93 | + 'extend' => '', | ||
94 | + 'options' => [ | ||
95 | + '1' => '是', | ||
96 | + '0' => '否', | ||
97 | + ], | ||
98 | + ), | ||
99 | + array( | ||
100 | + 'type' => 'radio', | ||
101 | + 'caption' => '开启搜索单页', | ||
102 | + 'field' => 'searchpage', | ||
103 | + 'rule' => '', | ||
104 | + 'extend' => '', | ||
105 | + 'options' => [ | ||
106 | + '1' => '是', | ||
107 | + '0' => '否', | ||
108 | + ], | ||
109 | + ), | ||
110 | + array( | ||
111 | + 'type' => 'radio', | ||
112 | + 'caption' => '开启搜索专题', | ||
113 | + 'field' => 'searchspecial', | ||
114 | + 'rule' => '', | ||
115 | + 'extend' => '', | ||
116 | + 'options' => [ | ||
117 | + '1' => '是', | ||
118 | + '0' => '否', | ||
119 | + ], | ||
120 | + ), | ||
121 | + array( | ||
122 | + 'type' => 'text', | ||
123 | + 'caption' => '正则搜索匹配索引', | ||
124 | + 'field' => 'searchregexindex', | ||
125 | + 'rule' => '', | ||
126 | + 'defaultvalue' => '1', | ||
127 | + 'extend' => '', | ||
128 | + 'options' => [], | ||
129 | + ) | ||
130 | + ) | ||
131 | + ), | ||
132 | + 'ask' => array( | ||
133 | + 'name' => '关联问答', | ||
134 | + 'config' => array( | ||
135 | + array( | ||
136 | + 'type' => 'text', | ||
137 | + 'caption' => '问题ID', | ||
138 | + 'field' => 'question_id', | ||
139 | + 'extend' => 'class="form-control selectpage" data-source="ask/question/index" data-field="title"', | ||
140 | + 'options' => '' | ||
141 | + ), | ||
142 | + array( | ||
143 | + 'type' => 'text', | ||
144 | + 'caption' => '文章ID', | ||
145 | + 'field' => 'article_id', | ||
146 | + 'extend' => 'class="form-control selectpage" data-source="ask/article/index" data-field="title"', | ||
147 | + 'options' => '' | ||
148 | + ), | ||
149 | + array( | ||
150 | + 'type' => 'radio', | ||
151 | + 'caption' => '开启搜索问题', | ||
152 | + 'field' => 'searchquestion', | ||
153 | + 'rule' => '', | ||
154 | + 'extend' => '', | ||
155 | + 'options' => [ | ||
156 | + '1' => '是', | ||
157 | + '0' => '否', | ||
158 | + ], | ||
159 | + ), | ||
160 | + array( | ||
161 | + 'type' => 'radio', | ||
162 | + 'caption' => '开启搜索文章', | ||
163 | + 'field' => 'searcharticle', | ||
164 | + 'rule' => '', | ||
165 | + 'extend' => '', | ||
166 | + 'options' => [ | ||
167 | + '1' => '是', | ||
168 | + '0' => '否', | ||
169 | + ], | ||
170 | + ), | ||
171 | + array( | ||
172 | + 'type' => 'text', | ||
173 | + 'caption' => '正则搜索匹配索引', | ||
174 | + 'field' => 'searchregexindex', | ||
175 | + 'rule' => '', | ||
176 | + 'defaultvalue' => '1', | ||
177 | + 'extend' => '', | ||
178 | + 'options' => [], | ||
179 | + ) | ||
180 | + ) | ||
181 | + ), | ||
182 | + 'vote' => array( | ||
183 | + 'name' => '关联投票', | ||
184 | + 'config' => array( | ||
185 | + array( | ||
186 | + 'type' => 'text', | ||
187 | + 'caption' => '投票主题ID', | ||
188 | + 'field' => 'subject_id', | ||
189 | + 'extend' => 'class="form-control selectpage" data-source="vote/subject/index" data-field="title"', | ||
190 | + 'rule' => '', | ||
191 | + 'options' => '' | ||
192 | + ), | ||
193 | + array( | ||
194 | + 'type' => 'text', | ||
195 | + 'caption' => '参赛人员ID', | ||
196 | + 'field' => 'player_id', | ||
197 | + 'rule' => '', | ||
198 | + 'extend' => 'class="form-control selectpage" data-source="vote/player/index" data-field="nickname"', | ||
199 | + 'options' => '' | ||
200 | + ), | ||
201 | + array( | ||
202 | + 'type' => 'radio', | ||
203 | + 'caption' => '开启搜索主题', | ||
204 | + 'field' => 'searchsubject', | ||
205 | + 'rule' => '', | ||
206 | + 'extend' => '', | ||
207 | + 'options' => [ | ||
208 | + '1' => '是', | ||
209 | + '0' => '否', | ||
210 | + ], | ||
211 | + ), | ||
212 | + array( | ||
213 | + 'type' => 'radio', | ||
214 | + 'caption' => '开启搜索参赛人员', | ||
215 | + 'field' => 'searchplayer', | ||
216 | + 'rule' => '', | ||
217 | + 'extend' => '', | ||
218 | + 'options' => [ | ||
219 | + '1' => '是', | ||
220 | + '0' => '否', | ||
221 | + ], | ||
222 | + ), | ||
223 | + array( | ||
224 | + 'type' => 'text', | ||
225 | + 'caption' => '正则搜索匹配索引', | ||
226 | + 'field' => 'searchregexindex', | ||
227 | + 'rule' => '', | ||
228 | + 'defaultvalue' => '1', | ||
229 | + 'extend' => '', | ||
230 | + 'options' => [], | ||
231 | + ) | ||
232 | + ) | ||
233 | + ), | ||
234 | + ); | ||
235 | + } | ||
236 | + | ||
237 | + /** | ||
238 | + * 应用交互 | ||
239 | + * @return array|bool|mixed|string | ||
240 | + */ | ||
241 | + public function response($obj, $openid, $message, $content, $context, $matches = null) | ||
242 | + { | ||
243 | + $response = false; | ||
244 | + if (isset($content['app'])) { | ||
245 | + $entry = null; | ||
246 | + $keyword = isset($content['searchregexindex']) && $content['searchregexindex'] > -1 && $matches && isset($matches[$content['searchregexindex']]) | ||
247 | + ? $matches[$content['searchregexindex']] : $message; | ||
248 | + switch ($content['app']) { | ||
249 | + case 'signin': | ||
250 | + $signinInfo = get_addon_info('signin'); | ||
251 | + if (!$signinInfo || !$signinInfo['state']) { | ||
252 | + return "请先在后台管理安装并启用《会员签到》插件"; | ||
253 | + } | ||
254 | + $thirdInfo = get_addon_info('third'); | ||
255 | + if (!$thirdInfo || !$thirdInfo['state']) { | ||
256 | + return "请先在后台管理安装并启用《第三方登录》插件"; | ||
257 | + } | ||
258 | + $user = self::getUserByOpenid($openid); | ||
259 | + if (!$user) { | ||
260 | + return "请先在会员中心绑定微信登录,<a href='" . addon_url('third/index/connect', [':platform' => 'wechat'], true, true) . "'>点击这里绑定</a>"; | ||
261 | + } | ||
262 | + $config = get_addon_config('signin'); | ||
263 | + $signdata = $config['signinscore']; | ||
264 | + $lastdata = Signin::where('user_id', $user->id)->order('id', 'desc')->find(); | ||
265 | + $successions = $lastdata && $lastdata['createtime'] > Date::unixtime('day', -1) ? $lastdata['successions'] : 0; | ||
266 | + $signin = Signin::where('user_id', $user->id)->whereTime('createtime', 'today')->find(); | ||
267 | + if ($signin) { | ||
268 | + return '今天已签到,请明天再来!'; | ||
269 | + } else { | ||
270 | + $successions++; | ||
271 | + Signin::create(['user_id' => $user->id, 'successions' => $successions, 'createtime' => time()]); | ||
272 | + $score = isset($signdata['s' . $successions]) ? $signdata['s' . $successions] : $signdata['sn']; | ||
273 | + | ||
274 | + $user->setInc('score', $score); | ||
275 | + User::score($score, $user->id, "连续签到{$successions}天"); | ||
276 | + return '签到成功!连续签到' . $successions . '天!获得' . $score . '积分,'; | ||
277 | + } | ||
278 | + break; | ||
279 | + case 'blog': | ||
280 | + $blogInfo = get_addon_info('blog'); | ||
281 | + if (!$blogInfo || !$blogInfo['state']) { | ||
282 | + return "请先在后台管理安装并启用《简单博客》插件"; | ||
283 | + } | ||
284 | + $entry = \addons\blog\model\Post::get($content['post_id']); | ||
285 | + if ($entry) { | ||
286 | + $entry['image'] = $entry['thumb']; | ||
287 | + } | ||
288 | + if (!$entry && $content['searchpost']) { | ||
289 | + $entry = \addons\blog\model\Post::where("title|description", 'like', "%{$keyword}%")->where('status', 'normal')->find(); | ||
290 | + } | ||
291 | + if (!$entry) { | ||
292 | + return "未搜索到任何匹配信息$keyword" . json_encode($matches); | ||
293 | + } | ||
294 | + break; | ||
295 | + case 'cms': | ||
296 | + $cmsInfo = get_addon_info('cms'); | ||
297 | + if (!$cmsInfo || !$cmsInfo['state']) { | ||
298 | + return "请先在后台管理安装并启用《CMS内容管理系统》插件"; | ||
299 | + } | ||
300 | + if (isset($content['archives_id']) && $content['archives_id']) { | ||
301 | + $entry = \addons\cms\model\Archives::get($content['archives_id']); | ||
302 | + } elseif (isset($content['page_id']) && $content['page_id']) { | ||
303 | + $entry = \addons\cms\model\Page::get($content['page_id']); | ||
304 | + } elseif (isset($content['special_id']) && $content['special_id']) { | ||
305 | + $entry = \addons\cms\model\Special::get($content['special_id']); | ||
306 | + } | ||
307 | + if (!$entry && $content['searcharchives']) { | ||
308 | + $entry = \addons\cms\model\Archives::where("title|description", 'like', "%{$keyword}%")->where('status', 'normal')->find(); | ||
309 | + } | ||
310 | + if (!$entry && $content['searchpage']) { | ||
311 | + $entry = \addons\cms\model\Page::where("title|description", 'like', "%{$keyword}%")->where('status', 'normal')->find(); | ||
312 | + } | ||
313 | + if (!$entry && $content['searchspecial']) { | ||
314 | + $entry = \addons\cms\model\Special::where("title|description", 'like', "%{$keyword}%")->where('status', 'normal')->find(); | ||
315 | + } | ||
316 | + if (!$entry) { | ||
317 | + return "未搜索到任何匹配信息"; | ||
318 | + } | ||
319 | + break; | ||
320 | + case 'ask': | ||
321 | + $blogInfo = get_addon_info('ask'); | ||
322 | + if (!$blogInfo || !$blogInfo['state']) { | ||
323 | + return "请先在后台管理安装并启用《知识付费问答》插件"; | ||
324 | + } | ||
325 | + | ||
326 | + if (isset($content['question_id']) && $content['question_id']) { | ||
327 | + $entry = \addons\ask\model\Question::get($content['question_id']); | ||
328 | + } elseif (isset($content['article_id']) && $content['article_id']) { | ||
329 | + $entry = \addons\ask\model\Article::get($content['article_id']); | ||
330 | + } | ||
331 | + | ||
332 | + if (!$entry && $content['searchquestion']) { | ||
333 | + $entry = \addons\ask\model\Question::where("title", 'like', "%{$keyword}%")->where('status', 'normal')->find(); | ||
334 | + } | ||
335 | + if (!$entry && $content['searcharticle']) { | ||
336 | + $entry = \addons\ask\model\Article::where("title|description", 'like', "%{$keyword}%")->where('status', 'normal')->find(); | ||
337 | + } | ||
338 | + if (!$entry) { | ||
339 | + return "未搜索到任何匹配信息"; | ||
340 | + } | ||
341 | + break; | ||
342 | + case 'vote': | ||
343 | + $blogInfo = get_addon_info('vote'); | ||
344 | + if (!$blogInfo || !$blogInfo['state']) { | ||
345 | + return "请先在后台管理安装并启用《在线投票系统》插件"; | ||
346 | + } | ||
347 | + if (isset($content['subject_id']) && $content['subject_id']) { | ||
348 | + $entry = \addons\vote\model\Subject::all($content['subject_id']); | ||
349 | + } elseif (isset($content['player_id']) && $content['player_id']) { | ||
350 | + $entry = \addons\vote\model\Player::all($content['player_id']); | ||
351 | + } | ||
352 | + | ||
353 | + if (!$entry && $content['searchsubject']) { | ||
354 | + $entry = \addons\vote\model\Subject::where("title|description", 'like', "%{$keyword}%")->where('status', 'normal')->find(); | ||
355 | + } | ||
356 | + if (!$entry && $content['searchplayer']) { | ||
357 | + $entry = \addons\vote\model\Player::where("nickname", 'like', "%{$keyword}%")->where('status', 'normal')->find(); | ||
358 | + } | ||
359 | + | ||
360 | + if (!$entry) { | ||
361 | + return "未搜索到任何匹配信息"; | ||
362 | + } | ||
363 | + break; | ||
364 | + default: | ||
365 | + break; | ||
366 | + } | ||
367 | + if (isset($entry) && $entry) { | ||
368 | + $items = [ | ||
369 | + new NewsItem([ | ||
370 | + 'title' => isset($entry['title']) ? $entry['title'] : (isset($entry['nickname']) ? $entry['nickname'] : ''), | ||
371 | + 'description' => isset($entry['description']) ? $entry['description'] : '', | ||
372 | + 'url' => $entry['fullurl'], | ||
373 | + 'image' => cdnurl($entry['image'], true), | ||
374 | + ]), | ||
375 | + ]; | ||
376 | + $news = new News($items); | ||
377 | + | ||
378 | + $response[] = $news; | ||
379 | + } | ||
380 | + } else { | ||
381 | + $response = isset($content['content']) ? $content['content'] : $response; | ||
382 | + } | ||
383 | + return $response; | ||
384 | + } | ||
385 | + | ||
386 | + /** | ||
387 | + * 获取Token | ||
388 | + */ | ||
389 | + public static function getAccessToken() | ||
390 | + { | ||
391 | + $token = Session::get('wechat_access_token'); | ||
392 | + if (!$token) { | ||
393 | + $config = get_addon_config('wechat'); | ||
394 | + $params = [ | ||
395 | + 'grant_type' => 'client_credential', | ||
396 | + 'appid' => $config['app_id'], | ||
397 | + 'secret' => $config['secret'], | ||
398 | + ]; | ||
399 | + $url = "https://api.weixin.qq.com/cgi-bin/token"; | ||
400 | + $result = Http::sendRequest($url, $params, 'GET'); | ||
401 | + if ($result['ret']) { | ||
402 | + $msg = (array)json_decode($result['msg'], true); | ||
403 | + if (isset($msg['access_token'])) { | ||
404 | + $token = $msg['access_token']; | ||
405 | + Session::set('wechat_access_token', $token, $msg['expires_in'] - 1); | ||
406 | + } | ||
407 | + } | ||
408 | + } | ||
409 | + return $token; | ||
410 | + } | ||
411 | + | ||
412 | + /** | ||
413 | + * 根据Openid获取用户信息 | ||
414 | + * @param string $openid 微信OpenID | ||
415 | + * @return User|null | ||
416 | + */ | ||
417 | + public static function getUserByOpenid($openid) | ||
418 | + { | ||
419 | + $third = Third::where('platform', 'wechat')->where('openid', $openid)->find(); | ||
420 | + if ($third && $third->user_id) { | ||
421 | + return User::get($third->user_id); | ||
422 | + } | ||
423 | + return null; | ||
424 | + } | ||
425 | +} |
addons/wechat/model/WechatAutoreply.php
0 → 100644
addons/wechat/model/WechatCaptcha.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\wechat\model; | ||
4 | + | ||
5 | +use fast\Random; | ||
6 | +use think\Model; | ||
7 | + | ||
8 | +class WechatCaptcha extends Model | ||
9 | +{ | ||
10 | + | ||
11 | + // 表名 | ||
12 | + protected $name = 'wechat_captcha'; | ||
13 | + // 自动写入时间戳字段 | ||
14 | + protected $autoWriteTimestamp = 'int'; | ||
15 | + // 定义时间戳字段名 | ||
16 | + protected $createTime = 'createtime'; | ||
17 | + protected $updateTime = ''; | ||
18 | + // 追加属性 | ||
19 | + protected $append = [ | ||
20 | + ]; | ||
21 | + | ||
22 | + /** | ||
23 | + * 发送验证码 | ||
24 | + * @param $openid string 用户OpenID | ||
25 | + * @param $event string 事件 | ||
26 | + * @param $ip string IP地址 | ||
27 | + * @return string | ||
28 | + */ | ||
29 | + public static function send($openid, $event, $ip) | ||
30 | + { | ||
31 | + $captcha = self::where(['openid' => $openid, 'event' => $event])->whereTime('createtime', '-2 minutes')->find(); | ||
32 | + if ($captcha) { | ||
33 | + return "验证码发送速度过快,请稍后重试"; | ||
34 | + } | ||
35 | + $code = Random::alnum(4); | ||
36 | + $data = [ | ||
37 | + 'event' => $event, | ||
38 | + 'openid' => $openid, | ||
39 | + 'code' => $code, | ||
40 | + 'ip' => $ip, | ||
41 | + ]; | ||
42 | + self::create($data); | ||
43 | + return "你的验证码是:{$code},2分钟内输入有效"; | ||
44 | + } | ||
45 | + | ||
46 | + /** | ||
47 | + * 检测验证码 | ||
48 | + * @param $code string 验证码 | ||
49 | + * @param $event string 事件 | ||
50 | + * @param $ip string IP | ||
51 | + * @return bool | ||
52 | + */ | ||
53 | + public static function check($code, $event, $ip = null) | ||
54 | + { | ||
55 | + $ip = is_null($ip) ? request()->ip() : $ip; | ||
56 | + $captcha = self::where(['ip' => $ip, 'event' => $event])->whereTime('createtime', '-2 minutes')->find(); | ||
57 | + if ($captcha && $captcha->code == $code && $captcha->times < 10) { | ||
58 | + $captcha->setInc("times"); | ||
59 | + return true; | ||
60 | + } | ||
61 | + //验证大于10次或超时 | ||
62 | + if ($captcha && ($captcha->times >= 10 || time() - $captcha->createtime > 120)) { | ||
63 | + $captcha->delete(); | ||
64 | + } | ||
65 | + | ||
66 | + return false; | ||
67 | + } | ||
68 | + | ||
69 | +} |
addons/wechat/model/WechatConfig.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\wechat\model; | ||
4 | + | ||
5 | +use think\Model; | ||
6 | + | ||
7 | +class WechatConfig extends Model | ||
8 | +{ | ||
9 | + | ||
10 | + // 表名,不含前缀 | ||
11 | + public $name = 'wechat_config'; | ||
12 | + // 自动写入时间戳字段 | ||
13 | + protected $autoWriteTimestamp = 'int'; | ||
14 | + // 定义时间戳字段名 | ||
15 | + protected $createTime = 'createtime'; | ||
16 | + protected $updateTime = 'updatetime'; | ||
17 | + // 追加属性 | ||
18 | + protected $append = [ | ||
19 | + ]; | ||
20 | + | ||
21 | + /** | ||
22 | + * 读取指定配置名称的值 | ||
23 | + * @param string $name | ||
24 | + * @return string | ||
25 | + */ | ||
26 | + public static function getValue($name) | ||
27 | + { | ||
28 | + $item = self::get(['name' => $name]); | ||
29 | + return $item ? $item->value : ''; | ||
30 | + } | ||
31 | + | ||
32 | +} |
addons/wechat/model/WechatContext.php
0 → 100644
addons/wechat/model/WechatResponse.php
0 → 100644
application/admin/controller/Command.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\controller; | ||
4 | + | ||
5 | +use app\common\controller\Backend; | ||
6 | +use think\Config; | ||
7 | +use think\console\Input; | ||
8 | +use think\Db; | ||
9 | +use think\Exception; | ||
10 | + | ||
11 | +/** | ||
12 | + * 在线命令管理 | ||
13 | + * | ||
14 | + * @icon fa fa-circle-o | ||
15 | + */ | ||
16 | +class Command extends Backend | ||
17 | +{ | ||
18 | + | ||
19 | + /** | ||
20 | + * Command模型对象 | ||
21 | + */ | ||
22 | + protected $model = null; | ||
23 | + protected $noNeedRight = ['get_controller_list', 'get_field_list']; | ||
24 | + | ||
25 | + public function _initialize() | ||
26 | + { | ||
27 | + parent::_initialize(); | ||
28 | + $this->model = model('Command'); | ||
29 | + $this->view->assign("statusList", $this->model->getStatusList()); | ||
30 | + } | ||
31 | + | ||
32 | + /** | ||
33 | + * 添加 | ||
34 | + */ | ||
35 | + public function add() | ||
36 | + { | ||
37 | + | ||
38 | + $tableList = []; | ||
39 | + $list = \think\Db::query("SHOW TABLES"); | ||
40 | + foreach ($list as $key => $row) { | ||
41 | + $tableList[reset($row)] = reset($row); | ||
42 | + } | ||
43 | + | ||
44 | + $this->view->assign("tableList", $tableList); | ||
45 | + return $this->view->fetch(); | ||
46 | + } | ||
47 | + | ||
48 | + /** | ||
49 | + * 获取字段列表 | ||
50 | + * @internal | ||
51 | + */ | ||
52 | + public function get_field_list() | ||
53 | + { | ||
54 | + $dbname = Config::get('database.database'); | ||
55 | + $prefix = Config::get('database.prefix'); | ||
56 | + $table = $this->request->request('table'); | ||
57 | + //从数据库中获取表字段信息 | ||
58 | + $sql = "SELECT * FROM `information_schema`.`columns` " | ||
59 | + . "WHERE TABLE_SCHEMA = ? AND table_name = ? " | ||
60 | + . "ORDER BY ORDINAL_POSITION"; | ||
61 | + //加载主表的列 | ||
62 | + $columnList = Db::query($sql, [$dbname, $table]); | ||
63 | + $fieldlist = []; | ||
64 | + foreach ($columnList as $index => $item) { | ||
65 | + $fieldlist[] = $item['COLUMN_NAME']; | ||
66 | + } | ||
67 | + $this->success("", null, ['fieldlist' => $fieldlist]); | ||
68 | + } | ||
69 | + | ||
70 | + /** | ||
71 | + * 获取控制器列表 | ||
72 | + * @internal | ||
73 | + */ | ||
74 | + public function get_controller_list() | ||
75 | + { | ||
76 | + //搜索关键词,客户端输入以空格分开,这里接收为数组 | ||
77 | + $word = (array)$this->request->request("q_word/a"); | ||
78 | + $word = implode('', $word); | ||
79 | + | ||
80 | + $adminPath = dirname(__DIR__) . DS; | ||
81 | + $controllerDir = $adminPath . 'controller' . DS; | ||
82 | + $files = new \RecursiveIteratorIterator( | ||
83 | + new \RecursiveDirectoryIterator($controllerDir), \RecursiveIteratorIterator::LEAVES_ONLY | ||
84 | + ); | ||
85 | + $list = []; | ||
86 | + foreach ($files as $name => $file) { | ||
87 | + if (!$file->isDir()) { | ||
88 | + $filePath = $file->getRealPath(); | ||
89 | + $name = str_replace($controllerDir, '', $filePath); | ||
90 | + $name = str_replace(DS, "/", $name); | ||
91 | + if (!preg_match("/(.*)\.php\$/", $name)) { | ||
92 | + continue; | ||
93 | + } | ||
94 | + if (!$word || stripos($name, $word) !== false) { | ||
95 | + $list[] = ['id' => $name, 'name' => $name]; | ||
96 | + } | ||
97 | + } | ||
98 | + } | ||
99 | + $pageNumber = $this->request->request("pageNumber"); | ||
100 | + $pageSize = $this->request->request("pageSize"); | ||
101 | + return json(['list' => array_slice($list, ($pageNumber - 1) * $pageSize, $pageSize), 'total' => count($list)]); | ||
102 | + } | ||
103 | + | ||
104 | + /** | ||
105 | + * 详情 | ||
106 | + */ | ||
107 | + public function detail($ids) | ||
108 | + { | ||
109 | + $row = $this->model->get($ids); | ||
110 | + if (!$row) { | ||
111 | + $this->error(__('No Results were found')); | ||
112 | + } | ||
113 | + $this->view->assign("row", $row); | ||
114 | + return $this->view->fetch(); | ||
115 | + } | ||
116 | + | ||
117 | + /** | ||
118 | + * 执行 | ||
119 | + */ | ||
120 | + public function execute($ids) | ||
121 | + { | ||
122 | + $row = $this->model->get($ids); | ||
123 | + if (!$row) { | ||
124 | + $this->error(__('No Results were found')); | ||
125 | + } | ||
126 | + $result = $this->doexecute($row['type'], json_decode($row['params'], true)); | ||
127 | + $this->success("", null, ['result' => $result]); | ||
128 | + } | ||
129 | + | ||
130 | + /** | ||
131 | + * 执行命令 | ||
132 | + */ | ||
133 | + public function command($action = '') | ||
134 | + { | ||
135 | + $commandtype = $this->request->request("commandtype"); | ||
136 | + $params = $this->request->request(); | ||
137 | + $allowfields = [ | ||
138 | + 'crud' => 'table,controller,model,fields,force,local,delete,menu', | ||
139 | + 'menu' => 'controller,delete', | ||
140 | + 'min' => 'module,resource,optimize', | ||
141 | + 'api' => 'url,module,output,template,force,title,author,class,language', | ||
142 | + ]; | ||
143 | + $argv = []; | ||
144 | + $allowfields = isset($allowfields[$commandtype]) ? explode(',', $allowfields[$commandtype]) : []; | ||
145 | + $allowfields = array_filter(array_intersect_key($params, array_flip($allowfields))); | ||
146 | + if (isset($params['local']) && !$params['local']) { | ||
147 | + $allowfields['local'] = $params['local']; | ||
148 | + } else { | ||
149 | + unset($allowfields['local']); | ||
150 | + } | ||
151 | + foreach ($allowfields as $key => $param) { | ||
152 | + $argv[] = "--{$key}=" . (is_array($param) ? implode(',', $param) : $param); | ||
153 | + } | ||
154 | + if ($commandtype == 'crud') { | ||
155 | + $extend = 'setcheckboxsuffix,enumradiosuffix,imagefield,filefield,intdatesuffix,switchsuffix,citysuffix,selectpagesuffix,selectpagessuffix,ignorefields,sortfield,editorsuffix,headingfilterfield'; | ||
156 | + $extendArr = explode(',', $extend); | ||
157 | + foreach ($params as $index => $item) { | ||
158 | + if (in_array($index, $extendArr)) { | ||
159 | + foreach (explode(',', $item) as $key => $value) { | ||
160 | + if ($value) { | ||
161 | + $argv[] = "--{$index}={$value}"; | ||
162 | + } | ||
163 | + } | ||
164 | + } | ||
165 | + } | ||
166 | + $isrelation = (int)$this->request->request('isrelation'); | ||
167 | + if ($isrelation && isset($params['relation'])) { | ||
168 | + foreach ($params['relation'] as $index => $relation) { | ||
169 | + foreach ($relation as $key => $value) { | ||
170 | + $argv[] = "--{$key}=" . (is_array($value) ? implode(',', $value) : $value); | ||
171 | + } | ||
172 | + } | ||
173 | + } | ||
174 | + } else { | ||
175 | + if ($commandtype == 'menu') { | ||
176 | + if (isset($params['allcontroller']) && $params['allcontroller']) { | ||
177 | + $argv[] = "--controller=all-controller"; | ||
178 | + } else { | ||
179 | + foreach (explode(',', $params['controllerfile']) as $index => $param) { | ||
180 | + if ($param) { | ||
181 | + $argv[] = "--controller=" . substr($param, 0, -4); | ||
182 | + } | ||
183 | + } | ||
184 | + } | ||
185 | + } else { | ||
186 | + if ($commandtype == 'min') { | ||
187 | + | ||
188 | + } else { | ||
189 | + if ($commandtype == 'api') { | ||
190 | + | ||
191 | + } else { | ||
192 | + | ||
193 | + } | ||
194 | + } | ||
195 | + } | ||
196 | + } | ||
197 | + if ($action == 'execute') { | ||
198 | + $result = $this->doexecute($commandtype, $argv); | ||
199 | + $this->success("", null, ['result' => $result]); | ||
200 | + } else { | ||
201 | + $this->success("", null, ['command' => "php think {$commandtype} " . implode(' ', $argv)]); | ||
202 | + } | ||
203 | + | ||
204 | + return; | ||
205 | + } | ||
206 | + | ||
207 | + protected function doexecute($commandtype, $argv) | ||
208 | + { | ||
209 | + $commandName = "\\app\\admin\\command\\" . ucfirst($commandtype); | ||
210 | + $input = new Input($argv); | ||
211 | + $output = new \addons\command\library\Output(); | ||
212 | + $command = new $commandName($commandtype); | ||
213 | + $data = [ | ||
214 | + 'type' => $commandtype, | ||
215 | + 'params' => json_encode($argv), | ||
216 | + 'command' => "php think {$commandtype} " . implode(' ', $argv), | ||
217 | + 'executetime' => time(), | ||
218 | + ]; | ||
219 | + $this->model->save($data); | ||
220 | + try { | ||
221 | + $command->run($input, $output); | ||
222 | + $result = implode("\n", $output->getMessage()); | ||
223 | + $this->model->status = 'successed'; | ||
224 | + } catch (Exception $e) { | ||
225 | + $result = implode("\n", $output->getMessage()) . "\n"; | ||
226 | + $result .= $e->getMessage(); | ||
227 | + $this->model->status = 'failured'; | ||
228 | + } | ||
229 | + $result = trim($result); | ||
230 | + $this->model->content = $result; | ||
231 | + $this->model->save(); | ||
232 | + return $result; | ||
233 | + } | ||
234 | + | ||
235 | + | ||
236 | +} |
application/admin/controller/Tablemake.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\controller; | ||
4 | + | ||
5 | +use app\common\controller\Backend; | ||
6 | +use think\Db; | ||
7 | +use think\Config; | ||
8 | +use think\Exception; | ||
9 | + | ||
10 | +//use think\Config; | ||
11 | + | ||
12 | +/** | ||
13 | + * 自建表管理 | ||
14 | + * | ||
15 | + * @icon fa fa-circle-o | ||
16 | + */ | ||
17 | +class Tablemake extends Backend { | ||
18 | + | ||
19 | + /** | ||
20 | + * Test模型对象 | ||
21 | + * @var \app\admin\model\Test | ||
22 | + */ | ||
23 | + protected $ModelOnline = null; | ||
24 | + protected $ModelFields = null; | ||
25 | + protected $searchFields = false;//关闭快捷搜索 | ||
26 | + | ||
27 | + protected $db_name = ''; | ||
28 | + protected $db_prefix = ''; | ||
29 | + | ||
30 | + | ||
31 | + public function _initialize() { | ||
32 | + parent::_initialize(); | ||
33 | + $this->ModelOnline = model('TableMakeTables'); | ||
34 | + $this->ModelFields = model('TableMakeFields'); | ||
35 | + | ||
36 | + $dictionary_url = url("tablemake/dictionary", [], true, true); | ||
37 | + $this->view->assign("dictionary_url", $dictionary_url); | ||
38 | + } | ||
39 | + | ||
40 | + /* | ||
41 | + * 数据表列表 | ||
42 | + */ | ||
43 | + | ||
44 | + public function index() { | ||
45 | + | ||
46 | + $this->searchFields = "name,table,desc"; | ||
47 | + if ($this->request->isAjax()) { | ||
48 | + $prefix = Config::get('database.prefix'); | ||
49 | + $this->model = $this->ModelOnline; | ||
50 | + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); | ||
51 | + $list = $this->model | ||
52 | + ->where($where) | ||
53 | + ->order($sort, $order) | ||
54 | + ->paginate($limit); | ||
55 | + $result = array("total" => $list->total(), "rows" => $list->items(), "prefix" => $prefix); | ||
56 | + return json($result); | ||
57 | + } | ||
58 | + | ||
59 | + return $this->view->fetch(); | ||
60 | + } | ||
61 | + | ||
62 | + /* | ||
63 | + * 创建数据表 | ||
64 | + */ | ||
65 | + | ||
66 | + public function add() { | ||
67 | + if ($this->request->isPost()) { | ||
68 | + $params = $this->request->post("row/a"); | ||
69 | + if ($params) { | ||
70 | + if ($this->dataLimit && $this->dataLimitFieldAutoFill) { | ||
71 | + $params[$this->dataLimitField] = $this->auth->id; | ||
72 | + } | ||
73 | + try { | ||
74 | + //是否采用模型验证 | ||
75 | + if ($this->modelValidate) { | ||
76 | + $name = str_replace("\\model\\", "\\validate\\", get_class($this->ModelOnline)); | ||
77 | + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate; | ||
78 | + $this->ModelOnline->validate($validate); | ||
79 | + } | ||
80 | + $params['createtime'] = time(); | ||
81 | + $params['updatetime'] = time(); | ||
82 | + $result = $this->ModelOnline->allowField(true)->save($params); | ||
83 | + $prefix = Config::get('database.prefix'); | ||
84 | + if ($result !== false) { | ||
85 | + //在此执行创建表的操作 | ||
86 | + $sql = "CREATE TABLE IF NOT EXISTS `{$prefix}" . $params['table'] . "` ( | ||
87 | + `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', | ||
88 | + PRIMARY KEY (`id`) | ||
89 | + ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='" . $params['name'] . "';"; | ||
90 | + | ||
91 | + $res = \think\Db::execute($sql); | ||
92 | + //var_export($res); | ||
93 | + $this->success(); | ||
94 | + } else { | ||
95 | + $this->error($this->ModelOnline->getError()); | ||
96 | + } | ||
97 | + } catch (\think\exception\PDOException $e) { | ||
98 | + $this->error($e->getMessage()); | ||
99 | + } catch (\think\Exception $e) { | ||
100 | + $this->error($e->getMessage()); | ||
101 | + } | ||
102 | + } | ||
103 | + $this->error(__('Parameter %s can not be empty', '')); | ||
104 | + } | ||
105 | + | ||
106 | + $prefix = Config::get('database.prefix'); | ||
107 | + $this->view->assign("prefix", $prefix); | ||
108 | + return $this->view->fetch(); | ||
109 | + } | ||
110 | + | ||
111 | + /* | ||
112 | + * 编辑数据表 | ||
113 | + */ | ||
114 | + | ||
115 | + public function edit($ids = NULL) { | ||
116 | + $row = $this->ModelOnline->get($ids); | ||
117 | + if (!$row) | ||
118 | + $this->error(__('No Results were found')); | ||
119 | + $adminIds = $this->getDataLimitAdminIds(); | ||
120 | + if (is_array($adminIds)) { | ||
121 | + if (!in_array($row[$this->dataLimitField], $adminIds)) { | ||
122 | + $this->error(__('You have no permission')); | ||
123 | + } | ||
124 | + } | ||
125 | + if ($this->request->isPost()) { | ||
126 | + $params = $this->request->post("row/a"); | ||
127 | + if ($params) { | ||
128 | + try { | ||
129 | + //是否采用模型验证 | ||
130 | + if ($this->modelValidate) { | ||
131 | + $name = basename(str_replace('\\', '/', get_class($this->ModelOnline))); | ||
132 | + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : true) : $this->modelValidate; | ||
133 | + $row->validate($validate); | ||
134 | + } | ||
135 | + $params['updatetime'] = time(); | ||
136 | + $result = $row->allowField(true)->save($params); | ||
137 | + if ($result !== false) { | ||
138 | + $prefix = Config::get('database.prefix'); | ||
139 | + $sql = "ALTER TABLE `{$prefix}" . $row['table'] . "` COMMENT='" . $row['name'] . "';"; | ||
140 | + $res = \think\Db::execute($sql); | ||
141 | + $this->success(); | ||
142 | + } else { | ||
143 | + $this->error($row->getError()); | ||
144 | + } | ||
145 | + } catch (\think\exception\PDOException $e) { | ||
146 | + $this->error($e->getMessage()); | ||
147 | + } catch (\think\Exception $e) { | ||
148 | + $this->error($e->getMessage()); | ||
149 | + } | ||
150 | + } | ||
151 | + $this->error(__('Parameter %s can not be empty', '')); | ||
152 | + } | ||
153 | + $prefix = Config::get('database.prefix'); | ||
154 | + $this->view->assign("row", $row); | ||
155 | + $this->view->assign("prefix", $prefix); | ||
156 | + return $this->view->fetch(); | ||
157 | + } | ||
158 | + | ||
159 | + /* | ||
160 | + * 删除模块 | ||
161 | + */ | ||
162 | + | ||
163 | + public function del($ids = NULL) { | ||
164 | + if ($ids) { | ||
165 | + $pk = $this->ModelOnline->getPk(); | ||
166 | + $adminIds = $this->getDataLimitAdminIds(); | ||
167 | + if (is_array($adminIds)) { | ||
168 | + $count = $this->ModelOnline->where($this->dataLimitField, 'in', $adminIds); | ||
169 | + } | ||
170 | + $list = $this->ModelOnline->where($pk, 'in', $ids)->select(); | ||
171 | + $prefix = Config::get('database.prefix'); | ||
172 | + $count = 0; | ||
173 | + foreach ($list as $k => $v) { | ||
174 | + $sql = "DROP TABLE IF EXISTS `{$prefix}" . $v->table . "`;"; | ||
175 | + try { | ||
176 | + $res = \think\Db::execute($sql); | ||
177 | + $this->ModelFields->where("mid", '=', $v->id)->delete(); | ||
178 | + $count += $v->delete(); | ||
179 | + if ($count) { | ||
180 | + $this->success(__('删除成功!'), null, __('删除成功!')); | ||
181 | + } else { | ||
182 | + $this->error(__('No rows were deleted')); | ||
183 | + } | ||
184 | + } catch (Exception $ex) { | ||
185 | + $this->error(__('No rows were deleted')); | ||
186 | + } | ||
187 | + } | ||
188 | + } | ||
189 | + $this->error(__('Parameter %s can not be empty', 'ids')); | ||
190 | + } | ||
191 | + | ||
192 | + /* | ||
193 | + * 验证重名 | ||
194 | + */ | ||
195 | + | ||
196 | + public function check($table = null, $name = null) { | ||
197 | + if ($table == null && $name == null) { | ||
198 | + if ($this->request->isAjax()) { | ||
199 | + $table = $this->request->request('table'); | ||
200 | + $name = $this->request->request('name'); | ||
201 | + } | ||
202 | + } | ||
203 | + if ($table && $name) { | ||
204 | + $sql = "describe `{$table}` `{$name}`"; | ||
205 | + $res = \think\Db::query($sql); | ||
206 | + if ($res) { | ||
207 | + return true; | ||
208 | + } else { | ||
209 | + return false; | ||
210 | + } | ||
211 | + } else { | ||
212 | + return false; | ||
213 | + } | ||
214 | + } | ||
215 | + | ||
216 | + /* | ||
217 | + * 字段列表 | ||
218 | + */ | ||
219 | + | ||
220 | + public function fields($ids = NULL) { | ||
221 | + $this->searchFields = "name,title,comment"; | ||
222 | + if ($ids == NULL) { | ||
223 | + $ids = intval($this->request->request('ids')); | ||
224 | + } | ||
225 | + $model = $this->ModelOnline->get($ids); | ||
226 | + if (!$model) { | ||
227 | + $this->error(__('No Results were found')); | ||
228 | + } | ||
229 | + | ||
230 | + if ($this->request->isAjax()) { | ||
231 | + $prefix = Config::get('database.prefix'); | ||
232 | + $this->model = $this->ModelFields; | ||
233 | + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); | ||
234 | + $list = $this->model | ||
235 | + ->where("mid", '=', $ids) | ||
236 | + ->where($where) | ||
237 | + ->order($sort, $order) | ||
238 | + ->paginate($limit); | ||
239 | + $result = array("total" => $list->total(), "rows" => $list->items(), "prefix" => $prefix); | ||
240 | + return json($result); | ||
241 | + | ||
242 | + | ||
243 | +// $list = $this->ModelFields->where("mid", '=', $ids)->order('id desc')->select(); | ||
244 | +// $total = count($list); | ||
245 | +// $prefix = Config::get('database.prefix'); | ||
246 | +// $result = array("total" => $total, "rows" => $list, "prefix" => $prefix); | ||
247 | +// return json($result); | ||
248 | + } | ||
249 | + $this->view->assign("ids", $ids); | ||
250 | + return $this->view->fetch(); | ||
251 | + } | ||
252 | + | ||
253 | + /* | ||
254 | + * 添加字段 | ||
255 | + */ | ||
256 | + | ||
257 | + public function field_add($mid = NULL) { | ||
258 | + $mod_table = $this->ModelOnline->get($mid); | ||
259 | + if (!$mod_table) | ||
260 | + $this->error(__('No Results were found')); | ||
261 | + if ($this->request->isPost()) { | ||
262 | + $params = $this->request->post("row/a"); | ||
263 | + if ($params) { | ||
264 | + try { | ||
265 | + //是否采用模型验证 | ||
266 | + if ($this->modelValidate) { | ||
267 | + $name = str_replace("\\model\\", "\\validate\\", get_class($this->ModelFields)); | ||
268 | + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate; | ||
269 | + $this->ModelFields->validate($validate); | ||
270 | + } | ||
271 | + $prefix = Config::get('database.prefix'); | ||
272 | + $field = array(); | ||
273 | + $fieldData = array(); | ||
274 | + switch ($params['category']) { | ||
275 | + case "1": | ||
276 | + $allow = array( | ||
277 | + "text" => array("suffix" => "text", "type" => "varchar", "length" => 200), | ||
278 | + "number" => array("suffix" => "number", "type" => "bigint", "length" => 11), | ||
279 | + "time" => array("suffix" => "time", "type" => "bigint", "length" => 11), | ||
280 | + "image" => array("suffix" => "image", "type" => "varchar", "length" => 255), | ||
281 | + "images" => array("suffix" => "images", "type" => "varchar", "length" => 2000), | ||
282 | + "file" => array("suffix" => "file", "type" => "varchar", "length" => 255), | ||
283 | + "files" => array("suffix" => "files", "type" => "varchar", "length" => 2000), | ||
284 | + "avatar" => array("suffix" => "avatar", "type" => "varchar", "length" => 255), | ||
285 | + "avatars" => array("suffix" => "avatars", "type" => "varchar", "length" => 2000), | ||
286 | + "content" => array("suffix" => "content", "type" => "text", "length" => 0), | ||
287 | + "_id" => array("suffix" => "_id", "type" => "bigint", "length" => 11), | ||
288 | + "_ids" => array("suffix" => "_ids", "type" => "varchar", "length" => 255), | ||
289 | + "list-enum" => array("suffix" => "list", "type" => "enum", "length" => 0), | ||
290 | + "list-set" => array("suffix" => "list", "type" => "set", "length" => 0), | ||
291 | + "data-enum" => array("suffix" => "data", "type" => "enum", "length" => 0), | ||
292 | + "data-set" => array("suffix" => "data", "type" => "set", "length" => 0), | ||
293 | + "json" => array("suffix" => "json", "type" => "varchar", "length" => 2000), | ||
294 | + "switch" => array("suffix" => "switch", "type" => "tinyint", "length" => 1), | ||
295 | + ); | ||
296 | + if (isset($allow[$params['suffix']]) && is_array($allow[$params['suffix']])) { | ||
297 | + $fieldData['special'] = ""; | ||
298 | + $fieldData['suffix'] = $params['suffix']; | ||
299 | + //$field['name'] = $params['name'] . $allow[$params['suffix']]['suffix']; //字段名 | ||
300 | + $field['name'] = $params['name']; //字段名 | ||
301 | + $field['field'] = $params['name'] . $allow[$params['suffix']]['suffix']; //字段名 | ||
302 | + $field['length'] = $field['length2'] = isset($params['length']) && intval($params['length']) ? intval($params['length']) : $allow[$params['suffix']]['length']; //字段长度 | ||
303 | + $field['type'] = $allow[$params['suffix']]['type']; //字段类型 | ||
304 | + $field['default'] = isset($params['default']) ? $params['default'] : ""; //默认值 | ||
305 | + if ($allow[$params['suffix']]['type'] == "enum" || $allow[$params['suffix']]['type'] == "set") { | ||
306 | + $comment = \GuzzleHttp\json_decode($params['comment'], true); | ||
307 | + $field['comment'] = $params['title'] . ":"; //备注 | ||
308 | + $field['length2'] = ""; | ||
309 | + $str = ""; | ||
310 | + $default_optional = array(); | ||
311 | + foreach ($comment as $k => $v) { | ||
312 | + $default_optional[] = $k; | ||
313 | + $field['comment'] .= $str . $k . "=" . $v; | ||
314 | + $field['length2'] .= $str . "'" . $k . "'"; | ||
315 | + $str = ","; | ||
316 | + } | ||
317 | + if (!in_array($field['default'], $default_optional)) { | ||
318 | + $field['default'] = $default_optional[0]; | ||
319 | + } | ||
320 | + } else { | ||
321 | + $params['comment'] = ""; | ||
322 | + $field['comment'] = $params['title']; //备注 | ||
323 | + } | ||
324 | + } else { | ||
325 | + $this->error(__('特殊字段类型不正确!')); | ||
326 | + } | ||
327 | + break; | ||
328 | + case "2": | ||
329 | + $allow = array( | ||
330 | + "varchar" => array("type" => "varchar", "length" => 255), | ||
331 | + "int" => array("type" => "bigint", "length" => 11), | ||
332 | + "enum" => array("type" => "enum", "length" => 0), | ||
333 | + "set" => array("type" => "set", "length" => 0), | ||
334 | + "float" => array("type" => "float", "length" => "10,2"), | ||
335 | + "text" => array("type" => "text", "length" => 0), | ||
336 | + "datetime" => array("type" => "datetime", "length" => 11), | ||
337 | + "date" => array("type" => "date", "length" => 11), | ||
338 | + "year" => array("type" => "year", "length" => 4), | ||
339 | + "timestamp" => array("type" => "timestamp", "length" => 11), | ||
340 | + ); | ||
341 | + if (isset($allow[$params['type']]) && is_array($allow[$params['type']])) { | ||
342 | + $fieldData['special'] = ""; | ||
343 | + $fieldData['suffix'] = ""; | ||
344 | + $params['suffix'] = ""; | ||
345 | + $field['name'] = $params['name']; //字段名 | ||
346 | + $field['field'] = $params['name']; //字段名 | ||
347 | + if ($params['type'] == "float") { | ||
348 | + $field['length'] = $field['length2'] = isset($params['length']) && $params['length'] ? $params['length'] : $allow[$params['type']]['length']; //字段长度 | ||
349 | + } else { | ||
350 | + $field['length'] = $field['length2'] = isset($params['length']) && intval($params['length']) ? intval($params['length']) : $allow[$params['type']]['length']; //字段长度 | ||
351 | + } | ||
352 | + $field['type'] = $allow[$params['type']]['type']; //字段类型 | ||
353 | + $field['default'] = isset($params['default']) ? $params['default'] : ""; //默认值 | ||
354 | + if ($allow[$params['type']]['type'] == "enum" || $allow[$params['type']]['type'] == "set") { | ||
355 | + $comment = \GuzzleHttp\json_decode($params['comment'], true); | ||
356 | + $field['comment'] = $params['title'] . ":"; //备注 | ||
357 | + $field['length2'] = ""; | ||
358 | + $str = ""; | ||
359 | + $default_optional = array(); | ||
360 | + foreach ($comment as $k => $v) { | ||
361 | + $default_optional[] = $k; | ||
362 | + $field['comment'] .= $str . $k . "=" . $v; | ||
363 | + $field['length2'] .= $str . "'" . $k . "'"; | ||
364 | + $str = ","; | ||
365 | + } | ||
366 | + if (!in_array($field['default'], $default_optional)) { | ||
367 | + $field['default'] = $default_optional[0]; | ||
368 | + } | ||
369 | + } else { | ||
370 | + $params['comment'] = ""; | ||
371 | + $field['comment'] = $params['title']; //备注 | ||
372 | + } | ||
373 | + } else { | ||
374 | + $this->error(__('特殊字段类型不正确!')); | ||
375 | + } | ||
376 | + break; | ||
377 | + case "3": | ||
378 | + $allow = array( | ||
379 | + "user_id" => array("title" => "会员ID(单选)", "type" => "bigint", "length" => 11), | ||
380 | + "category_id" => array("title" => "分类ID(单选)", "type" => "bigint", "length" => 11), | ||
381 | + "category_ids" => array("title" => "分类ID(多选)", "type" => "varchar", "length" => 200), | ||
382 | + "weigh" => array("title" => "权重", "type" => "bigint", "length" => 11), | ||
383 | + "status" => array("title" => "状态", "type" => "enum", "length" => 0), | ||
384 | + "createtime" => array("title" => "创建时间", "type" => "bigint", "length" => 11), | ||
385 | + "updatetime" => array("title" => "更新时间", "type" => "bigint", "length" => 11), | ||
386 | + "deletetime" => array("title" => "删除时间", "type" => "bigint", "length" => 11), | ||
387 | + ); | ||
388 | + if (isset($allow[$params['special']]) && is_array($allow[$params['special']])) { | ||
389 | + $fieldData['special'] = $params['special']; | ||
390 | + $fieldData['suffix'] = ""; | ||
391 | + //$params['title'] = $allow[$params['special']]['title']; | ||
392 | +// $params['comment'] = $params['suffix'] = ""; | ||
393 | + $field['name'] = $params['special']; //字段名 | ||
394 | + $field['field'] = $params['special']; //字段名 | ||
395 | + $field['length'] = $field['length2'] = $allow[$params['special']]['length']; //字段长度 | ||
396 | +// $field['comment'] = $params['title']; //备注 | ||
397 | + $field['type'] = $allow[$params['special']]['type']; //字段类型 | ||
398 | + $field['default'] = $field['type'] == "varchar" ? "" : "0"; //默认值 | ||
399 | + | ||
400 | + if ($params['special'] == "status") { | ||
401 | + $comment = \GuzzleHttp\json_decode($params['comment'], true); | ||
402 | + $field['comment'] = $params['title'] . ":"; //备注 | ||
403 | + $field['length2'] = ""; | ||
404 | + $str = ""; | ||
405 | + $default_optional = array(); | ||
406 | + foreach ($comment as $k => $v) { | ||
407 | + $default_optional[] = $k; | ||
408 | + $field['comment'] .= $str . $k . "=" . $v; | ||
409 | + $field['length2'] .= $str . "'" . $k . "'"; | ||
410 | + $str = ","; | ||
411 | + } | ||
412 | + if (!in_array($field['default'], $default_optional)) { | ||
413 | + $field['default'] = $default_optional[0]; | ||
414 | + } | ||
415 | + } else { | ||
416 | + $params['comment'] = ""; | ||
417 | + $field['comment'] = $params['title']; //备注 | ||
418 | + } | ||
419 | + } else { | ||
420 | + $this->error(__('特殊字段类型不正确!')); | ||
421 | + } | ||
422 | + break; | ||
423 | + default : | ||
424 | + $this->error(__('No Results were found')); | ||
425 | + break; | ||
426 | + } | ||
427 | + | ||
428 | + if ($this->check($prefix . $mod_table['table'], $field['name'])) { | ||
429 | + $this->error(__('字段已经存在!')); | ||
430 | + } | ||
431 | + $fieldData['mid'] = $params['mid']; | ||
432 | + $fieldData['category'] = $params['category']; | ||
433 | + $fieldData['title'] = $params['title']; | ||
434 | + $fieldData['name'] = $field['name']; | ||
435 | + $fieldData['field'] = $field['field']; | ||
436 | + $fieldData['type'] = $field['type']; | ||
437 | + $fieldData['length'] = $field['length']; | ||
438 | + $fieldData['default'] = $field['default']; | ||
439 | + $fieldData['comment'] = $field['comment']; | ||
440 | + $fieldData['desc'] = $params['desc']; | ||
441 | + $fieldData['createtime'] = time(); | ||
442 | + $fieldData['updatetime'] = time(); | ||
443 | + if ($fieldData['type'] == "text") { | ||
444 | + $fieldData['default'] = ""; | ||
445 | + } | ||
446 | + if ($field['type'] == "bigint" || $field['type'] == "int") { | ||
447 | + $field['default'] = intval($field['default']); | ||
448 | + } elseif ($field['type'] == "tinyint") { | ||
449 | + $field['default'] = in_array($field['default'], [0, 1]) ? $field['default'] : 0; | ||
450 | + } elseif ($field['type'] == "float") { | ||
451 | + $field['default'] = is_float($field['default']) ? $field['default'] : 0; | ||
452 | + } | ||
453 | + | ||
454 | + \think\Db::startTrans(); | ||
455 | + try { | ||
456 | + $result = $this->ModelFields->allowField(true)->save($fieldData); | ||
457 | + if ($result !== false) { | ||
458 | + //在此执行添加字段的操作 | ||
459 | + if (in_array($field['type'], ["text", "datetime", "date", "year", "timestamp"])) { | ||
460 | + $sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` ADD COLUMN `{$field['field']}` {$field['type']} NOT NULL COMMENT '{$field['comment']}';"; | ||
461 | + } else { | ||
462 | + $sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` ADD COLUMN `{$field['field']}` {$field['type']}({$field['length2']}) NOT NULL DEFAULT '{$field['default']}' COMMENT '{$field['comment']}';"; | ||
463 | + } | ||
464 | + try { | ||
465 | + $res = \think\Db::execute($sql); | ||
466 | + } catch (Exception $ex) { | ||
467 | + new Exception('参数错误,请检查字段名,字段长度或者默认值等输入参数是否合法'); | ||
468 | + } | ||
469 | + } else { | ||
470 | + new Exception($this->ModelFields->getError()); | ||
471 | + } | ||
472 | + \think\Db::commit(); | ||
473 | + } catch (Exception $e) { | ||
474 | + \think\Db::rollback(); | ||
475 | + $this->error($e->getMessage()); | ||
476 | + } | ||
477 | + $this->success(); | ||
478 | + } catch (\think\exception\PDOException $e) { | ||
479 | + $this->error($e->getMessage()); | ||
480 | + } catch (\think\Exception $e) { | ||
481 | + $this->error($e->getMessage()); | ||
482 | + } | ||
483 | + } | ||
484 | + $this->error(__('Parameter %s can not be empty', '')); | ||
485 | + } | ||
486 | + $prefix = Config::get('database.prefix'); | ||
487 | + $this->view->assign("prefix", $prefix); | ||
488 | + $this->view->assign("mid", $mid); | ||
489 | + return $this->view->fetch(); | ||
490 | + } | ||
491 | + | ||
492 | + /* | ||
493 | + * 修改字段 | ||
494 | + */ | ||
495 | + | ||
496 | + public function field_edit($ids = NULL) { | ||
497 | + //$oldField_info = $this->ModelFields->get($ids); | ||
498 | + $field_info = $this->ModelFields->get($ids); | ||
499 | + $oldField_info = $field_info->toArray(); | ||
500 | + //var_dump($field_info); | ||
501 | + if (!$field_info) | ||
502 | + $this->error(__('No Results were found')); | ||
503 | + | ||
504 | + $mod_table = $this->ModelOnline->get($field_info['mid']); | ||
505 | + if (!$mod_table) | ||
506 | + $this->error(__('No Results were found')); | ||
507 | + | ||
508 | + if ($this->request->isPost()) { | ||
509 | + $params = $this->request->post("row/a"); | ||
510 | + if ($params) { | ||
511 | + try { | ||
512 | + //是否采用模型验证 | ||
513 | + if ($this->modelValidate) { | ||
514 | + $name = str_replace("\\model\\", "\\validate\\", get_class($this->ModelFields)); | ||
515 | + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : true) : $this->modelValidate; | ||
516 | + $this->ModelFields->validate($validate); | ||
517 | + } | ||
518 | + $prefix = Config::get('database.prefix'); | ||
519 | + $field = array(); | ||
520 | + $fieldData = array(); | ||
521 | + switch ($field_info['category']) { | ||
522 | + case "1": | ||
523 | + $allow = array( | ||
524 | + "text" => array("suffix" => "text", "type" => "varchar", "length" => 200), | ||
525 | + "number" => array("suffix" => "number", "type" => "bigint", "length" => 11), | ||
526 | + "time" => array("suffix" => "time", "type" => "bigint", "length" => 11), | ||
527 | + "image" => array("suffix" => "image", "type" => "varchar", "length" => 255), | ||
528 | + "images" => array("suffix" => "images", "type" => "varchar", "length" => 2000), | ||
529 | + "file" => array("suffix" => "file", "type" => "varchar", "length" => 255), | ||
530 | + "files" => array("suffix" => "files", "type" => "varchar", "length" => 2000), | ||
531 | + "avatar" => array("suffix" => "avatar", "type" => "varchar", "length" => 255), | ||
532 | + "avatars" => array("suffix" => "avatars", "type" => "varchar", "length" => 2000), | ||
533 | + "content" => array("suffix" => "content", "type" => "text", "length" => 0), | ||
534 | + "_id" => array("suffix" => "_id", "type" => "bigint", "length" => 11), | ||
535 | + "_ids" => array("suffix" => "_ids", "type" => "varchar", "length" => 255), | ||
536 | + "list-enum" => array("suffix" => "list", "type" => "enum", "length" => 0), | ||
537 | + "list-set" => array("suffix" => "list", "type" => "set", "length" => 0), | ||
538 | + "data-enum" => array("suffix" => "data", "type" => "enum", "length" => 0), | ||
539 | + "data-set" => array("suffix" => "data", "type" => "set", "length" => 0), | ||
540 | + "json" => array("suffix" => "json", "type" => "varchar", "length" => 2000), | ||
541 | + "switch" => array("suffix" => "switch", "type" => "tinyint", "length" => 1), | ||
542 | + ); | ||
543 | + if (isset($allow[$params['suffix']]) && is_array($allow[$params['suffix']])) { | ||
544 | + $fieldData['special'] = ""; | ||
545 | + $fieldData['suffix'] = $params['suffix']; | ||
546 | + $field['name'] = $params['name']; //字段名 | ||
547 | + $field['field'] = $params['name'] . $allow[$params['suffix']]['suffix']; //字段名 | ||
548 | + $field['length'] = $field['length2'] = isset($params['length']) && intval($params['length']) ? intval($params['length']) : $allow[$params['suffix']]['length']; //字段长度 | ||
549 | + $field['type'] = $allow[$params['suffix']]['type']; //字段类型 | ||
550 | + $field['default'] = isset($params['default']) ? $params['default'] : ""; //默认值 | ||
551 | + if ($allow[$params['suffix']]['type'] == "enum" || $allow[$params['suffix']]['type'] == "set") { | ||
552 | + $comment = \GuzzleHttp\json_decode($params['comment'], true); | ||
553 | + $field['comment'] = $params['title'] . ":"; //备注 | ||
554 | + $field['length2'] = ""; | ||
555 | + $str = ""; | ||
556 | + $default_optional = array(); | ||
557 | + foreach ($comment as $k => $v) { | ||
558 | + $default_optional[] = $k; | ||
559 | + $field['comment'] .= $str . $k . "=" . $v; | ||
560 | + $field['length2'] .= $str . "'" . $k . "'"; | ||
561 | + $str = ","; | ||
562 | + } | ||
563 | + if (!in_array($field['default'], $default_optional)) { | ||
564 | + $field['default'] = $default_optional[0]; | ||
565 | + } | ||
566 | + } else { | ||
567 | + $params['comment'] = ""; | ||
568 | + $field['comment'] = $params['title']; //备注 | ||
569 | + } | ||
570 | + } else { | ||
571 | + $this->error(__('特殊字段类型不正确!')); | ||
572 | + } | ||
573 | + break; | ||
574 | + case "2": | ||
575 | + $allow = array( | ||
576 | + "varchar" => array("type" => "varchar", "length" => 255), | ||
577 | + "int" => array("type" => "bigint", "length" => 11), | ||
578 | + "enum" => array("type" => "enum", "length" => 0), | ||
579 | + "set" => array("type" => "set", "length" => 0), | ||
580 | + "float" => array("type" => "float", "length" => "10,2"), | ||
581 | + "text" => array("type" => "text", "length" => 0), | ||
582 | + "datetime" => array("type" => "datetime", "length" => 11), | ||
583 | + "date" => array("type" => "date", "length" => 11), | ||
584 | + "year" => array("type" => "year", "length" => 4), | ||
585 | + "timestamp" => array("type" => "timestamp", "length" => 11), | ||
586 | + ); | ||
587 | + if (isset($allow[$params['type']]) && is_array($allow[$params['type']])) { | ||
588 | + $fieldData['special'] = ""; | ||
589 | + $fieldData['suffix'] = ""; | ||
590 | + $params['suffix'] = ""; | ||
591 | + $field['name'] = $params['name']; //字段名 | ||
592 | + $field['field'] = $params['name']; //字段名 | ||
593 | + if ($params['type'] == "float") { | ||
594 | + $field['length'] = $field['length2'] = isset($params['length']) && $params['length'] ? $params['length'] : $allow[$params['type']]['length']; //字段长度 | ||
595 | + } else { | ||
596 | + $field['length'] = $field['length2'] = isset($params['length']) && intval($params['length']) ? intval($params['length']) : $allow[$params['type']]['length']; //字段长度 | ||
597 | + } | ||
598 | + $field['type'] = $allow[$params['type']]['type']; //字段类型 | ||
599 | + $field['default'] = isset($params['default']) ? $params['default'] : ""; //默认值 | ||
600 | + if ($allow[$params['type']]['type'] == "enum" || $allow[$params['type']]['type'] == "set") { | ||
601 | + $comment = \GuzzleHttp\json_decode($params['comment'], true); | ||
602 | + $field['comment'] = $params['title'] . ":"; //备注 | ||
603 | + $field['length2'] = ""; | ||
604 | + $str = ""; | ||
605 | + $default_optional = array(); | ||
606 | + foreach ($comment as $k => $v) { | ||
607 | + $default_optional[] = $k; | ||
608 | + $field['comment'] .= $str . $k . "=" . $v; | ||
609 | + $field['length2'] .= $str . "'" . $k . "'"; | ||
610 | + $str = ","; | ||
611 | + } | ||
612 | + if (!in_array($field['default'], $default_optional)) { | ||
613 | + $field['default'] = $default_optional[0]; | ||
614 | + } | ||
615 | + } else { | ||
616 | + $params['comment'] = ""; | ||
617 | + $field['comment'] = $params['title']; //备注 | ||
618 | + } | ||
619 | + } else { | ||
620 | + $this->error(__('特殊字段类型不正确!')); | ||
621 | + } | ||
622 | + break; | ||
623 | + case "3": | ||
624 | + $allow = array( | ||
625 | + "user_id" => array("title" => "会员ID(单选)", "type" => "bigint", "length" => 11), | ||
626 | + "category_id" => array("title" => "分类ID(单选)", "type" => "bigint", "length" => 11), | ||
627 | + "category_ids" => array("title" => "分类ID(多选)", "type" => "varchar", "length" => 200), | ||
628 | + "weigh" => array("title" => "权重", "type" => "bigint", "length" => 11), | ||
629 | + "status" => array("title" => "状态", "type" => "enum", "length" => 0), | ||
630 | + "createtime" => array("title" => "创建时间", "type" => "bigint", "length" => 11), | ||
631 | + "updatetime" => array("title" => "更新时间", "type" => "bigint", "length" => 11), | ||
632 | + "deletetime" => array("title" => "删除时间", "type" => "bigint", "length" => 11), | ||
633 | + ); | ||
634 | + if (isset($allow[$params['special']]) && is_array($allow[$params['special']])) { | ||
635 | + $fieldData['special'] = $params['special']; | ||
636 | + $fieldData['suffix'] = ""; | ||
637 | +// $params['title'] = $allow[$params['special']]['title']; | ||
638 | +// if ($params['special'] != "status") { | ||
639 | +// $params['comment'] = ""; | ||
640 | +// } | ||
641 | +// $params['comment'] = | ||
642 | + $params['suffix'] = ""; | ||
643 | + $field['name'] = $params['special']; //字段名 | ||
644 | + $field['field'] = $params['special']; //字段名 | ||
645 | + $field['length'] = $field['length2'] = $allow[$params['special']]['length']; //字段长度 | ||
646 | +// $field['comment'] = $params['title']; //备注 | ||
647 | + $field['type'] = $allow[$params['special']]['type']; //字段类型 | ||
648 | + $field['default'] = $field['type'] == "varchar" ? "" : "0"; //默认值 | ||
649 | + | ||
650 | + if ($params['special'] == "status") { | ||
651 | + $comment = \GuzzleHttp\json_decode($params['comment'], true); | ||
652 | + $field['comment'] = $params['title'] . ":"; //备注 | ||
653 | + $field['length2'] = ""; | ||
654 | + $str = ""; | ||
655 | + $default_optional = array(); | ||
656 | + foreach ($comment as $k => $v) { | ||
657 | + $default_optional[] = $k; | ||
658 | + $field['comment'] .= $str . $k . "=" . $v; | ||
659 | + $field['length2'] .= $str . "'" . $k . "'"; | ||
660 | + $str = ","; | ||
661 | + } | ||
662 | + if (!in_array($field['default'], $default_optional)) { | ||
663 | + $field['default'] = $default_optional[0]; | ||
664 | + } | ||
665 | + } else { | ||
666 | + $params['comment'] = ""; | ||
667 | + $field['comment'] = $params['title']; //备注 | ||
668 | + } | ||
669 | + | ||
670 | + } else { | ||
671 | + $this->error(__('特殊字段类型不正确!')); | ||
672 | + } | ||
673 | + break; | ||
674 | + default : | ||
675 | + $this->error(__('No Results were found')); | ||
676 | + break; | ||
677 | + } | ||
678 | + /* | ||
679 | + if ($this->check($prefix . $mod_table['table'], $field['name'])) { | ||
680 | + $this->error(__('字段已经存在!')); | ||
681 | + } */ | ||
682 | + $fieldData['mid'] = $params['mid']; | ||
683 | + //$fieldData['category'] = $params['category']; | ||
684 | + $fieldData['title'] = $params['title']; | ||
685 | + $fieldData['name'] = $field['name']; | ||
686 | + $fieldData['field'] = $field['field']; | ||
687 | + $fieldData['type'] = $field['type']; | ||
688 | + $fieldData['length'] = $field['length']; | ||
689 | + $fieldData['default'] = $field['default']; | ||
690 | + $fieldData['comment'] = $field['comment']; | ||
691 | + $fieldData['desc'] = $params['desc']; | ||
692 | + $fieldData['updatetime'] = time(); | ||
693 | + if ($fieldData['type'] == "text") { | ||
694 | + $fieldData['default'] = ""; | ||
695 | + } | ||
696 | + | ||
697 | + | ||
698 | + if ($field['type'] == "bigint" || $field['type'] == "int") { | ||
699 | + $field['default'] = intval($field['default']); | ||
700 | + } elseif ($field['type'] == "tinyint") { | ||
701 | + $field['default'] = in_array($field['default'], [0, 1]) ? $field['default'] : 0; | ||
702 | + } elseif ($field['type'] == "float") { | ||
703 | + $field['default'] = is_float($field['default']) ? $field['default'] : 0; | ||
704 | + } | ||
705 | + | ||
706 | + \think\Db::startTrans(); | ||
707 | + try { | ||
708 | + $result = $field_info->save($fieldData); | ||
709 | + if ($result !== false) { | ||
710 | + //在此执行添加字段的操作 | ||
711 | + if (in_array($field['type'], ["text", "datetime", "date", "year", "timestamp"])) { | ||
712 | + $sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` CHANGE COLUMN `{$oldField_info['field']}` `{$field['field']}` {$field['type']} NOT NULL COMMENT '{$field['comment']}' ;"; | ||
713 | + } else { | ||
714 | + $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']}' ;"; | ||
715 | + } | ||
716 | + try { | ||
717 | + $res = \think\Db::execute($sql); | ||
718 | + } catch (Exception $ex) { | ||
719 | + // $field_info->save($oldField_info); | ||
720 | + throw new Exception('参数错误,请检查字段名,字段长度或者默认值等输入参数是否合法'); | ||
721 | + } | ||
722 | + } else { | ||
723 | + throw new Exception($this->ModelFields->getError()); | ||
724 | + } | ||
725 | + \think\Db::commit(); | ||
726 | + } catch (Exception $e) { | ||
727 | + \think\Db::rollback(); | ||
728 | + $this->error($e->getMessage()); | ||
729 | + } | ||
730 | + $this->success(); | ||
731 | + } catch (\think\exception\PDOException $e) { | ||
732 | + $field_info->save($oldField_info); | ||
733 | + $this->error($e->getMessage()); | ||
734 | + } catch (\think\Exception $e) { | ||
735 | + $field_info->save($oldField_info); | ||
736 | + $this->error($e->getMessage()); | ||
737 | + } | ||
738 | + } | ||
739 | + $this->error(__('Parameter %s can not be empty', '')); | ||
740 | + } | ||
741 | + $comment = ""; | ||
742 | + if ($field_info['type'] == "enum" || $field_info['type'] == "set") { | ||
743 | + //echo $field_info['comment']; | ||
744 | + $commentStr = substr($field_info['comment'], strpos($field_info['comment'], ":") + 1); | ||
745 | + | ||
746 | + $commentArr = []; | ||
747 | + foreach (explode(",", $commentStr) as $k => $v) { | ||
748 | + | ||
749 | + list($key, $val) = explode("=", $v); | ||
750 | + | ||
751 | + $commentArr[$key] = $val; | ||
752 | + } | ||
753 | + | ||
754 | + $comment = \json_encode($commentArr); | ||
755 | + } | ||
756 | + $prefix = Config::get('database.prefix'); | ||
757 | + $this->view->assign("field_info", $field_info); | ||
758 | + $this->view->assign("row", $field_info); | ||
759 | + $this->view->assign("prefix", $prefix); | ||
760 | + $this->view->assign("comment", $comment); | ||
761 | + $this->view->assign("mid", $field_info['mid']); | ||
762 | + return $this->view->fetch(); | ||
763 | + } | ||
764 | + | ||
765 | + public function field_del($ids = NULL) { | ||
766 | + if ($ids) { | ||
767 | + $pk = $this->ModelFields->getPk(); | ||
768 | + $adminIds = $this->getDataLimitAdminIds(); | ||
769 | + if (is_array($adminIds)) { | ||
770 | + $count = $this->ModelFields->where($this->dataLimitField, 'in', $adminIds); | ||
771 | + } | ||
772 | + $list = $this->ModelFields->where($pk, 'in', $ids)->select(); | ||
773 | + $prefix = Config::get('database.prefix'); | ||
774 | + $count = 0; | ||
775 | + foreach ($list as $k => $v) { | ||
776 | + $mod_table = $this->ModelOnline->get($v['mid']); | ||
777 | + $sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` DROP `{$v['field']}` "; | ||
778 | + try { | ||
779 | + $res = \think\Db::execute($sql); | ||
780 | + $count += $v->delete(); | ||
781 | + if ($count) { | ||
782 | + $this->success(); | ||
783 | + } else { | ||
784 | + $this->error(__('No rows were deleted')); | ||
785 | + } | ||
786 | + } catch (Exception $ex) { | ||
787 | + $this->error(__('No rows were deleted')); | ||
788 | + } | ||
789 | + } | ||
790 | + } | ||
791 | + $this->error(__('Parameter %s can not be empty', 'ids')); | ||
792 | + } | ||
793 | + | ||
794 | + public function dictionary() { | ||
795 | + | ||
796 | + $this->db_name = \config("database.database"); | ||
797 | + $this->db_prefix = \config("database.prefix"); | ||
798 | + $this->view->assign('db_name', $this->db_name); | ||
799 | + $this->view->assign('db_prefix', $this->db_prefix); | ||
800 | + | ||
801 | + $dictionary = [ | ||
802 | + 'make' => [], | ||
803 | + 'system' => [], | ||
804 | + 'other' => [], | ||
805 | + ]; | ||
806 | + | ||
807 | + //读取所有表 | ||
808 | + $tables_res = Db::table("information_schema.TABLES")->field("TABLE_NAME")->where(['TABLE_SCHEMA' => $this->db_name,])->select(); | ||
809 | + $tables_all = array_column($tables_res, 'TABLE_NAME'); | ||
810 | + | ||
811 | + //已经获取到数据字典的表 | ||
812 | + $tables_isset = []; | ||
813 | + | ||
814 | + //声明系统表 获取系统表的数据字典 | ||
815 | + $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']; | ||
816 | + foreach ($tables_system as $k => $v) { | ||
817 | + $table_name = $this->db_prefix . $v; | ||
818 | + $dictionary['system'][] = $this->getSystemTableInfo($table_name); | ||
819 | + $tables_isset[] = $table_name; | ||
820 | + } | ||
821 | + | ||
822 | + //读取自建表 获取自建表数据字典 | ||
823 | + $tables_make = \app\admin\model\TableMakeTables::all(function ($query) { | ||
824 | + $query->order("weigh desc,id desc"); | ||
825 | + }); | ||
826 | + foreach ($tables_make as $k => $v) { | ||
827 | + $table_name = $this->db_prefix . $v['table']; | ||
828 | + $dictionary['make'][] = $this->getMakeTableInfo($table_name, $v); | ||
829 | + $tables_isset[] = $table_name; | ||
830 | + } | ||
831 | + | ||
832 | + //获取其他表数据字典 求差集,计算出其他表 | ||
833 | + $tables_other = array_diff($tables_all, $tables_isset); | ||
834 | + foreach ($tables_other as $k => $v) { | ||
835 | + $table_name = $v; | ||
836 | + $dictionary['other'][] = $this->getOtherTableInfo($table_name); | ||
837 | + $tables_isset[] = $table_name; | ||
838 | + } | ||
839 | + | ||
840 | + $this->view->assign('dictionary', $dictionary); | ||
841 | + $this->view->engine->layout(false); | ||
842 | + return $this->view->fetch(); | ||
843 | + | ||
844 | + } | ||
845 | + | ||
846 | + | ||
847 | + /** | ||
848 | + * 根据表名获取系统表的数据字典数据 | ||
849 | + * @param $table_name 表名 | ||
850 | + * @return array | ||
851 | + */ | ||
852 | + protected function getSystemTableInfo($table_name) { | ||
853 | + return $this->getOtherTableInfo($table_name); | ||
854 | + } | ||
855 | + | ||
856 | + /** | ||
857 | + * 根据表名获取非自建表的数据字典信息 | ||
858 | + * @param $table_name | ||
859 | + * @return array | ||
860 | + */ | ||
861 | + protected function getOtherTableInfo($table_name) { | ||
862 | + $table_info = $this->getTableInfo($table_name); | ||
863 | + $result = [ | ||
864 | + 'name' => $table_info['table_info']['TABLE_COMMENT'] ? $table_info['table_info']['TABLE_COMMENT'] : $table_name, | ||
865 | + 'table' => preg_replace('/^(' . $this->db_prefix . ').*?/is', '', $table_name),//表名去前缀 | ||
866 | + 'table_name' => $table_name, | ||
867 | + 'desc' => $table_info['table_info']['TABLE_COMMENT'], | ||
868 | + 'engine' => $table_info['table_info']['ENGINE'], | ||
869 | + 'table_comment' => $table_info['table_info']['TABLE_COMMENT'], | ||
870 | + 'table_collation' => $table_info['table_info']['TABLE_COLLATION'], | ||
871 | + 'create_time' => $table_info['table_info']['CREATE_TIME'], | ||
872 | + 'update_time' => $table_info['table_info']['UPDATE_TIME'], | ||
873 | + 'fields' => $this->getTableFields($table_info['table_fields']), | ||
874 | + ]; | ||
875 | + return $result; | ||
876 | + } | ||
877 | + | ||
878 | + /** | ||
879 | + * 根据表名、自建表信息数据,获取自建表的数据字典信息 | ||
880 | + * @param $table_name 表名 | ||
881 | + * @param $table | ||
882 | + * @return array | ||
883 | + * @throws \think\exception\DbException | ||
884 | + */ | ||
885 | + protected function getMakeTableInfo($table_name, $table) { | ||
886 | + $model_fields = \app\admin\model\TableMakeFields::all(function ($query) use ($table) { | ||
887 | + $query->where(['mid' => $table['id']]); | ||
888 | + $query->order("weigh desc,id desc"); | ||
889 | + }); | ||
890 | + $result = $this->getOtherTableInfo($table_name); | ||
891 | + $result['name'] = $table['name']; | ||
892 | + $result['table'] = $table['table']; | ||
893 | + $result['desc'] = $table['desc']; | ||
894 | + $result['create_time'] = date("Y-m-d H:i:s", $table['createtime']); | ||
895 | + $result['update_time'] = date("Y-m-d H:i:s", $table['updatetime']); | ||
896 | + $result['fields'] = $this->getTableFieldsByMake($result['fields'], $model_fields); | ||
897 | + return $result; | ||
898 | + } | ||
899 | + | ||
900 | + /** | ||
901 | + * 结合表的字段备注 自建表存储的信息,生成自建表的字段数据字典 | ||
902 | + * @param $fields | ||
903 | + * @param array $make_fields | ||
904 | + * @return array | ||
905 | + */ | ||
906 | + protected function getTableFieldsByMake($fields, $make_fields = []) { | ||
907 | + $result = []; | ||
908 | + $field_list = []; | ||
909 | + foreach ($fields as $k => $v) { | ||
910 | + $field_list[$v['field_name']] = $v; | ||
911 | + } | ||
912 | + $result[] = $field_list['id']; | ||
913 | + foreach ($make_fields as $k => $v) { | ||
914 | + $result[] = [ | ||
915 | + "field_title" => $v['title'], | ||
916 | + "field_name" => $v['field'], | ||
917 | + "character" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['character'] : NULL, | ||
918 | + "field_collation" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['field_collation'] : NULL, | ||
919 | + "data_type" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['data_type'] : NULL,//字段类型 | ||
920 | + "column_type" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['column_type'] : NULL,//列类型 | ||
921 | + "is_nullable" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['is_nullable'] : NULL,//是否能为空 | ||
922 | + "length" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['length'] : NULL,//字符串长度 | ||
923 | + "column_comment" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['column_comment'] : NULL,//字段备注 | ||
924 | + "default" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['default'] : NULL,//字段默认值 | ||
925 | + "desc" => $v['desc'], | ||
926 | + ]; | ||
927 | + } | ||
928 | + return $result; | ||
929 | + } | ||
930 | + | ||
931 | + /** | ||
932 | + * 根据表的字段备注,生成字段数据字典 | ||
933 | + * @param $fields | ||
934 | + * @return array | ||
935 | + */ | ||
936 | + protected function getTableFields($fields) { | ||
937 | + $result = []; | ||
938 | + foreach ($fields as $k => $v) { | ||
939 | + $column_type = preg_replace('/(unsigned).*?/is', '(无符号)', $v['COLUMN_TYPE']); | ||
940 | + list($field_name) = explode(":", $v['COLUMN_COMMENT']); | ||
941 | + $result[] = [ | ||
942 | + "field_title" => $field_name ? $field_name : $v['COLUMN_NAME'], | ||
943 | + "field_name" => $v['COLUMN_NAME'], | ||
944 | + "character" => $v['CHARACTER_SET_NAME'], | ||
945 | + "field_collation" => $v['COLLATION_NAME'], | ||
946 | + "data_type" => $v['DATA_TYPE'],//字段类型 | ||
947 | + "column_type" => $column_type,//列类型 | ||
948 | + "is_nullable" => $v['IS_NULLABLE'],//是否能为空 | ||
949 | + "length" => $v['CHARACTER_MAXIMUM_LENGTH'],//字符串长度 | ||
950 | + "column_comment" => $v['COLUMN_COMMENT'],//字段备注 | ||
951 | + "default" => $v['COLUMN_DEFAULT'],//字段默认值 | ||
952 | + "desc" => "",//字段默认值 | ||
953 | + ]; | ||
954 | + } | ||
955 | + return $result; | ||
956 | + | ||
957 | + } | ||
958 | + | ||
959 | + /** | ||
960 | + * 获取指定表的基本信息 | ||
961 | + * @param $table_name | ||
962 | + * @return array | ||
963 | + * @throws \think\db\exception\DataNotFoundException | ||
964 | + * @throws \think\db\exception\ModelNotFoundException | ||
965 | + * @throws \think\exception\DbException | ||
966 | + */ | ||
967 | + protected function getTableInfo($table_name) { | ||
968 | +// //读取表信息 | ||
969 | +// $sql = "SELECT * FROM information_schema.TABLES WHERE table_schema = '{$db_name}' and TABLE_NAME='{$table_name}'"; | ||
970 | +// $res = Db::query($sql); | ||
971 | +// //读取表结构 | ||
972 | +// $sql = "SELECT * FROM information_schema.COLUMNS where table_schema ='{$db_name}' and TABLE_NAME = '{$table_name}'"; | ||
973 | +// $res = Db::query($sql); | ||
974 | + | ||
975 | + //读取表信息 | ||
976 | + $table_info = Db::table("information_schema.TABLES")->field("*")->where(['TABLE_SCHEMA' => $this->db_name, 'TABLE_NAME' => $table_name])->find(); | ||
977 | + //读取表结构 | ||
978 | + $table_fields = Db::table("information_schema.COLUMNS")->field("*")->where(['TABLE_SCHEMA' => $this->db_name, 'TABLE_NAME' => $table_name])->select(); | ||
979 | + return [ | ||
980 | + 'table_info' => $table_info, | ||
981 | + 'table_fields' => $table_fields, | ||
982 | + ]; | ||
983 | + } | ||
984 | + | ||
985 | +} |
application/admin/controller/Third.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\controller; | ||
4 | + | ||
5 | +use app\common\controller\Backend; | ||
6 | + | ||
7 | +/** | ||
8 | + * 第三方登录管理 | ||
9 | + * | ||
10 | + * @icon fa fa-circle-o | ||
11 | + */ | ||
12 | +class Third extends Backend | ||
13 | +{ | ||
14 | + | ||
15 | + /** | ||
16 | + * Third模型对象 | ||
17 | + * @var \app\admin\model\Third | ||
18 | + */ | ||
19 | + protected $model = null; | ||
20 | + | ||
21 | + public function _initialize() | ||
22 | + { | ||
23 | + parent::_initialize(); | ||
24 | + $this->model = new \app\admin\model\Third; | ||
25 | + } | ||
26 | + | ||
27 | + /** | ||
28 | + * 查看 | ||
29 | + */ | ||
30 | + public function index() | ||
31 | + { | ||
32 | + $this->relationSearch = true; | ||
33 | + //设置过滤方法 | ||
34 | + $this->request->filter(['strip_tags']); | ||
35 | + if ($this->request->isAjax()) { | ||
36 | + //如果发送的来源是Selectpage,则转发到Selectpage | ||
37 | + if ($this->request->request('keyField')) { | ||
38 | + return $this->selectpage(); | ||
39 | + } | ||
40 | + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); | ||
41 | + $total = $this->model | ||
42 | + ->with(['user']) | ||
43 | + ->where($where) | ||
44 | + ->order($sort, $order) | ||
45 | + ->count(); | ||
46 | + | ||
47 | + $list = $this->model | ||
48 | + ->with(['user']) | ||
49 | + ->where($where) | ||
50 | + ->order($sort, $order) | ||
51 | + ->limit($offset, $limit) | ||
52 | + ->select(); | ||
53 | + foreach ($list as $index => $item) { | ||
54 | + if ($item->user) { | ||
55 | + $item->user->visible(['nickname']); | ||
56 | + } | ||
57 | + } | ||
58 | + $list = collection($list)->toArray(); | ||
59 | + $result = array("total" => $total, "rows" => $list); | ||
60 | + | ||
61 | + return json($result); | ||
62 | + } | ||
63 | + return $this->view->fetch(); | ||
64 | + } | ||
65 | + | ||
66 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\controller\wechat; | ||
4 | + | ||
5 | +use app\common\controller\Backend; | ||
6 | +use app\admin\model\WechatResponse; | ||
7 | + | ||
8 | +/** | ||
9 | + * 微信自动回复管理 | ||
10 | + * | ||
11 | + * @icon fa fa-circle-o | ||
12 | + */ | ||
13 | +class Autoreply extends Backend | ||
14 | +{ | ||
15 | + | ||
16 | + protected $model = null; | ||
17 | + protected $noNeedRight = ['check_text_unique']; | ||
18 | + | ||
19 | + public function _initialize() | ||
20 | + { | ||
21 | + parent::_initialize(); | ||
22 | + $this->model = model('WechatAutoreply'); | ||
23 | + } | ||
24 | + | ||
25 | + /** | ||
26 | + * 编辑 | ||
27 | + */ | ||
28 | + public function edit($ids = null) | ||
29 | + { | ||
30 | + $row = $this->model->get(['id' => $ids]); | ||
31 | + if (!$row) { | ||
32 | + $this->error(__('No Results were found')); | ||
33 | + } | ||
34 | + if ($this->request->isPost()) { | ||
35 | + $params = $this->request->post("row/a"); | ||
36 | + if ($params) { | ||
37 | + $row->save($params); | ||
38 | + $this->success(); | ||
39 | + } | ||
40 | + $this->error(); | ||
41 | + } | ||
42 | + $response = WechatResponse::get(['eventkey' => $row['eventkey']]); | ||
43 | + $this->view->assign("response", $response); | ||
44 | + $this->view->assign("row", $row); | ||
45 | + return $this->view->fetch(); | ||
46 | + } | ||
47 | + | ||
48 | + /** | ||
49 | + * 判断文本是否唯一 | ||
50 | + * @internal | ||
51 | + */ | ||
52 | + public function check_text_unique() | ||
53 | + { | ||
54 | + $row = $this->request->post("row/a"); | ||
55 | + $except = $this->request->post("except"); | ||
56 | + $text = isset($row['text']) ? $row['text'] : ''; | ||
57 | + if ($this->model->where('text', $text)->where(function ($query) use ($except) { | ||
58 | + if ($except) { | ||
59 | + $query->where('text', '<>', $except); | ||
60 | + } | ||
61 | + })->count() == 0) { | ||
62 | + $this->success(); | ||
63 | + } else { | ||
64 | + $this->error(__('Text already exists')); | ||
65 | + } | ||
66 | + } | ||
67 | + | ||
68 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\controller\wechat; | ||
4 | + | ||
5 | +use app\common\controller\Backend; | ||
6 | +use think\Controller; | ||
7 | +use think\Request; | ||
8 | + | ||
9 | +/** | ||
10 | + * 微信配置管理 | ||
11 | + * | ||
12 | + * @icon fa fa-circle-o | ||
13 | + */ | ||
14 | +class Config extends Backend | ||
15 | +{ | ||
16 | + | ||
17 | + protected $model = null; | ||
18 | + | ||
19 | + public function _initialize() | ||
20 | + { | ||
21 | + parent::_initialize(); | ||
22 | + $this->model = model('WechatConfig'); | ||
23 | + } | ||
24 | + | ||
25 | + /** | ||
26 | + * 添加 | ||
27 | + */ | ||
28 | + public function add() | ||
29 | + { | ||
30 | + if ($this->request->isPost()) { | ||
31 | + $params = $this->request->post("row/a"); | ||
32 | + if ($params) { | ||
33 | + foreach ($params as $k => &$v) { | ||
34 | + $v = is_array($v) ? implode(',', $v) : $v; | ||
35 | + } | ||
36 | + | ||
37 | + if ($params['mode'] == 'json') { | ||
38 | + //JSON字段 | ||
39 | + $fieldarr = $valuearr = []; | ||
40 | + $field = $this->request->post('field/a'); | ||
41 | + $value = $this->request->post('value/a'); | ||
42 | + foreach ($field as $k => $v) { | ||
43 | + if ($v != '') { | ||
44 | + $fieldarr[] = $field[$k]; | ||
45 | + $valuearr[] = $value[$k]; | ||
46 | + } | ||
47 | + } | ||
48 | + $params['value'] = json_encode(array_combine($fieldarr, $valuearr), JSON_UNESCAPED_UNICODE); | ||
49 | + } | ||
50 | + unset($params['mode']); | ||
51 | + try { | ||
52 | + //是否采用模型验证 | ||
53 | + if ($this->modelValidate) { | ||
54 | + $name = basename(str_replace('\\', '/', get_class($this->model))); | ||
55 | + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate; | ||
56 | + $this->model->validate($validate); | ||
57 | + } | ||
58 | + $result = $this->model->save($params); | ||
59 | + if ($result !== false) { | ||
60 | + $this->success(); | ||
61 | + } else { | ||
62 | + $this->error($this->model->getError()); | ||
63 | + } | ||
64 | + } catch (\think\exception\PDOException $e) { | ||
65 | + $this->error($e->getMessage()); | ||
66 | + } | ||
67 | + } | ||
68 | + $this->error(__('Parameter %s can not be empty', '')); | ||
69 | + } | ||
70 | + return $this->view->fetch(); | ||
71 | + } | ||
72 | + | ||
73 | + /** | ||
74 | + * 编辑 | ||
75 | + */ | ||
76 | + public function edit($ids = null) | ||
77 | + { | ||
78 | + $row = $this->model->get($ids); | ||
79 | + if (!$row) { | ||
80 | + $this->error(__('No Results were found')); | ||
81 | + } | ||
82 | + if ($this->request->isPost()) { | ||
83 | + $params = $this->request->post("row/a"); | ||
84 | + if ($params) { | ||
85 | + foreach ($params as $k => &$v) { | ||
86 | + $v = is_array($v) ? implode(',', $v) : $v; | ||
87 | + } | ||
88 | + | ||
89 | + if ($params['mode'] == 'json') { | ||
90 | + //JSON字段 | ||
91 | + $fieldarr = $valuearr = []; | ||
92 | + $field = $this->request->post('field/a'); | ||
93 | + $value = $this->request->post('value/a'); | ||
94 | + foreach ($field as $k => $v) { | ||
95 | + if ($v != '') { | ||
96 | + $fieldarr[] = $field[$k]; | ||
97 | + $valuearr[] = $value[$k]; | ||
98 | + } | ||
99 | + } | ||
100 | + $params['value'] = json_encode(array_combine($fieldarr, $valuearr), JSON_UNESCAPED_UNICODE); | ||
101 | + } | ||
102 | + unset($params['mode']); | ||
103 | + try { | ||
104 | + //是否采用模型验证 | ||
105 | + if ($this->modelValidate) { | ||
106 | + $name = basename(str_replace('\\', '/', get_class($this->model))); | ||
107 | + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate; | ||
108 | + $row->validate($validate); | ||
109 | + } | ||
110 | + $result = $row->save($params); | ||
111 | + if ($result !== false) { | ||
112 | + $this->success(); | ||
113 | + } else { | ||
114 | + $this->error($row->getError()); | ||
115 | + } | ||
116 | + } catch (\think\exception\PDOException $e) { | ||
117 | + $this->error($e->getMessage()); | ||
118 | + } | ||
119 | + } | ||
120 | + $this->error(__('Parameter %s can not be empty', '')); | ||
121 | + } | ||
122 | + $this->view->assign("row", $row); | ||
123 | + $this->view->assign("value", (array)json_decode($row->value, true)); | ||
124 | + return $this->view->fetch(); | ||
125 | + } | ||
126 | + | ||
127 | +} |
application/admin/controller/wechat/Menu.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\controller\wechat; | ||
4 | + | ||
5 | +use addons\wechat\library\Config; | ||
6 | +use app\common\controller\Backend; | ||
7 | +use app\admin\model\WechatResponse; | ||
8 | +use EasyWeChat\Factory; | ||
9 | +use think\Exception; | ||
10 | + | ||
11 | +/** | ||
12 | + * 菜单管理 | ||
13 | + * | ||
14 | + * @icon fa fa-list-alt | ||
15 | + */ | ||
16 | +class Menu extends Backend | ||
17 | +{ | ||
18 | + protected $wechatcfg = null; | ||
19 | + | ||
20 | + public function _initialize() | ||
21 | + { | ||
22 | + parent::_initialize(); | ||
23 | + $this->wechatcfg = \app\admin\model\WechatConfig::get(['name' => 'menu']); | ||
24 | + } | ||
25 | + | ||
26 | + /** | ||
27 | + * 查看 | ||
28 | + */ | ||
29 | + public function index() | ||
30 | + { | ||
31 | + $responselist = array(); | ||
32 | + $all = WechatResponse::all(); | ||
33 | + foreach ($all as $k => $v) { | ||
34 | + $responselist[$v['eventkey']] = $v['title']; | ||
35 | + } | ||
36 | + $this->view->assign('responselist', $responselist); | ||
37 | + $this->view->assign('menu', (array)json_decode($this->wechatcfg->value, true)); | ||
38 | + return $this->view->fetch(); | ||
39 | + } | ||
40 | + | ||
41 | + /** | ||
42 | + * 修改 | ||
43 | + */ | ||
44 | + public function edit($ids = null) | ||
45 | + { | ||
46 | + $menu = $this->request->post("menu"); | ||
47 | + $menu = (array)json_decode($menu, true); | ||
48 | + foreach ($menu as $index => &$item) { | ||
49 | + if (isset($item['sub_button'])) { | ||
50 | + foreach ($item['sub_button'] as &$subitem) { | ||
51 | + if ($subitem['type'] == 'view') { | ||
52 | + $allowFields = ['type', 'name', 'url']; | ||
53 | + $subitem = ['type' => $subitem['type'], 'name' => $subitem['name'], 'url' => $subitem['url']]; | ||
54 | + } else { | ||
55 | + if ($subitem['type'] == 'miniprogram') { | ||
56 | + $allowFields = ['type', 'name', 'url', 'appid', 'pagepath']; | ||
57 | + $subitem = ['type' => $subitem['type'], 'name' => $subitem['name'], 'url' => $subitem['url'], 'appid' => $subitem['appid'], 'pagepath' => $subitem['pagepath']]; | ||
58 | + } else { | ||
59 | + $allowFields = ['type', 'name', 'key']; | ||
60 | + $subitem = ['type' => $subitem['type'], 'name' => $subitem['name'], 'key' => $subitem['key']]; | ||
61 | + } | ||
62 | + } | ||
63 | + $subitem = array_intersect_key($subitem, array_flip($allowFields)); | ||
64 | + } | ||
65 | + } else { | ||
66 | + if ($item['type'] == 'view') { | ||
67 | + $allowFields = ['type', 'name', 'url']; | ||
68 | + } else { | ||
69 | + if ($item['type'] == 'miniprogram') { | ||
70 | + $allowFields = ['type', 'name', 'url', 'appid', 'pagepath']; | ||
71 | + } else { | ||
72 | + $allowFields = ['type', 'name', 'key']; | ||
73 | + } | ||
74 | + } | ||
75 | + $item = array_intersect_key($item, array_flip($allowFields)); | ||
76 | + } | ||
77 | + } | ||
78 | + $this->wechatcfg->value = json_encode($menu, JSON_UNESCAPED_UNICODE); | ||
79 | + $this->wechatcfg->save(); | ||
80 | + $this->success(); | ||
81 | + } | ||
82 | + | ||
83 | + /** | ||
84 | + * 加载远程菜单 | ||
85 | + */ | ||
86 | + public function remote() | ||
87 | + { | ||
88 | + $app = Factory::officialAccount(Config::load()); | ||
89 | + | ||
90 | + try { | ||
91 | + $list = $app->menu->list(); | ||
92 | + } catch (\Exception $e) { | ||
93 | + $this->error($e->getMessage()); | ||
94 | + } | ||
95 | + if (isset($list['menu']['button'])) { | ||
96 | + $buttons = $list['menu']['button']; | ||
97 | + foreach ($buttons as $index => &$item) { | ||
98 | + if (isset($item['sub_button'])) { | ||
99 | + if ($item['sub_button']) { | ||
100 | + foreach ($item['sub_button'] as $key => &$value) { | ||
101 | + if (!isset($value['sub_button']) || !$value['sub_button']) { | ||
102 | + unset($value['sub_button']); | ||
103 | + } | ||
104 | + } | ||
105 | + } else { | ||
106 | + unset($item['sub_button']); | ||
107 | + } | ||
108 | + } | ||
109 | + } | ||
110 | + $this->wechatcfg->value = json_encode($buttons, JSON_UNESCAPED_UNICODE); | ||
111 | + $this->wechatcfg->save(); | ||
112 | + $this->success(); | ||
113 | + } else { | ||
114 | + $this->error("加载菜单失败"); | ||
115 | + } | ||
116 | + } | ||
117 | + | ||
118 | + /** | ||
119 | + * 同步到服务器 | ||
120 | + */ | ||
121 | + public function sync($ids = null) | ||
122 | + { | ||
123 | + $app = Factory::officialAccount(Config::load()); | ||
124 | + try { | ||
125 | + $hasError = false; | ||
126 | + $menu = json_decode($this->wechatcfg->value, true); | ||
127 | + foreach ($menu as $k => $v) { | ||
128 | + if (isset($v['sub_button'])) { | ||
129 | + foreach ($v['sub_button'] as $m => $n) { | ||
130 | + if ($n['type'] == 'click' && isset($n['key']) && !$n['key']) { | ||
131 | + $hasError = true; | ||
132 | + break 2; | ||
133 | + } | ||
134 | + } | ||
135 | + } else { | ||
136 | + if ($v['type'] == 'click' && isset($v['key']) && !$v['key']) { | ||
137 | + $hasError = true; | ||
138 | + break; | ||
139 | + } | ||
140 | + } | ||
141 | + } | ||
142 | + if (!$hasError) { | ||
143 | + try { | ||
144 | + $ret = $app->menu->create($menu); | ||
145 | + } catch (\Exception $e) { | ||
146 | + $this->error($e->getMessage()); | ||
147 | + } | ||
148 | + if ($ret['errcode'] == 0) { | ||
149 | + $this->success(); | ||
150 | + } else { | ||
151 | + $this->error($ret['errmsg']); | ||
152 | + } | ||
153 | + } else { | ||
154 | + $this->error(__('Invalid parameters')); | ||
155 | + } | ||
156 | + } catch (Exception $e) { | ||
157 | + $this->error($e->getMessage()); | ||
158 | + } | ||
159 | + } | ||
160 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\controller\wechat; | ||
4 | + | ||
5 | +use app\common\controller\Backend; | ||
6 | +use addons\wechat\library\Wechat; | ||
7 | + | ||
8 | +/** | ||
9 | + * 资源管理 | ||
10 | + * | ||
11 | + * @icon fa fa-list-alt | ||
12 | + */ | ||
13 | +class Response extends Backend | ||
14 | +{ | ||
15 | + | ||
16 | + protected $model = null; | ||
17 | + protected $searchFields = 'id,title'; | ||
18 | + | ||
19 | + public function _initialize() | ||
20 | + { | ||
21 | + parent::_initialize(); | ||
22 | + $this->model = model('WechatResponse'); | ||
23 | + } | ||
24 | + | ||
25 | + /** | ||
26 | + * 选择素材 | ||
27 | + */ | ||
28 | + public function select() | ||
29 | + { | ||
30 | + return $this->view->fetch(); | ||
31 | + } | ||
32 | + | ||
33 | + /** | ||
34 | + * 添加 | ||
35 | + */ | ||
36 | + public function add() | ||
37 | + { | ||
38 | + if ($this->request->isPost()) { | ||
39 | + $params = $this->request->post("row/a"); | ||
40 | + $params['eventkey'] = isset($params['eventkey']) && $params['eventkey'] ? $params['eventkey'] : uniqid(); | ||
41 | + $params['content'] = json_encode($params['content']); | ||
42 | + $params['createtime'] = time(); | ||
43 | + if ($params) { | ||
44 | + $this->model->save($params); | ||
45 | + $this->success(); | ||
46 | + $this->content = $params; | ||
47 | + } | ||
48 | + $this->error(); | ||
49 | + } | ||
50 | + $appConfig = Wechat::appConfig(); | ||
51 | + $this->view->applist = $appConfig; | ||
52 | + return $this->view->fetch(); | ||
53 | + } | ||
54 | + | ||
55 | + /** | ||
56 | + * 编辑 | ||
57 | + */ | ||
58 | + public function edit($ids = NULL) | ||
59 | + { | ||
60 | + $row = $this->model->get($ids); | ||
61 | + if (!$row) | ||
62 | + $this->error(__('No Results were found')); | ||
63 | + if ($this->request->isPost()) { | ||
64 | + $params = $this->request->post("row/a"); | ||
65 | + $params['eventkey'] = isset($params['eventkey']) && $params['eventkey'] ? $params['eventkey'] : uniqid(); | ||
66 | + $params['content'] = json_encode($params['content']); | ||
67 | + if ($params) { | ||
68 | + $row->save($params); | ||
69 | + $this->success(); | ||
70 | + } | ||
71 | + $this->error(); | ||
72 | + } | ||
73 | + $this->view->assign("row", $row); | ||
74 | + $appConfig = Wechat::appConfig(); | ||
75 | + $this->view->applist = $appConfig; | ||
76 | + return $this->view->fetch(); | ||
77 | + } | ||
78 | + | ||
79 | +} |
application/admin/lang/zh-cn/command.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +return [ | ||
4 | + 'Id' => 'ID', | ||
5 | + 'Type' => '类型', | ||
6 | + 'Params' => '参数', | ||
7 | + 'Command' => '命令', | ||
8 | + 'Content' => '返回结果', | ||
9 | + 'Executetime' => '执行时间', | ||
10 | + 'Createtime' => '创建时间', | ||
11 | + 'Updatetime' => '更新时间', | ||
12 | + 'Execute again' => '再次执行', | ||
13 | + 'Successed' => '成功', | ||
14 | + 'Failured' => '失败', | ||
15 | + 'Status' => '状态' | ||
16 | +]; |
application/admin/lang/zh-cn/tablemake.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +return [ | ||
4 | + 'Id' => 'ID', | ||
5 | + 'mid' => '自建表ID', | ||
6 | + 'm_name' => '自建表名称', | ||
7 | + 'm_table' => '自建表表名', | ||
8 | + 'm_desc' => '自建表描述', | ||
9 | + 'Admin_id' => '管理员ID', | ||
10 | + 'Category_id' => '分类ID(单选)', | ||
11 | + 'Flag' => '标志(多选)', | ||
12 | + 'Flag hot' => '热门', | ||
13 | + 'Flag index' => '首页', | ||
14 | + 'Flag recommend' => '推荐', | ||
15 | + 'Title' => '标题', | ||
16 | + 'Content' => '内容', | ||
17 | + 'Image' => '图片', | ||
18 | + 'Keywords' => '关键字', | ||
19 | + 'Description' => '描述', | ||
20 | + 'Views' => '点击', | ||
21 | + 'Refreshtime' => '刷新时间(int)', | ||
22 | + 'Createtime' => '创建时间', | ||
23 | + 'Updatetime' => '更新时间', | ||
24 | + 'Weigh' => '权重', | ||
25 | + 'Status' => '状态', | ||
26 | + 'State' => '状态值', | ||
27 | + 'State 0' => '未审核', | ||
28 | + 'State 1' => '正常', | ||
29 | + 'State 2' => '推荐' | ||
30 | +]; |
application/admin/lang/zh-cn/third.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +return [ | ||
4 | + 'Id' => 'ID', | ||
5 | + 'User_id' => '会员ID', | ||
6 | + 'Platform' => '第三方应用', | ||
7 | + 'Unionid' => '第三方UnionID', | ||
8 | + 'Openid' => '第三方OpenID', | ||
9 | + 'Openname' => '第三方会员昵称', | ||
10 | + 'Access_token' => 'AccessToken', | ||
11 | + 'Expires_in' => '有效期', | ||
12 | + 'Createtime' => '创建时间', | ||
13 | + 'Updatetime' => '更新时间', | ||
14 | + 'Logintime' => '登录时间', | ||
15 | + 'Expiretime' => '过期时间' | ||
16 | +]; |
-
请 注册 或 登录 后发表评论