title = 'Cursor账号管理'; // 创建查询对象 $query = $this->_query('cursor_accounts'); // 数据列表处理 $query->equal('is_used')->like('email'); // 列表排序并显示 $query->order('id desc')->page(); } /** * 生成激活码 * @auth true */ public function generate() { if ($this->request->isPost()) { // 获取参数 $count = intval(input('count', 1)); $days = intval(input('days', 30)); $agentId = input('agent_id', ''); $price = floatval(input('price', 0)); // 参数验证 if ($count < 1 || $count > 500) { $this->error('生成数量必须在1-100之间'); } if ($days < 1) { $this->error('有效天数必须大于0'); } // 开启事务 \think\facade\Db::startTrans(); $codes = []; $now = date('Y-m-d H:i:s'); // 生成激活码 for ($i = 0; $i < $count; $i++) { $codes[] = [ 'code' => strtoupper(substr(md5(uniqid() . mt_rand()), 0, 16)), 'days' => $days, 'created_at' => $now, 'is_used' => 0, 'status' => 1 // 设置默认状态为正常 ]; } // 批量插入激活码 $result = \think\facade\Db::name('cursor_activation_codes')->insertAll($codes); if (!$result) { \think\facade\Db::rollback(); $this->error('激活码生成失败'); } // 获取插入的ID范围 $firstId = \think\facade\Db::name('cursor_activation_codes')->getLastInsID(); $lastId = $firstId + count($codes) - 1; // 如果指定了代理商,则自动分配 if (!empty($agentId) && $price > 0) { $agent = \think\facade\Db::name('cursor_agents') ->where('id', $agentId) ->find(); if ($agent) { $agentCodes = []; $commission = $price * ($agent['commission_rate'] / 100); // 如果是二级代理,计算上级佣金 $parentCommission = 0; if ($agent['level'] == 2 && $agent['parent_id'] > 0) { $parent = \think\facade\Db::name('cursor_agents') ->where('id', $agent['parent_id']) ->find(); if ($parent) { $parentCommission = $price * ($parent['commission_rate'] / 100); } } // 准备代理商激活码数据 for ($id = $firstId; $id <= $lastId; $id++) { $agentCodes[] = [ 'agent_id' => $agent['id'], 'code_id' => $id, 'price' => $price, 'commission' => $commission, 'parent_commission' => $parentCommission, 'status' => 0, 'created_at' => $now, 'updated_at' => $now ]; } // 批量插入代理商激活码关联 if (!empty($agentCodes)) { $result = \think\facade\Db::name('cursor_agent_codes')->insertAll($agentCodes); if (!$result) { \think\facade\Db::rollback(); $this->error('代理商激活码分配失败'); } } } } \think\facade\Db::commit(); $this->success('生成成功!'); } else { // 获取代理商列表 $this->agents = \think\facade\Db::name('cursor_agents') ->where('status', 1) ->select() ->toArray(); $this->fetch(); } } /** * 激活码管理 * @auth true * @menu true */ public function codes() { $this->title = '激活码管理'; // 获取代理商列表用于筛选 $this->agents = \think\facade\Db::name('cursor_agents') ->where('status', 1) ->select() ->toArray(); // 创建查询对象 $query = $this->_query('cursor_activation_codes')->alias('c') ->leftJoin('cursor_agent_codes ac', 'c.id = ac.code_id') ->leftJoin('cursor_agents a', 'ac.agent_id = a.id') ->field([ 'c.*', // 包含所有激活码字段,包括 status 'a.id as agent_id', 'a.username as agent_name', 'a.level as agent_level', 'ac.price', 'ac.commission', 'ac.parent_commission', 'ac.status as settle_status' ]); // 数据列表处理 $query->where(function($query) { $agentId = input('agent_id', ''); if ($agentId !== '') { $query->where('a.id', '=', $agentId); } $isUsed = input('is_used', ''); if ($isUsed !== '') { $query->where('c.is_used', '=', $isUsed); } $code = input('code', ''); if ($code) { $query->whereLike('c.code', "%{$code}%"); } $usedBy = input('used_by', ''); if ($usedBy) { $query->whereLike('c.used_by', "%{$usedBy}%"); } // 添加天数筛选 $days = input('days', ''); if ($days !== '') { $query->where('c.days', '=', intval($days)); } // 添加状态筛选 $status = input('status', ''); if ($status !== '') { $query->where('c.status', '=', $status); } }); // 列表排序并显示 $query->order('c.id desc')->page(); } /** * 修改账号状态 * @auth true */ public function state() { $this->_applyFormToken(); $this->_save('cursor_accounts', ['is_used' => input('state')]); } /** * 删除账号 * @auth true */ public function remove() { $this->_applyFormToken(); $this->_delete('cursor_accounts'); } /** * 删除激活码 * @auth true */ public function removeCode() { $this->_applyFormToken(); $this->_delete('cursor_activation_codes'); } /** * 批量删除激活码 * @auth true */ public function batchRemoveCodes() { $this->_applyFormToken(); $ids = $this->request->post('ids', ''); // 如果是字符串,转换为数组 if (is_string($ids)) { $ids = explode(',', $ids); } // 确保ids是数组且不为空 if (empty($ids) || !is_array($ids)) { $this->error('请选择要删除的激活码'); } // 删除激活码 $deleteResult1 = \think\facade\Db::name('cursor_activation_codes')->whereIn('id', $ids)->delete(); // 删除关联的代理商激活码记录 $deleteResult2 = \think\facade\Db::name('cursor_agent_codes')->whereIn('code_id', $ids)->delete(); // 只要有一个删除操作成功就认为是成功的 if ($deleteResult1 || $deleteResult2) { $this->success('批量删除成功!'); } else { $this->success('没有需要删除的数据!'); } } /** * 设备账号管理 * @auth true * @menu true */ public function devices() { $this->title = '设备账号管理'; // 创建查询对象 $query = $this->_query('cursor_activation_codes')->alias('c') ->field([ 'c.used_by', 'MIN(c.used_at) as first_activation', 'COUNT(c.id) as total_codes', 'SUM(c.days) as total_days', 'GROUP_CONCAT(DISTINCT a.username) as agent_names' ]) ->leftJoin('cursor_agent_codes ac', 'c.id = ac.code_id') ->leftJoin('cursor_agents a', 'ac.agent_id = a.id') ->where('c.used_by', '<>', '') ->where('c.is_used', 1) ->group('c.used_by'); // 数据列表处理 $query->where(function($query) { $usedBy = input('used_by', ''); if ($usedBy) { $query->whereLike('c.used_by', "%{$usedBy}%"); } }); // 获取数据 $result = $query->order('first_activation desc')->page(); // 处理列表数据 $list = []; foreach ($result['list'] as $item) { // 获取当前使用的账号 $account = \think\facade\Db::name('cursor_accounts') ->where('used_by', $item['used_by']) ->where('is_used', 1) ->find(); // 计算到期时间 $firstActivationTime = strtotime($item['first_activation']); $expireTime = $firstActivationTime + ($item['total_days'] * 24 * 3600); // 检查缓存状态 $cacheKey = "device_account_{$item['used_by']}"; $cooldownKey = "device_cooldown_{$item['used_by']}"; $cachedAccount = \think\facade\Cache::get($cacheKey); $cooldownTime = \think\facade\Cache::get($cooldownKey); // 构建数据 $list[] = [ 'used_by' => $item['used_by'], 'email' => $account ? $account['email'] : '--', 'agent_names' => $item['agent_names'] ?: '--', 'total_codes' => $item['total_codes'], 'total_days' => $item['total_days'], 'first_activation' => $item['first_activation'], 'expire_time' => date('Y-m-d H:i:s', $expireTime), 'days_left' => ceil(($expireTime - time()) / 86400), 'has_cache' => !empty($cachedAccount), 'in_cooldown' => $cooldownTime > time(), 'cooldown_time' => $cooldownTime ? date('Y-m-d H:i:s', $cooldownTime) : '' ]; } // 传递数据到模板 $this->assign([ 'list' => $list, 'page' => $result['page'] ]); // 渲染模板 $this->fetch(); } /** * 重置设备账号 * @auth true */ public function resetDevice() { $this->_applyFormToken(); try { $machineId = input('machine_id', ''); if (empty($machineId)) { $this->error('设备ID不能为空'); } // 清除设备的账号缓存 $cacheKey = "device_account_{$machineId}"; \think\facade\Cache::delete($cacheKey); // 清除冷却期 $cooldownKey = "device_cooldown_{$machineId}"; \think\facade\Cache::delete($cooldownKey); // 将该设备使用的账号标记为未使用 \think\facade\Db::name('cursor_accounts') ->where('used_by', $machineId) ->update([ 'is_used' => 0, 'used_at' => null, 'used_by' => '' ]); $this->success('重置成功!'); } catch (\Exception $e) { $this->error("重置失败:{$e->getMessage()}"); } } /** * 批量切换代理商 * @auth true */ public function batchChangeAgent() { if ($this->request->isPost()) { $data = $this->_vali([ 'agent_id.require' => '代理商不能为空', 'code_ids.require' => '请选择要切换的激活码', 'price.require' => '销售价格不能为空', 'price.float' => '销售价格必须是数字' ]); // 检查代理商是否存在 $agent = \think\facade\Db::name('cursor_agents') ->where('id', $data['agent_id']) ->where('status', 1) ->find(); if (empty($agent)) { $this->error('代理商不存在或已被禁用!'); } // 解析激活码ID $codeIds = explode(',', $data['code_ids']); if (empty($codeIds)) { $this->error('请选择要切换的激活码!'); } // 开启事务 \think\facade\Db::startTrans(); $now = date('Y-m-d H:i:s'); // 计算佣金 $commission = $data['price'] * ($agent['commission_rate'] / 100); // 如果是二级代理,计算上级佣金 $parentCommission = 0; if ($agent['level'] == 2 && $agent['parent_id'] > 0) { $parent = \think\facade\Db::name('cursor_agents') ->where('id', $agent['parent_id']) ->find(); if ($parent) { $parentCommission = $data['price'] * ($parent['commission_rate'] / 100); } } // 删除旧的代理商关联 $deleteResult = \think\facade\Db::name('cursor_agent_codes') ->whereIn('code_id', $codeIds) ->delete(); // 批量插入新的关联 $insertData = []; foreach ($codeIds as $codeId) { $insertData[] = [ 'agent_id' => $agent['id'], 'code_id' => $codeId, 'price' => $data['price'], 'commission' => $commission, 'parent_commission' => $parentCommission, 'status' => 0, 'created_at' => $now, 'updated_at' => $now ]; } // 插入新数据 if (!empty($insertData)) { $insertResult = \think\facade\Db::name('cursor_agent_codes')->insertAll($insertData); if ($insertResult === false) { \think\facade\Db::rollback(); $this->error('切换失败:插入新数据失败'); } } \think\facade\Db::commit(); $this->success('切换成功!'); } else { // 获取代理商列表 $this->agents = \think\facade\Db::name('cursor_agents') ->where('status', 1) ->select() ->toArray(); $this->fetch(); } } /** * 代理商激活码管理 * @auth true * @menu true */ public function agentCodes() { $this->title = '代理商激活码'; // 获取当前管理员ID和角色 $adminId = session('user.id'); $isSuper = AdminService::isSuper(); if (!$isSuper) { // 普通管理员,获取关联的代理商信息 $agent = \think\facade\Db::name('cursor_agents') ->where('admin_id', $adminId) ->where('status', 1) ->find(); if (empty($agent)) { $this->error('未找到关联的代理商账号'); } } // 创建查询对象 $query = $this->_query('cursor_activation_codes')->alias('c') ->leftJoin('cursor_agent_codes ac', 'c.id = ac.code_id') ->leftJoin('cursor_agents a', 'ac.agent_id = a.id') ->field([ 'c.*', // 包含所有激活码字段,包括 status 'ac.price', 'ac.commission', 'ac.status as settle_status', // 重命名代理商激活码的状态字段 'a.username as agent_name', 'a.level as agent_level' ]); // 如果不是超级管理员,只显示自己的激活码 if (!$isSuper) { $query->where('ac.agent_id', $agent['id']); } // 数据列表处理 $query->where(function($query) use ($isSuper) { $code = input('code', ''); if ($code) { $query->whereLike('c.code', "%{$code}%"); } $isUsed = input('is_used', ''); if ($isUsed !== '') { $query->where('c.is_used', '=', $isUsed); } $status = input('status', ''); if ($status !== '') { $query->where('c.status', '=', $status); } // 添加天数筛选 $days = input('days', ''); if ($days !== '') { $query->where('c.days', '=', intval($days)); } // 超级管理员可以按代理商筛选 if ($isSuper) { $agentId = input('agent_id', ''); if ($agentId !== '') { $query->where('ac.agent_id', '=', $agentId); } } // 添加时间范围筛选 $createTime = input('create_time', ''); if ($createTime) { $createTimeArr = explode(' - ', $createTime); if (count($createTimeArr) == 2) { $query->whereBetween('c.created_at', [ "{$createTimeArr[0]} 00:00:00", "{$createTimeArr[1]} 23:59:59" ]); } } // 使用时间范围筛选 $useTime = input('use_time', ''); if ($useTime) { $useTimeArr = explode(' - ', $useTime); if (count($useTimeArr) == 2) { $query->whereBetween('c.used_at', [ "{$useTimeArr[0]} 00:00:00", "{$useTimeArr[1]} 23:59:59" ]); } } }); // 获取代理商列表(仅超级管理员可见) if ($isSuper) { $this->agents = \think\facade\Db::name('cursor_agents') ->where('status', 1) ->select() ->toArray(); } // 列表排序并显示 $query->order('c.id desc')->page(); } /** * 禁用激活码 * @auth true */ public function disableCode() { $this->_applyFormToken(); $id = input('id'); // 更新激活码状态为禁用 (0) $result = \think\facade\Db::name('cursor_activation_codes') ->where('id', $id) ->update(['status' => 0]); if ($result !== false) { $this->success('禁用成功!'); } else { $this->error('禁用失败!'); } } /** * 批量禁用激活码 * @auth true */ public function batchDisableCodes() { $this->_applyFormToken(); $ids = $this->request->post('ids', ''); if (empty($ids)) { $this->error('请选择要禁用的激活码'); } // 如果是字符串,转换为数组 if (is_string($ids)) { $ids = explode(',', $ids); } // 批量更新状态为禁用 (0) $result = \think\facade\Db::name('cursor_activation_codes') ->whereIn('id', $ids) ->update(['status' => 0]); if ($result !== false) { $this->success('批量禁用成功!'); } else { $this->error('批量禁用失败!'); } } /** * 导出激活码到txt文件 * @auth true */ public function exportCodes() { try { // 获取当前管理员ID和角色 $adminId = session('user.id'); $isSuper = AdminService::isSuper(); if (!$isSuper) { // 普通管理员,获取关联的代理商信息 $agent = \think\facade\Db::name('cursor_agents') ->where('admin_id', $adminId) ->where('status', 1) ->find(); if (empty($agent)) { $this->error('未找到关联的代理商账号'); } } // 创建查询对象 $query = \think\facade\Db::name('cursor_activation_codes')->alias('c') ->leftJoin('cursor_agent_codes ac', 'c.id = ac.code_id') ->leftJoin('cursor_agents a', 'ac.agent_id = a.id') ->field([ 'c.code', 'c.days', 'c.is_used', 'c.status' ]); // 如果不是超级管理员,只显示自己的激活码 if (!$isSuper) { $query->where('ac.agent_id', $agent['id']); } // 应用筛选条件 $code = input('code', ''); if ($code) { $query->whereLike('c.code', "%{$code}%"); } $isUsed = input('is_used', ''); if ($isUsed !== '') { $query->where('c.is_used', '=', $isUsed); } $status = input('status', ''); if ($status !== '') { $query->where('c.status', '=', $status); } $days = input('days', ''); if ($days !== '') { $query->where('c.days', '=', intval($days)); } // 超级管理员可以按代理商筛选 if ($isSuper) { $agentId = input('agent_id', ''); if ($agentId !== '') { $query->where('ac.agent_id', '=', $agentId); } } // 获取数据 $list = $query->order('c.id desc')->select()->toArray(); // 生成文件内容 $content = ''; foreach ($list as $item) { // 获取状态文本 $statusText = $item['status'] == 1 ? '正常' : '禁用'; $usedText = $item['is_used'] == 1 ? '已使用' : '未使用'; // 格式化每一行: 激活码 天数 状态 $content .= sprintf("%s\t%d\t%s/%s\n", $item['code'], $item['days'], $usedText, $statusText ); } // 设置响应头 header('Content-Type: text/plain'); header('Content-Disposition: attachment; filename="activation_codes_' . date('YmdHis') . '.txt"'); // 输出内容 echo $content; exit; } catch (\Exception $e) { $this->error($e->getMessage()); } } }