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; } } }