diff --git a/app/admin/controller/VerificationCode.php b/app/admin/controller/VerificationCode.php
new file mode 100644
index 0000000..7533305
--- /dev/null
+++ b/app/admin/controller/VerificationCode.php
@@ -0,0 +1,29 @@
+order('id', 'desc')
+ ->paginate([ 'query' => request()->param() ]);
+ View::assign([
+ 'list' => $list,
+ 'account' => $account,
+ ]);
+ return View::fetch('VerificationCode/index');
+ }
+}
\ No newline at end of file
diff --git a/app/admin/route/app.php b/app/admin/route/app.php
index da1fa99..4b4952b 100755
--- a/app/admin/route/app.php
+++ b/app/admin/route/app.php
@@ -479,4 +479,9 @@ Route::rule('diamond_edit', 'Diamond/edit', 'GET|POST');
Route::rule('diamond_del', 'Diamond/del', 'GET|POST');
Route::rule('diamond_status', 'Diamond/status', 'POST');
Route::rule('diamond_get_max_sort', 'Diamond/get_max_sort', 'GET');
+
+#============================
+#VerificationCode.php 验证码管理
+#============================
+Route::rule('verification_code', 'VerificationCode/index', 'GET|POST');
\ No newline at end of file
diff --git a/app/admin/view/VerificationCode/index.html b/app/admin/view/VerificationCode/index.html
new file mode 100644
index 0000000..b5b8b3a
--- /dev/null
+++ b/app/admin/view/VerificationCode/index.html
@@ -0,0 +1,55 @@
+{include file="Public:header3" /}
+
+
+
+
+
+
+
+
+
+
+
+ | ID |
+ 手机号 |
+ 验证码 |
+ IP地址 |
+ 发送时间 |
+ 过期时间 |
+
+
+
+ {volist name="list" id="item"}
+
+ | {$item.id} |
+ {$item.account} |
+ {$item.code} |
+ {$item.ip_address} |
+ {$item.created_at} |
+ {$item.expired_at} |
+
+ {/volist}
+
+
+
{$list|raw}
+
+
+
+
+{include file="Public:footer3" /}
\ No newline at end of file
diff --git a/app/common/model/UserVerificationCode.php b/app/common/model/UserVerificationCode.php
new file mode 100644
index 0000000..818d39b
--- /dev/null
+++ b/app/common/model/UserVerificationCode.php
@@ -0,0 +1,177 @@
+ '注册',
+ self::TYPE_LOGIN => '登录',
+ self::TYPE_RESET_PASSWORD => '找回密码',
+ self::TYPE_CHANGE_MOBILE => '修改手机',
+ self::TYPE_CHANGE_EMAIL => '修改邮箱',
+ self::TYPE_OTHER => '其他'
+ ];
+ }
+
+ /**
+ * 获取状态列表
+ * @return array
+ */
+ public static function getStatusList(): array
+ {
+ return [
+ self::STATUS_UNUSED => '未使用',
+ self::STATUS_USED => '已使用',
+ self::STATUS_EXPIRED => '已失效'
+ ];
+ }
+
+ /**
+ * 获取发送渠道列表
+ * @return array
+ */
+ public static function getChannelList(): array
+ {
+ return [
+ self::CHANNEL_SMS => '短信',
+ self::CHANNEL_EMAIL => '邮件'
+ ];
+ }
+
+ /**
+ * 创建验证码
+ * @param string $account 账号
+ * @param string $code 验证码
+ * @param int $codeType 验证码类型
+ * @param string $channel 发送渠道
+ * @param string $ipAddress IP地址
+ * @param int $userId 用户ID
+ * @param int $expireMinutes 过期时间(分钟)
+ * @return UserVerificationCode
+ */
+ public static function createCode(
+ string $account,
+ string $code,
+ int $codeType,
+ string $channel,
+ string $ipAddress = '',
+ int $userId = 0,
+ int $expireMinutes = 5
+ ): self {
+ $data = [
+ 'user_id' => $userId,
+ 'account' => $account,
+ 'code' => $code,
+ 'code_type' => $codeType,
+ 'channel' => $channel,
+ 'ip_address' => $ipAddress,
+ 'status' => self::STATUS_UNUSED,
+ 'expired_at' => date('Y-m-d H:i:s', time() + $expireMinutes * 60)
+ ];
+
+ return self::create($data);
+ }
+
+ /**
+ * 验证验证码
+ * @param string $account 账号
+ * @param string $code 验证码
+ * @param int $codeType 验证码类型
+ * @return bool
+ */
+ public static function verifyCode(string $account, string $code, int $codeType): bool
+ {
+ $verificationCode = self::where([
+ 'account' => $account,
+ 'code' => $code,
+ 'code_type' => $codeType,
+ 'status' => self::STATUS_UNUSED
+ ])
+ ->where('expired_at', '>', date('Y-m-d H:i:s'))
+ ->find();
+
+ if (!$verificationCode) {
+ return false;
+ }
+
+ // 更新验证码状态
+ $verificationCode->status = self::STATUS_USED;
+ $verificationCode->used_at = date('Y-m-d H:i:s');
+ return $verificationCode->save();
+ }
+
+ /**
+ * 使验证码失效
+ * @param string $account 账号
+ * @param int $codeType 验证码类型
+ * @return bool
+ */
+ public static function invalidateCode(string $account, int $codeType): bool
+ {
+ return self::where([
+ 'account' => $account,
+ 'code_type' => $codeType,
+ 'status' => self::STATUS_UNUSED
+ ])->update([
+ 'status' => self::STATUS_EXPIRED
+ ]);
+ }
+
+ /**
+ * 获取最近的验证码
+ * @param string $account 账号
+ * @param int $codeType 验证码类型
+ * @return UserVerificationCode|null
+ */
+ public static function getLatestCode(string $account, int $codeType): ?self
+ {
+ return self::where([
+ 'account' => $account,
+ 'code_type' => $codeType,
+ 'status' => self::STATUS_UNUSED
+ ])
+ ->where('expired_at', '>', date('Y-m-d H:i:s'))
+ ->order('id', 'desc')
+ ->find();
+ }
+}
\ No newline at end of file
diff --git a/config/menu.php b/config/menu.php
index 0adaefa..8a7c6b0 100755
--- a/config/menu.php
+++ b/config/menu.php
@@ -36,9 +36,15 @@ return [
'url' => '/admin/sign_config',
'name' => '用户签到设置',
],
+
+ // [
+ // 'url' => '/admin/user_loginStat',
+ // 'name' => '用户登录统计',
+ // ],
+ //验证码
[
- 'url' => '/admin/user_loginStat',
- 'name' => '用户登录统计',
+ 'url' => '/admin/verification_code',
+ 'name' => '验证码列表',
],
],
],