734 lines
24 KiB
PHP
734 lines
24 KiB
PHP
<?php
|
|
|
|
namespace app\manager\controller;
|
|
|
|
use think\admin\Controller;
|
|
use think\admin\service\AdminService;
|
|
|
|
/**
|
|
* Cursor账号管理
|
|
* Class Account
|
|
* @package app\manager\controller
|
|
*/
|
|
class Account extends Controller
|
|
{
|
|
/**
|
|
* Cursor账号管理
|
|
* @auth true
|
|
* @menu true
|
|
*/
|
|
public function index()
|
|
{
|
|
$this->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());
|
|
}
|
|
}
|
|
}
|