[更新]增加开放平台粉丝管理

This commit is contained in:
Anyon 2019-07-23 10:52:08 +08:00
parent d2903e8944
commit 5b4d61ab59
6 changed files with 423 additions and 2 deletions

View File

@ -0,0 +1,163 @@
<?php
// +----------------------------------------------------------------------
// | ThinkAdmin
// +----------------------------------------------------------------------
// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
// +----------------------------------------------------------------------
// | 官方网站: http://demo.thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/ThinkAdmin
// | github 代码仓库https://github.com/zoujingli/ThinkAdmin
// +----------------------------------------------------------------------
namespace app\service\controller;
use app\admin\service\QueueService;
use app\service\service\WechatService;
use app\service\queue\WechatQueue;
use library\Controller;
use think\Db;
use think\exception\HttpResponseException;
/**
* 微信粉丝管理
* Class Fans
* @package app\wechat\controller
*/
class Fans extends Controller
{
protected $appid = '';
/**
* 绑定数据表
* @var string
*/
protected $table = 'WechatFans';
/**
* 初始化函数
* Fans constructor.
*/
public function __construct()
{
parent::__construct();
$this->appid = input('appid', session('current_appid'));
if (empty($this->appid)) {
$this->appid = Db::name('WechatServiceConfig')->value('authorizer_appid');
}
if (empty($this->appid)) {
$this->fetch('/not-auth');
} else {
session('current_appid', $this->appid);
}
if ($this->request->isGet()) {
$this->wechats = Db::name('WechatServiceConfig')->where(['status' => '1'])->column('authorizer_appid,nick_name');
}
}
/**
* 微信粉丝管理
* @auth true
* @menu true
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @throws \think\exception\PDOException
*/
public function index()
{
$this->title = '微信粉丝管理';
$query = $this->_query($this->table)->like('nickname')->equal('subscribe,is_black');
$query->dateBetween('subscribe_at')->where(['appid' => $this->appid])->order('subscribe_time desc')->page();
}
/**
* 列表数据处理
* @param array $data
*/
protected function _index_page_filter(array &$data)
{
$tags = Db::name('WechatFansTags')->column('id,name');
foreach ($data as &$user) {
$user['tags'] = [];
foreach (explode(',', $user['tagid_list']) as $tagid) {
if (isset($tags[$tagid])) $user['tags'][] = $tags[$tagid];
}
}
}
/**
* 批量拉黑粉丝
* @auth true
*/
public function setBlack()
{
$this->applyCsrfToken();
try {
foreach (array_chunk(explode(',', $this->request->post('openid')), 20) as $openids) {
WechatService::WeChatUser($this->appid)->batchBlackList($openids);
Db::name('WechatFans')->whereIn('openid', $openids)->update(['is_black' => '1']);
}
$this->success('拉黑粉丝信息成功!');
} catch (HttpResponseException $exception) {
throw $exception;
} catch (\Exception $e) {
$this->error("拉黑粉丝信息失败,请稍候再试!{$e->getMessage()}");
}
}
/**
* 取消拉黑粉丝
* @auth true
*/
public function delBlack()
{
try {
$this->applyCsrfToken();
foreach (array_chunk(explode(',', $this->request->post('openid')), 20) as $openids) {
WechatService::WeChatUser($this->appid)->batchUnblackList($openids);
Db::name('WechatFans')->whereIn('openid', $openids)->update(['is_black' => '0']);
}
$this->success('取消拉黑粉丝信息成功!');
} catch (HttpResponseException $exception) {
throw $exception;
} catch (\Exception $e) {
$this->error("取消拉黑粉丝信息失败,请稍候再试!{$e->getMessage()}");
}
}
/**
* 同步粉丝列表
* @auth true
*/
public function sync()
{
try {
sysoplog('微信管理', "创建微信{$this->appid}粉丝同步任务");
QueueService::add("同步{$this->appid}粉丝列表", WechatQueue::URI, 0, ['appid' => $this->appid], 0);
$this->success('创建同步粉丝任务成功,需要时间来完成。<br>请到系统任务管理查看进度!');
} catch (HttpResponseException $exception) {
throw $exception;
} catch (\Exception $e) {
$this->error("创建同步粉丝任务失败,请稍候再试!<br> {$e->getMessage()}");
}
}
/**
* 删除粉丝信息
* @auth true
* @throws \think\Exception
* @throws \think\exception\PDOException
*/
public function remove()
{
$this->applyCsrfToken();
$this->_delete($this->table);
}
}

View File

@ -0,0 +1,82 @@
<?php
// +----------------------------------------------------------------------
// | ThinkAdmin
// +----------------------------------------------------------------------
// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
// +----------------------------------------------------------------------
// | 官方网站: http://demo.thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/ThinkAdmin
// | github 代码仓库https://github.com/zoujingli/ThinkAdmin
// +----------------------------------------------------------------------
namespace app\service\queue;
use app\admin\queue\JobsQueue;
use app\service\service\WechatService;
use app\wechat\service\FansService;
use think\Db;
/**
* Class Jobs
* @package app\wechat
*/
class WechatQueue extends JobsQueue
{
/**
* 当前任务URI
*/
const URI = self::class;
/**
* 当前操作APPID
* @var string
*/
protected $appid;
/**
* 执行任务
* @return boolean
*/
public function execute()
{
try {
$this->appid = $this->data['appid'];
$wechat = WechatService::WeChatUser($this->appid);
$next = ''; // 获取远程粉丝
$this->output->writeln('Start synchronizing fans from the Wechat server');
while (is_array($result = $wechat->getUserList($next)) && !empty($result['data']['openid'])) {
foreach (array_chunk($result['data']['openid'], 100) as $chunk)
if (is_array($list = $wechat->getBatchUserInfo($chunk)) && !empty($list['user_info_list']))
foreach ($list['user_info_list'] as $user) FansService::set($user, $this->appid);
if (in_array($result['next_openid'], $result['data']['openid'])) break;
$next = $result['next_openid'];
}
$next = ''; // 同步粉丝黑名单
$this->output->writeln('Start synchronizing black from the Wechat server');
while (is_array($result = $wechat->getBlackList($next)) && !empty($result['data']['openid'])) {
foreach (array_chunk($result['data']['openid'], 100) as $chunk) {
$where = [['is_black', 'eq', '0'], ['openid', 'in', $chunk]];
Db::name('WechatFans')->where($where)->update(['is_black' => '1']);
}
if (in_array($result['next_openid'], $result['data']['openid'])) break;
$next = $result['next_openid'];
}
// 同步粉丝标签列表
$this->output->writeln('Start synchronizing tags from the Wechat server');
if (is_array($list = WechatService::WeChatTags($this->appid)->getTags()) && !empty($list['tags'])) {
foreach ($list['tags'] as &$tag) $tag['appid'] = $this->appid;
Db::name('WechatFansTags')->where('1=1')->delete();
Db::name('WechatFansTags')->insertAll($list['tags']);
}
return true;
} catch (\Exception $e) {
$this->statusDesc = $e->getMessage();
return false;
}
}
}

View File

@ -0,0 +1,98 @@
{extend name='admin@main'}
{block name="button"}
{if auth("service/fans/setblack")}
<button data-action='{:url("setblack")}' data-rule="openid#{key}" data-csrf="{:systoken('service/fans/setblack')}" class='layui-btn layui-btn-sm layui-btn-primary'>批量拉黑</button>
{/if}
{if auth("service/fans/delblack")}
<button data-action='{:url("delblack")}' data-rule="openid#{key}" data-csrf="{:systoken('service/fans/delblack')}" class='layui-btn layui-btn-sm layui-btn-primary'>取消拉黑</button>
{/if}
{if auth("service/fans/sync")}
<button data-load='{:url("sync")}' class='layui-btn layui-btn-sm layui-btn-primary'>同步粉丝</button>
{/if}
{/block}
{block name="content"}
<div class="think-box-shadow">
{include file='fans/index_search'}
<table class="layui-table margin-top-10" lay-skin="line">
{notempty name='list'}
<thead>
<tr>
<th class='list-table-check-td think-checkbox'><input data-auto-none data-check-target='.list-check-box' type='checkbox'></th>
<th width="180px" class='text-left nowrap'>微信昵称</th>
<th width="180px" class="text-left nowrap">粉丝标签</th>
<th width="150px" class='text-left nowrap'>性别语言</th>
<th width="180px" class='text-left nowrap'>关注时间</th>
<th width="80px"></th>
<th></th>
</tr>
</thead>
{/notempty}
<tbody>
{foreach $list as $key=>$vo}
<tr>
<td class='list-table-check-td think-checkbox'>
<input class="list-check-box" value='{$vo.openid}' type='checkbox'>
</td>
<td class='text-left nowrap relative layui-elip'>
<img src="{$vo.headimgurl|default=''}" onerror="$(this).remove()" data-tips-image class="inline-block" style="width:40px;height:40px;vertical-align:top;margin-right:5px">
<div class="inline-block">
昵称:{$vo.nickname|default='--'}
<br>
区域:{$vo.country|default='--'} {$vo.province} {$vo.city}
</div>
</td>
<td class="text-left padding-0">
<div style="max-height:60px;overflow:auto">{foreach $vo.tags as $t}<p><span class="layui-badge layui-bg-cyan margin-right-5">{$t|default='--'}</span></p>{/foreach}</div>
</td>
<td class='text-left nowrap'>
性别:{switch name='vo.sex'}{case value='1'}男{/case}{case value='2'}女{/case}{default}未知{/switch}
<br>
语言:{$vo.language|raw}
</td>
<td class='text-left nowrap'>
日期:{$vo.subscribe_at|format_datetime|str_replace=' ','<br>时间:',###|raw}
</td>
<td class='text-center nowrap'>
{eq name='vo.subscribe' value='0'}
<span class="layui-badge">未关注</span>
{else}
<span class="layui-badge layui-bg-green">已关注</span>
{/eq}
<br>
{eq name='vo.is_black' value='0'}
<span class="layui-badge layui-bg-green">未拉黑</span>
{else}
<span class="layui-badge">已拉黑</span>
{/eq}
</td>
<td class="nowrap">
{eq name='vo.is_black' value='0'}
<!--{if auth("service/fans/setblack")}-->
<a class="margin-left-10 layui-btn layui-btn-normal layui-btn-sm" data-action="{:url('setblack')}" data-value="openid#{$vo.openid}" data-csrf="{:systoken('service/fans/setblack')}">拉 黑</a>
<!--{/if}-->
{else}
<!--{if auth("service/fans/delblack")}-->
<a class="margin-left-10 layui-btn layui-btn-normal layui-btn-sm" data-action="{:url('delblack')}" data-value="openid#{$vo.openid}" data-csrf="{:systoken('service/fans/delblack')}">拉 白</a>
<!--{/if}-->
{/eq}
{if auth("service/fans/remove")}
<a class="layui-btn layui-btn-sm layui-btn-danger" data-confirm="确定要删除该粉丝吗?" data-action="{:url('remove')}" data-value="id#{$vo.id}" data-csrf="{:systoken('service/fans/remove')}">删 除</a>
{/if}
</td>
</tr>
{/foreach}
</tbody>
</table>
{empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
</div>
{/block}

View File

@ -0,0 +1,76 @@
<!-- 表单搜索 开始 -->
<fieldset>
<legend>条件搜索</legend>
<form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
<div class="layui-form-item layui-inline">
<label class="layui-form-label">当前微信</label>
<div class="layui-input-inline">
<select class="layui-select" name="appid" lay-search>
<!--{foreach $wechats as $k=>$v}-->
<!--{if $k eq $appid}-->
<option selected value="{$k}">{$v}</option>
<!--{else}-->
<option value="{$k}">{$v}</option>
<!--{/if}-->
<!--{/foreach}-->
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">微信昵称</label>
<div class="layui-input-inline">
<input name="nickname" value="{$Think.get.nickname|default=''}" placeholder="请输入微信昵称" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">关注状态</label>
<div class="layui-input-inline">
<select class="layui-select" name="subscribe">
{foreach [''=>'-- 全部 --','0'=>'显示未关注的粉丝','1'=>'显示已关注的粉丝'] as $k=>$v}
{eq name='Think.get.subscribe' value='$k.""'}
<option selected value="{$k}">{$v}</option>
{else}
<option value="{$k}">{$v}</option>
{/eq}
{/foreach}
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">拉黑状态</label>
<div class="layui-input-inline">
<select class="layui-select" name="is_black">
{foreach [''=>'-- 全部 --','0'=>'显示未拉黑的粉丝','1'=>'显示已拉黑的粉丝'] as $k=>$v}
{eq name='Think.get.is_black' value='$k.""'}
<option selected value="{$k}">{$v}</option>
{else}
<option value="{$k}">{$v}</option>
{/eq}
{/foreach}
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">关注时间</label>
<div class="layui-input-inline">
<input name="subscribe_at" value="{$Think.get.subscribe_at|default=''}" placeholder="请选择关注时间" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-inline">
<button class="layui-btn layui-btn-primary"><i class="layui-icon">&#xe615;</i> 搜 索</button>
</div>
</form>
</fieldset>
<script>
window.form.render();
window.laydate.render({range: true, elem: '[name="subscribe_at"]'});
</script>
<!-- 表单搜索 结束 -->

View File

@ -0,0 +1 @@
还没有授权,请授权公众号

View File

@ -48,8 +48,9 @@ class Fans extends Controller
public function index()
{
$this->title = '微信粉丝管理';
$this->where = ['appid' => WechatService::getAppid()];
$query = $this->_query($this->table)->like('nickname')->equal('subscribe,is_black');
$query->dateBetween('subscribe_at')->order('subscribe_time desc')->page();
$query->dateBetween('subscribe_at')->where($this->where)->order('subscribe_time desc')->page();
}
/**
@ -115,7 +116,7 @@ class Fans extends Controller
{
try {
sysoplog('微信管理', '创建微信粉丝同步任务');
QueueService::add('同步粉丝列表', WechatQueue::URI, 0, [], 0);
QueueService::add("同步粉丝列表", WechatQueue::URI, 0, [], 0);
$this->success('创建同步粉丝任务成功,需要时间来完成。<br>请到系统任务管理查看进度!');
} catch (HttpResponseException $exception) {
throw $exception;