yunzer/app/index/controller/UserController.php
2025-06-07 09:15:14 +08:00

755 lines
25 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
/**
* 商业使用授权协议
*
* Copyright (c) 2025 [云泽网]. 保留所有权利.
*
* 本软件仅供评估使用。任何商业用途必须获得书面授权许可。
* 未经授权商业使用本软件属于侵权行为,将承担法律责任。
*
* 授权购买请联系: 357099073@qq.com
* 官方网站: https://www.yunzer.cn
*
* 评估用户须知:
* 1. 禁止移除版权声明
* 2. 禁止用于生产环境
* 3. 禁止转售或分发
*/
namespace app\index\controller;
use think\Controller;
use app\index\model\Users;
use think\facade\Redirect;
use think\facade\View;
use \think\facade\Log;
use \think\facade\Cache;
use PHPMailer\PHPMailer\PHPMailer;
use think\Response;
use app\index\model\UserMessage;
use app\index\model\SystemNotice;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\Writer\PngWriter;
class UserController extends BaseController
{
/**
* 用户登录
*
* @return \think\Response
*/
public function login()
{
if ($this->request->isPost()) {
$data = $this->request->post();
try {
// 验证数据
$validate = validate([
'account' => 'require|email',
'password' => 'require'
]);
if (!$validate->check($data)) {
return json(['code' => 1, 'msg' => $validate->getError()]);
}
// 查询用户
$user = Users::where('account', $data['account'])->find();
if (!$user) {
return json(['code' => 1, 'msg' => '用户不存在']);
}
// 验证密码
if ($user->password !== md5($data['password'])) {
return json(['code' => 1, 'msg' => '密码错误']);
}
// 登录成功设置session
session('user_id', $user->id);
session('user_name', $user->name);
session('user_avatar', $user->avatar ?? '/static/images/avatar.png');
// 设置cookie有效期7天
$expire = 7 * 24 * 3600;
cookie('user_id', $user->id, ['expire' => $expire]);
cookie('user_account', $user->account, ['expire' => $expire]);
cookie('user_name', $user->name, ['expire' => $expire]);
cookie('user_avatar', $user->avatar ?? '/static/images/avatar.png', ['expire' => $expire]);
// 记录登录日志
Log::record('用户登录成功:' . $user->account, 'info');
return json(['code' => 0, 'msg' => '登录成功']);
} catch (\Exception $e) {
Log::record('登录失败:' . $e->getMessage(), 'error');
return json(['code' => 1, 'msg' => '登录失败:' . $e->getMessage()]);
}
}
return view('login');
}
/**
* 用户注册
*
* @return \think\Response
*/
public function register()
{
if ($this->request->isPost()) {
$data = $this->request->post();
try {
// 验证数据
$validate = validate([
'account' => 'require|email|unique:users',
'code' => 'require|number|length:6',
'password' => 'require|min:6|max:20',
'repassword' => 'require|confirm:password'
], [
'account.require' => '账户不能为空',
'account.email' => '邮箱格式不正确',
'account.unique' => '该邮箱已注册',
'code.require' => '验证码不能为空',
'code.number' => '验证码必须为数字',
'code.length' => '验证码长度必须为6位',
'password.require' => '密码不能为空',
'password.min' => '密码长度不能小于6个字符',
'password.max' => '密码长度不能超过20个字符',
'repassword.require' => '确认密码不能为空',
'repassword.confirm' => '两次输入的密码不一致'
]);
if (!$validate->check($data)) {
return json(['code' => 1, 'msg' => $validate->getError()]);
}
// 验证邮箱验证码
$emailCode = cache('email_code_' . $data['account']);
if (!$emailCode || $emailCode != $data['code']) {
return json(['code' => 1, 'msg' => '验证码错误或已过期']);
}
// 创建用户
$user = new Users;
$user->account = $data['account'];
$user->password = md5($data['password']);
$user->name = $this->generateRandomName();
$user->create_time = time();
$user->save();
// 清除验证码缓存
cache('email_code_' . $data['account'], null);
return json(['code' => 0, 'msg' => '注册成功']);
} catch (\Exception $e) {
return json(['code' => 1, 'msg' => '注册失败:' . $e->getMessage()]);
}
}
return view('register');
}
/**
* 退出登录
*
* @return \think\Response
*/
public function logout()
{
try {
Log::record('用户退出登录', 'info');
// 清除所有会话和缓存数据
session(null);
Cache::tag('user_cache')->clear();
// 清除所有cookie
$cookies = [
'user_id',
'user_account',
'user_name',
'user_avatar',
'expire_time',
'is_auto_login',
'auto_login_attempted',
'PHPSESSID'
];
foreach ($cookies as $cookie) {
cookie($cookie, null, ['expire' => -1]);
}
return json(['code' => 0, 'msg' => '退出成功', 'data' => ['clear_storage' => true]]);
} catch (\Exception $e) {
Log::record('退出登录失败:' . $e->getMessage(), 'error');
return json(['code' => 1, 'msg' => '退出失败:' . $e->getMessage()]);
}
}
// 生成随机用户名
private function generateRandomName()
{
return '云朵_' . mt_rand(100000, 999999);
}
// 发送短信验证码
public function sendSmsCode()
{
if ($this->request->isPost()) {
$phone = $this->request->post('phone');
// 验证手机号
$validate = validate([
'phone' => 'require|mobile|unique:user'
], [
'phone.require' => '手机号不能为空',
'phone.mobile' => '手机号格式不正确',
'phone.unique' => '该手机号已注册'
]);
if (!$validate->check(['phone' => $phone])) {
return json(['code' => 0, 'msg' => $validate->getError()]);
}
// 生成6位随机验证码
$code = mt_rand(100000, 999999);
// 这里应该调用短信服务商API发送验证码
// 示例代码,实际使用时需要替换为真实的短信发送逻辑
try {
// TODO: 调用短信服务商API发送验证码
// $result = sendSms($phone, $code);
// 将验证码保存到缓存有效期5分钟
cache('sms_code_' . $phone, $code, 300);
return json(['code' => 1, 'msg' => '验证码发送成功']);
} catch (\Exception $e) {
return json(['code' => 0, 'msg' => '验证码发送失败:' . $e->getMessage()]);
}
}
return json(['code' => 0, 'msg' => '非法请求']);
}
// 微信授权回调
// public function wechatCallback()
// {
// $code = $this->request->get('code');
// if (!$code) {
// return json(['code' => 0, 'msg' => '微信授权失败']);
// }
// try {
// // 这里应该调用微信API获取用户信息
// // 示例代码实际使用时需要替换为真实的微信API调用逻辑
// // $wechatUser = getWechatUserInfo($code);
// // 模拟获取到的微信用户信息
// $wechatUser = [
// 'openid' => 'test_openid_' . time(),
// 'nickname' => '微信用户',
// 'avatar' => ''
// ];
// // 检查用户是否已注册
// $user = Users::where('openid', $wechatUser['openid'])->find();
// if ($user) {
// // 已注册,直接登录
// session('user_id', $user->id);
// return json(['code' => 1, 'msg' => '登录成功']);
// }
// // 未注册,返回注册所需信息
// return json([
// 'code' => 2,
// 'msg' => '需要注册',
// 'data' => $wechatUser
// ]);
// } catch (\Exception $e) {
// return json(['code' => 0, 'msg' => '微信授权失败:' . $e->getMessage()]);
// }
// }
// 发送邮箱验证码
public function sendEmailCode()
{
// 设置响应头
header('Content-Type: application/json; charset=utf-8');
if (!$this->request->isPost()) {
return json(['code' => 1, 'msg' => '请求方法无效']);
}
$email = $this->request->post('account');
if (empty($email)) {
return json(['code' => 1, 'msg' => '邮箱不能为空']);
}
// 验证邮箱格式
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return json(['code' => 1, 'msg' => '邮箱格式不正确']);
}
// 检查邮箱是否已注册
$exists = Users::where('account', $email)->find();
if ($exists) {
return json(['code' => 1, 'msg' => '该邮箱已注册']);
}
// 生成6位随机验证码
$code = mt_rand(100000, 999999);
// 发送验证码邮件
$result = parent::sendEmail($email, "您的注册验证码是:{$code}有效期为5分钟。", '注册验证码');
if ($result === '发送成功') { // 修改这里的判断条件
// 将验证码存入缓存有效期5分钟
cache('email_code_' . $email, $code, 300);
return json(['code' => 0, 'msg' => '验证码已发送']);
} else {
return json(['code' => 1, 'msg' => '发送失败:' . $result]);
}
}
//个人中心
public function profile()
{
// 检查用户是否登录
if (!cookie('user_account')) {
return redirect('/index/user/login');
}
// 获取用户信息
$user = Users::where('account', cookie('user_account'))->find();
// var_dump($user);
if (!$user) {
return redirect('/index/user/login');
}
View::assign('user', $user);
return $this->fetch();
}
//个人资料
public function saveBasic()
{
// 检查用户是否登录
if (!cookie('user_account')) {
return json(['code' => 1, 'msg' => '请先登录']);
}
// 获取用户信息
$user = Users::where('account', cookie('user_account'))->find();
if (!$user) {
return json(['code' => 1, 'msg' => '用户不存在']);
}
// 获取表单数据
$data = $this->request->post();
// 验证用户名
if (empty($data['name'])) {
return json(['code' => 1, 'msg' => '用户名不能为空']);
}
// 验证手机号格式
if (!empty($data['phone']) && !preg_match('/^1[3-9]\d{9}$/', $data['phone'])) {
return json(['code' => 1, 'msg' => '请检查手机号']);
}
// 检查用户名是否已被使用(排除当前用户)
$existingUser = Users::where('name', $data['name'])
->where('uid', '<>', $user->uid) // 排除当前用户
->find();
if ($existingUser) {
return json(['code' => 1, 'msg' => '该用户名已被使用']);
}
// 更新用户信息
$user->name = $data['name'];
$user->phone = $data['phone'] ?? '';
$user->sex = $data['sex'] ?? 0;
$user->qq = $data['qq'] ?? '';
$user->wechat = $data['wechat'] ?? '';
$user->update_time = time();
if ($user->save()) {
return json(['code' => 0, 'msg' => '保存成功']);
} else {
return json(['code' => 1, 'msg' => '保存失败']);
}
}
//更新头像
public function update_avatar()
{
// 检查用户是否登录
if (!cookie('user_account')) {
return json(['code' => 1, 'msg' => '请先登录']);
}
// 获取用户信息
$user = Users::where('account', cookie('user_account'))->find();
if (!$user) {
return json(['code' => 1, 'msg' => '用户不存在']);
}
// 获取上传的文件
$file = $this->request->file('avatar');
if (!$file) {
return json(['code' => 1, 'msg' => '请选择要上传的头像']);
}
try {
// 验证文件大小和类型
if ($file->getSize() > 2097152) { // 2MB
return json(['code' => 1, 'msg' => '图片大小不能超过2MB']);
}
$ext = strtolower($file->getOriginalExtension());
if (!in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
return json(['code' => 1, 'msg' => '只支持jpg、jpeg、png、gif、webp格式的图片']);
}
// 移动到指定目录
$savename = \think\facade\Filesystem::disk('public')->putFile('avatar', $file);
if (!$savename) {
return json(['code' => 1, 'msg' => '图片上传失败']);
}
// 获取文件URL
$avatarUrl = '/storage/' . $savename;
// 更新用户头像
$user->avatar = $avatarUrl;
$user->update_time = time();
if ($user->save()) {
return json(['code' => 0, 'msg' => '头像更新成功', 'data' => ['url' => $avatarUrl]]);
} else {
return json(['code' => 1, 'msg' => '头像更新失败']);
}
} catch (\Exception $e) {
return json(['code' => 1, 'msg' => '系统错误:' . $e->getMessage()]);
}
}
/**
* 获取系统通知列表
*/
public function getNotifications()
{
// 检查用户是否登录
if (!cookie('user_account')) {
return json(['code' => 1, 'msg' => '请先登录']);
}
$type = $this->request->get('type', 'all'); // 获取通知类型all, unread, read
$userId = cookie('user_id');
try {
// 构建查询条件
$where = [
['status', '=', 1] // 只获取启用的通知
];
// 查询系统通知
$notices = SystemNotice::where($where)
->order('is_top', 'desc') // 置顶的排在前面
->order('create_time', 'desc')
->select();
// 格式化数据
$data = [];
foreach ($notices as $notice) {
// 检查用户是否已读该通知
$isRead = SystemNotice::where([
['user_id', '=', $userId],
['notice_id', '=', $notice->id],
['is_read', '=', 1]
])->find();
// 根据type过滤
if ($type == 'unread' && $isRead)
continue;
if ($type == 'read' && !$isRead)
continue;
$data[] = [
'id' => $notice->id,
'title' => $notice->title,
'content' => $notice->content,
'type' => $notice->type,
'is_top' => $notice->is_top,
'is_read' => $isRead ? 1 : 0,
'create_time' => date('Y-m-d H:i:s', $notice->create_time)
];
}
return json(['code' => 0, 'msg' => '获取成功', 'data' => $data]);
} catch (\Exception $e) {
return json(['code' => 1, 'msg' => '获取失败:' . $e->getMessage()]);
}
}
/**
* 查看通知详情
*/
public function readNotification()
{
// 检查用户是否登录
if (!cookie('user_account')) {
return json(['code' => 1, 'msg' => '请先登录']);
}
$data = $this->request->post();
$noticeId = $data['id'] ?? 0;
$userId = cookie('user_id');
try {
// 查询通知
$notice = SystemNotice::where('id', $noticeId)
->where('status', 1)
->find();
if (!$notice) {
return json(['code' => 1, 'msg' => '通知不存在']);
}
// 记录用户已读状态
$message = SystemNotice::where([
['user_id', '=', $userId],
['notice_id', '=', $noticeId]
])->find();
if (!$message) {
// 创建新的已读记录
$message = new SystemNotice;
$message->user_id = $userId;
$message->notice_id = $noticeId;
$message->is_read = 1;
$message->read_time = time();
$message->save();
} elseif (!$message->is_read) {
// 更新已读状态
$message->is_read = 1;
$message->read_time = time();
$message->save();
}
return json(['code' => 0, 'msg' => '操作成功']);
} catch (\Exception $e) {
return json(['code' => 1, 'msg' => '操作失败:' . $e->getMessage()]);
}
}
/**
* 通知详情页面
*/
public function notificationDetail()
{
// 检查用户是否登录
if (!cookie('user_account')) {
return redirect('/index/user/login');
}
$noticeId = $this->request->get('id');
$userId = cookie('user_id');
try {
// 查询通知
$notice = SystemNotice::where('id', $noticeId)
->where('status', 1)
->find();
if (!$notice) {
return $this->error('通知不存在');
}
// 记录用户已读状态
$message = SystemNotice::where([
['user_id', '=', $userId],
['notice_id', '=', $noticeId]
])->find();
if (!$message) {
// 创建新的已读记录
$message = new SystemNotice;
$message->user_id = $userId;
$message->notice_id = $noticeId;
$message->is_read = 1;
$message->read_time = time();
$message->save();
} elseif (!$message->is_read) {
// 更新已读状态
$message->is_read = 1;
$message->read_time = time();
$message->save();
}
// 增加查看次数
$notice->view_count = $notice->view_count + 1;
$notice->save();
View::assign('notice', $notice);
return $this->fetch('notification_detail');
} catch (\Exception $e) {
return $this->error('获取通知详情失败:' . $e->getMessage());
}
}
/**
* 获取系统通知列表
*/
public function getMessages()
{
// 检查用户是否登录
if (!cookie('user_account')) {
return json(['code' => 1, 'msg' => '请先登录']);
}
$type = $this->request->get('type', 'all'); // 获取通知类型all, unread, read
$userId = cookie('user_id');
try {
// 构建查询条件
$where = [
['status', '=', 1] // 只获取启用的通知
];
// 查询系统通知
$notices = UserMessage::where($where)
->order('is_top', 'desc') // 置顶的排在前面
->order('create_time', 'desc')
->select();
// 格式化数据
$data = [];
foreach ($notices as $notice) {
// 检查用户是否已读该通知
$isRead = UserMessage::where([
['user_id', '=', $userId],
['notice_id', '=', $notice->id],
['is_read', '=', 1]
])->find();
// 根据type过滤
if ($type == 'unread' && $isRead)
continue;
if ($type == 'read' && !$isRead)
continue;
$data[] = [
'id' => $notice->id,
'title' => $notice->title,
'content' => $notice->content,
'type' => $notice->type,
'is_top' => $notice->is_top,
'is_read' => $isRead ? 1 : 0,
'create_time' => date('Y-m-d H:i:s', $notice->create_time)
];
}
return json(['code' => 0, 'msg' => '获取成功', 'data' => $data]);
} catch (\Exception $e) {
return json(['code' => 1, 'msg' => '获取失败:' . $e->getMessage()]);
}
}
//修改密码
public function updatePassword()
{
// 检查用户是否登录
if (!cookie('user_account')) {
return redirect('/index/user/login');
}
// 获取用户信息
$user = Users::where('account', cookie('user_account'))->find();
if (!$user) {
return redirect('/index/user/login');
}
// 如果是GET请求显示修改密码页面
if ($this->request->isGet()) {
return $this->fetch();
}
// 如果是POST请求处理密码修改
if ($this->request->isPost()) {
$data = $this->request->post();
// 验证旧密码
if ($user->password !== md5($data['old_password'])) {
return json(['code' => 1, 'msg' => '旧密码错误']);
}
// 验证新密码
if ($data['new_password'] !== $data['confirm_password']) {
return json(['code' => 1, 'msg' => '两次输入的密码不一致']);
}
// 更新密码
$user->password = md5($data['new_password']);
$user->update_time = time();
if ($user->save()) {
// 清除登录状态
cookie('user_id', null, ['expire' => -1]);
cookie('user_account', null, ['expire' => -1]);
cookie('user_name', null, ['expire' => -1]);
cookie('user_avatar', null, ['expire' => -1]);
return json(['code' => 0, 'msg' => '密码修改成功,请重新登录']);
} else {
return json(['code' => 1, 'msg' => '密码修改失败']);
}
}
}
//生成二维码绑定微信
public function qrcode()
{
// 检查用户是否登录
if (!cookie('user_account')) {
return json(['code'=> -1,'msg'=> '请先登录']);
}
// 获取当前用户信息
$user = Users::where('account', cookie('user_account'))->find();
if (!$user) {
return json(['code' => -1, 'msg' => '用户信息获取失败']);
}
// 假设这里生成一个唯一的绑定标识例如使用用户ID和时间戳组合
$bindToken = md5($user->id . time());
// 生成实际的绑定 URL
$domain = $this->request->domain();
$bindUrl = "{$domain}/wechat_bind?token={$bindToken}";
// 将绑定标识存入缓存设置有效期例如30分钟
cache('wechat_bind_token_' . $user->id, $bindToken, 1800);
try {
// 创建二维码实例
$qrCode = QrCode::create($bindUrl);
$writer = new PngWriter();
// 生成二维码图片
$result = $writer->write($qrCode);
$qrCodeDataUri = $result->getDataUri();
return json(['code' => 0, 'msg' => '二维码生成成功', 'data' => ['qrcode_url' => $qrCodeDataUri]]);
} catch (\Exception $e) {
return json(['code' => -1, 'msg' => '二维码生成失败: ' . $e->getMessage()]);
}
}
}