225 lines
7.3 KiB
PHP
225 lines
7.3 KiB
PHP
<?php
|
||
|
||
/**
|
||
* @name 管理员-用户注销审核控制器
|
||
* @desc 管理员审核用户注销申请,通过秒注销,拒绝则保留账号
|
||
* @Time 2026-04-27
|
||
* @LastUpdate v9.0.0 修复index查询(buildparams where兼容问题),新增user_device清理
|
||
*/
|
||
|
||
namespace app\admin\controller;
|
||
|
||
use app\common\controller\Backend;
|
||
use think\Db;
|
||
use think\Request;
|
||
|
||
class Userdeletion extends Backend
|
||
{
|
||
protected $model = null;
|
||
protected $noNeedLogin = [];
|
||
protected $noNeedRight = ['*'];
|
||
|
||
public function _initialize()
|
||
{
|
||
parent::_initialize();
|
||
}
|
||
|
||
public function index()
|
||
{
|
||
if ($this->request->isAjax()) {
|
||
$sort = $this->request->get('sort', 'createtime');
|
||
$order = $this->request->get('order', 'desc');
|
||
$offset = $this->request->get('offset', 0, 'intval');
|
||
$limit = $this->request->get('limit', 10, 'intval');
|
||
$filterJson = $this->request->get('filter', '{}');
|
||
|
||
$query = Db::name('user_deletion');
|
||
$listQuery = Db::name('user_deletion');
|
||
|
||
try {
|
||
$filter = json_decode($filterJson, true);
|
||
if (is_array($filter)) {
|
||
foreach ($filter as $key => $val) {
|
||
if ($val !== '' && $val !== null) {
|
||
$query->where($key, '=', $val);
|
||
$listQuery->where($key, '=', $val);
|
||
}
|
||
}
|
||
}
|
||
} catch (\Exception $e) {}
|
||
|
||
$total = $query->count();
|
||
$list = $listQuery
|
||
->order($sort ?: 'createtime', $order ?: 'desc')
|
||
->limit($offset, $limit)
|
||
->select();
|
||
|
||
foreach ($list as &$item) {
|
||
$statusMap = [0 => '待审核', 1 => '已通过', 2 => '已拒绝', 3 => '已自动注销'];
|
||
$item['status_text'] = $statusMap[$item['status']] ?? '未知';
|
||
$item['createtime_text'] = date('Y-m-d H:i:s', $item['createtime']);
|
||
$item['auto_delete_time_text'] = date('Y-m-d H:i:s', $item['auto_delete_time']);
|
||
if (isset($item['deletetime']) && $item['deletetime']) {
|
||
$item['deletetime_text'] = date('Y-m-d H:i:s', $item['deletetime']);
|
||
} else {
|
||
$item['deletetime_text'] = '-';
|
||
}
|
||
|
||
$remain = $item['auto_delete_time'] - time();
|
||
if ($item['status'] == 0 && $remain > 0) {
|
||
$days = floor($remain / 86400);
|
||
$hours = floor(($remain % 86400) / 3600);
|
||
$item['countdown'] = "{$days}天{$hours}小时后自动注销";
|
||
} elseif ($item['status'] == 0) {
|
||
$item['countdown'] = '已超时,待自动注销';
|
||
} else {
|
||
$item['countdown'] = '-';
|
||
}
|
||
}
|
||
unset($item);
|
||
|
||
$result = ['total' => $total, 'rows' => $list];
|
||
return json($result);
|
||
}
|
||
|
||
$pendingCount = Db::name('user_deletion')->where('status', 0)->count();
|
||
$this->view->assign('pendingCount', $pendingCount);
|
||
$this->view->assign('title', '用户注销审核');
|
||
return $this->view->fetch();
|
||
}
|
||
|
||
public function approve()
|
||
{
|
||
if (!$this->request->isPost()) {
|
||
$this->error('请求方式错误');
|
||
}
|
||
|
||
$id = $this->request->post('id', 0, 'intval');
|
||
$remark = $this->request->post('remark', '', 'trim');
|
||
|
||
if (!$id) {
|
||
$this->error('参数错误');
|
||
}
|
||
|
||
$record = Db::name('user_deletion')->where('id', $id)->find();
|
||
if (!$record) {
|
||
$this->error('记录不存在');
|
||
}
|
||
if ($record['status'] != 0) {
|
||
$this->error('该申请已处理');
|
||
}
|
||
|
||
$this->_deleteUser($record, 1, $remark, $this->auth->id);
|
||
$this->success('已通过注销申请,用户数据已删除');
|
||
}
|
||
|
||
public function reject()
|
||
{
|
||
if (!$this->request->isPost()) {
|
||
$this->error('请求方式错误');
|
||
}
|
||
|
||
$id = $this->request->post('id', 0, 'intval');
|
||
$remark = $this->request->post('remark', '管理员拒绝', 'trim');
|
||
|
||
if (!$id) {
|
||
$this->error('参数错误');
|
||
}
|
||
|
||
$record = Db::name('user_deletion')->where('id', $id)->find();
|
||
if (!$record) {
|
||
$this->error('记录不存在');
|
||
}
|
||
if ($record['status'] != 0) {
|
||
$this->error('该申请已处理');
|
||
}
|
||
|
||
Db::name('user_deletion')->where('id', $id)->update([
|
||
'status' => 2,
|
||
'admin_id' => $this->auth->id,
|
||
'admin_remark' => $remark,
|
||
'updatetime' => time(),
|
||
]);
|
||
|
||
$this->success('已拒绝注销申请');
|
||
}
|
||
|
||
public function process_auto()
|
||
{
|
||
$now = time();
|
||
$list = Db::name('user_deletion')
|
||
->where('status', 0)
|
||
->where('auto_delete_time', '<=', $now)
|
||
->select();
|
||
|
||
$count = 0;
|
||
foreach ($list as $record) {
|
||
$this->_deleteUser($record, 3, '3天未审核,自动注销', 0);
|
||
$count++;
|
||
}
|
||
|
||
$this->success("已处理 {$count} 条自动注销");
|
||
}
|
||
|
||
private function _deleteUser($record, $status, $remark, $adminId)
|
||
{
|
||
$userId = $record['user_id'];
|
||
|
||
Db::startTrans();
|
||
try {
|
||
$relatedTables = [
|
||
'user_token',
|
||
'user_device',
|
||
'user_signin',
|
||
'user_favorite',
|
||
'user_note',
|
||
'user_score_log',
|
||
'user_money_log',
|
||
'user_title_log',
|
||
'coin_log',
|
||
'article_like',
|
||
'article_rating',
|
||
'feed_interaction',
|
||
'user_exp_log',
|
||
'user_badge',
|
||
'user_task',
|
||
];
|
||
|
||
foreach ($relatedTables as $table) {
|
||
try {
|
||
Db::name($table)->where('user_id', $userId)->delete();
|
||
} catch (\Exception $e) {}
|
||
}
|
||
|
||
try {
|
||
Db::name('article')->where('user_id', $userId)->update([
|
||
'deletetime' => time(),
|
||
'status' => 'rejected',
|
||
]);
|
||
} catch (\Exception $e) {}
|
||
|
||
try { Db::name('user_deletion')->where('user_id', $userId)->where('id', '<>', $record['id'])->delete(); } catch (\Exception $e) {}
|
||
|
||
Db::name('user')->where('id', $userId)->delete();
|
||
|
||
// 注销完成后,对username做SHA256哈希(PIPL最小化保留原则)
|
||
// 保留6个月后由cleanupOldDeletionRecords接口自动清理
|
||
$hashedUsername = hash('sha256', $record['username'] ?? '');
|
||
|
||
Db::name('user_deletion')->where('id', $record['id'])->update([
|
||
'status' => $status,
|
||
'admin_id' => $adminId,
|
||
'admin_remark' => $remark,
|
||
'updatetime' => time(),
|
||
'deletetime' => time(),
|
||
'username' => $hashedUsername,
|
||
]);
|
||
|
||
Db::commit();
|
||
} catch (\Exception $e) {
|
||
Db::rollback();
|
||
throw $e;
|
||
}
|
||
}
|
||
}
|