From 257a5671e901737cdb36b1d34b08ab52bc638e0a Mon Sep 17 00:00:00 2001 From: Anyon Date: Thu, 15 Mar 2018 20:47:29 +0800 Subject: [PATCH] =?UTF-8?q?[=E6=9B=B4=E6=96=B0]=E5=BE=AE=E4=BF=A1=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/admin/controller/Block.php | 114 +++++++ application/admin/controller/Fans.php | 191 +++++++++++ application/admin/controller/Keys.php | 202 ++++++++++++ application/admin/controller/News.php | 297 +++++++++++++++++ application/admin/controller/Review.php | 61 ++++ application/admin/controller/Tags.php | 159 +++++++++ application/admin/controller/api/Push.php | 257 +++++++++++++++ application/admin/service/FansService.php | 123 +++++++ application/admin/service/MediaService.php | 101 ++++++ application/admin/service/TagsService.php | 69 ++++ application/admin/view/block/index.html | 160 +++++++++ application/admin/view/fans/index.html | 160 +++++++++ application/admin/view/fans/tags_inc.html | 80 +++++ application/admin/view/keys/form.html | 292 +++++++++++++++++ application/admin/view/keys/index.html | 187 +++++++++++ application/admin/view/news/form.html | 362 +++++++++++++++++++++ application/admin/view/news/image.html | 42 +++ application/admin/view/news/index.html | 168 ++++++++++ application/admin/view/news/push.html | 192 +++++++++++ application/admin/view/news/select.html | 80 +++++ application/admin/view/review/index.html | 177 ++++++++++ application/admin/view/tags/form.html | 18 + application/admin/view/tags/index.html | 89 +++++ application/wechat/controller/Block.php | 10 +- application/wechat/controller/Config.php | 7 +- application/wechat/controller/Fans.php | 8 +- application/wechat/controller/Keys.php | 57 +--- application/wechat/controller/Review.php | 2 +- application/wechat/controller/api/Push.php | 2 +- application/wechat/view/block/index.html | 6 +- application/wechat/view/config/index.html | 2 +- application/wechat/view/fans/index.html | 6 +- application/wechat/view/keys/form.html | 6 +- application/wechat/view/review/index.html | 2 +- application/wechat/view/tags/index.html | 2 +- 35 files changed, 3619 insertions(+), 72 deletions(-) create mode 100644 application/admin/controller/Block.php create mode 100644 application/admin/controller/Fans.php create mode 100644 application/admin/controller/Keys.php create mode 100644 application/admin/controller/News.php create mode 100644 application/admin/controller/Review.php create mode 100644 application/admin/controller/Tags.php create mode 100644 application/admin/controller/api/Push.php create mode 100644 application/admin/service/FansService.php create mode 100644 application/admin/service/MediaService.php create mode 100644 application/admin/service/TagsService.php create mode 100644 application/admin/view/block/index.html create mode 100644 application/admin/view/fans/index.html create mode 100644 application/admin/view/fans/tags_inc.html create mode 100644 application/admin/view/keys/form.html create mode 100644 application/admin/view/keys/index.html create mode 100644 application/admin/view/news/form.html create mode 100644 application/admin/view/news/image.html create mode 100644 application/admin/view/news/index.html create mode 100644 application/admin/view/news/push.html create mode 100644 application/admin/view/news/select.html create mode 100644 application/admin/view/review/index.html create mode 100644 application/admin/view/tags/form.html create mode 100644 application/admin/view/tags/index.html diff --git a/application/admin/controller/Block.php b/application/admin/controller/Block.php new file mode 100644 index 000000000..333622c8f --- /dev/null +++ b/application/admin/controller/Block.php @@ -0,0 +1,114 @@ + + * @date 2017/03/27 14:43 + */ +class Block extends BasicAdmin +{ + + /** + * 定义当前默认数据表 + * @var string + */ + public $table = 'WechatFans'; + + /** + * 黑名单列表 + * @return array|string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + * @throws \think\Exception + */ + public function index() + { + $this->title = '微信黑名单管理'; + $get = $this->request->get(); + $db = Db::name($this->table)->where(['is_black' => '1']); + (isset($get['sex']) && $get['sex'] !== '') && $db->where('sex', $get['sex']); + foreach (['nickname', 'country', 'province', 'city'] as $key) { + (isset($get[$key]) && $get[$key] !== '') && $db->whereLike($key, "%{$get[$key]}%"); + } + if (isset($get['tag']) && $get['tag'] !== '') { + $db->where("concat(',',tagid_list,',') like :tag", ['tag' => "%,{$get['tag']},%"]); + } + if (isset($get['create_at']) && $get['create_at'] !== '') { + list($start, $end) = explode(' - ', $get['create_at']); + $db->whereBetween('subscribe_at', ["{$start} 00:00:00", "{$end} 23:59:59"]); + } + return parent::_list($db->order('subscribe_time desc')); + } + + /** + * 列表数据处理 + * @param array $list + */ + protected function _data_filter(&$list) + { + $tags = Db::name('WechatFansTags')->column('id,name'); + foreach ($list as &$vo) { + list($vo['tags_list'], $vo['nickname']) = [[], ToolsService::emojiDecode($vo['nickname'])]; + foreach (explode(',', $vo['tagid_list']) as $tag) { + if ($tag !== '' && isset($tags[$tag])) { + $vo['tags_list'][$tag] = $tags[$tag]; + } elseif ($tag !== '') { + $vo['tags_list'][$tag] = $tag; + } + } + } + $this->assign('tags', $tags); + } + + /** + * 取消黑名 + */ + public function backdel() + { + $openids = $this->_getActionOpenids(); + try { + WechatService::user()->batchUnblackList($openids); + Db::name($this->table)->whereIn('openid', $openids)->setField('is_black', '0'); + } catch (\Exception $e) { + $this->error("设备黑名单失败,请稍候再试!" . $e->getMessage()); + } + $this->success("已成功将 " . count($openids) . " 名粉丝从黑名单中移除!", ''); + } + + /** + * 获取当前操作用户openid数组 + * @return array + */ + private function _getActionOpenids() + { + $ids = $this->request->post('id', ''); + empty($ids) && $this->error('没有需要操作的数据!'); + $openids = Db::name($this->table)->whereIn('id', explode(',', $ids))->column('openid'); + empty($openids) && $this->error('没有需要操作的数据!'); + return $openids; + } + +} diff --git a/application/admin/controller/Fans.php b/application/admin/controller/Fans.php new file mode 100644 index 000000000..6b96aeedb --- /dev/null +++ b/application/admin/controller/Fans.php @@ -0,0 +1,191 @@ + + * @date 2017/03/27 14:43 + */ +class Fans extends BasicAdmin +{ + + /** + * 定义当前默认数据表 + * @var string + */ + public $table = 'WechatFans'; + + /** + * 显示粉丝列表 + * @return array|string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + * @throws \think\Exception + */ + public function index() + { + $this->title = '微信粉丝管理'; + $get = $this->request->get(); + $db = Db::name($this->table)->where(['is_black' => '0']); + (isset($get['sex']) && $get['sex'] !== '') && $db->where('sex', $get['sex']); + foreach (['nickname', 'country', 'province', 'city'] as $key) { + (isset($get[$key]) && $get[$key] !== '') && $db->whereLike($key, "%{$get[$key]}%"); + } + if (isset($get['tag']) && $get['tag'] !== '') { + $db->where("concat(',',tagid_list,',') like :tag", ['tag' => "%,{$get['tag']},%"]); + } + if (isset($get['create_at']) && $get['create_at'] !== '') { + list($start, $end) = explode(' - ', $get['create_at']); + $db->whereBetween('subscribe_at', ["{$start} 00:00:00", "{$end} 23:59:59"]); + } + return parent::_list($db->order('subscribe_time desc')); + } + + /** + * 列表数据处理 + * @param array $list + */ + protected function _data_filter(&$list) + { + $tags = Db::name('WechatFansTags')->column('id,name'); + foreach ($list as &$vo) { + list($vo['tags_list'], $vo['nickname']) = [[], ToolsService::emojiDecode($vo['nickname'])]; + foreach (explode(',', $vo['tagid_list']) as $tag) { + if ($tag !== '' && isset($tags[$tag])) { + $vo['tags_list'][$tag] = $tags[$tag]; + } elseif ($tag !== '') { + $vo['tags_list'][$tag] = $tag; + } + } + } + $this->assign('tags', $tags); + } + + /** + * 设置黑名单 + */ + public function backadd() + { + try { + $openids = $this->_getActionOpenids(); + WechatService::user()->batchBlackList($openids); + Db::name($this->table)->whereIn('openid', $openids)->setField('is_black', '1'); + } catch (\Exception $e) { + $this->error("设置黑名单失败,请稍候再试!"); + } + $this->success('设置黑名单成功!', ''); + } + + /** + * 标签选择 + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function tagset() + { + $tags = $this->request->post('tags', ''); + $fans_id = $this->request->post('fans_id', ''); + $fans = Db::name('WechatFans')->where(['id' => $fans_id])->find(); + empty($fans) && $this->error('需要操作的数据不存在!'); + try { + $wechat = WechatService::tags(); + foreach (explode(',', $fans['tagid_list']) as $tagid) { + is_numeric($tagid) && $wechat->batchUntagging([$fans['openid']], $tagid); + } + foreach (explode(',', $tags) as $tagid) { + is_numeric($tagid) && $wechat->batchTagging([$fans['openid']], $tagid); + } + Db::name('WechatFans')->where(['id' => $fans_id])->setField('tagid_list', $tags); + } catch (\Exception $e) { + $this->error('粉丝标签设置失败, 请稍候再试!'); + } + $this->success('粉丝标签成功!', ''); + } + + /** + * 给粉丝增加标签 + */ + public function tagadd() + { + $tagid = $this->request->post('tag_id', 0); + empty($tagid) && $this->error('没有可能操作的标签ID'); + try { + $openids = $this->_getActionOpenids(); + WechatService::tags()->batchTagging($openids, $tagid); + } catch (\Exception $e) { + $this->error("设置粉丝标签失败, 请稍候再试! " . $e->getMessage()); + } + $this->success('设置粉丝标签成功!', ''); + } + + /** + * 移除粉丝标签 + */ + public function tagdel() + { + $tagid = $this->request->post('tag_id', 0); + empty($tagid) && $this->error('没有可能操作的标签ID'); + try { + $openids = $this->_getActionOpenids(); + WechatService::tags()->batchUntagging($openids, $tagid); + } catch (\Exception $e) { + $this->error("删除粉丝标签失败, 请稍候再试! "); + } + $this->success('删除粉丝标签成功!', ''); + } + + /** + * 获取当前操作用户openid数组 + * @return array + */ + private function _getActionOpenids() + { + $ids = $this->request->post('id', ''); + empty($ids) && $this->error('没有需要操作的数据!'); + $openids = Db::name($this->table)->whereIn('id', explode(',', $ids))->column('openid'); + empty($openids) && $this->error('没有需要操作的数据!'); + return $openids; + } + + /** + * 同步粉丝列表 + */ + public function sync() + { + try { + Db::name($this->table)->where('1=1')->delete(); + FansService::sync(); + TagsService::sync(); + LogService::write('微信管理', '同步全部微信粉丝成功'); + } catch (\Exception $e) { + $this->error('同步粉丝记录失败,请稍候再试!'); + } + $this->success('同步获取所有粉丝成功!', ''); + } + +} diff --git a/application/admin/controller/Keys.php b/application/admin/controller/Keys.php new file mode 100644 index 000000000..6c7302dfe --- /dev/null +++ b/application/admin/controller/Keys.php @@ -0,0 +1,202 @@ + + * @date 2017/03/27 14:43 + */ +class Keys extends BasicAdmin +{ + + /** + * 指定当前数据表 + * @var string + */ + public $table = 'WechatKeys'; + + /** + * 显示关键字列表 + * @return array|string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + * @throws \think\Exception + */ + public function index() + { + $this->assign('title', '微信关键字'); + $db = Db::name($this->table)->whereNotIn('keys', ['subscribe', 'default']); + return $this->_list($db->order('id desc')); + } + + /** + * 列表数据处理 + * @param array $data + * @throws \WeChat\Exceptions\InvalidResponseException + * @throws \WeChat\Exceptions\LocalCacheException + */ + protected function _index_data_filter(&$data) + { + $types = [ + 'keys' => '关键字', 'image' => '图片', 'news' => '图文', + 'music' => '音乐', 'text' => '文字', 'video' => '视频', 'voice' => '语音', + ]; + $wechat = WechatService::qrcode(); + foreach ($data as &$vo) { + $result = $wechat->create($vo['keys']); + $vo['qrc'] = $wechat->url($result['ticket']); + $vo['type'] = isset($types[$vo['type']]) ? $types[$vo['type']] : $vo['type']; + } + } + + /** + * 添加关键字 + * @return string + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function add() + { + $this->title = '添加关键字规则'; + return $this->_form($this->table, 'form'); + } + + /** + * 编辑关键字 + * @return string + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function edit() + { + $this->title = '编辑关键字规则'; + return $this->_form($this->table, 'form'); + } + + + /** + * 删除关键字 + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public function del() + { + if (DataService::update($this->table)) { + $this->success("关键字删除成功!", ''); + } + $this->error("关键字删除失败,请稍候再试!"); + } + + /** + * 关键字禁用 + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public function forbid() + { + if (DataService::update($this->table)) { + $this->success("关键字禁用成功!", ''); + } + $this->error("关键字禁用失败,请稍候再试!"); + } + + /** + * 关键字禁用 + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public function resume() + { + if (DataService::update($this->table)) { + $this->success("关键字启用成功!", ''); + } + $this->error("关键字启用失败,请稍候再试!"); + } + + /** + * 关注默认回复 + * @return array|string + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function subscribe() + { + $this->assign('title', '编辑默认回复'); + $extend = ['keys' => 'subscribe']; + return $this->_form($this->table, 'form', 'keys', $extend, $extend); + } + + + /** + * 无配置默认回复 + * @return array|string + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function defaults() + { + $this->assign('title', '编辑无配置默认回复'); + $extend = ['keys' => 'default']; + return $this->_form($this->table, 'form', 'keys', $extend, $extend); + } + + /** + * 添加数据处理 + * @param array $data + */ + protected function _form_filter(array &$data) + { + if ($this->request->isPost() && isset($data['keys'])) { + $db = Db::name($this->table)->where('keys', $data['keys']); + !empty($data['id']) && $db->where('id', 'neq', $data['id']); + $data['content'] = htmlspecialchars_decode($data['content']); + $db->count() > 0 && $this->error('关键字已经存在,请使用其它关键字!'); + } + } + + /** + * 编辑结果处理 + * @param $result + */ + protected function _form_result($result) + { + if ($result !== false) { + list($url, $keys) = ['', $this->request->post('keys')]; + if (!in_array($keys, ['subscribe', 'default'])) { + $url = url('@admin') . '#' . url('wechat/keys/index') . '?spm=' . $this->request->get('spm'); + } + $this->success('恭喜, 关键字保存成功!', $url); + } + $this->error('关键字保存失败, 请稍候再试!'); + } + +} diff --git a/application/admin/controller/News.php b/application/admin/controller/News.php new file mode 100644 index 000000000..851d01853 --- /dev/null +++ b/application/admin/controller/News.php @@ -0,0 +1,297 @@ + + * @date 2017/03/27 14:43 + */ +class News extends BasicAdmin +{ + + /** + * 设置默认操作表 + * @var string + */ + public $table = 'WechatNews'; + + /** + * 图文列表 + * @return array|string + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function index() + { + $this->title = '微信图文列表'; + $db = Db::name($this->table)->where(['is_deleted' => '0']); + return parent::_list($db->order('id desc')); + } + + /** + * 图文列表数据处理 + * @param array $data + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + protected function _index_data_filter(&$data) + { + foreach ($data as &$vo) { + $vo = MediaService::getNewsById($vo['id']); + } + } + + /** + * 图文选择器 + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + * @throws \think\Exception + */ + public function select() + { + return $this->index(); + } + + /** + * 图文列表数据处理 + * @param array $data + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + protected function _select_data_filter(&$data) + { + foreach ($data as &$vo) { + $vo = MediaService::getNewsById($vo['id']); + } + } + + /** + * 媒体资源显示 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + * @throws \think\Exception + */ + public function image() + { + $_GET['rows'] = 18; + $this->assign('field', $this->request->get('field', 'local_url')); + return $this->_list(Db::name('WechatNewsMedia')->where('type', 'image')); + } + + /** + * 添加图文 + * @return string + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public function add() + { + if ($this->request->isGet()) { + return $this->fetch('form', ['title' => '新建图文']); + } + if ($this->request->isPost()) { + $data = $this->request->post(); + if (($ids = $this->_apply_news_article($data['data'])) && !empty($ids)) { + $post = ['article_id' => $ids, 'create_by' => session('user.id')]; + if (DataService::save($this->table, $post, 'id') !== false) { + $url = url('@admin') . '#' . url('@wechat/news/index') . '?spm=' . $this->request->get('spm'); + $this->success('图文添加成功!', $url); + } + } + $this->error('图文添加失败,请稍候再试!'); + } + } + + /** + * 编辑图文 + * @return string + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public function edit() + { + $id = $this->request->get('id', ''); + if ($this->request->isGet()) { + empty($id) && $this->error('参数错误,请稍候再试!'); + return $this->fetch('form', ['title' => '编辑图文', 'vo' => MediaService::getNewsById($id)]); + } + $data = $this->request->post(); + $ids = $this->_apply_news_article($data['data']); + if (!empty($ids)) { + $post = ['id' => $id, 'article_id' => $ids, 'create_by' => session('user.id')]; + if (false !== DataService::save('wechat_news', $post, 'id')) { + $url = url('@admin') . '#' . url('@wechat/news/index') . '?spm=' . $this->request->get('spm'); + $this->success('图文更新成功!', $url); + } + } + $this->error('图文更新失败,请稍候再试!'); + } + + /** + * 图文更新操作 + * @param array $data + * @param array $ids + * @return string + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + protected function _apply_news_article($data, $ids = []) + { + foreach ($data as &$vo) { + $vo['create_by'] = session('user.id'); + $vo['create_at'] = date('Y-m-d H:i:s'); + if (empty($vo['digest'])) { + $vo['digest'] = mb_substr(strip_tags(str_replace(["\s", ' '], '', htmlspecialchars_decode($vo['content']))), 0, 120); + } + if (empty($vo['id'])) { + $result = $id = Db::name('WechatNewsArticle')->insertGetId($vo); + } else { + $id = intval($vo['id']); + $result = Db::name('WechatNewsArticle')->where('id', $id)->update($vo); + } + if ($result !== false) { + $ids[] = $id; + } + } + return join(',', $ids); + } + + /** + * 删除用户 + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public function del() + { + if (DataService::update($this->table)) { + $this->success("图文删除成功!", ''); + } + $this->error("图文删除失败, 请稍候再试!"); + } + + /** + * 推荐图文 + * @return array + * @throws \WeChat\Exceptions\InvalidResponseException + * @throws \WeChat\Exceptions\LocalCacheException + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + * @throws \think\exception\PDOException + */ + public function push() + { + # 获取将要推送的粉丝列表 + switch (strtolower($this->request->get('action', ''))) { + case 'getuser': + if ('' === ($params = $this->request->post('group', ''))) { + return ['code' => 'SUCCESS', 'data' => []]; + } + list($ids, $db) = [explode(',', $params), Db::name('WechatFans')]; + !in_array('0', $ids) && $db->where("concat(',',tagid_list,',') REGEXP '," . join(',|,', $ids) . ",'"); + $list = $db->where(['subscribe' => '1'])->limit(200)->column('nickname'); + foreach ($list as &$vo) { + $vo = ToolsService::emojiDecode($vo); + } + return ['code' => "SUCCESS", 'data' => $list]; + default : + $news_id = $this->request->get('id', ''); + // 显示及图文 + $newsinfo = MediaService::getNewsById($news_id); + // Get 请求,显示选择器界面 + if ($this->request->isGet()) { + $fans_tags = (array)Db::name('WechatFansTags')->select(); + $count = Db::name('WechatFans')->where(['subscribe' => '1'])->count(); + array_unshift($fans_tags, ['id' => 0, 'name' => '全部', 'count' => $count]); + return $this->fetch('push', ['vo' => $newsinfo, 'fans_tags' => $fans_tags]); + } + // Post 请求,执行图文推送操作 + $post = $this->request->post(); + empty($post['fans_tags']) && $this->error('还没有选择要粉丝对象!'); + // 图文上传操作 + !$this->_uploadWechatNews($newsinfo) && $this->error('图文上传失败,请稍候再试!'); + // 数据拼装 + $data = []; + if (in_array('0', $post['fans_tags'])) { + $data['msgtype'] = 'mpnews'; + $data['filter'] = ['is_to_all' => true]; + $data['mpnews'] = ['media_id' => $newsinfo['media_id']]; + } else { + $data['msgtype'] = 'mpnews'; + $data['filter'] = ['is_to_all' => false, 'tag_id' => join(',', $post['fans_tags'])]; + $data['mpnews'] = ['media_id' => $newsinfo['media_id']]; + } + $wechat = WechatService::custom(); + if (false !== $wechat->massSendAll($data)) { + LogService::write('微信管理', "图文[{$news_id}]推送成功"); + $this->success('微信图文推送成功!', ''); + } + $this->error("微信图文推送失败"); + } + } + + /** + * 上传永久图文 + * @param array $news + * @return bool + * @throws \WeChat\Exceptions\InvalidResponseException + * @throws \WeChat\Exceptions\LocalCacheException + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + private function _uploadWechatNews(&$news) + { + foreach ($news['articles'] as &$article) { + $article['thumb_media_id'] = MediaService::uploadForeverMedia($article['local_url']); + $article['content'] = preg_replace_callback("//i", function ($matches) { + $src = MediaService::uploadImage($matches[2]); + return ""; + }, htmlspecialchars_decode($article['content'])); + } + $wechat = WechatService::media(); + // 如果已经上传过,先删除之前的历史记录 + !empty($news['media_id']) && $wechat->delMaterial($news['media_id']); + // 上传图文到微信服务器 + $result = $wechat->addNews(['articles' => $news['articles']]); + if (isset($result['media_id'])) { + $news['media_id'] = $result['media_id']; + return Db::name('WechatNews')->where(['id' => $news['id']])->update(['media_id' => $result['media_id']]); + } + Log::error("上传永久图文失败"); + return false; + } + +} diff --git a/application/admin/controller/Review.php b/application/admin/controller/Review.php new file mode 100644 index 000000000..62ffdf5b3 --- /dev/null +++ b/application/admin/controller/Review.php @@ -0,0 +1,61 @@ +", $this->request->get('content', '', 'urldecode')); // 内容 + $type = $this->request->get('type', 'text'); // 类型 + // 图文处理 + if ($type === 'news' && is_numeric($content) && !empty($content)) { + $news = MediaService::getNewsById($content); + $this->assign('articles', $news['articles']); + } + // 文章预览 + if ($type === 'article' && is_numeric($content) && !empty($content)) { + $article = Db::name('WechatNewsArticle')->where('id', $content)->find(); + if (!empty($article['content_source_url'])) { + $this->redirect($article['content_source_url']); + } + $article['content'] = htmlspecialchars_decode($article['content']); + $this->assign('vo', $article); + } + $this->assign('type', $type); + $this->assign('content', $content); + $this->assign($this->request->get()); + // 渲染模板并显示 + return $this->fetch(); + } + +} diff --git a/application/admin/controller/Tags.php b/application/admin/controller/Tags.php new file mode 100644 index 000000000..49a44899a --- /dev/null +++ b/application/admin/controller/Tags.php @@ -0,0 +1,159 @@ +title = '微信粉丝标签管理'; + list($get, $db) = [$this->request->get(), Db::name($this->table)]; + foreach (['name'] as $key) { + (isset($get[$key]) && $get[$key] !== '') && $db->whereLike($key, "%{$get[$key]}%"); + } + return parent::_list($db->order('id asc')); + } + + /** + * 添加粉丝标签 + * @return array|string + * @throws \WeChat\Exceptions\InvalidResponseException + * @throws \WeChat\Exceptions\LocalCacheException + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + * @throws \think\exception\PDOException + */ + public function add() + { + if ($this->request->isGet()) { + return parent::_form($this->table, 'form', 'id'); + } + $name = $this->request->post('name', ''); + empty($name) && $this->error('粉丝标签名不能为空!'); + if (Db::name($this->table)->where('name', $name)->count() > 0) { + $this->error('粉丝标签标签名已经存在, 请使用其它标签名!'); + } + $wechat = WechatService::tags(); + if (false === ($result = $wechat->createTags($name)) && isset($result['tag'])) { + $this->error("添加粉丝标签失败. "); + } + $result['tag']['count'] = 0; + if (DataService::save($this->table, $result['tag'], 'id')) { + $this->success('添加粉丝标签成功!', ''); + } + $this->error('粉丝标签添加失败, 请稍候再试!'); + } + + /** + * 编辑粉丝标签 + * @return array|string + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function edit() + { + // 显示编辑界面 + if ($this->request->isGet()) { + return parent::_form($this->table, 'form', 'id'); + } + // 接收提交的数据 + $id = $this->request->post('id', '0'); + $name = $this->request->post('name', ''); + $info = Db::name($this->table)->where(['name' => $name])->find(); + if (!empty($info)) { + if (intval($info['id']) === intval($id)) { + $this->error('粉丝标签名没有改变, 无需修改!'); + } + $this->error('标签已经存在, 使用其它名称再试!'); + } + try { + WechatService::tags()->updateTags($id, $name); + DataService::save($this->table, ['id' => $id, 'name' => $name], 'id'); + } catch (\Exception $e) { + $this->error('编辑标签失败, 请稍后再试!' . $e->getMessage()); + } + $this->success('编辑标签成功!', ''); + } + + + /** + * 删除粉丝标签 + * @throws \WeChat\Exceptions\InvalidResponseException + * @throws \WeChat\Exceptions\LocalCacheException + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public function del() + { + $wechat = WechatService::tags(); + foreach (explode(',', $this->request->post('id', '')) as $id) { + if ($wechat->deleteTags($id)) { + Db::name('WechatFansTags')->where(['id' => $id])->delete(); + } else { + $this->error('移除粉丝标签失败,请稍候再试!'); + } + } + $this->success('移除粉丝标签成功!', ''); + } + + /** + * 同步粉丝标签列表 + * @throws \WeChat\Exceptions\InvalidResponseException + * @throws \WeChat\Exceptions\LocalCacheException + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public function sync() + { + Db::name($this->table)->where('1=1')->delete(); + if (TagsService::sync()) { + LogService::write('微信管理', '同步全部微信粉丝标签成功'); + $this->success('同步获取所有粉丝标签成功!', ''); + } + $this->error('同步获取粉丝标签失败, 请稍候再!'); + } + +} diff --git a/application/admin/controller/api/Push.php b/application/admin/controller/api/Push.php new file mode 100644 index 000000000..c1a847b49 --- /dev/null +++ b/application/admin/controller/api/Push.php @@ -0,0 +1,257 @@ + + */ +class Push +{ + + /** + * 当前公众号APPID + * @var string + */ + protected $appid; + + /** + * 当前微信用户openid + * @var string + */ + protected $openid; + + /** + * 当前微信消息对象 + * @var array + */ + protected $receive; + + /** + * 微信消息接口 + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public function __construct() + { + $request = app('request'); + $this->appid = $request->post('appid', '', null); + $this->openid = $request->post('openid', '', null); + $this->receive = unserialize($request->post('receive', '', null)); + p($this->receive); + if (empty($this->appid) || empty($this->openid) || empty($this->receive)) { + throw new Exception('微信API实例缺失必要参数[appid,openid,event].'); + } + if ($this->appid !== sysconf('wechat_appid')) { + throw new Exception('微信API实例APPID验证失败.'); + } + // text,event,image,location + if (method_exists($this, ($method = $this->receive['MsgType']))) { + $this->$method(); + } + } + + /** + * 文件消息处理 + * @return bool + * @throws \Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + protected function text() + { + return $this->keys("wechat_keys#keys#{$this->receive['Content']}"); + } + + /** + * 事件消息处理 + * @return bool|string + * @throws \Exception + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + * @throws \think\exception\PDOException + */ + protected function event() + { + switch (strtolower($this->receive['Event'])) { + case 'subscribe': + $this->updateFansinfo(true); + if (isset($this->receive['EventKey']) && is_string($this->receive['EventKey'])) { + if (($key = preg_replace('/^qrscene_/i', '', $this->receive['EventKey']))) { + [$this->updateSpread($key), $this->keys("wechat_keys#keys#{$key}")]; + } + } + return $this->keys('wechat_keys#keys#subscribe', true); + case 'unsubscribe': + return $this->updateFansinfo(false); + case 'click': + return $this->keys($this->receive['EventKey']); + case 'scancode_push': + case 'scancode_waitmsg': + if (isset($this->receive['ScanCodeInfo'])) { + $this->receive['ScanCodeInfo'] = (array)$this->receive['ScanCodeInfo']; + if (!empty($this->receive['ScanCodeInfo']['ScanResult'])) { + return $this->keys("wechat_keys#keys#{$this->receive['ScanCodeInfo']['ScanResult']}"); + } + } + return false; + case 'scan': + if (!empty($this->receive['EventKey'])) { + return $this->keys("wechat_keys#keys#{$this->receive['EventKey']}"); + } + return false; + } + return false; + } + + /** + * 关键字处理 + * @param string $rule 关键字规则 + * @param bool $isLastReply 强制结束 + * @return bool + * @throws \Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + protected function keys($rule, $isLastReply = false) + { + list($table, $field, $value) = explode('#', $rule . '##'); + $info = Db::name($table)->where($field, $value)->find(); + p($info); + if (empty($info['type']) || (array_key_exists('status', $info) && empty($info['status']))) { + // 切换默认回复 + return $isLastReply ? false : $this->keys('wechat_keys#keys#default', true); + } + switch ($info['type']) { + case 'customservice': + return $this->sendMessage('text', ['content' => $info['content']]); + case 'keys': + $content = empty($info['content']) ? $info['name'] : $info['content']; + return $this->keys("wechat_keys#keys#{$content}"); + case 'text': + return $this->sendMessage('text', ['content' => $info['content']]); + case 'news': + list($news, $data) = [MediaService::getNewsById($info['news_id']), []]; + if (empty($news['articles'])) { + return false; + } + foreach ($news['articles'] as $vo) { + $url = url("@wechat/review", '', true, true) . "?content={$vo['id']}&type=article"; + $data[] = ['url' => $url, 'title' => $vo['title'], 'picurl' => $vo['local_url'], 'description' => $vo['digest']]; + } + return $this->sendMessage('news', ['articles' => $data]); + case 'music': + if (empty($info['music_url']) || empty($info['music_title']) || empty($info['music_desc'])) { + return false; + } + $media_id = empty($info['music_image']) ? '' : MediaService::uploadForeverMedia($info['music_image'], 'image'); + $data = ['title' => $info['music_title'], 'description' => $info['music_desc'], 'musicurl' => $info['music_url'], 'hqmusicurl' => $info['music_url'], 'thumb_media_id' => $media_id]; + return $this->sendMessage('music', $data); + case 'voice': + if (empty($info['voice_url']) || !($media_id = MediaService::uploadForeverMedia($info['voice_url'], 'voice'))) { + return false; + } + return $this->sendMessage('voice', ['media_id' => $media_id]); + case 'image': + if (empty($info['image_url']) || !($media_id = MediaService::uploadForeverMedia($info['image_url'], 'image'))) { + return false; + } + return $this->sendMessage('image', ['media_id' => $media_id]); + case 'video': + if (empty($info['video_url']) || empty($info['video_desc']) || empty($info['video_title'])) { + return false; + } + $videoData = ['title' => $info['video_title'], 'introduction' => $info['video_desc']]; + if (!($media_id = MediaService::uploadForeverMedia($info['video_url'], 'video', $videoData))) { + return false; + } + $data = ['media_id' => $media_id, 'title' => $info['video_title'], 'description' => $info['video_desc']]; + return $this->sendMessage('video', $data); + default: + return false; + } + } + + /** + * 发送消息到公众号 + * @param string $type 消息类型(text|image|voice|video|music|news|mpnews|wxcard) + * @param array $data 消息内容 + * @return array|bool + * @throws \Exception + */ + protected function sendMessage($type, $data) + { + $msgData = ['touser' => $this->openid, 'msgtype' => $type, "{$type}" => $data]; + p($msgData); + return WechatService::custom()->send($msgData); + } + + /** + * 更新推荐二维码关系 + * @param string $key + * @return bool + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + * @throws \think\exception\PDOException + */ + protected function updateSpread($key) + { + // 检测推荐是否有效 + $fans = Db::name('WechatFans')->where(['openid' => $key])->find(); + if (empty($fans['openid']) || $fans['openid'] === $this->openid) { + return false; + } + // 标识推荐关系 + $data = ['spread_openid' => $fans['openid'], 'spread_at' => date('Y-m-d H:i:s')]; + $where = "openid='{$this->openid}' and (spread_openid is null or spread_openid='')"; + return Db::name('WechatFans')->where($where)->update($data) !== false; + } + + /** + * 同步粉丝状态 + * @param bool $subscribe 关注状态 + * @return string + * @throws \Exception + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + protected function updateFansinfo($subscribe = true) + { + if ($subscribe) { + $userInfo = WechatService::user()->getUserInfo($this->openid); + $userInfo['subscribe'] = intval($subscribe); + FansService::set($userInfo); + } else { + $fans = ['subscribe' => '0', 'openid' => $this->openid, 'appid' => $this->appid]; + DataService::save('WechatFans', $fans, 'openid', ['appid' => $this->appid]); + } + } + +} diff --git a/application/admin/service/FansService.php b/application/admin/service/FansService.php new file mode 100644 index 000000000..d7732cbb7 --- /dev/null +++ b/application/admin/service/FansService.php @@ -0,0 +1,123 @@ + $openid, 'appid' => sysconf('wechat_appid')]; + $user = Db::name('WechatFans')->where($map)->find(); + foreach (['country', 'province', 'city', 'nickname', 'remark'] as $k) { + isset($user[$k]) && $user[$k] = ToolsService::emojiDecode($user[$k]); + } + return $user; + } + + /** + * 同步所有粉丝记录 + * @param string $next_openid + * @return bool + * @throws \WeChat\Exceptions\InvalidResponseException + * @throws \WeChat\Exceptions\LocalCacheException + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public static function sync($next_openid = '') + { + $wechat = WechatService::user(); + $result = $wechat->getUserList($next_openid); + if (empty($result['data']['openid'])) { + return false; + } + foreach (array_chunk($result['data']['openid'], 100) as $openids) { + foreach ($wechat->getBatchUserInfo($openids)['user_info_list'] as $user) { + if (false === self::set($user)) { + return false; + } + if ($result['next_openid'] === $user['openid']) { + unset($result['next_openid']); + } + } + } + return empty($result['next_openid']) ? true : self::sync($result['next_openid']); + } + + /** + * 同步获取黑名单信息 + * @param string $next_openid + * @return bool + * @throws \WeChat\Exceptions\InvalidResponseException + * @throws \WeChat\Exceptions\LocalCacheException + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public static function syncBlack($next_openid = '') + { + $wechat = WechatService::user(); + $result = $wechat->getBlackList($next_openid); + foreach (array_chunk($result['data']['openid'], 100) as $openids) { + $info = $wechat->getBatchUserInfo($openids); + foreach ($info as $user) { + $user['is_black'] = '1'; + if (self::set($user) && $result['next_openid'] === $user['openid']) { + unset($result['next_openid']); + } + } + } + return empty($result['next_openid']) ? true : self::syncBlack($result['next_openid']); + } + +} \ No newline at end of file diff --git a/application/admin/service/MediaService.php b/application/admin/service/MediaService.php new file mode 100644 index 000000000..342c0dbf7 --- /dev/null +++ b/application/admin/service/MediaService.php @@ -0,0 +1,101 @@ +where(['id' => $id])->where($where)->find(); + $article_ids = explode(',', $data['article_id']); + $articles = Db::name('WechatNewsArticle')->whereIn('id', $article_ids)->select(); + $data['articles'] = []; + foreach ($article_ids as $article_id) { + foreach ($articles as $article) { + if (intval($article['id']) === intval($article_id)) { + unset($article['create_by'], $article['create_at']); + $article['content'] = htmlspecialchars_decode($article['content']); + $data['articles'][] = $article; + } + } + } + return $data; + } + + /** + * 上传图片到微信服务器 + * @param string $local_url 图文地址 + * @return string + * @throws \WeChat\Exceptions\InvalidResponseException + * @throws \WeChat\Exceptions\LocalCacheException + */ + public static function uploadImage($local_url) + { + $media_url = Db::name('WechatNewsImage')->where(['md5' => md5($local_url)])->value('media_url'); + if (!empty($media_url)) { + return $media_url; + } + $result = WechatService::wechat()->upFile(base64_encode(file_get_contents($local_url)), $local_url); + $info = WechatService::media()->uploadImg($result['file']); + WechatService::wechat()->rmFile($local_url); + $data = ['local_url' => $local_url, 'media_url' => $info['url'], 'md5' => md5($local_url)]; + Db::name('WechatNewsImage')->insert($data); + return $info['url']; + } + + /** + * 上传图片永久素材,返回素材media_id + * @param string $local_url 文件URL地址 + * @param string $type 文件类型 + * @param array $video_info 视频信息 + * @return string|null + * @throws \WeChat\Exceptions\InvalidResponseException + * @throws \WeChat\Exceptions\LocalCacheException + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public static function uploadForeverMedia($local_url, $type = 'image', $video_info = []) + { + $map = ['md5' => md5($local_url), 'appid' => sysconf('wechat_appid')]; + if (($media_id = Db::name('WechatNewsMedia')->where($map)->value('media_id'))) { + return $media_id; + } + $result = WechatService::wechat()->upFile(base64_encode(file_get_contents($local_url)), $local_url); + $result = WechatService::media()->addMaterial($result['file'], $type, $video_info); + WechatService::wechat()->rmFile($local_url); + $data = ['md5' => $map['md5'], 'type' => $type, 'appid' => $map['appid'], 'media_id' => $result['media_id'], 'local_url' => $local_url]; + isset($result['url']) && $data['media_url'] = $result['url']; + Db::name('WechatNewsMedia')->insert($data); + return $data['media_id']; + } + +} \ No newline at end of file diff --git a/application/admin/service/TagsService.php b/application/admin/service/TagsService.php new file mode 100644 index 000000000..52ec49ffc --- /dev/null +++ b/application/admin/service/TagsService.php @@ -0,0 +1,69 @@ +getUserTagId($openid); + if (!is_array($tagsid)) { + return false; + } + $data = ['openid' => $openid, 'tagid_list' => join(',', $tagsid)]; + return DataService::save('WechatFans', $data, 'openid', ['appid' => sysconf('wechat_appid')]); + } + + /** + * 从微信服务器获取所有标签 + * @return bool + * @throws \WeChat\Exceptions\InvalidResponseException + * @throws \WeChat\Exceptions\LocalCacheException + * @throws \think\Exception + * @throws \think\exception\PDOException + */ + public static function sync() + { + $appid = sysconf('wechat_appid'); + $result = WechatService::tags()->getTags(); + Db::name('WechatFansTags')->where(['appid' => $appid])->delete(); + foreach (array_chunk($result['tags'], 100) as $list) { + foreach ($list as &$vo) { + $vo['appid'] = $appid; + } + Db::name('WechatFansTags')->insertAll($list); + } + return true; + } + +} \ No newline at end of file diff --git a/application/admin/view/block/index.html b/application/admin/view/block/index.html new file mode 100644 index 000000000..f79abcfc8 --- /dev/null +++ b/application/admin/view/block/index.html @@ -0,0 +1,160 @@ +{extend name='admin@public/content'} + +{block name="button"} + + + + + + + + + +{/block} + +{block name="content"} + + + + +
+ +

没 有 记 录 哦!

+ + + + + + + + + + + + + + + + {foreach $list as $key=>$vo} + + + + + + + + + + {/foreach} + +
+ + 用户昵称性别用户标签所在区域关注时间操作
+ + + + {$vo.nickname|default='未设置微信昵称'} + + {$vo.sex==1?'男':($vo.sex==2?'女':'未知')} + + {if auth("$classuri/tagset")} + + + {/if} + {if empty($vo.tags_list)} + 尚未设置标签 + {else} + {foreach $vo.tags_list as $k=>$tag}{$tag}{/foreach} + {/if} + + {$vo.country|default='未设置区域信息'|raw}{$vo.province}{$vo.city} + {$vo.subscribe_at|format_datetime} + {if auth("$classuri/backdel")}移出黑名单{/if} +
+ {if isset($page)}

{$page|raw}

{/if} + +
+{/block} + +{block name="script"} + + + +{if auth("$classuri/tagset")}{include file='wechat@fans/tags_inc'}{/if} +{/block} + diff --git a/application/admin/view/fans/index.html b/application/admin/view/fans/index.html new file mode 100644 index 000000000..c3cffc4dc --- /dev/null +++ b/application/admin/view/fans/index.html @@ -0,0 +1,160 @@ +{extend name='admin@public/content'} + +{block name="button"} + + + + + + + + + +{/block} + +{block name="content"} + + + + +
+ +

没 有 记 录 哦!

+ + + + + + + + + + + + + + + + {foreach $list as $key=>$vo} + + + + + + + + + + {/foreach} + +
+ + 用户昵称性别标签区域关注时间
+ + + + {$vo.nickname|default='未设置微信昵称'} + + {$vo.sex==1?'男':($vo.sex==2?'女':'未知')} + + {if auth("$classuri/tagset")} + + + {/if} + {if empty($vo.tags_list)} + 尚未设置标签 + {else} + {foreach $vo.tags_list as $k=>$tag}{$tag}{/foreach} + {/if} + + {$vo.country|default='未设置区域信息'|raw}{$vo.province}{$vo.city} + {$vo.subscribe_at|format_datetime} + {if auth("$classuri/backdel")}拉黑{/if} +
+ {if isset($page)}

{$page|raw}

{/if} + +
+{/block} + +{block name="script"} + + + + +{if auth("$classuri/tagset")}{include file='wechat@fans/tags_inc'}{/if} +{/block} diff --git a/application/admin/view/fans/tags_inc.html b/application/admin/view/fans/tags_inc.html new file mode 100644 index 000000000..85dab465e --- /dev/null +++ b/application/admin/view/fans/tags_inc.html @@ -0,0 +1,80 @@ + + +
+
+
+ {foreach $tags as $key=>$tag} +
+ +
+ {/foreach} +
+
+
+ + +
+
+
+ + \ No newline at end of file diff --git a/application/admin/view/keys/form.html b/application/admin/view/keys/form.html new file mode 100644 index 000000000..cf6d79adf --- /dev/null +++ b/application/admin/view/keys/form.html @@ -0,0 +1,292 @@ +{extend name='admin@public/content'} + +{block name="style"} + +{/block} + +{block name="content"} + + +
+
公众号
+
+ +
+
+ + +
+
+
+
+ {$title} +
+ +
+ +
+ +
+
+ + + +
+ +
+
+ {foreach ['1'=>'启用','0'=>'禁用'] as $k=>$v} + + {/foreach} +
+
+
+
+ +
+ {foreach ['text'=>'文字','news'=>'图文','image'=>'图片','music'=>'音乐','video'=>'视频'] as $k=>$v} + + {/foreach} +
+
+ +
+ +
+ +
+
+ +
+ +
+ 选择图文 + +
+
+ +
+ +
+ +

文件最大2Mb,支持bmp/png/jpeg/jpg/gif格式

+ + 上传图片 +
+
+ +
+ +
+
+ + +
+

文件最大2Mb,播放长度不超过60s,mp3/wma/wav/amr格式

+
+
+ +
+ +
+ +
+
+
+ +
+
+ + +
+
+
+
+ +
+ +
+
+
+ +
+ +

文件最大64KB,只支持JPG格式

+ + 上传图片 +
+
+ +
+ +
+ +
+
+
+ +
+
+ + +
+

文件最大10MB,只支持MP4格式

+
+
+
+ +
+ +
+
+ +
+
+ + + + +
+ {if isset($vo['id'])}{/if} +
+
+
+
+
+{/block} + +{block name="script"} + +{/block} \ No newline at end of file diff --git a/application/admin/view/keys/index.html b/application/admin/view/keys/index.html new file mode 100644 index 000000000..42c4f161d --- /dev/null +++ b/application/admin/view/keys/index.html @@ -0,0 +1,187 @@ +{extend name='admin@public/content'} + +{block name="button"} + + + + + + + + + +{/block} + +{block name='content'} +
+ {if empty($list)} +

没 有 记 录 哦!

+ {else} + + + + + + + + + + + + + + + + {foreach $list as $key=>$vo} + + + + + + + + + + + {/foreach} + +
+ + + + 关键字类型预览添加时间状态
+ + + + + {if !empty($vo.qrc)}{/if} + {$vo.keys} + {$vo.type} + {if $vo.type eq '音乐'} + 预览 + {elseif $vo.type eq '文字'} + 预览 + {elseif $vo.type eq '图片'} + 预览 + {elseif $vo.type eq '图文'} + 预览 + {elseif $vo.type eq '视频'} + 预览 + {else} + {$vo.content} + {/if} + {$vo.create_at|format_datetime} + {if $vo.status eq 0}已禁用{elseif $vo.status eq 1}使用中{/if} + + + {if auth("$classuri/edit")} + | + 编辑 + {/if} + + {if $vo.status eq 1 and auth("$classuri/forbid")} + | + 禁用 + {elseif auth("$classuri/resume")} + | + 启用 + {/if} + + {if auth("$classuri/del")} + | + 删除 + {/if} + +
+ {if isset($page)}

{$page|raw}

{/if} + {/if} +
+ +{/block} + +{block name="script"} + +{/block} \ No newline at end of file diff --git a/application/admin/view/news/form.html b/application/admin/view/news/form.html new file mode 100644 index 000000000..befbff4ec --- /dev/null +++ b/application/admin/view/news/form.html @@ -0,0 +1,362 @@ +{extend name='admin@public/content'} + +{block name='content'} + + +
+
图文列表
+
+ {if empty($vo['articles']) eq false} + +
+ + {$value.title} +
+
+ + {else} +
+ + +
+
+ {/if} + + + +
+
+ + + +
+
图文内容编辑
+
+
+ +
+
+
+ 标 题 + + +
+
+
+ +
+
+
+ 作 者 + +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+
+ 上传图片 + 选择图片 +

+ +
+
+

封面大图片建议尺寸:900像素 * 500像素

+
+
+
+ +
+
+
+ +
+
+ + +
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
+ + +{/block} + + +{block name='script'} + + +{/block} + +{block name="style"} + +{/block} \ No newline at end of file diff --git a/application/admin/view/news/image.html b/application/admin/view/news/image.html new file mode 100644 index 000000000..fc4a13b33 --- /dev/null +++ b/application/admin/view/news/image.html @@ -0,0 +1,42 @@ +{extend name='admin@public/main'} + +{block name='style'} + +{/block} + +{block name="body"} +
+ {foreach $list as $key=>$vo} + + {/foreach} +
+
+
+
+ {if isset($page)}{$page|raw}{/if} +
+{/block} + +{block name="script"} + +{/block} diff --git a/application/admin/view/news/index.html b/application/admin/view/news/index.html new file mode 100644 index 000000000..8930a12cf --- /dev/null +++ b/application/admin/view/news/index.html @@ -0,0 +1,168 @@ +{extend name='admin@public/content'} + +{block name="button"} + +{/block} + +{block name='content'} + +
+ {foreach $list as $vo} +
+ + {foreach $vo.articles as $k => $v} + {if $k < 1} +
+ {if $v.title}

{$v.title}

{/if} +
+
+ {else} +
+
{$v.title}
+
+
+
+ {/if} + {/foreach} +
+ {/foreach} +
+ {if empty($list)} +

没 有 记 录 哦!

+ {/if} +
+{if isset($page)}

{$page|raw}

{/if} + +{/block} + +{block name='script'} + +{/block} + +{block name="style"} + +{/block} \ No newline at end of file diff --git a/application/admin/view/news/push.html b/application/admin/view/news/push.html new file mode 100644 index 000000000..67fba17b0 --- /dev/null +++ b/application/admin/view/news/push.html @@ -0,0 +1,192 @@ +
+ +
+
微信图文
+
+ {foreach $vo.articles as $key=>$value} +
+
+ {$value.title} +
+
+ {/foreach} +
+
+ +
+
指定粉丝标签推送 全选
+
+ + {foreach $fans_tags as $tag} + + {/foreach} + + {literal} + + {/literal} +
+
+
+
+ +
+ + +
+ +
+ + + + \ No newline at end of file diff --git a/application/admin/view/news/select.html b/application/admin/view/news/select.html new file mode 100644 index 000000000..ebb2a4543 --- /dev/null +++ b/application/admin/view/news/select.html @@ -0,0 +1,80 @@ +{extend name='admin@public/main'} + +{block name='style'} + +{/block} + +{block name="body"} +
+ {foreach $list as $vo} +
+ {foreach $vo.articles as $k => $v} + {if $k < 1} +
+ {if $v.title}

{$v.title}

{/if} +
+
+ {else} +
+
{$v.title}
+
+
+
+ {/if} + {/foreach} +
+ {/foreach} +
+ {if empty($list)}

没 有 记 录 哦!

{/if} +
+
+
{if isset($page)}{$page|raw}{/if}
+{/block} + + +{block name="script"} + +{/block} \ No newline at end of file diff --git a/application/admin/view/review/index.html b/application/admin/view/review/index.html new file mode 100644 index 000000000..5d75c7136 --- /dev/null +++ b/application/admin/view/review/index.html @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + {if ($type eq 'text') or ($type eq 'image') or ($type eq 'music')} +
+
{:date('H:i')}
+
+
+ +
+
+ {if $type eq 'text'} +
+
+
+ {$content|default=''|raw|htmlspecialchars_decode} +
+ {elseif $type eq 'image'} +
+
+
+ +
+ {elseif $type eq 'music'} +
+
+
+ + + + + + + + +
+ {$title|default=''} + +
+
+ +
+
+ {$desc|default=''}           +
+
+ {/if} +
+
+
+ {elseif $type eq 'article'} +
+
+
{$vo.title|default=''}
+
+
+ {:date('Y-m-d',strtotime($vo['create_at']))} + {$vo.author|default=''} +
+
+ {if $vo.show_cover_pic eq 1} +
+ {/if} +
{$vo.content|default=''|raw}
+ {if $vo.content_source_url} + + {/if} +
+
+ {elseif $type eq 'video'} +
+
{:date('H:i')}
+
+
+
+
+
+ {$title|default=''} +
+
{:date('m月d日')}
+
+ +
+ +
+
+
+
+
+ + {elseif $type eq 'news'} +
+
{:date('H:i')}
+
+
+
+ {if !empty($articles)} + {foreach $articles as $key=>$vo} + {if count($articles) gt 1} + {if $key < 1} +
+
+
+ {$vo.title|default=''} +
+
+ {else} + + + + + +
{$vo.title}
+ {/if} + {else} +
+
+ {$vo.title|default=''} +
+
+ {:date('m月d日')} +
+
+
+ {:str_replace([' ',"\n"],'',strip_tags($vo.digest))} ... +
+
+ + {/if} + {/foreach} + {/if} +
+
+
+
+ + {/if} + + \ No newline at end of file diff --git a/application/admin/view/tags/form.html b/application/admin/view/tags/form.html new file mode 100644 index 000000000..39ed800e6 --- /dev/null +++ b/application/admin/view/tags/form.html @@ -0,0 +1,18 @@ +
+ +
+ +
+ +
+
+ +
+ +
+ {if isset($vo['id'])}{/if} + + +
+ +
diff --git a/application/admin/view/tags/index.html b/application/admin/view/tags/index.html new file mode 100644 index 000000000..a53e2842f --- /dev/null +++ b/application/admin/view/tags/index.html @@ -0,0 +1,89 @@ +{extend name='admin@public/content'} + +{block name="button"} + + + + + + + + + + + + + +{/block} + +{block name="content"} + + + + +
+ {if empty($list)} +

没 有 记 录 哦!

+ {else} + + + + + + + + + + + + + + {foreach $list as $key=>$vo} + + + + + + + + + {/foreach} + +
+ + ID标签名称标签类型粉丝数操作
+ + {$vo.id|default='0'}{$vo.name|default=''}{$vo.id < 100 ? "系统标签" : "自定义标签"}{$vo.count|default=''} + + {if auth("$classuri/edit")} + | + + 编辑 + + 编辑 + + {/if} + + {if auth("$classuri/del")} + | + + 删除 + + 删除 + + {/if} +
+ {if isset($page)}

{$page|raw}

{/if} + {/if} +
+{/block} \ No newline at end of file diff --git a/application/wechat/controller/Block.php b/application/wechat/controller/Block.php index 5eae5a96f..333622c8f 100644 --- a/application/wechat/controller/Block.php +++ b/application/wechat/controller/Block.php @@ -46,9 +46,9 @@ class Block extends BasicAdmin */ public function index() { - $this->title = '微信粉丝黑名单管理'; + $this->title = '微信黑名单管理'; $get = $this->request->get(); - $db = Db::name($this->table)->where(['is_black' => '1'])->order('subscribe_time desc'); + $db = Db::name($this->table)->where(['is_black' => '1']); (isset($get['sex']) && $get['sex'] !== '') && $db->where('sex', $get['sex']); foreach (['nickname', 'country', 'province', 'city'] as $key) { (isset($get[$key]) && $get[$key] !== '') && $db->whereLike($key, "%{$get[$key]}%"); @@ -56,11 +56,11 @@ class Block extends BasicAdmin if (isset($get['tag']) && $get['tag'] !== '') { $db->where("concat(',',tagid_list,',') like :tag", ['tag' => "%,{$get['tag']},%"]); } - if (isset($get['date']) && $get['date'] !== '') { - list($start, $end) = explode(' - ', $get['date']); + if (isset($get['create_at']) && $get['create_at'] !== '') { + list($start, $end) = explode(' - ', $get['create_at']); $db->whereBetween('subscribe_at', ["{$start} 00:00:00", "{$end} 23:59:59"]); } - return parent::_list($db); + return parent::_list($db->order('subscribe_time desc')); } /** diff --git a/application/wechat/controller/Config.php b/application/wechat/controller/Config.php index a2598292b..caacc43ee 100644 --- a/application/wechat/controller/Config.php +++ b/application/wechat/controller/Config.php @@ -44,14 +44,15 @@ class Config extends BasicAdmin { if ($this->request->isGet()) { $code = encode(url('@admin', '', true, true) . '#' . $this->request->url()); - return $this->fetch('', [ + $assign = [ 'title' => '微信接口配置', 'appuri' => url("@wechat/api.push", '', true, true), 'appid' => $this->request->get('appid', sysconf('wechat_appid')), 'appkey' => $this->request->get('appkey', sysconf('wechat_appkey')), - 'authurl' => config('wechat.service_url') . "/wechat/api.push/auth/redirect/{$code}.html", + 'authurl' => "http://wm.cuci.cc/wechat/api.push/auth/{$code}.html", 'wechat' => WechatService::instance('config')->getConfig(), - ]); + ]; + return $this->fetch('', $assign); } try { sysconf('wechat_appid', $this->request->post('wechat_appid')); diff --git a/application/wechat/controller/Fans.php b/application/wechat/controller/Fans.php index cc25ac55f..fb1d51775 100644 --- a/application/wechat/controller/Fans.php +++ b/application/wechat/controller/Fans.php @@ -50,7 +50,7 @@ class Fans extends BasicAdmin { $this->title = '微信粉丝管理'; $get = $this->request->get(); - $db = Db::name($this->table)->where(['is_black' => '0'])->order('subscribe_time desc'); + $db = Db::name($this->table)->where(['is_black' => '0']); (isset($get['sex']) && $get['sex'] !== '') && $db->where('sex', $get['sex']); foreach (['nickname', 'country', 'province', 'city'] as $key) { (isset($get[$key]) && $get[$key] !== '') && $db->whereLike($key, "%{$get[$key]}%"); @@ -58,11 +58,11 @@ class Fans extends BasicAdmin if (isset($get['tag']) && $get['tag'] !== '') { $db->where("concat(',',tagid_list,',') like :tag", ['tag' => "%,{$get['tag']},%"]); } - if (isset($get['date']) && $get['date'] !== '') { - list($start, $end) = explode(' - ', $get['date']); + if (isset($get['create_at']) && $get['create_at'] !== '') { + list($start, $end) = explode(' - ', $get['create_at']); $db->whereBetween('subscribe_at', ["{$start} 00:00:00", "{$end} 23:59:59"]); } - return parent::_list($db); + return parent::_list($db->order('subscribe_time desc')); } /** diff --git a/application/wechat/controller/Keys.php b/application/wechat/controller/Keys.php index 03ea8ff09..a1b5a7d9d 100644 --- a/application/wechat/controller/Keys.php +++ b/application/wechat/controller/Keys.php @@ -84,20 +84,6 @@ class Keys extends BasicAdmin return $this->_form($this->table, 'form'); } - /** - * 添加数据处理 - * @param array $data - */ - protected function _add_form_filter(array &$data) - { - if ($this->request->isPost() && isset($data['keys'])) { - $db = Db::name($this->table)->where('keys', $data['keys']); - !empty($data['id']) && $db->where('id', 'neq', $data['id']); - $data['content'] = htmlspecialchars_decode($data['content']); - $db->count() > 0 && $this->error('关键字已经存在,请使用其它关键字!'); - } - } - /** * 编辑关键字 * @return string @@ -112,14 +98,6 @@ class Keys extends BasicAdmin return $this->_form($this->table, 'form'); } - /** - * 编辑数据处理 - * @param array $data - */ - protected function _edit_form_filter(array &$data) - { - $this->_add_form_filter($data); - } /** * 删除关键字 @@ -171,23 +149,10 @@ class Keys extends BasicAdmin public function subscribe() { $this->assign('title', '编辑默认回复'); - return $this->_form($this->table, 'form'); + $extend = ['keys' => 'subscribe']; + return $this->_form($this->table, 'form', 'keys', $extend, $extend); } - /** - * 关注默认回复表单处理 - * @param array $data - * @throws \think\db\exception\DataNotFoundException - * @throws \think\db\exception\ModelNotFoundException - * @throws \think\exception\DbException - */ - protected function _subscribe_form_filter(&$data) - { - if ($this->request->isGet()) { - $data = Db::name($this->table)->where(['keys' => 'subscribe'])->find(); - } - $data['keys'] = 'subscribe'; - } /** * 无配置默认回复 @@ -200,22 +165,22 @@ class Keys extends BasicAdmin public function defaults() { $this->assign('title', '编辑无配置默认回复'); - return $this->_form($this->table, 'form'); + $extend = ['keys' => 'default']; + return $this->_form($this->table, 'form', 'keys', $extend, $extend); } /** - * 无配置默认回复表单处理 + * 添加数据处理 * @param array $data - * @throws \think\db\exception\DataNotFoundException - * @throws \think\db\exception\ModelNotFoundException - * @throws \think\exception\DbException */ - protected function _defaults_form_filter(&$data) + protected function _form_filter(array &$data) { - if ($this->request->isGet()) { - $data = Db::name($this->table)->where(['keys' => 'default'])->find(); + if ($this->request->isPost() && isset($data['keys'])) { + $db = Db::name($this->table)->where('keys', $data['keys']); + !empty($data['id']) && $db->where('id', 'neq', $data['id']); + $data['content'] = htmlspecialchars_decode($data['content']); + $db->count() > 0 && $this->error('关键字已经存在,请使用其它关键字!'); } - $data['keys'] = 'default'; } /** diff --git a/application/wechat/controller/Review.php b/application/wechat/controller/Review.php index 5ea6bd62c..c656e4021 100644 --- a/application/wechat/controller/Review.php +++ b/application/wechat/controller/Review.php @@ -35,7 +35,7 @@ class Review extends Controller */ public function index() { - $content = str_replace("\n", "
", $this->request->get('content', '')); // 内容 + $content = str_replace("\n", "
", $this->request->get('content', '', 'urldecode')); // 内容 $type = $this->request->get('type', 'text'); // 类型 // 图文处理 if ($type === 'news' && is_numeric($content) && !empty($content)) { diff --git a/application/wechat/controller/api/Push.php b/application/wechat/controller/api/Push.php index 9e9ea9c4a..3f2c14658 100644 --- a/application/wechat/controller/api/Push.php +++ b/application/wechat/controller/api/Push.php @@ -59,7 +59,6 @@ class Push $this->appid = $request->post('appid', '', null); $this->openid = $request->post('openid', '', null); $this->receive = unserialize($request->post('receive', '', null)); - p($this->receive); if (empty($this->appid) || empty($this->openid) || empty($this->receive)) { throw new Exception('微信API实例缺失必要参数[appid,openid,event].'); } @@ -207,6 +206,7 @@ class Push protected function sendMessage($type, $data) { $msgData = ['touser' => $this->openid, 'msgtype' => $type, "{$type}" => $data]; + p($msgData); return WechatService::custom()->send($msgData); } diff --git a/application/wechat/view/block/index.html b/application/wechat/view/block/index.html index d7d62efb7..f79abcfc8 100644 --- a/application/wechat/view/block/index.html +++ b/application/wechat/view/block/index.html @@ -7,7 +7,7 @@ - + {/block} @@ -79,7 +79,7 @@
- +
@@ -151,7 +151,7 @@ {block name="script"} diff --git a/application/wechat/view/config/index.html b/application/wechat/view/config/index.html index dc1eed6ef..dec8ee245 100644 --- a/application/wechat/view/config/index.html +++ b/application/wechat/view/config/index.html @@ -7,7 +7,7 @@
-
+
diff --git a/application/wechat/view/fans/index.html b/application/wechat/view/fans/index.html index 0adb56c58..c3cffc4dc 100644 --- a/application/wechat/view/fans/index.html +++ b/application/wechat/view/fans/index.html @@ -7,7 +7,7 @@ - + {/block} @@ -79,7 +79,7 @@
- +
@@ -151,7 +151,7 @@ {block name="script"} diff --git a/application/wechat/view/keys/form.html b/application/wechat/view/keys/form.html index f585d4ab3..cf6d79adf 100644 --- a/application/wechat/view/keys/form.html +++ b/application/wechat/view/keys/form.html @@ -100,7 +100,7 @@
- +
@@ -153,7 +153,7 @@
- +
@@ -187,7 +187,7 @@
- +
diff --git a/application/wechat/view/review/index.html b/application/wechat/view/review/index.html index 073164fd8..5d75c7136 100644 --- a/application/wechat/view/review/index.html +++ b/application/wechat/view/review/index.html @@ -34,7 +34,7 @@
- {$content|default=''} + {$content|default=''|raw|htmlspecialchars_decode}
{elseif $type eq 'image'}
diff --git a/application/wechat/view/tags/index.html b/application/wechat/view/tags/index.html index a89cd176c..a53e2842f 100644 --- a/application/wechat/view/tags/index.html +++ b/application/wechat/view/tags/index.html @@ -11,7 +11,7 @@ - + {/block}