Files
xianyan/docs/toolsapi/application/admin/controller/Userdeletion.php
2026-06-27 04:57:00 +08:00

225 lines
7.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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;
}
}
}