第二阶段完善代理商激活码
This commit is contained in:
272
app/admin/controller/api/Account.php
Normal file
272
app/admin/controller/api/Account.php
Normal file
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\admin\controller\api;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* Cursor账号管理接口
|
||||
*/
|
||||
class Account extends Controller
|
||||
{
|
||||
/**
|
||||
* 添加账号
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
try {
|
||||
$data = $this->_vali([
|
||||
'email.require' => '邮箱不能为空',
|
||||
'password.require' => '密码不能为空',
|
||||
'first_name.require' => '名字不能为空',
|
||||
'last_name.require' => '姓氏不能为空',
|
||||
'access_token.require' => 'access_token不能为空',
|
||||
'refresh_token.require' => 'refresh_token不能为空',
|
||||
'registration_time.require' => '注册时间不能为空'
|
||||
]);
|
||||
|
||||
// 检查邮箱是否已存在
|
||||
if (Db::name('cursor_accounts')->where('email', $data['email'])->find()) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'msg' => '该邮箱已存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 准备插入数据
|
||||
$insertData = [
|
||||
'email' => $data['email'],
|
||||
'password' => $data['password'],
|
||||
'first_name' => $data['first_name'],
|
||||
'last_name' => $data['last_name'],
|
||||
'access_token' => $data['access_token'],
|
||||
'refresh_token' => $data['refresh_token'],
|
||||
'machine_id' => $data['machine_id'] ?? '',
|
||||
'user_agent' => $data['user_agent'] ?? '',
|
||||
'registration_time' => $data['registration_time'],
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'is_used' => 0
|
||||
];
|
||||
|
||||
// 插入数据
|
||||
$id = Db::name('cursor_accounts')->insertGetId($insertData);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '添加成功',
|
||||
'data' => ['id' => $id]
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return json([
|
||||
'code' => 500,
|
||||
'msg' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取未使用的账号
|
||||
*/
|
||||
public function getUnused()
|
||||
{
|
||||
try {
|
||||
// 获取machine_id
|
||||
$machineId = input('machine_id', '');
|
||||
if (empty($machineId)) {
|
||||
return json([
|
||||
'code' => 401,
|
||||
'msg' => '设备ID不能为空'
|
||||
]);
|
||||
}
|
||||
|
||||
// 检查设备是否在冷却期
|
||||
$cooldownKey = "device_cooldown_{$machineId}";
|
||||
$isInCooldown = \think\facade\Cache::get($cooldownKey);
|
||||
|
||||
if ($isInCooldown) {
|
||||
return json([
|
||||
'code' => 429,
|
||||
'msg' => '请求过于频繁,请稍后再试',
|
||||
'data' => [
|
||||
'cooldown_expires' => date('Y-m-d H:i:s', $isInCooldown)
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
// 查询设备激活状态
|
||||
$activations = Db::name('cursor_activation_codes')
|
||||
->where('used_by', '=', $machineId)
|
||||
->where('is_used', '=', 1)
|
||||
->order('used_at desc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
if (empty($activations)) {
|
||||
return json([
|
||||
'code' => 401,
|
||||
'msg' => '设备未激活'
|
||||
]);
|
||||
}
|
||||
|
||||
// 计算总天数和到期时间
|
||||
$totalDays = array_sum(array_column($activations, 'days'));
|
||||
$firstActivationTime = strtotime($activations[count($activations)-1]['used_at']);
|
||||
$expireTime = $firstActivationTime + ($totalDays * 24 * 3600);
|
||||
|
||||
// 检查是否过期
|
||||
if (time() > $expireTime) {
|
||||
return json([
|
||||
'code' => 401,
|
||||
'msg' => '设备授权已过期'
|
||||
]);
|
||||
}
|
||||
|
||||
// 检查缓存中是否有该设备最近使用的账号
|
||||
$cacheKey = "device_account_{$machineId}";
|
||||
$cachedAccount = \think\facade\Cache::get($cacheKey);
|
||||
|
||||
if ($cachedAccount) {
|
||||
// 检查账号是否仍然可用
|
||||
$account = Db::name('cursor_accounts')
|
||||
->where('id', $cachedAccount['id'])
|
||||
->find();
|
||||
|
||||
if ($account) {
|
||||
// 更新缓存时间
|
||||
\think\facade\Cache::set($cacheKey, $account, 600); // 10分钟缓存
|
||||
|
||||
// 返回账号信息
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'email' => $account['email'],
|
||||
'password' => $account['password'],
|
||||
'access_token' => $account['access_token'],
|
||||
'refresh_token' => $account['refresh_token'],
|
||||
'expire_time' => date('Y-m-d H:i:s', $expireTime),
|
||||
'days_left' => ceil(($expireTime - time()) / 86400)
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// 记录冷却期
|
||||
$cooldownExpires = time() + 1800; // 30分钟冷却期
|
||||
\think\facade\Cache::set($cooldownKey, $cooldownExpires, 1800);
|
||||
|
||||
// 开启事务
|
||||
Db::startTrans();
|
||||
try {
|
||||
// 获取一个未使用的账号
|
||||
$account = Db::name('cursor_accounts')
|
||||
->where('is_used', 0)
|
||||
->lock(true)
|
||||
->find();
|
||||
|
||||
if (empty($account)) {
|
||||
Db::rollback();
|
||||
return json([
|
||||
'code' => 404,
|
||||
'msg' => '没有可用的账号'
|
||||
]);
|
||||
}
|
||||
|
||||
// 如果有旧账号,将其标记为未使用
|
||||
if ($cachedAccount) {
|
||||
Db::name('cursor_accounts')
|
||||
->where('id', $cachedAccount['id'])
|
||||
->update([
|
||||
'is_used' => 0,
|
||||
'used_at' => null,
|
||||
'used_by' => ''
|
||||
]);
|
||||
}
|
||||
|
||||
// 更新新账号状态
|
||||
Db::name('cursor_accounts')
|
||||
->where('id', $account['id'])
|
||||
->update([
|
||||
'is_used' => 1,
|
||||
'used_at' => date('Y-m-d H:i:s'),
|
||||
'used_by' => $machineId
|
||||
]);
|
||||
|
||||
Db::commit();
|
||||
|
||||
// 缓存新账号信息
|
||||
\think\facade\Cache::set($cacheKey, $account, 600); // 10分钟缓存
|
||||
|
||||
// 返回账号信息
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'email' => $account['email'],
|
||||
'password' => $account['password'],
|
||||
'access_token' => $account['access_token'],
|
||||
'refresh_token' => $account['refresh_token'],
|
||||
'expire_time' => date('Y-m-d H:i:s', $expireTime),
|
||||
'days_left' => ceil(($expireTime - time()) / 86400)
|
||||
]
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return json([
|
||||
'code' => 500,
|
||||
'msg' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台强制重置设备账号
|
||||
* @auth true
|
||||
*/
|
||||
public function resetDeviceAccount()
|
||||
{
|
||||
try {
|
||||
$data = $this->_vali([
|
||||
'machine_id.require' => '设备ID不能为空'
|
||||
]);
|
||||
|
||||
$machineId = $data['machine_id'];
|
||||
|
||||
// 清除设备的账号缓存
|
||||
$cacheKey = "device_account_{$machineId}";
|
||||
\think\facade\Cache::delete($cacheKey);
|
||||
|
||||
// 清除冷却期
|
||||
$cooldownKey = "device_cooldown_{$machineId}";
|
||||
\think\facade\Cache::delete($cooldownKey);
|
||||
|
||||
// 将该设备使用的账号标记为未使用
|
||||
Db::name('cursor_accounts')
|
||||
->where('used_by', $machineId)
|
||||
->update([
|
||||
'is_used' => 0,
|
||||
'used_at' => null,
|
||||
'used_by' => ''
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '重置成功'
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return json([
|
||||
'code' => 500,
|
||||
'msg' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
225
app/admin/controller/api/Agent.php
Normal file
225
app/admin/controller/api/Agent.php
Normal file
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\admin\controller\api;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\facade\Db;
|
||||
use think\facade\Cache;
|
||||
|
||||
/**
|
||||
* 代理商接口
|
||||
*/
|
||||
class Agent extends Controller
|
||||
{
|
||||
/**
|
||||
* 代理商登录
|
||||
*/
|
||||
public function login()
|
||||
{
|
||||
try {
|
||||
$data = $this->_vali([
|
||||
'username.require' => '用户名不能为空',
|
||||
'password.require' => '密码不能为空'
|
||||
]);
|
||||
|
||||
// 查询代理商
|
||||
$agent = Db::name('cursor_agents')
|
||||
->where('username', $data['username'])
|
||||
->find();
|
||||
|
||||
if (empty($agent)) {
|
||||
return json(['code' => 400, 'msg' => '用户名或密码错误']);
|
||||
}
|
||||
|
||||
// 验证密码
|
||||
if (!password_verify($data['password'], $agent['password'])) {
|
||||
return json(['code' => 400, 'msg' => '用户名或密码错误']);
|
||||
}
|
||||
|
||||
// 检查状态
|
||||
if ($agent['status'] != 1) {
|
||||
return json(['code' => 400, 'msg' => '账号已被禁用']);
|
||||
}
|
||||
|
||||
// 生成token
|
||||
$token = md5($agent['id'] . time() . rand(1000, 9999));
|
||||
|
||||
// 存储token,有效期7天
|
||||
Cache::set('agent_token_' . $token, $agent['id'], 7 * 24 * 3600);
|
||||
|
||||
// 更新登录信息
|
||||
Db::name('cursor_agents')
|
||||
->where('id', $agent['id'])
|
||||
->update([
|
||||
'last_login_time' => date('Y-m-d H:i:s'),
|
||||
'last_login_ip' => $this->request->ip(),
|
||||
'updated_at' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
|
||||
// 返回登录信息
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '登录成功',
|
||||
'data' => [
|
||||
'token' => $token,
|
||||
'agent' => [
|
||||
'id' => $agent['id'],
|
||||
'username' => $agent['username'],
|
||||
'nickname' => $agent['nickname'],
|
||||
'level' => $agent['level'],
|
||||
'balance' => $agent['balance'],
|
||||
'commission_rate' => $agent['commission_rate']
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return json(['code' => 500, 'msg' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证token
|
||||
*/
|
||||
protected function checkToken()
|
||||
{
|
||||
$token = $this->request->header('token');
|
||||
if (empty($token)) {
|
||||
return json(['code' => 401, 'msg' => '请先登录']);
|
||||
}
|
||||
|
||||
$agentId = Cache::get('agent_token_' . $token);
|
||||
if (empty($agentId)) {
|
||||
return json(['code' => 401, 'msg' => '登录已过期,请重新登录']);
|
||||
}
|
||||
|
||||
return $agentId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取代理商信息
|
||||
*/
|
||||
public function info()
|
||||
{
|
||||
try {
|
||||
$agentId = $this->checkToken();
|
||||
if (!is_numeric($agentId)) {
|
||||
return $agentId; // 返回错误信息
|
||||
}
|
||||
|
||||
$agent = Db::name('cursor_agents')
|
||||
->where('id', $agentId)
|
||||
->find();
|
||||
|
||||
if (empty($agent)) {
|
||||
return json(['code' => 400, 'msg' => '代理商不存在']);
|
||||
}
|
||||
|
||||
// 获取激活码统计
|
||||
$codeStats = Db::name('cursor_agent_codes')
|
||||
->where('agent_id', $agentId)
|
||||
->field([
|
||||
'COUNT(*) as total_codes',
|
||||
'SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as settled_codes',
|
||||
'SUM(commission) as total_commission',
|
||||
'SUM(CASE WHEN status = 1 THEN commission ELSE 0 END) as settled_commission'
|
||||
])
|
||||
->find();
|
||||
|
||||
// 获取未使用的激活码
|
||||
$unusedCodes = Db::name('cursor_agent_codes')
|
||||
->alias('ac')
|
||||
->join('cursor_activation_codes c', 'ac.code_id = c.id')
|
||||
->where('ac.agent_id', $agentId)
|
||||
->where('c.is_used', 0)
|
||||
->field('c.code, c.days, ac.price')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'agent' => [
|
||||
'id' => $agent['id'],
|
||||
'username' => $agent['username'],
|
||||
'nickname' => $agent['nickname'],
|
||||
'level' => $agent['level'],
|
||||
'balance' => $agent['balance'],
|
||||
'total_income' => $agent['total_income'],
|
||||
'commission_rate' => $agent['commission_rate'],
|
||||
'last_login_time' => $agent['last_login_time']
|
||||
],
|
||||
'stats' => [
|
||||
'total_codes' => $codeStats['total_codes'] ?? 0,
|
||||
'settled_codes' => $codeStats['settled_codes'] ?? 0,
|
||||
'total_commission' => $codeStats['total_commission'] ?? 0,
|
||||
'settled_commission' => $codeStats['settled_commission'] ?? 0
|
||||
],
|
||||
'unused_codes' => $unusedCodes
|
||||
]
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return json(['code' => 500, 'msg' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取代理商的激活码列表
|
||||
*/
|
||||
public function codes()
|
||||
{
|
||||
try {
|
||||
$agentId = $this->checkToken();
|
||||
if (!is_numeric($agentId)) {
|
||||
return $agentId;
|
||||
}
|
||||
|
||||
$page = input('page/d', 1);
|
||||
$limit = input('limit/d', 20);
|
||||
$status = input('status');
|
||||
|
||||
$query = Db::name('cursor_agent_codes')
|
||||
->alias('ac')
|
||||
->join('cursor_activation_codes c', 'ac.code_id = c.id')
|
||||
->where('ac.agent_id', $agentId);
|
||||
|
||||
if (isset($status)) {
|
||||
$query = $query->where('c.is_used', intval($status));
|
||||
}
|
||||
|
||||
$total = $query->count();
|
||||
$list = $query->field([
|
||||
'c.code',
|
||||
'c.days',
|
||||
'c.is_used',
|
||||
'c.used_at',
|
||||
'c.used_by',
|
||||
'ac.price',
|
||||
'ac.commission',
|
||||
'ac.status as settle_status',
|
||||
'ac.created_at'
|
||||
])
|
||||
->page($page, $limit)
|
||||
->order('ac.created_at desc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'list' => $list,
|
||||
'total' => $total,
|
||||
'page' => $page,
|
||||
'limit' => $limit
|
||||
]
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return json(['code' => 500, 'msg' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,16 @@ class Mail extends Controller
|
||||
'BROWSER_USER_AGENT' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.92 Safari/537.36',
|
||||
'MAIL_SERVER' => 'https://tempmail.plus'
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => '备用配置2',
|
||||
'config' => [
|
||||
'DOMAIN' => 'wuen.site',
|
||||
'TEMP_MAIL' => 'actoke',
|
||||
'TEMP_MAIL_EXT' => '@mailto.plus',
|
||||
'BROWSER_USER_AGENT' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.92 Safari/537.36',
|
||||
'MAIL_SERVER' => 'https://tempmail.plus'
|
||||
]
|
||||
]
|
||||
|
||||
];
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace app\admin\controller\api;
|
||||
|
||||
use app\manager\model\Member as MemberModel;
|
||||
use think\admin\Controller;
|
||||
use think\facade\Db;
|
||||
|
||||
|
||||
/**
|
||||
@@ -82,4 +83,208 @@ class Member extends Controller
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活码验证并激活
|
||||
* @return void
|
||||
*/
|
||||
public function activate()
|
||||
{
|
||||
try {
|
||||
// 验证激活码
|
||||
$code = input('code');
|
||||
if (empty($code)) {
|
||||
return json(['code' => 400, 'msg' => '激活码不能为空']);
|
||||
}
|
||||
|
||||
// 获取设备信息
|
||||
$machineId = input('machine_id', '');
|
||||
if (empty($machineId)) {
|
||||
return json(['code' => 400, 'msg' => '设备ID不能为空']);
|
||||
}
|
||||
|
||||
// 收集设备详细信息
|
||||
$deviceInfo = [
|
||||
'machine_id' => $machineId,
|
||||
'os' => input('os', ''), // 操作系统信息
|
||||
'device_name' => input('device_name', ''), // 设备名称
|
||||
'ip' => $this->request->ip(), // IP地址
|
||||
'user_agent' => $this->request->header('user-agent', ''), // UA信息
|
||||
'location' => input('location', '') // 地理位置(如果有)
|
||||
];
|
||||
|
||||
// 获取激活码信息
|
||||
$activation = Db::name('cursor_activation_codes')
|
||||
->where('code', $code)
|
||||
->where('is_used', 0)
|
||||
->find();
|
||||
|
||||
if (empty($activation)) {
|
||||
return json(['code' => 400, 'msg' => '激活码无效或已被使用']);
|
||||
}
|
||||
|
||||
// 开启事务
|
||||
Db::startTrans();
|
||||
try {
|
||||
// 标记新激活码为已使用
|
||||
Db::name('cursor_activation_codes')
|
||||
->where('id', $activation['id'])
|
||||
->update([
|
||||
'is_used' => 1,
|
||||
'used_at' => date('Y-m-d H:i:s'),
|
||||
'used_by' => $machineId,
|
||||
'device_info' => json_encode($deviceInfo)
|
||||
]);
|
||||
|
||||
Db::commit();
|
||||
|
||||
// 获取该设备所有的激活记录
|
||||
$activations = Db::name('cursor_activation_codes')
|
||||
->where('used_by', '=', $machineId)
|
||||
->where('is_used', '=', 1)
|
||||
->order('used_at desc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 计算总天数
|
||||
$totalDays = array_sum(array_column($activations, 'days'));
|
||||
|
||||
// 计算最终到期时间
|
||||
$now = time();
|
||||
$firstActivationTime = strtotime($activations[count($activations)-1]['used_at']); // 第一次激活时间
|
||||
$expireTime = $firstActivationTime + ($totalDays * 24 * 3600); // 总天数转换为秒数
|
||||
$daysLeft = ceil(($expireTime - $now) / 86400);
|
||||
|
||||
// 返回成功信息
|
||||
$result = [
|
||||
'code' => 200,
|
||||
'msg' => '激活成功',
|
||||
'data' => [
|
||||
'expire_time' => date('Y-m-d H:i:s', $expireTime),
|
||||
'total_days' => $totalDays,
|
||||
'added_days' => $activation['days'],
|
||||
'days_left' => $daysLeft,
|
||||
'machine_id' => $machineId,
|
||||
'device_info' => $deviceInfo,
|
||||
'activation_time' => date('Y-m-d H:i:s'),
|
||||
'activation_records' => array_map(function($record) {
|
||||
return [
|
||||
'code' => $record['code'],
|
||||
'days' => $record['days'],
|
||||
'activation_time' => $record['used_at'],
|
||||
'device_info' => json_decode($record['device_info'], true)
|
||||
];
|
||||
}, $activations)
|
||||
]
|
||||
];
|
||||
|
||||
return json($result);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return json([
|
||||
'code' => 500,
|
||||
'msg' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员状态
|
||||
*/
|
||||
public function status()
|
||||
{
|
||||
try {
|
||||
// 获取设备ID
|
||||
$machineId = input('machine_id', '');
|
||||
if (empty($machineId)) {
|
||||
return json(['code' => 400, 'msg' => '设备ID不能为空']);
|
||||
}
|
||||
|
||||
// 获取该设备所有的激活记录
|
||||
$activations = Db::name('cursor_activation_codes')
|
||||
->where('used_by', '=', $machineId)
|
||||
->where('is_used', '=', 1)
|
||||
->order('used_at desc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
if (empty($activations)) {
|
||||
return json([
|
||||
'code' => 401,
|
||||
'msg' => '未激活',
|
||||
'data' => [
|
||||
'status' => 'inactive',
|
||||
'expire_time' => '',
|
||||
'total_days' => 0,
|
||||
'days_left' => 0,
|
||||
'activation_records' => []
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
// 计算总天数
|
||||
$totalDays = array_sum(array_column($activations, 'days'));
|
||||
|
||||
// 计算最终到期时间
|
||||
$now = time();
|
||||
$firstActivationTime = strtotime($activations[count($activations)-1]['used_at']); // 第一次激活时间
|
||||
$expireTime = $firstActivationTime + ($totalDays * 24 * 3600); // 总天数转换为秒数
|
||||
$daysLeft = ceil(($expireTime - $now) / 86400);
|
||||
|
||||
// 判断是否过期
|
||||
if ($daysLeft <= 0) {
|
||||
return json([
|
||||
'code' => 401,
|
||||
'msg' => '已过期',
|
||||
'data' => [
|
||||
'status' => 'expired',
|
||||
'expire_time' => date('Y-m-d H:i:s', $expireTime),
|
||||
'total_days' => $totalDays,
|
||||
'days_left' => 0,
|
||||
'machine_id' => $machineId,
|
||||
'activation_records' => array_map(function($record) {
|
||||
return [
|
||||
'code' => $record['code'],
|
||||
'days' => $record['days'],
|
||||
'activation_time' => $record['used_at'],
|
||||
'device_info' => json_decode($record['device_info'], true)
|
||||
];
|
||||
}, $activations)
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
// 返回正常状态
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '正常',
|
||||
'data' => [
|
||||
'status' => 'active',
|
||||
'expire_time' => date('Y-m-d H:i:s', $expireTime),
|
||||
'total_days' => $totalDays,
|
||||
'days_left' => $daysLeft,
|
||||
'machine_id' => $machineId,
|
||||
'activation_records' => array_map(function($record) {
|
||||
return [
|
||||
'code' => $record['code'],
|
||||
'days' => $record['days'],
|
||||
'activation_time' => $record['used_at'],
|
||||
'device_info' => json_decode($record['device_info'], true)
|
||||
];
|
||||
}, $activations)
|
||||
]
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return json([
|
||||
'code' => 500,
|
||||
'msg' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
108
app/agent/controller/Index.php
Normal file
108
app/agent/controller/Index.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace app\agent\controller;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* 代理商后台
|
||||
*/
|
||||
class Index extends Controller
|
||||
{
|
||||
/**
|
||||
* 生成激活码
|
||||
*/
|
||||
public function generate()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$count = intval(input('count', 1));
|
||||
$count = max(1, min($count, 100)); // 限制一次最多生成100个
|
||||
|
||||
// 获取当前代理商信息
|
||||
$agentId = session('agent.id');
|
||||
$agent = Db::name('cursor_agents')->where('id', $agentId)->find();
|
||||
if (empty($agent)) {
|
||||
$this->error('代理商信息不存在!');
|
||||
}
|
||||
|
||||
// 开启事务
|
||||
Db::startTrans();
|
||||
try {
|
||||
$codes = [];
|
||||
$agentCodes = [];
|
||||
$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' => 30, // 固定30天
|
||||
'created_at' => $now,
|
||||
'is_used' => 0
|
||||
];
|
||||
}
|
||||
|
||||
// 批量插入激活码
|
||||
$codeIds = Db::name('cursor_activation_codes')->insertAll($codes);
|
||||
|
||||
// 计算佣金
|
||||
$price = 100; // 固定价格100元
|
||||
$commission = $price * ($agent['commission_rate'] / 100);
|
||||
|
||||
// 如果是二级代理,计算上级佣金
|
||||
$parentCommission = 0;
|
||||
if ($agent['level'] == 2 && $agent['parent_id'] > 0) {
|
||||
$parent = Db::name('cursor_agents')->where('id', $agent['parent_id'])->find();
|
||||
if ($parent) {
|
||||
$parentCommission = $price * ($parent['commission_rate'] / 100);
|
||||
}
|
||||
}
|
||||
|
||||
// 准备代理商激活码数据
|
||||
foreach ($codes as $index => $code) {
|
||||
$agentCodes[] = [
|
||||
'agent_id' => $agentId,
|
||||
'code_id' => $codeIds[$index],
|
||||
'price' => $price,
|
||||
'commission' => $commission,
|
||||
'parent_commission' => $parentCommission,
|
||||
'status' => 0,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now
|
||||
];
|
||||
}
|
||||
|
||||
// 批量插入代理商激活码关联
|
||||
Db::name('cursor_agent_codes')->insertAll($agentCodes);
|
||||
|
||||
Db::commit();
|
||||
$this->success('生成成功!');
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error('生成失败:' . $e->getMessage());
|
||||
}
|
||||
} else {
|
||||
$this->fetch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 我的激活码列表
|
||||
*/
|
||||
public function codes()
|
||||
{
|
||||
$this->title = '我的激活码';
|
||||
$agentId = session('agent.id');
|
||||
|
||||
$query = $this->_query('cursor_agent_codes')->alias('ac')
|
||||
->join('cursor_activation_codes c', 'c.id = ac.code_id')
|
||||
->where('ac.agent_id', $agentId)
|
||||
->field('ac.*, c.code, c.days, c.is_used, c.used_at, c.used_by');
|
||||
|
||||
// 数据列表处理
|
||||
$query->equal('c.is_used')->equal('ac.status');
|
||||
// 列表排序并显示
|
||||
$query->order('ac.id desc')->page();
|
||||
}
|
||||
}
|
||||
83
app/agent/view/index/codes.html
Normal file
83
app/agent/view/index/codes.html
Normal file
@@ -0,0 +1,83 @@
|
||||
{extend name="../../admin/view/main"}
|
||||
|
||||
{block name="button"}
|
||||
<button class='layui-btn layui-btn-sm layui-btn-primary' data-modal='{:url("generate")}'>生成激活码</button>
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<div class="think-box-shadow">
|
||||
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">使用状态</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name='is_used' lay-search class='layui-select'>
|
||||
<option value=''>-- 全部 --</option>
|
||||
<option value='0' {if isset($get.is_used) and $get.is_used=='0'}selected{/if}>未使用</option>
|
||||
<option value='1' {if isset($get.is_used) and $get.is_used=='1'}selected{/if}>已使用</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">结算状态</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name='status' lay-search class='layui-select'>
|
||||
<option value=''>-- 全部 --</option>
|
||||
<option value='0' {if isset($get.status) and $get.status=='0'}selected{/if}>未结算</option>
|
||||
<option value='1' {if isset($get.status) and $get.status=='1'}selected{/if}>已结算</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<button class="layui-btn layui-btn-primary"><i class="layui-icon"></i> 搜 索</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table class="layui-table margin-top-10" lay-skin="line">
|
||||
{notempty name='list'}
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='text-left'>激活码</th>
|
||||
<th class='text-left'>有效天数</th>
|
||||
<th class='text-left'>销售价格</th>
|
||||
<th class='text-left'>佣金</th>
|
||||
<th class='text-left'>使用状态</th>
|
||||
<th class='text-left'>使用时间</th>
|
||||
<th class='text-left'>使用者</th>
|
||||
<th class='text-left'>结算状态</th>
|
||||
<th class='text-left'>生成时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{/notempty}
|
||||
<tbody>
|
||||
{foreach $list as $key=>$vo}
|
||||
<tr>
|
||||
<td class='text-left'>{$vo.code}</td>
|
||||
<td class='text-left'>{$vo.days} 天</td>
|
||||
<td class='text-left'>{$vo.price}</td>
|
||||
<td class='text-left'>{$vo.commission}</td>
|
||||
<td class='text-left'>
|
||||
{if $vo.is_used eq 1}
|
||||
<span class="color-red">已使用</span>
|
||||
{else}
|
||||
<span class="color-green">未使用</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>{$vo.used_at|format_datetime|default='--'}</td>
|
||||
<td class='text-left'>{$vo.used_by|default='--'}</td>
|
||||
<td class='text-left'>
|
||||
{if $vo.status eq 1}
|
||||
<span class="color-blue">已结算</span>
|
||||
{else}
|
||||
<span class="color-red">未结算</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>{$vo.created_at|format_datetime}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
{empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
|
||||
</div>
|
||||
{/block}
|
||||
20
app/agent/view/index/generate.html
Normal file
20
app/agent/view/index/generate.html
Normal file
@@ -0,0 +1,20 @@
|
||||
{extend name="../../admin/view/main"}
|
||||
|
||||
{block name="content"}
|
||||
<form class="layui-form layui-card" action="{:request()->url()}" data-auto="true" method="post">
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">生成数量</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="count" value="1" required placeholder="请输入要生成的激活码数量" class="layui-input">
|
||||
<tip class="help-block">一次最多可生成100个激活码,每个激活码售价100元</tip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="layui-form-item text-center">
|
||||
<button class="layui-btn" type="submit">确定生成</button>
|
||||
<button class="layui-btn layui-btn-danger" type="button" data-close>取消</button>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
304
app/manager/controller/Account.php
Normal file
304
app/manager/controller/Account.php
Normal file
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
namespace app\manager\controller;
|
||||
|
||||
use think\admin\Controller;
|
||||
|
||||
/**
|
||||
* 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 > 100) {
|
||||
$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
|
||||
];
|
||||
}
|
||||
|
||||
// 批量插入激活码
|
||||
$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.*',
|
||||
'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}%");
|
||||
}
|
||||
});
|
||||
|
||||
// 列表排序并显示
|
||||
$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
|
||||
* @menu true
|
||||
*/
|
||||
public function devices()
|
||||
{
|
||||
$this->title = '设备账号管理';
|
||||
// 创建查询对象
|
||||
$query = $this->_query('cursor_accounts')
|
||||
->where('used_by', '<>', '')
|
||||
->where('is_used', 1);
|
||||
|
||||
// 数据列表处理
|
||||
$query->like('email,used_by');
|
||||
// 列表排序并显示
|
||||
$query->order('used_at desc')->page();
|
||||
|
||||
// 获取列表数据
|
||||
$list = $this->app->db->getList();
|
||||
|
||||
// 检查每个设备的缓存状态
|
||||
foreach ($list as &$item) {
|
||||
if (!empty($item['used_by'])) {
|
||||
// 检查账号缓存
|
||||
$cacheKey = "device_account_{$item['used_by']}";
|
||||
$cachedAccount = \think\facade\Cache::get($cacheKey);
|
||||
$item['has_cache'] = !empty($cachedAccount);
|
||||
|
||||
// 检查冷却期
|
||||
$cooldownKey = "device_cooldown_{$item['used_by']}";
|
||||
$cooldownTime = \think\facade\Cache::get($cooldownKey);
|
||||
$item['in_cooldown'] = $cooldownTime > time();
|
||||
$item['cooldown_time'] = $cooldownTime ? date('Y-m-d H:i:s', $cooldownTime) : '';
|
||||
|
||||
// 检查缓存账号是否与数据库一致
|
||||
$item['cache_match'] = false;
|
||||
if ($cachedAccount) {
|
||||
$item['cache_match'] = ($cachedAccount['id'] == $item['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->list = $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置设备账号
|
||||
* @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()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
275
app/manager/controller/Agent.php
Normal file
275
app/manager/controller/Agent.php
Normal file
@@ -0,0 +1,275 @@
|
||||
<?php
|
||||
|
||||
namespace app\manager\controller;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* 代理商管理
|
||||
* Class Agent
|
||||
* @package app\manager\controller
|
||||
*/
|
||||
class Agent extends Controller
|
||||
{
|
||||
/**
|
||||
* 代理商列表
|
||||
* @auth true
|
||||
* @menu true
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->title = '代理商管理';
|
||||
// 创建查询对象
|
||||
$query = $this->_query('cursor_agents');
|
||||
// 数据列表处理
|
||||
$query->equal('level,status')->like('username,nickname');
|
||||
// 列表排序并显示
|
||||
$query->order('id desc')->page();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加代理商
|
||||
* @auth true
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->_vali([
|
||||
'username.require' => '用户名不能为空',
|
||||
'password.require' => '密码不能为空',
|
||||
'nickname.default' => '',
|
||||
'level.require' => '代理级别不能为空',
|
||||
'parent_id.default' => 0,
|
||||
'commission_rate.require' => '佣金比例不能为空',
|
||||
'status.default' => 1,
|
||||
'remark.default' => ''
|
||||
]);
|
||||
|
||||
// 检查用户名是否存在
|
||||
if (Db::name('cursor_agents')->where('username', $data['username'])->find()) {
|
||||
$this->error('用户名已存在!');
|
||||
}
|
||||
|
||||
// 如果是二级代理,检查上级代理
|
||||
if ($data['level'] == 2) {
|
||||
if (empty($data['parent_id'])) {
|
||||
$this->error('请选择上级代理!');
|
||||
}
|
||||
$parent = Db::name('cursor_agents')->where('id', $data['parent_id'])->find();
|
||||
if (empty($parent) || $parent['level'] != 1) {
|
||||
$this->error('上级代理不存在或不是一级代理!');
|
||||
}
|
||||
}
|
||||
|
||||
// 处理密码
|
||||
$data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
|
||||
$data['created_at'] = $data['updated_at'] = date('Y-m-d H:i:s');
|
||||
|
||||
if (Db::name('cursor_agents')->insert($data) !== false) {
|
||||
$this->success('添加成功!');
|
||||
} else {
|
||||
$this->error('添加失败!');
|
||||
}
|
||||
} else {
|
||||
// 获取一级代理列表(用于选择上级)
|
||||
$this->agents = Db::name('cursor_agents')
|
||||
->where('level', 1)
|
||||
->where('status', 1)
|
||||
->select();
|
||||
$this->fetch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑代理商
|
||||
* @auth true
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$this->_applyFormToken();
|
||||
$this->_form('cursor_agents', 'form');
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改代理商状态
|
||||
* @auth true
|
||||
*/
|
||||
public function state()
|
||||
{
|
||||
$this->_applyFormToken();
|
||||
$this->_save('cursor_agents', ['status' => input('status')]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除代理商
|
||||
* @auth true
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
$this->_applyFormToken();
|
||||
$this->_delete('cursor_agents');
|
||||
}
|
||||
|
||||
/**
|
||||
* 分配激活码
|
||||
* @auth true
|
||||
*/
|
||||
public function assignCodes()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->_vali([
|
||||
'agent_id.require' => '代理商不能为空',
|
||||
'code_ids.require' => '请选择要分配的激活码',
|
||||
'price.require' => '请设置销售价格'
|
||||
]);
|
||||
|
||||
// 开启事务
|
||||
Db::startTrans();
|
||||
try {
|
||||
$agent = Db::name('cursor_agents')->where('id', $data['agent_id'])->find();
|
||||
if (empty($agent)) {
|
||||
$this->error('代理商不存在!');
|
||||
}
|
||||
|
||||
$codeIds = explode(',', $data['code_ids']);
|
||||
$insertData = [];
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
foreach ($codeIds as $codeId) {
|
||||
// 检查激活码是否已分配
|
||||
$exists = Db::name('cursor_agent_codes')->where('code_id', $codeId)->find();
|
||||
if ($exists) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 计算佣金
|
||||
$commission = $data['price'] * ($agent['commission_rate'] / 100);
|
||||
|
||||
// 如果是二级代理,计算上级佣金
|
||||
$parentCommission = 0;
|
||||
if ($agent['level'] == 2 && $agent['parent_id'] > 0) {
|
||||
$parent = Db::name('cursor_agents')->where('id', $agent['parent_id'])->find();
|
||||
if ($parent) {
|
||||
$parentCommission = $data['price'] * ($parent['commission_rate'] / 100);
|
||||
}
|
||||
}
|
||||
|
||||
$insertData[] = [
|
||||
'agent_id' => $data['agent_id'],
|
||||
'code_id' => $codeId,
|
||||
'price' => $data['price'],
|
||||
'commission' => $commission,
|
||||
'parent_commission' => $parentCommission,
|
||||
'status' => 0,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now
|
||||
];
|
||||
}
|
||||
|
||||
// 批量插入数据
|
||||
if (!empty($insertData)) {
|
||||
Db::name('cursor_agent_codes')->insertAll($insertData);
|
||||
}
|
||||
|
||||
Db::commit();
|
||||
$this->success('分配成功!');
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error('分配失败:' . $e->getMessage());
|
||||
}
|
||||
} else {
|
||||
// 获取未分配的激活码
|
||||
$this->codes = Db::name('cursor_activation_codes')
|
||||
->where('is_used', 0)
|
||||
->whereNotExists(function($query) {
|
||||
$query->table('cursor_agent_codes')->whereRaw('cursor_agent_codes.code_id = cursor_activation_codes.id');
|
||||
})
|
||||
->select();
|
||||
|
||||
// 获取代理商列表
|
||||
$this->agents = Db::name('cursor_agents')
|
||||
->where('status', 1)
|
||||
->select();
|
||||
|
||||
$this->fetch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看代理商激活码
|
||||
* @auth true
|
||||
*/
|
||||
public function codes()
|
||||
{
|
||||
$this->title = '代理商激活码';
|
||||
$query = $this->_query('cursor_agent_codes')->alias('ac')
|
||||
->join('cursor_agents a', 'a.id = ac.agent_id')
|
||||
->join('cursor_activation_codes c', 'c.id = ac.code_id')
|
||||
->field('ac.*, a.username as agent_name, c.code, c.days, c.is_used, c.used_at, c.used_by');
|
||||
|
||||
// 数据列表处理
|
||||
$query->equal('ac.agent_id')->equal('c.is_used')->equal('ac.status');
|
||||
// 列表排序并显示
|
||||
$query->order('ac.id desc')->page();
|
||||
}
|
||||
|
||||
/**
|
||||
* 结算佣金
|
||||
* @auth true
|
||||
*/
|
||||
public function settle()
|
||||
{
|
||||
$id = input('id');
|
||||
if (empty($id)) {
|
||||
$this->error('参数错误!');
|
||||
}
|
||||
|
||||
$agentCode = Db::name('cursor_agent_codes')->where('id', $id)->find();
|
||||
if (empty($agentCode)) {
|
||||
$this->error('记录不存在!');
|
||||
}
|
||||
|
||||
if ($agentCode['status'] == 1) {
|
||||
$this->error('该记录已结算!');
|
||||
}
|
||||
|
||||
// 开启事务
|
||||
Db::startTrans();
|
||||
try {
|
||||
// 更新代理商余额
|
||||
Db::name('cursor_agents')
|
||||
->where('id', $agentCode['agent_id'])
|
||||
->inc('balance', $agentCode['commission'])
|
||||
->inc('total_income', $agentCode['commission'])
|
||||
->update();
|
||||
|
||||
// 如果有上级佣金,更新上级代理商余额
|
||||
if ($agentCode['parent_commission'] > 0) {
|
||||
$agent = Db::name('cursor_agents')->where('id', $agentCode['agent_id'])->find();
|
||||
if ($agent && $agent['parent_id'] > 0) {
|
||||
Db::name('cursor_agents')
|
||||
->where('id', $agent['parent_id'])
|
||||
->inc('balance', $agentCode['parent_commission'])
|
||||
->inc('total_income', $agentCode['parent_commission'])
|
||||
->update();
|
||||
}
|
||||
}
|
||||
|
||||
// 更新结算状态
|
||||
Db::name('cursor_agent_codes')
|
||||
->where('id', $id)
|
||||
->update([
|
||||
'status' => 1,
|
||||
'settle_time' => date('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
|
||||
Db::commit();
|
||||
$this->success('结算成功!');
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error('结算失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
39
app/manager/model/ActivationCode.php
Normal file
39
app/manager/model/ActivationCode.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace app\manager\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class ActivationCode extends Model
|
||||
{
|
||||
protected $name = 'cursor_activation_codes';
|
||||
|
||||
// 自动写入时间戳
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected $createTime = 'created_at';
|
||||
protected $updateTime = false;
|
||||
|
||||
// 设置字段类型
|
||||
protected $type = [
|
||||
'used_at' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
];
|
||||
|
||||
// 获取代理商分配信息
|
||||
public function agentCode()
|
||||
{
|
||||
return $this->hasOne('app\manager\model\AgentCode', 'code_id');
|
||||
}
|
||||
|
||||
// 检查是否已分配给代理商
|
||||
public function isAssigned()
|
||||
{
|
||||
return (bool)$this->agentCode;
|
||||
}
|
||||
|
||||
// 检查是否可用
|
||||
public function isAvailable()
|
||||
{
|
||||
return !$this->is_used && !$this->isAssigned();
|
||||
}
|
||||
}
|
||||
51
app/manager/model/Agent.php
Normal file
51
app/manager/model/Agent.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace app\manager\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class Agent extends Model
|
||||
{
|
||||
protected $name = 'cursor_agents';
|
||||
|
||||
// 自动写入时间戳
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected $createTime = 'created_at';
|
||||
protected $updateTime = 'updated_at';
|
||||
|
||||
// 设置字段类型
|
||||
protected $type = [
|
||||
'balance' => 'float',
|
||||
'total_income' => 'float',
|
||||
'commission_rate' => 'float',
|
||||
'last_login_time' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
// 获取父级代理
|
||||
public function parent()
|
||||
{
|
||||
return $this->belongsTo(Agent::class, 'parent_id');
|
||||
}
|
||||
|
||||
// 获取子级代理
|
||||
public function children()
|
||||
{
|
||||
return $this->hasMany(Agent::class, 'parent_id');
|
||||
}
|
||||
|
||||
// 获取代理的激活码
|
||||
public function codes()
|
||||
{
|
||||
return $this->hasMany('app\manager\model\AgentCode', 'agent_id');
|
||||
}
|
||||
|
||||
// 更新余额
|
||||
public function updateBalance($amount)
|
||||
{
|
||||
$this->balance += $amount;
|
||||
$this->total_income += max(0, $amount);
|
||||
return $this->save();
|
||||
}
|
||||
}
|
||||
68
app/manager/model/AgentCode.php
Normal file
68
app/manager/model/AgentCode.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace app\manager\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class AgentCode extends Model
|
||||
{
|
||||
protected $name = 'cursor_agent_codes';
|
||||
|
||||
// 自动写入时间戳
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected $createTime = 'created_at';
|
||||
protected $updateTime = 'updated_at';
|
||||
|
||||
// 设置字段类型
|
||||
protected $type = [
|
||||
'price' => 'float',
|
||||
'commission' => 'float',
|
||||
'parent_commission' => 'float',
|
||||
'settle_time' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
// 获取所属代理商
|
||||
public function agent()
|
||||
{
|
||||
return $this->belongsTo('app\manager\model\Agent', 'agent_id');
|
||||
}
|
||||
|
||||
// 获取激活码信息
|
||||
public function code()
|
||||
{
|
||||
return $this->belongsTo('app\manager\model\ActivationCode', 'code_id');
|
||||
}
|
||||
|
||||
// 结算佣金
|
||||
public function settle()
|
||||
{
|
||||
if ($this->status == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 开启事务
|
||||
$this->startTrans();
|
||||
try {
|
||||
// 更新代理商余额
|
||||
$this->agent->updateBalance($this->commission);
|
||||
|
||||
// 如果有上级佣金,更新上级代理商余额
|
||||
if ($this->parent_commission > 0 && $this->agent->parent) {
|
||||
$this->agent->parent->updateBalance($this->parent_commission);
|
||||
}
|
||||
|
||||
// 更新结算状态
|
||||
$this->status = 1;
|
||||
$this->settle_time = date('Y-m-d H:i:s');
|
||||
$this->save();
|
||||
|
||||
$this->commit();
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
$this->rollback();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
123
app/manager/view/account/codes.html
Normal file
123
app/manager/view/account/codes.html
Normal file
@@ -0,0 +1,123 @@
|
||||
{extend name="../../admin/view/main"}
|
||||
|
||||
{block name="button"}
|
||||
<button class='layui-btn layui-btn-sm layui-btn-primary' data-modal='{:url("generate")}'>生成激活码</button>
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<div class="think-box-shadow">
|
||||
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">激活码</label>
|
||||
<div class="layui-input-inline">
|
||||
<input name="code" value="{$get.code|default=''}" placeholder="请输入激活码" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">代理商</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name='agent_id' lay-search class='layui-select'>
|
||||
<option value=''>-- 全部 --</option>
|
||||
{foreach $agents as $agent}
|
||||
<option value='{$agent.id}' {if isset($get.agent_id) and $get.agent_id==$agent.id}selected{/if}>
|
||||
{$agent.username} ({if $agent.level==1}一级代理{else}二级代理{/if})
|
||||
</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">使用状态</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name='is_used' lay-search class='layui-select'>
|
||||
<option value=''>-- 全部 --</option>
|
||||
<option value='0' {if isset($get.is_used) and $get.is_used=='0'}selected{/if}>未使用</option>
|
||||
<option value='1' {if isset($get.is_used) and $get.is_used=='1'}selected{/if}>已使用</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<button class="layui-btn layui-btn-primary"><i class="layui-icon"></i> 搜 索</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table class="layui-table margin-top-10" lay-skin="line">
|
||||
{notempty name='list'}
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='list-table-check-td think-checkbox'>
|
||||
<label><input data-auto-none data-check-target='.list-check-box' type='checkbox'></label>
|
||||
</th>
|
||||
<th class='text-left'>激活码</th>
|
||||
<th class='text-left'>有效天数</th>
|
||||
<th class='text-left'>代理商</th>
|
||||
<th class='text-left'>代理级别</th>
|
||||
<th class='text-left'>销售价格</th>
|
||||
<th class='text-left'>佣金</th>
|
||||
<th class='text-left'>上级佣金</th>
|
||||
<th class='text-left'>结算状态</th>
|
||||
<th class='text-left'>使用状态</th>
|
||||
<th class='text-left'>使用时间</th>
|
||||
<th class='text-left'>使用者</th>
|
||||
<th class='text-left'>生成时间</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
{/notempty}
|
||||
<tbody>
|
||||
{foreach $list as $key=>$vo}
|
||||
<tr>
|
||||
<td class='list-table-check-td think-checkbox'>
|
||||
<label><input class="list-check-box" value='{$vo.id}' type='checkbox'></label>
|
||||
</td>
|
||||
<td class='text-left'>{$vo.code}</td>
|
||||
<td class='text-left'>{$vo.days} 天</td>
|
||||
<td class='text-left'>{$vo.agent_name|default='--'}</td>
|
||||
<td class='text-left'>
|
||||
{if $vo.agent_level eq 1}
|
||||
<span class="color-blue">一级代理</span>
|
||||
{elseif $vo.agent_level eq 2}
|
||||
<span class="color-green">二级代理</span>
|
||||
{else}
|
||||
--
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>{$vo.price|default='--'}</td>
|
||||
<td class='text-left'>{$vo.commission|default='--'}</td>
|
||||
<td class='text-left'>{$vo.parent_commission|default='--'}</td>
|
||||
<td class='text-left'>
|
||||
{if isset($vo.settle_status)}
|
||||
{if $vo.settle_status eq 1}
|
||||
<span class="color-blue">已结算</span>
|
||||
{else}
|
||||
<span class="color-red">未结算</span>
|
||||
{/if}
|
||||
{else}
|
||||
--
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>
|
||||
{if $vo.is_used eq 1}
|
||||
<span class="color-red">已使用</span>
|
||||
{else}
|
||||
<span class="color-green">未使用</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>{$vo.used_at|format_datetime|default='--'}</td>
|
||||
<td class='text-left'>{$vo.used_by|default='--'}</td>
|
||||
<td class='text-left'>{$vo.created_at|format_datetime}</td>
|
||||
<td class='text-left'>
|
||||
{if auth("removeCode")}
|
||||
<a class="layui-btn layui-btn-sm layui-btn-danger" data-confirm="确定要删除该激活码吗?" data-csrf="{:systoken('removeCode')}" data-action='{:url("removeCode")}' data-value="id#{$vo.id}">删 除</a>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
{empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
|
||||
</div>
|
||||
{/block}
|
||||
75
app/manager/view/account/devices.html
Normal file
75
app/manager/view/account/devices.html
Normal file
@@ -0,0 +1,75 @@
|
||||
{extend name="../../admin/view/main"}
|
||||
|
||||
{block name="content"}
|
||||
<div class="think-box-shadow">
|
||||
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">账号邮箱</label>
|
||||
<div class="layui-input-inline">
|
||||
<input name="email" value="{$get.email|default=''}" placeholder="请输入账号邮箱" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">设备ID</label>
|
||||
<div class="layui-input-inline">
|
||||
<input name="used_by" value="{$get.used_by|default=''}" placeholder="请输入设备ID" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<button class="layui-btn layui-btn-primary"><i class="layui-icon"></i> 搜 索</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table class="layui-table margin-top-10" lay-skin="line">
|
||||
{notempty name='list'}
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='text-left'>账号邮箱</th>
|
||||
<th class='text-left'>设备ID</th>
|
||||
<th class='text-left'>使用时间</th>
|
||||
<th class='text-left'>注册时间</th>
|
||||
<th class='text-left'>缓存状态</th>
|
||||
<th class='text-left'>冷却状态</th>
|
||||
<th class='text-left'>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{/notempty}
|
||||
<tbody>
|
||||
{foreach $list as $key=>$vo}
|
||||
<tr>
|
||||
<td class='text-left'>{$vo.email}</td>
|
||||
<td class='text-left'>{$vo.used_by}</td>
|
||||
<td class='text-left'>{$vo.used_at|format_datetime}</td>
|
||||
<td class='text-left'>{$vo.registration_time|format_datetime}</td>
|
||||
<td class='text-left'>
|
||||
{if $vo.has_cache}
|
||||
{if $vo.cache_match}
|
||||
<span class="color-green">正常</span>
|
||||
{else}
|
||||
<span class="color-red">异常(缓存不匹配)</span>
|
||||
{/if}
|
||||
{else}
|
||||
<span class="color-gray">无缓存</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>
|
||||
{if $vo.in_cooldown}
|
||||
<span class="color-red">冷却中 (至 {$vo.cooldown_time})</span>
|
||||
{else}
|
||||
<span class="color-green">可用</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>
|
||||
{if auth("resetDevice")}
|
||||
<a class="layui-btn layui-btn-sm layui-btn-warm" data-confirm="确定要重置该设备的账号吗?" data-csrf="{:systoken('resetDevice')}" data-action='{:url("resetDevice")}' data-value="machine_id#{$vo.used_by}">重置账号</a>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
{empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
|
||||
</div>
|
||||
{/block}
|
||||
57
app/manager/view/account/generate.html
Normal file
57
app/manager/view/account/generate.html
Normal file
@@ -0,0 +1,57 @@
|
||||
{extend name="../../admin/view/main"}
|
||||
|
||||
{block name="content"}
|
||||
<form class="layui-form layui-card" action="{:request()->url()}" data-auto="true" method="post">
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">生成数量</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="count" value="1" required placeholder="请输入要生成的激活码数量" class="layui-input">
|
||||
<tip class="help-block">一次最多可生成100个激活码</tip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">有效天数</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="days" value="30" required placeholder="请输入激活码有效天数" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">选择代理</label>
|
||||
<div class="layui-input-block">
|
||||
<select name='agent_id' class='layui-select' lay-filter='agent_id'>
|
||||
<option value=''>不分配给代理商</option>
|
||||
{foreach $agents as $agent}
|
||||
<option value='{$agent.id}'>{$agent.username} ({if $agent.level==1}一级代理{else}二级代理{/if}) - 佣金比例{$agent.commission_rate}%</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
<tip class="help-block">如果选择代理商,需要设置销售价格</tip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item" id="price_item" style="display:none;">
|
||||
<label class="layui-form-label">销售价格</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="price" value="0" placeholder="请输入销售价格" class="layui-input">
|
||||
<tip class="help-block">设置激活码的销售价格,用于计算佣金</tip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="layui-form-item text-center">
|
||||
<button class="layui-btn" type="submit">确定生成</button>
|
||||
<button class="layui-btn layui-btn-danger" type="button" data-close>取消</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
layui.form.on('select(agent_id)', function(data){
|
||||
if(data.value){
|
||||
$('#price_item').show();
|
||||
$('input[name=price]').attr('required', true);
|
||||
}else{
|
||||
$('#price_item').hide();
|
||||
$('input[name=price]').removeAttr('required');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{/block}
|
||||
86
app/manager/view/account/index.html
Normal file
86
app/manager/view/account/index.html
Normal file
@@ -0,0 +1,86 @@
|
||||
{extend name="../../admin/view/main"}
|
||||
|
||||
{block name="button"}
|
||||
<!--{if auth("add")}-->
|
||||
<button class='layui-btn layui-btn-sm layui-btn-primary' data-modal='{:url("add")}'>添加账号</button>
|
||||
<!--{/if}-->
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<div class="think-box-shadow">
|
||||
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">邮箱账号</label>
|
||||
<div class="layui-input-inline">
|
||||
<input name="email" value="{$get.email|default=''}" placeholder="请输入邮箱账号" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">使用状态</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name='is_used' lay-search class='layui-select' lay-filter='is_used'>
|
||||
<option value=''>-- 全部 --</option>
|
||||
<option value='0' {if isset($get.is_used) and $get.is_used=='0'}selected{/if}>未使用</option>
|
||||
<option value='1' {if isset($get.is_used) and $get.is_used=='1'}selected{/if}>已使用</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<button class="layui-btn layui-btn-primary"><i class="layui-icon"></i> 搜 索</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table id="AccountTable" class="layui-table margin-top-10" lay-skin="line">
|
||||
{notempty name='list'}
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='list-table-check-td think-checkbox'>
|
||||
<label><input data-auto-none data-check-target='.list-check-box' type='checkbox'></label>
|
||||
</th>
|
||||
<th class='text-left'>邮箱账号</th>
|
||||
<th class='text-left'>姓名</th>
|
||||
<th class='text-left'>机器ID</th>
|
||||
<th class='text-left'>注册时间</th>
|
||||
<th class='text-left'>使用状态</th>
|
||||
<th class='text-left'>使用时间</th>
|
||||
<th class='text-left'>使用者</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
{/notempty}
|
||||
<tbody>
|
||||
{foreach $list as $key=>$vo}
|
||||
<tr>
|
||||
<td class='list-table-check-td think-checkbox'>
|
||||
<label><input class="list-check-box" value='{$vo.id}' type='checkbox'></label>
|
||||
</td>
|
||||
<td class='text-left'>{$vo.email|default=''}</td>
|
||||
<td class='text-left'>{$vo.first_name|default=''} {$vo.last_name|default=''}</td>
|
||||
<td class='text-left'>{$vo.machine_id|default=''}</td>
|
||||
<td class='text-left'>{$vo.registration_time|format_datetime}</td>
|
||||
<td class='text-left'>
|
||||
{if $vo.is_used eq 1}
|
||||
<span class="color-red">已使用</span>
|
||||
{else}
|
||||
<span class="color-green">未使用</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>{$vo.used_at|format_datetime|default='--'}</td>
|
||||
<td class='text-left'>{$vo.used_by|default='--'}</td>
|
||||
<td class='text-left'>
|
||||
{if auth("state") and $vo.is_used eq 1}
|
||||
<a class="layui-btn layui-btn-sm" data-action='{:url("state")}' data-value="id#{$vo.id};state#0" data-csrf="{:systoken('state')}">标记未使用</a>
|
||||
{/if}
|
||||
{if auth("remove")}
|
||||
<a class="layui-btn layui-btn-sm layui-btn-danger" data-confirm="确定要删除该账号吗?" data-csrf="{:systoken('remove')}" data-action='{:url("remove")}' data-value="id#{$vo.id}">删 除</a>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
{empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
|
||||
</div>
|
||||
{/block}
|
||||
93
app/manager/view/agent/add.html
Normal file
93
app/manager/view/agent/add.html
Normal file
@@ -0,0 +1,93 @@
|
||||
{extend name="../../admin/view/main"}
|
||||
|
||||
{block name="content"}
|
||||
<form class="layui-form layui-card" action="{:request()->url()}" data-auto="true" method="post">
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户名</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="username" value='' required placeholder="请输入用户名" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">密码</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="password" name="password" value='' required placeholder="请输入密码" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">昵称</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="nickname" value='' placeholder="请输入昵称" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">代理级别</label>
|
||||
<div class="layui-input-block">
|
||||
<select name='level' class='layui-select' lay-filter='level' required>
|
||||
<option value=''>请选择代理级别</option>
|
||||
<option value='1'>一级代理</option>
|
||||
<option value='2'>二级代理</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item parent-agent" style="display:none;">
|
||||
<label class="layui-form-label">上级代理</label>
|
||||
<div class="layui-input-block">
|
||||
<select name='parent_id' class='layui-select'>
|
||||
<option value=''>请选择上级代理</option>
|
||||
{foreach $agents as $agent}
|
||||
<option value='{$agent.id}'>{$agent.username}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">佣金比例</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="commission_rate" value='0' required placeholder="请输入佣金比例" class="layui-input">
|
||||
<tip class="help-block">请输入0-100之间的数字,表示佣金百分比</tip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
<select name='status' class='layui-select'>
|
||||
<option value='1'>正常</option>
|
||||
<option value='0'>禁用</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea name="remark" placeholder="请输入备注" class="layui-textarea"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="layui-form-item text-center">
|
||||
<button class="layui-btn" type='submit'>保存数据</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-close>取消编辑</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
layui.form.on('select(level)', function(data){
|
||||
if(data.value == '2'){
|
||||
$('.parent-agent').show();
|
||||
}else{
|
||||
$('.parent-agent').hide();
|
||||
$('select[name=parent_id]').val('');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{/block}
|
||||
63
app/manager/view/agent/assign_codes.html
Normal file
63
app/manager/view/agent/assign_codes.html
Normal file
@@ -0,0 +1,63 @@
|
||||
{extend name="../../admin/view/main"}
|
||||
|
||||
{block name="content"}
|
||||
<form class="layui-form layui-card" action="{:request()->url()}" data-auto="true" method="post">
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">选择代理</label>
|
||||
<div class="layui-input-block">
|
||||
<select name='agent_id' class='layui-select' lay-verify="required">
|
||||
<option value=''>请选择代理商</option>
|
||||
{foreach $agents as $agent}
|
||||
<option value='{$agent.id}'>{$agent.username} ({if $agent.level==1}一级代理{else}二级代理{/if})</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">销售价格</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="price" value='0' required placeholder="请输入销售价格" class="layui-input">
|
||||
<tip class="help-block">设置激活码的销售价格,用于计算佣金</tip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">选择激活码</label>
|
||||
<div class="layui-input-block">
|
||||
<table class="layui-table margin-top-10" lay-skin="line">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='list-table-check-td think-checkbox'>
|
||||
<label><input data-auto-none data-check-target='.list-check-box' type='checkbox'></label>
|
||||
</th>
|
||||
<th>激活码</th>
|
||||
<th>有效天数</th>
|
||||
<th>生成时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach $codes as $code}
|
||||
<tr>
|
||||
<td class='list-table-check-td think-checkbox'>
|
||||
<label><input class="list-check-box" name="code_ids[]" value='{$code.id}' type='checkbox'></label>
|
||||
</td>
|
||||
<td>{$code.code}</td>
|
||||
<td>{$code.days} 天</td>
|
||||
<td>{$code.created_at}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="layui-form-item text-center">
|
||||
<button class="layui-btn" type='submit'>确定分配</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-close>取消</button>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
103
app/manager/view/agent/codes.html
Normal file
103
app/manager/view/agent/codes.html
Normal file
@@ -0,0 +1,103 @@
|
||||
{extend name="../../admin/view/main"}
|
||||
|
||||
{block name="content"}
|
||||
<div class="think-box-shadow">
|
||||
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">代理商</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name='agent_id' lay-search class='layui-select'>
|
||||
<option value=''>-- 全部 --</option>
|
||||
{foreach $agents as $agent}
|
||||
<option value='{$agent.id}' {if isset($get.agent_id) and $get.agent_id==$agent.id}selected{/if}>
|
||||
{$agent.username} ({if $agent.level==1}一级代理{else}二级代理{/if})
|
||||
</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">使用状态</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name='is_used' lay-search class='layui-select'>
|
||||
<option value=''>-- 全部 --</option>
|
||||
<option value='0' {if isset($get.is_used) and $get.is_used=='0'}selected{/if}>未使用</option>
|
||||
<option value='1' {if isset($get.is_used) and $get.is_used=='1'}selected{/if}>已使用</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">结算状态</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name='status' lay-search class='layui-select'>
|
||||
<option value=''>-- 全部 --</option>
|
||||
<option value='0' {if isset($get.status) and $get.status=='0'}selected{/if}>未结算</option>
|
||||
<option value='1' {if isset($get.status) and $get.status=='1'}selected{/if}>已结算</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<button class="layui-btn layui-btn-primary"><i class="layui-icon"></i> 搜 索</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table class="layui-table margin-top-10" lay-skin="line">
|
||||
{notempty name='list'}
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='text-left'>激活码</th>
|
||||
<th class='text-left'>代理商</th>
|
||||
<th class='text-left'>有效天数</th>
|
||||
<th class='text-left'>销售价格</th>
|
||||
<th class='text-left'>佣金</th>
|
||||
<th class='text-left'>上级佣金</th>
|
||||
<th class='text-left'>使用状态</th>
|
||||
<th class='text-left'>使用时间</th>
|
||||
<th class='text-left'>使用者</th>
|
||||
<th class='text-left'>结算状态</th>
|
||||
<th class='text-left'>分配时间</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
{/notempty}
|
||||
<tbody>
|
||||
{foreach $list as $key=>$vo}
|
||||
<tr>
|
||||
<td class='text-left'>{$vo.code}</td>
|
||||
<td class='text-left'>{$vo.agent_name}</td>
|
||||
<td class='text-left'>{$vo.days} 天</td>
|
||||
<td class='text-left'>{$vo.price}</td>
|
||||
<td class='text-left'>{$vo.commission}</td>
|
||||
<td class='text-left'>{$vo.parent_commission|default='--'}</td>
|
||||
<td class='text-left'>
|
||||
{if $vo.is_used eq 1}
|
||||
<span class="color-red">已使用</span>
|
||||
{else}
|
||||
<span class="color-green">未使用</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>{$vo.used_at|format_datetime|default='--'}</td>
|
||||
<td class='text-left'>{$vo.used_by|default='--'}</td>
|
||||
<td class='text-left'>
|
||||
{if $vo.status eq 1}
|
||||
<span class="color-blue">已结算</span>
|
||||
{else}
|
||||
<span class="color-red">未结算</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>{$vo.created_at|format_datetime}</td>
|
||||
<td class='text-left'>
|
||||
{if auth("settle") and $vo.status eq 0 and $vo.is_used eq 1}
|
||||
<a class="layui-btn layui-btn-sm" data-action='{:url("settle")}' data-value="id#{$vo.id}" data-csrf="{:systoken('settle')}">结 算</a>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
{empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
|
||||
</div>
|
||||
{/block}
|
||||
102
app/manager/view/agent/form.html
Normal file
102
app/manager/view/agent/form.html
Normal file
@@ -0,0 +1,102 @@
|
||||
{extend name="../../admin/view/main"}
|
||||
|
||||
{block name="content"}
|
||||
<form class="layui-form layui-card" action="{:request()->url()}" data-auto="true" method="post">
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户名</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="username" value='{$vo.username|default=""}' required placeholder="请输入用户名" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">密码</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="password" name="password" value='' {if empty($vo)} required {/if} placeholder="请输入密码" class="layui-input">
|
||||
<tip class="help-block">编辑时不填写表示不修改密码</tip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">昵称</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="nickname" value='{$vo.nickname|default=""}' placeholder="请输入昵称" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">代理级别</label>
|
||||
<div class="layui-input-block">
|
||||
<select name='level' class='layui-select' lay-filter='level'>
|
||||
<option value='1' {if isset($vo.level) and $vo.level==1}selected{/if}>一级代理</option>
|
||||
<option value='2' {if isset($vo.level) and $vo.level==2}selected{/if}>二级代理</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item parent-agent" style="display:none;">
|
||||
<label class="layui-form-label">上级代理</label>
|
||||
<div class="layui-input-block">
|
||||
<select name='parent_id' class='layui-select'>
|
||||
<option value=''>请选择上级代理</option>
|
||||
{foreach $agents as $agent}
|
||||
<option value='{$agent.id}' {if isset($vo.parent_id) and $vo.parent_id==$agent.id}selected{/if}>{$agent.username}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">佣金比例</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="commission_rate" value='{$vo.commission_rate|default="0"}' required placeholder="请输入佣金比例" class="layui-input">
|
||||
<tip class="help-block">请输入0-100之间的数字,表示佣金百分比</tip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
<select name='status' class='layui-select'>
|
||||
<option value='1' {if isset($vo.status) and $vo.status==1}selected{/if}>正常</option>
|
||||
<option value='0' {if isset($vo.status) and $vo.status==0}selected{/if}>禁用</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea name="remark" placeholder="请输入备注" class="layui-textarea">{$vo.remark|default=""}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="layui-form-item text-center">
|
||||
{notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
|
||||
<button class="layui-btn" type='submit'>保存数据</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-close>取消编辑</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
layui.form.on('select(level)', function(data){
|
||||
if(data.value == '2'){
|
||||
$('.parent-agent').show();
|
||||
}else{
|
||||
$('.parent-agent').hide();
|
||||
$('select[name=parent_id]').val('');
|
||||
}
|
||||
});
|
||||
|
||||
// 页面加载完成时检查
|
||||
$(function(){
|
||||
var level = $('select[name=level]').val();
|
||||
if(level == '2'){
|
||||
$('.parent-agent').show();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{/block}
|
||||
123
app/manager/view/agent/index.html
Normal file
123
app/manager/view/agent/index.html
Normal file
@@ -0,0 +1,123 @@
|
||||
{extend name="../../admin/view/main"}
|
||||
|
||||
{block name="button"}
|
||||
<!--{if auth("add")}-->
|
||||
<button class='layui-btn layui-btn-sm layui-btn-primary' data-modal='{:url("add")}'>添加代理商</button>
|
||||
<!--{/if}-->
|
||||
<!--{if auth("assignCodes")}-->
|
||||
<button class='layui-btn layui-btn-sm layui-btn-primary' data-modal='{:url("assignCodes")}'>分配激活码</button>
|
||||
<!--{/if}-->
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<div class="think-box-shadow">
|
||||
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">用户名</label>
|
||||
<div class="layui-input-inline">
|
||||
<input name="username" value="{$get.username|default=''}" placeholder="请输入用户名" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">代理级别</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name='level' lay-search class='layui-select'>
|
||||
<option value=''>-- 全部 --</option>
|
||||
<option value='1' {if isset($get.level) and $get.level=='1'}selected{/if}>一级代理</option>
|
||||
<option value='2' {if isset($get.level) and $get.level=='2'}selected{/if}>二级代理</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name='status' lay-search class='layui-select'>
|
||||
<option value=''>-- 全部 --</option>
|
||||
<option value='1' {if isset($get.status) and $get.status=='1'}selected{/if}>正常</option>
|
||||
<option value='0' {if isset($get.status) and $get.status=='0'}selected{/if}>禁用</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<button class="layui-btn layui-btn-primary"><i class="layui-icon"></i> 搜 索</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table class="layui-table margin-top-10" lay-skin="line">
|
||||
{notempty name='list'}
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='list-table-check-td think-checkbox'>
|
||||
<label><input data-auto-none data-check-target='.list-check-box' type='checkbox'></label>
|
||||
</th>
|
||||
<th class='text-left'>用户名</th>
|
||||
<th class='text-left'>昵称</th>
|
||||
<th class='text-left'>代理级别</th>
|
||||
<th class='text-left'>上级代理</th>
|
||||
<th class='text-left'>佣金比例</th>
|
||||
<th class='text-left'>余额</th>
|
||||
<th class='text-left'>总收入</th>
|
||||
<th class='text-left'>状态</th>
|
||||
<th class='text-left'>最后登录</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
{/notempty}
|
||||
<tbody>
|
||||
{foreach $list as $key=>$vo}
|
||||
<tr>
|
||||
<td class='list-table-check-td think-checkbox'>
|
||||
<label><input class="list-check-box" value='{$vo.id}' type='checkbox'></label>
|
||||
</td>
|
||||
<td class='text-left'>{$vo.username}</td>
|
||||
<td class='text-left'>{$vo.nickname|default='--'}</td>
|
||||
<td class='text-left'>
|
||||
{if $vo.level eq 1}
|
||||
<span class="color-blue">一级代理</span>
|
||||
{else}
|
||||
<span class="color-green">二级代理</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>
|
||||
{if $vo.parent_id}
|
||||
{$vo.parent_name|default='--'}
|
||||
{else}
|
||||
--
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>{$vo.commission_rate}%</td>
|
||||
<td class='text-left'>{$vo.balance}</td>
|
||||
<td class='text-left'>{$vo.total_income}</td>
|
||||
<td class='text-left'>
|
||||
{if $vo.status eq 1}
|
||||
<span class="color-green">正常</span>
|
||||
{else}
|
||||
<span class="color-red">禁用</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class='text-left'>{$vo.last_login_time|format_datetime|default='--'}</td>
|
||||
<td class='text-left'>
|
||||
{if auth("edit")}
|
||||
<a class="layui-btn layui-btn-sm" data-modal='{:url("edit")}?id={$vo.id}'>编 辑</a>
|
||||
{/if}
|
||||
|
||||
{if auth("state") and $vo.status eq 1}
|
||||
<a class="layui-btn layui-btn-sm layui-btn-warm" data-action='{:url("state")}' data-value="id#{$vo.id};status#0" data-csrf="{:systoken('state')}">禁 用</a>
|
||||
{elseif auth("state") and $vo.status eq 0}
|
||||
<a class="layui-btn layui-btn-sm layui-btn-warm" data-action='{:url("state")}' data-value="id#{$vo.id};status#1" data-csrf="{:systoken('state')}">启 用</a>
|
||||
{/if}
|
||||
|
||||
{if auth("remove")}
|
||||
<a class="layui-btn layui-btn-sm layui-btn-danger" data-confirm="确定要删除该代理商吗?" data-csrf="{:systoken('remove')}" data-action='{:url("remove")}' data-value="id#{$vo.id}">删 除</a>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
{empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
|
||||
</div>
|
||||
{/block}
|
||||
31
database/migrations/20240212001_agents.php
Normal file
31
database/migrations/20240212001_agents.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use think\migration\Migrator;
|
||||
use think\migration\db\Column;
|
||||
|
||||
class Agents extends Migrator
|
||||
{
|
||||
public function change()
|
||||
{
|
||||
$table = $this->table('cursor_agents', ['engine' => 'InnoDB']);
|
||||
$table->addColumn('username', 'string', ['limit' => 50, 'null' => false, 'comment' => '代理商用户名'])
|
||||
->addColumn('password', 'string', ['limit' => 255, 'null' => false, 'comment' => '密码'])
|
||||
->addColumn('nickname', 'string', ['limit' => 50, 'null' => true, 'comment' => '昵称'])
|
||||
->addColumn('parent_id', 'integer', ['null' => true, 'default' => 0, 'comment' => '上级代理ID,0表示一级代理'])
|
||||
->addColumn('level', 'integer', ['limit' => 1, 'null' => false, 'default' => 1, 'comment' => '代理级别:1=一级代理,2=二级代理'])
|
||||
->addColumn('balance', 'decimal', ['precision' => 10, 'scale' => 2, 'default' => '0.00', 'comment' => '余额'])
|
||||
->addColumn('total_income', 'decimal', ['precision' => 10, 'scale' => 2, 'default' => '0.00', 'comment' => '总收入'])
|
||||
->addColumn('commission_rate', 'decimal', ['precision' => 5, 'scale' => 2, 'default' => '0.00', 'comment' => '佣金比例'])
|
||||
->addColumn('status', 'integer', ['limit' => 1, 'null' => false, 'default' => 1, 'comment' => '状态:0=禁用,1=启用'])
|
||||
->addColumn('remark', 'string', ['limit' => 255, 'null' => true, 'comment' => '备注'])
|
||||
->addColumn('last_login_time', 'datetime', ['null' => true, 'comment' => '最后登录时间'])
|
||||
->addColumn('last_login_ip', 'string', ['limit' => 50, 'null' => true, 'comment' => '最后登录IP'])
|
||||
->addColumn('created_at', 'datetime', ['null' => false, 'comment' => '创建时间'])
|
||||
->addColumn('updated_at', 'datetime', ['null' => false, 'comment' => '更新时间'])
|
||||
->addIndex(['username'], ['unique' => true])
|
||||
->addIndex(['parent_id'])
|
||||
->addIndex(['level'])
|
||||
->addIndex(['status'])
|
||||
->create();
|
||||
}
|
||||
}
|
||||
25
database/migrations/20240212002_agent_codes.php
Normal file
25
database/migrations/20240212002_agent_codes.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
use think\migration\Migrator;
|
||||
use think\migration\db\Column;
|
||||
|
||||
class AgentCodes extends Migrator
|
||||
{
|
||||
public function change()
|
||||
{
|
||||
$table = $this->table('cursor_agent_codes', ['engine' => 'InnoDB']);
|
||||
$table->addColumn('agent_id', 'integer', ['null' => false, 'comment' => '代理商ID'])
|
||||
->addColumn('code_id', 'integer', ['null' => false, 'comment' => '激活码ID'])
|
||||
->addColumn('price', 'decimal', ['precision' => 10, 'scale' => 2, 'default' => '0.00', 'comment' => '销售价格'])
|
||||
->addColumn('commission', 'decimal', ['precision' => 10, 'scale' => 2, 'default' => '0.00', 'comment' => '佣金'])
|
||||
->addColumn('parent_commission', 'decimal', ['precision' => 10, 'scale' => 2, 'default' => '0.00', 'comment' => '上级佣金'])
|
||||
->addColumn('status', 'integer', ['limit' => 1, 'null' => false, 'default' => 0, 'comment' => '状态:0=未结算,1=已结算'])
|
||||
->addColumn('settle_time', 'datetime', ['null' => true, 'comment' => '结算时间'])
|
||||
->addColumn('created_at', 'datetime', ['null' => false, 'comment' => '创建时间'])
|
||||
->addColumn('updated_at', 'datetime', ['null' => false, 'comment' => '更新时间'])
|
||||
->addIndex(['agent_id'])
|
||||
->addIndex(['code_id'])
|
||||
->addIndex(['status'])
|
||||
->create();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user