修改微信粉丝管理

This commit is contained in:
邹景立 2021-08-24 14:02:14 +08:00
parent 322e8d9ffc
commit 30b36727c2
5 changed files with 120 additions and 147 deletions

View File

@ -50,7 +50,7 @@
</label>
<div class="layui-input-block">
<input id="storage.alioss_bucket" type="text" name="storage.alioss_bucket" required value="{:sysconf('storage.alioss_bucket')}" placeholder="请输入阿里云OSS存储 Bucket (空间名称)" class="layui-input">
<p class="help-block">填写阿里云OSS存储空间名称think-admin-oss(需要是全区唯一的值,不存在时会自动创建)</p>
<p class="help-block">填写阿里云OSS存储空间名称think-admin-oss</p>
</div>
</div>
@ -92,7 +92,7 @@
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消修改吗?" data-close>取消修改</button>
</div>
<script>form.render()</script>
<script>layui.form.render()</script>
</div>
</form>

View File

@ -18,6 +18,7 @@ namespace app\wechat\controller;
use app\wechat\service\WechatService;
use think\admin\Controller;
use think\admin\helper\QueryHelper;
use think\exception\HttpResponseException;
/**
@ -37,17 +38,18 @@ class Fans extends Controller
* 微信用户管理
* @auth true
* @menu true
* @throws \think\admin\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function index()
{
$this->title = '微信用户管理';
$this->where = ['appid' => WechatService::instance()->getAppid()];
$query = $this->_query($this->table)->like('nickname')->equal('subscribe,is_black');
$query->dateBetween('subscribe_at')->where($this->where)->order('subscribe_time desc')->page();
$this->_query($this->table)->layTable(function () {
$this->title = '微信用户管理';
}, function (QueryHelper $query) {
$query->where(['appid' => WechatService::instance()->getAppid()]);
$query->like('nickname')->equal('subscribe,is_black')->dateBetween('subscribe_at');
});
}
/**
@ -56,13 +58,7 @@ class Fans extends Controller
*/
protected function _index_page_filter(array &$data)
{
$tags = $this->app->db->name('WechatFansTags')->column('name', 'id');
foreach ($data as &$vo) {
$vo['tags'] = [];
foreach (explode(',', $vo['tagid_list']) as $tagid) {
if (isset($tags[$tagid])) $vo['tags'][] = $tags[$tagid];
}
}
foreach ($data as &$vo) $vo['subscribe_at'] = format_datetime($vo['subscribe_at']);
}
/**
@ -76,19 +72,34 @@ class Fans extends Controller
}
/**
* 清空用户数据
* 黑名单列表操作
* @auth true
*/
public function truncate()
public function black()
{
$data = $this->_vali([
'openid.require' => '操作用户不能为空!',
'black.require' => '操作类型不能为空!',
]);
try {
$this->_query('WechatFans')->empty();
$this->_query('WechatFansTags')->empty();
$this->success('清空用户数据成功!');
} catch (\think\exception\HttpResponseException $exception) {
foreach (array_chunk(explode(',', $data['openid']), 20) as $openids) {
if ($data['black']) {
WechatService::WeChatUser()->batchBlackList($openids);
$this->app->db->name('WechatFans')->whereIn('openid', $openids)->update(['is_black' => 1]);
} else {
WechatService::WeChatUser()->batchUnblackList($openids);
$this->app->db->name('WechatFans')->whereIn('openid', $openids)->update(['is_black' => 0]);
}
}
if (empty($data['black'])) {
$this->success('移出黑名单成功!');
} else {
$this->success('拉入黑名单成功!');
}
} catch (HttpResponseException $exception) {
throw $exception;
} catch (\Exception $exception) {
$this->error("清空用户数据失败,{$exception->getMessage()}");
$this->error("黑名单操作失败,请稍候再试!<br>{$exception->getMessage()}");
}
}
@ -99,48 +110,23 @@ class Fans extends Controller
*/
public function remove()
{
$this->_applyFormToken();
$this->_delete($this->table);
}
/**
* 用户拉入黑名单
* 清空用户数据
* @auth true
*/
public function blackAdd()
public function truncate()
{
try {
$this->_applyFormToken();
foreach (array_chunk(explode(',', $this->request->post('openid')), 20) as $openids) {
WechatService::WeChatUser()->batchBlackList($openids);
$this->app->db->name('WechatFans')->whereIn('openid', $openids)->update(['is_black' => '1']);
}
$this->success('拉入黑名单成功!');
$this->_query('WechatFans')->empty();
$this->_query('WechatFansTags')->empty();
$this->success('清空用户数据成功!');
} catch (HttpResponseException $exception) {
throw $exception;
} catch (\Exception $exception) {
$this->error("拉入黑名单失败,请稍候再试!<br>{$exception->getMessage()}");
$this->error("清空用户数据失败,{$exception->getMessage()}");
}
}
/**
* 用户移出黑名单
* @auth true
*/
public function blackDel()
{
try {
$this->_applyFormToken();
foreach (array_chunk(explode(',', $this->request->post('openid')), 20) as $openids) {
WechatService::WeChatUser()->batchUnblackList($openids);
$this->app->db->name('WechatFans')->whereIn('openid', $openids)->update(['is_black' => '0']);
}
$this->success('移出黑名单成功!');
} catch (HttpResponseException $exception) {
throw $exception;
} catch (\Exception $exception) {
$this->error("移出黑名单失败,请稍候再试!<br>{$exception->getMessage()}");
}
}
}

View File

@ -43,24 +43,24 @@
<div class="layui-form-item">
<label class="layui-form-label"><b>PushApi</b><br><span class="nowrap color-desc">消息推送接收</span></label>
<div class="layui-input-block">
<div class="relative">
<label class="relative block">
<input value="服务器授权IP{$geoip}" disabled class="layui-input layui-bg-gray">
<a data-copy="{$geoip}" class="input-right-icon"><i class="iconfont icon-copy"></i></a>
</div>
<div class="relative margin-top-5">
<a data-copy="{$geoip}" class="layui-icon layui-icon-release input-right-icon"></a>
</label>
<label class="relative block margin-top-5">
<input value="消息推送地址:{$thrNotify}" disabled class="layui-input layui-bg-gray">
<a data-copy="{$thrNotify}" class="input-right-icon"><i class="iconfont icon-copy"></i></a>
</div>
<a data-copy="{$thrNotify}" class="layui-icon layui-icon-release input-right-icon"></a>
</label>
<p class="help-block">公众号服务平台消息推送接口及服务器授权IP地址需在公众号接口开发处配置。</p>
</div>
</div>
<div class="hr-line-dashed margin-top-30"></div>
<input type="hidden" name="wechat.type" value="api">
</div>
<div class="layui-form-item text-center">
<button class="layui-btn" type="submit">保存配置</button>
</div>
<div class="hr-line-dashed"></div>
<input type="hidden" name="wechat.type" value="api">
<div class="layui-form-item text-center">
<button class="layui-btn" type="submit">保存配置</button>
</div>
</form>

View File

@ -46,28 +46,29 @@
<div class="layui-form-item">
<label class="layui-form-label"><b>AppKey</b><br><span class="nowrap color-desc">服务接口密钥</span></label>
<div class="layui-input-block">
<input name="wechat.thr_appkey" required placeholder="请输入32位第三方平台接口密钥AppKey必填" value="{:sysconf('wechat.thr_appkey')}" maxlength="32" pattern="^[0-9a-z]{32}$" class="layui-input">
<p class="help-block">公众号服务平台接口密钥, 通过微信第三方授权自动获取, 若没有值请进行微信第三方授权。</p>
<label class="relative block">
<input name="wechat.thr_appkey" required placeholder="请输入32位第三方平台接口密钥AppKey必填" value="{:sysconf('wechat.thr_appkey')}" maxlength="32" pattern="^[0-9a-z]{32}$" class="layui-input">
<p class="help-block">公众号服务平台接口密钥, 通过微信第三方授权自动获取, 若没有值请进行微信第三方授权。</p>
</label>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><b>PushApi</b><br><span class="nowrap color-desc">服务推送接口</span></label>
<div class="layui-input-block">
<div class="relative margin-top-5">
<label class="relative block">
<input value="{$thrNotify}" disabled class="layui-input layui-bg-gray">
<a data-copy="{$thrNotify}" class="input-right-icon"><i class="iconfont icon-copy"></i></a>
</div>
<a data-copy="{$thrNotify}" class="layui-icon layui-icon-release input-right-icon"></a>
</label>
<p class="help-block">公众号绑定服务平台接口通知 URL, 公众号消息接收与回复等。</p>
</div>
</div>
</div>
<div class="hr-line-dashed margin-top-30"></div>
<input type="hidden" name="wechat.type" value="thr">
<div class="layui-form-item text-center">
<button class="layui-btn" type="submit">保存配置</button>
</div>
<div class="hr-line-dashed"></div>
<input type="hidden" name="wechat.type" value="thr">
<div class="layui-form-item text-center">
<button class="layui-btn" type="submit">保存配置</button>
</div>
</form>

View File

@ -1,12 +1,9 @@
{extend name="../../admin/view/main"}
{extend name="../../admin/view/table"}
{block name="button"}
<!--{if auth("blackAdd")}-->
<button data-action='{:url("blackAdd")}' data-rule="openid#{key}" data-csrf="{:systoken('blackAdd')}" class='layui-btn layui-btn-sm layui-btn-primary'>拉入黑名单</button>
<!--{/if}-->
<!--{if auth("blackDel")}-->
<button data-action='{:url("blackDel")}' data-rule="openid#{key}" data-csrf="{:systoken('blackDel')}" class='layui-btn layui-btn-sm layui-btn-primary'>移出黑名单</button>
<!--{if auth("black")}-->
<button data-action='{:url("black")}' data-table-id="UserData" data-rule="openid#{openid};black#1" class='layui-btn layui-btn-sm layui-btn-primary'>拉入黑名单</button>
<button data-action='{:url("black")}' data-table-id="UserData" data-rule="openid#{openid};black#0" class='layui-btn layui-btn-sm layui-btn-primary'>移出黑名单</button>
<!--{/if}-->
<!--{if auth("truncate")}-->
@ -14,77 +11,66 @@
<!--{/if}-->
<!--{if auth("sync")}-->
<button data-queue='{:url("sync")}' data-confirm="确定要创建同步用户数据的后台任务?" class='layui-btn layui-btn-sm layui-btn-primary'>同步用户数据</button>
<button data-queue='{:url("sync")}' data-table-id="UserData" data-confirm="确定要创建同步用户数据的后台任务?" 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'>
<label><input data-auto-none data-check-target='.list-check-box' type='checkbox'></label>
</th>
<th width="180px" class='text-left nowrap'>微信昵称</th>
<th width="180px"></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'>
<label><input class="list-check-box" value='{$vo.openid}' type='checkbox'></label>
</td>
<td class='text-left nowrap'>
<div class="headimg" data-tips-image data-lazy-src="{$vo.headimgurl|default=''}"></div>
<div class="inline-block">
<p>昵称:{$vo.nickname|default='--'}</p>
<p>区域:{$vo.country|default='--'} {$vo.province|default=''} {$vo.city|default=''}</p>
</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'>
<div class="notselect">
{eq name='vo.subscribe' value='0'}<span class="layui-badge">未订阅</span>{else}<span class="layui-badge layui-bg-green">已订阅</span>{/eq}
{eq name='vo.is_black' value='0'}<span class="layui-badge layui-bg-green">未拉黑</span>{else}<span class="layui-badge">已拉黑</span>{/eq}
</div>
</td>
<td class="nowrap">
<!--{if auth('blackAdd') and $vo.is_black eq 0}-->
<a class="layui-btn layui-btn-sm" data-action="{:url('blackAdd')}" data-value="openid#{$vo.openid}" data-csrf="{:systoken('blackAdd')}">加入黑名单</a>
<!--{elseif auth('blackDel') and $vo.is_black eq 1}-->
<a class="layui-btn layui-btn-sm" data-action="{:url('blackDel')}" data-value="openid#{$vo.openid}" data-csrf="{:systoken('blackDel')}">移出黑名单</a>
<!--{/if}-->
<!--{if auth("remove")}-->
<a class="layui-btn layui-btn-sm layui-btn-danger" data-action="{:url('remove')}" data-value="id#{$vo.id}" data-csrf="{:systoken('remove')}" data-confirm="确定要删除该用户吗?"> </a>
<!--{/if}-->
</td>
</tr>
{/foreach}
</tbody>
</table>
{empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
<table id="UserData" data-url="{:sysuri()}" data-target-search="form.form-search"></table>
</div>
{/block}
{block name='script'}
<script>
$(function () {
$('#UserData').layTable({
even: true, height: 'full',
sort: {field: 'subscribe_time', type: 'desc'},
cols: [[
{checkbox: true},
{field: 'nickname', title: '微信昵称', minWidth: 100, align: 'center'},
{field: 'province', title: '所在区域', minWidth: 120, templet: '<div>{{d.country}} {{d.province}} {{d.city}}</div>'},
{field: 'sex', title: '性别', align: 'center', minWidth: 80, templet: '<div>{{d.sex==1 ? "男" : (d.sex==2 ? "女" : "未知")}}</div>'},
{field: 'language', title: '所属国家', align: 'center', minWidth: 100, templet: '<div>{{d.language}}</div>'},
{field: 'subscribe_time', title: '关注时间', minWidth: 170, align: 'center', sort: true, templet: '<div>{{d.subscribe_at}}</div>'},
{
field: 'subscribe', title: '订阅状态', align: "center", templet: function (d) {
if (d.subscribe > 0) return '<span class="layui-badge layui-bg-green">已订阅</span>';
return '<span class="layui-badge">未订阅</span>';
}
},
{field: 'is_black', title: '是否黑名单', align: 'center', minWidth: 110, templet: '#StatusSwitchTpl'},
{toolbar: '#toolbar', title: '操作面板', align: 'center', fixed: 'right'}
]]
});
// 数据状态切换操作
layui.form.on('switch(StatusSwitch)', function (obj) {
var data = {openid: obj.value, black: obj.elem.checked > 0 ? 1 : 0};
$.form.load("{:url('black')}", data, 'post', function (ret) {
if (ret.code < 1) $.msg.error(ret.info, 3, function () {
$('#UserData').trigger('reload'); // 操作异常时重载数据
});
return false;
}, false);
});
});
</script>
<!-- 数据状态切换模板 -->
<script type="text/html" id="StatusSwitchTpl">
<!--{if auth("black")}-->
<input type="checkbox" value="{{d.openid}}" lay-skin="switch" lay-text="已拉黑|未拉黑" lay-filter="StatusSwitch" {{d.is_black>0?'checked':''}}>
<!--{else}-->
{{d.status ? '<b class="color-red">已拉黑</b>' : '<b class="color-green">未拉黑</b>'}}
<!--{/if}-->
</script>
<script type="text/html" id="toolbar">
<!--{if auth("remove")}-->
<a class="layui-btn layui-btn-sm layui-btn-danger" data-action="{:url('remove')}" data-value="id#{{d.id}}" data-confirm="确定要删除该用户吗?"> </a>
<!--{/if}-->
</script>
{/block}