feat: IEO后端 — 申购+配售码+开奖+后台

This commit is contained in:
testadmin
2026-04-28 17:42:00 +08:00
parent dc19fdb5da
commit 928d573b11
7 changed files with 633 additions and 0 deletions
@@ -0,0 +1,190 @@
<?php
namespace App\Http\Controllers\Admin;
use App\IeoProject;
use App\IeoOrder;
use App\IeoAllocationCode;
use App\UsersWallet;
use App\AccountLog;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class IeoController extends Controller
{
public function projectIndex() { return view('manages.ieo.projects'); }
public function orderIndex() { return view('manages.ieo.orders'); }
public function projectList(Request $request)
{
$data = IeoProject::orderBy('id', 'desc')->paginate($request->input('limit', 20));
return $this->layuiData($data);
}
public function projectSave(Request $request)
{
$id = $request->input('id');
$fields = $request->only([
'name','symbol','description','whitepaper_url','thumb_image',
'token_price','total_supply','min_buy','max_buy','start_time','end_time',
'type','status','fake_progress',
'subscription_limit','announce_time','listing_time','unlock_time'
]);
// Normalize empty datetime strings to null to avoid MySQL errors
foreach (['announce_time','listing_time','unlock_time','start_time','end_time'] as $k) {
if (isset($fields[$k]) && $fields[$k] === '') $fields[$k] = null;
}
if ($id) {
IeoProject::where('id', $id)->update($fields);
} else {
IeoProject::create($fields);
}
return $this->success('OK');
}
public function projectDelete(Request $request)
{
IeoProject::destroy($request->input('id'));
return $this->success('Deleted');
}
public function orderList(Request $request)
{
$query = IeoOrder::query()
->leftJoin('users', 'ieo_order.user_id', '=', 'users.id')
->leftJoin('ieo_project', 'ieo_order.project_id', '=', 'ieo_project.id')
->select('ieo_order.*', 'users.phone as user_phone', 'users.email as user_email', 'ieo_project.name as project_name', 'ieo_project.symbol');
$project_id = $request->input('project_id');
if ($project_id) $query->where('ieo_order.project_id', $project_id);
$data = $query->orderBy('ieo_order.id', 'desc')->paginate($request->input('limit', 20));
$statusMap = ['0'=>'待开奖','1'=>'已中签','2'=>'未中签'];
$forceMap = [null=>'-','1'=>'强制中签','2'=>'强制未中'];
foreach ($data as $item) {
$item->status_text = $statusMap[$item->status] ?? '';
$item->force_text = $forceMap[$item->force_result] ?? '-';
}
return $this->layuiData($data);
}
public function forceResult(Request $request)
{
$ids = $request->input('ids');
$result = $request->input('result'); // 1=win, 2=lose
if (!$ids) return $this->error('No orders selected');
IeoOrder::whereIn('id', explode(',', $ids))->update(['force_result' => $result]);
return $this->success('Set ' . ($result == 1 ? 'Force Win' : 'Force Lose'));
}
public function lottery(Request $request)
{
$project_id = $request->input('project_id');
$project = IeoProject::find($project_id);
if (!$project) return $this->error('Project not found');
$orders = IeoOrder::where('project_id', $project_id)->where('status', 0)->get();
if ($orders->isEmpty()) return $this->error('No pending orders');
$won = 0; $lost = 0;
DB::beginTransaction();
try {
foreach ($orders as $order) {
if ($order->force_result == 1) $result = 1;
elseif ($order->force_result == 2) $result = 2;
else $result = rand(1, 100) <= 50 ? 1 : 2;
if ($result == 1) {
$order->update(['status' => 1, 'token_amount' => $project->token_price > 0 ? sprintf("%.6f", $order->amount / $project->token_price) : 0]);
$won++;
} else {
$wallet = UsersWallet::where('user_id', $order->user_id)->where('currency', 3)->first();
if ($wallet) {
$before = $wallet->legal_balance;
$wallet->legal_balance = bc_add($wallet->legal_balance, $order->amount, 6);
$wallet->save();
AccountLog::insertLog(
['user_id'=>$order->user_id,'value'=>$order->amount,'info'=>'IEO Refund - '.$project->name,'type'=>AccountLog::IEO_OPERATION,'currency'=>3],
['balance_type'=>1,'wallet_id'=>$wallet->id,'lock_type'=>0,'before'=>$before,'change'=>$order->amount,'after'=>$wallet->legal_balance]
);
}
$order->update(['status' => 2]);
$lost++;
}
}
$creditOrders = \App\CreditIeoOrder::where('project_id', $project_id)->where('status', 0)->get();
$creditWon = 0; $creditLost = 0;
foreach ($creditOrders as $co) {
$cResult = rand(1, 100) <= 50 ? 1 : 2;
if ($cResult == 1) {
$co->update([
'status' => 4,
'token_amount' => $project->token_price > 0 ? sprintf("%.6f", $co->amount / $project->token_price) : 0,
]);
$creditWon++;
} else {
$line = \App\CreditLine::find($co->credit_line_id);
if ($line) {
$line->used_amount = max(0, bc_sub($line->used_amount, $co->amount, 6));
$line->available_amount = bc_add($line->available_amount, $co->amount, 6);
if ($line->available_amount > $line->total_amount) $line->available_amount = $line->total_amount;
$line->save();
}
$co->update(['status' => 2]);
$creditLost++;
}
}
$project->update(['status' => 2]);
DB::commit();
return $this->success("Lottery: {$won} won/{$lost} lost, Credit: {$creditWon} won/{$creditLost} lost");
} catch (\Exception $e) {
DB::rollBack();
return $this->error($e->getMessage());
}
}
public function generateCodes(Request $request)
{
$project_id = intval($request->input('project_id'));
$count = intval($request->input('count'));
$amount = floatval($request->input('amount'));
if (!$project_id || $count <= 0 || $amount <= 0) return $this->error('Invalid params');
if ($count > 1000) return $this->error('Max 1000 per batch');
$project = IeoProject::find($project_id);
if (!$project) return $this->error('Project not found');
$generated = 0; $attempts = 0;
$maxAttempts = $count * 5;
while ($generated < $count && $attempts < $maxAttempts) {
$attempts++;
$code = strtoupper(substr(str_shuffle('ABCDEFGHJKLMNPQRSTUVWXYZ23456789'), 0, 6));
$exists = IeoAllocationCode::where('code', $code)->exists();
if ($exists) continue;
IeoAllocationCode::create([
'project_id' => $project_id,
'code' => $code,
'amount' => $amount,
'used' => 0,
'user_id' => 0,
]);
$generated++;
}
return $this->success("Generated {$generated} codes");
}
public function codeList(Request $request)
{
$project_id = $request->input('project_id');
$query = IeoAllocationCode::query()
->leftJoin('users', 'ieo_allocation_code.user_id', '=', 'users.id')
->leftJoin('ieo_project', 'ieo_allocation_code.project_id', '=', 'ieo_project.id')
->select('ieo_allocation_code.*', 'users.phone as user_phone', 'users.email as user_email', 'ieo_project.name as project_name');
if ($project_id) $query->where('ieo_allocation_code.project_id', $project_id);
$data = $query->orderBy('ieo_allocation_code.id', 'desc')->paginate($request->input('limit', 50));
foreach ($data as $item) {
$item->used_text = $item->used ? 'Used' : 'Available';
}
return $this->layuiData($data);
}
}
+183
View File
@@ -0,0 +1,183 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Api\Controller;
use App\IeoProject;
use App\IeoOrder;
use App\IeoAllocationCode;
use App\UsersWallet;
use App\AccountLog;
use Illuminate\Http\Request;
use App\Token;
use App\Users;
use Illuminate\Support\Facades\DB;
class IeoController extends Controller
{
public function list(Request $request)
{
$status = $request->input('status', 'all');
$query = IeoProject::query();
if ($status !== 'all') $query->where('status', $status);
$list = $query->orderBy('id', 'desc')->get();
foreach ($list as $item) {
$real_pct = $item->total_supply > 0 ? round($item->real_sold / $item->total_supply * 100, 2) : 0;
$item->progress = $item->type == 1 ? max($item->fake_progress, $real_pct) : min($item->fake_progress, 100);
}
return $this->success($list);
}
public function detail(Request $request)
{
$id = $request->input('id');
$project = IeoProject::find($id);
if (!$project) return $this->error('Not found');
$real_pct = $project->total_supply > 0 ? round($project->real_sold / $project->total_supply * 100, 2) : 0;
$project->progress = $project->type == 1 ? max($project->fake_progress, $real_pct) : min($project->fake_progress, 100);
$user_id = Token::getUserIdByToken(Token::getToken());
$user = \App\Users::find($user_id);
$project->my_order = null;
$project->my_order_count = 0;
if ($user) {
$order = IeoOrder::where('user_id', $user->id)->where('project_id', $id)->orderBy('id', 'desc')->first();
if ($order) {
$statusMap = ['0' => 'Pending', '1' => 'Won', '2' => 'Lost'];
$order->status_text = $statusMap[$order->status] ?? '';
$project->my_order = $order;
}
$project->my_order_count = IeoOrder::where('user_id', $user->id)->where('project_id', $id)->count();
}
return $this->success($project);
}
public function subscribe(Request $request)
{
$user_id = Token::getUserIdByToken(Token::getToken());
$user = \App\Users::find($user_id);
if (!$user) return $this->error('Please login');
$project_id = $request->input('project_id');
$amount = floatval($request->input('amount'));
$pay_pwd = $request->input('pay_pwd');
if ($amount <= 0) return $this->error('Invalid amount');
$project = IeoProject::find($project_id);
if (!$project || $project->status != 1) return $this->error('IEO not active');
if ($amount < $project->min_buy) return $this->error('Min: ' . $project->min_buy . ' USDC');
if ($project->max_buy > 0 && $amount > $project->max_buy) return $this->error('Max: ' . $project->max_buy . ' USDC');
$limit = intval($project->subscription_limit);
if ($limit > 0) {
$userOrderCount = IeoOrder::where('user_id', $user->id)->where('project_id', $project_id)->count();
if ($userOrderCount >= $limit) return $this->error('Subscription limit reached: ' . $limit);
}
$existingCredit = \App\CreditIeoOrder::where('user_id', $user->id)->where('project_id', $project_id)->whereIn('status', [0, 1])->exists();
if ($existingCredit) return $this->error('Already subscribed via credit IEO');
$wallet = UsersWallet::where('user_id', $user->id)->where('currency', 3)->lockForUpdate()->first();
if (!$wallet || $wallet->legal_balance < $amount) return $this->error('Insufficient balance');
DB::beginTransaction();
try {
$before = $wallet->legal_balance;
$wallet->legal_balance = bc_sub($wallet->legal_balance, $amount, 6);
$wallet->save();
AccountLog::insertLog(
['user_id' => $user->id, 'value' => -$amount, 'info' => 'IEO Subscribe - ' . $project->name, 'type' => AccountLog::IEO_OPERATION, 'currency' => 3],
['balance_type' => 1, 'wallet_id' => $wallet->id, 'lock_type' => 0, 'before' => $before, 'change' => -$amount, 'after' => $wallet->legal_balance]
);
$token_amount = $project->token_price > 0 ? sprintf("%.6f", $amount / $project->token_price) : 0;
IeoOrder::create([
'user_id' => $user->id, 'project_id' => $project_id,
'amount' => $amount, 'token_amount' => $token_amount, 'status' => 0,
]);
$project->increment('real_sold', $token_amount);
DB::commit();
return $this->success('Subscription successful');
} catch (\Exception $e) {
DB::rollBack();
return $this->error($e->getMessage());
}
}
public function myOrders(Request $request)
{
$user_id = Token::getUserIdByToken(Token::getToken());
$user = \App\Users::find($user_id);
if (!$user) return $this->error('Please login');
$list = IeoOrder::where('user_id', $user->id)->with('project:id,name,symbol')->orderBy('id', 'desc')->get();
$statusMap = ['0' => 'Pending', '1' => 'Won', '2' => 'Lost'];
foreach ($list as $item) {
$item->status_text = $statusMap[$item->status] ?? '';
}
return $this->success($list);
}
public function redeemCode(Request $request)
{
$user_id = Token::getUserIdByToken(Token::getToken());
$user = \App\Users::find($user_id);
if (!$user) return $this->error('Please login');
$code = trim((string)$request->input('code'));
$project_id = intval($request->input('project_id'));
if ($code === '' || !$project_id) return $this->error('Invalid params');
$project = IeoProject::find($project_id);
if (!$project || $project->status != 1) return $this->error('IEO not active');
DB::beginTransaction();
try {
$allocCode = IeoAllocationCode::where('project_id', $project_id)
->where('code', $code)
->lockForUpdate()
->first();
if (!$allocCode) { DB::rollBack(); return $this->error('Invalid code'); }
if ($allocCode->used) { DB::rollBack(); return $this->error('Code already used'); }
$amount = floatval($allocCode->amount);
if ($amount <= 0) { DB::rollBack(); return $this->error('Invalid code amount'); }
$wallet = UsersWallet::where('user_id', $user->id)->where('currency', 3)->first();
if (!$wallet || $wallet->legal_balance < $amount) { DB::rollBack(); return $this->error('Insufficient balance'); }
$before = $wallet->legal_balance;
$wallet->legal_balance = bc_sub($wallet->legal_balance, $amount, 6);
$wallet->save();
AccountLog::insertLog(
['user_id' => $user->id, 'value' => -$amount, 'info' => 'IEO Allocation - ' . $project->name, 'type' => AccountLog::IEO_OPERATION, 'currency' => 3],
['balance_type' => 1, 'wallet_id' => $wallet->id, 'lock_type' => 0, 'before' => $before, 'change' => -$amount, 'after' => $wallet->legal_balance]
);
$token_amount = $project->token_price > 0 ? sprintf("%.6f", $amount / $project->token_price) : 0;
IeoOrder::create([
'user_id' => $user->id, 'project_id' => $project_id,
'amount' => $amount, 'token_amount' => $token_amount, 'status' => 1,
]);
$project->increment('real_sold', $token_amount);
$allocCode->used = 1;
$allocCode->user_id = $user->id;
$allocCode->save();
DB::commit();
return $this->success('Redeemed successfully');
} catch (\Exception $e) {
DB::rollBack();
return $this->error($e->getMessage());
}
}
public function allocationOrders(Request $request)
{
$user_id = Token::getUserIdByToken(Token::getToken());
$user = \App\Users::find($user_id);
if (!$user) return $this->error('Please login');
$list = IeoAllocationCode::where('user_id', $user->id)
->where('used', 1)
->with('project:id,name,symbol,token_price,listing_time,unlock_time')
->orderBy('id', 'desc')
->get();
return $this->success($list);
}
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class IeoAllocationCode extends Model
{
protected $table = 'ieo_allocation_code';
protected $fillable = ['project_id','code','amount','used','user_id'];
public function project() { return $this->belongsTo(IeoProject::class, 'project_id'); }
public function user() { return $this->belongsTo(Users::class, 'user_id'); }
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class IeoOrder extends Model
{
protected $table = 'ieo_order';
protected $fillable = ['user_id','project_id','amount','token_amount','status','force_result'];
public function project() { return $this->belongsTo(IeoProject::class, 'project_id'); }
public function user() { return $this->belongsTo(Users::class, 'user_id'); }
}
+9
View File
@@ -0,0 +1,9 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class IeoProject extends Model
{
protected $table = 'ieo_project';
protected $fillable = ['name','symbol','description','whitepaper_url','thumb_image','token_price','total_supply','min_buy','max_buy','start_time','end_time','type','status','fake_progress','real_sold','subscription_limit','announce_time','listing_time','unlock_time'];
}
@@ -0,0 +1,65 @@
@extends('admin._layoutNew')
@section('title', 'IEO订单管理')
@section('page-content')
<div class="layui-card">
<div class="layui-card-header">IEO订单管理</div>
<div class="layui-card-body">
<div class="layui-btn-group" style="margin-bottom:15px;">
<button class="layui-btn layui-btn-sm" onclick="loadData()"><i class="layui-icon">&#xe9aa;</i> 刷新</button>
<button class="layui-btn layui-btn-sm layui-btn-normal" onclick="forceResult(1)"><i class="layui-icon">&#xe605;</i> 强制中签</button>
<button class="layui-btn layui-btn-sm layui-btn-danger" onclick="forceResult(2)"><i class="layui-icon">&#x1006;</i> 强制未中</button>
<button class="layui-btn layui-btn-sm layui-btn-warm" onclick="runLottery()"><i class="layui-icon">&#xe63c;</i> 执行开奖</button>
</div>
<table id="orderTable" lay-filter="orderTable"></table>
</div>
</div>
@endsection
@section('scripts')
<script>
layui.use(['table','layer'], function(){
var table = layui.table;
window.loadData = function(){ table.reload('orderTable'); };
table.render({
elem:'#orderTable', url:'/admin/ieo/order/list', page:true,
cols:[[
{type:'checkbox'},
{field:'id',title:'ID',width:60},
{field:'user_id',title:'用户ID',width:70},
{field:'user_email',title:'邮箱',width:180},
{field:'project_name',title:'项目',width:120},
{field:'symbol',title:'代号',width:80},
{field:'amount',title:'申购金额',width:100},
{field:'token_amount',title:'获得代币',width:100},
{field:'status_text',title:'状态',width:90,templet:function(d){
var cls=d.status==1?'layui-bg-green':(d.status==2?'':'layui-bg-orange');
return '<span class="layui-badge '+cls+'">'+d.status_text+'</span>';
}},
{field:'force_text',title:'强制结果',width:100},
{field:'created_at',title:'申购时间',width:170}
]]
});
window.forceResult = function(result){
var checked = table.checkStatus('orderTable').data;
if(!checked.length) return layer.msg('请先选择订单');
var ids = checked.map(function(d){return d.id}).join(',');
$.post('/admin/ieo/order/force',{ids:ids,result:result,_token:'{{csrf_token()}}'},function(r){
if(r.type=='ok'){layer.msg(r.message);loadData();}else layer.msg(r.message,{icon:2});
});
};
window.runLottery = function(){
layer.prompt({title:'请输入项目ID'}, function(pid,index){
layer.close(index);
layer.confirm('确定对项目ID '+pid+' 执行开奖?', function(ci){
layer.close(ci);
$.post('/admin/ieo/order/lottery',{project_id:pid,_token:'{{csrf_token()}}'},function(r){
if(r.type=='ok'){layer.msg(r.message);loadData();}else layer.msg(r.message,{icon:2});
});
});
});
};
});
</script>
@endsection
@@ -0,0 +1,162 @@
@extends('admin._layoutNew')
@section('title', 'IEO项目管理')
@section('page-content')
<div class="layui-card">
<div class="layui-card-header">IEO项目管理</div>
<div class="layui-card-body">
<button class="layui-btn layui-btn-sm" onclick="addProject()"><i class="layui-icon">&#xe654;</i> 添加项目</button>
<button class="layui-btn layui-btn-sm layui-btn-primary" onclick="loadData()"><i class="layui-icon">&#xe9aa;</i> 刷新</button>
<table id="projectTable" lay-filter="projectTable"></table>
</div>
</div>
<script type="text/html" id="statusTpl">
@{{# if(d.status==0){ }}<span class="layui-badge layui-bg-gray">待发行</span>@{{# } }}
@{{# if(d.status==1){ }}<span class="layui-badge layui-bg-green">发行中</span>@{{# } }}
@{{# if(d.status==2){ }}<span class="layui-badge">已结束</span>@{{# } }}
</script>
<script type="text/html" id="typeTpl">
@{{# if(d.type==1){ }}申购@{{# } }}
@{{# if(d.type==2){ }}配售@{{# } }}
</script>
<script type="text/html" id="actionTpl">
<button class="layui-btn layui-btn-xs" lay-event="edit">编辑</button>
@{{# if(d.type==2){ }}
<button class="layui-btn layui-btn-xs layui-btn-normal" lay-event="codes">配售码</button>
@{{# } }}
<button class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</button>
</script>
@endsection
@section('scripts')
<script>
layui.use(['table','layer','form','laydate'], function(){
var table = layui.table;
var laydate = layui.laydate;
window.loadData = function(){ table.reload('projectTable'); };
table.render({
elem:'#projectTable', url:'/admin/ieo/project/list', page:true,
cols:[[
{field:'id',title:'ID',width:60,sort:true},
{field:'name',title:'项目名称',width:120},
{field:'symbol',title:'代号',width:80},
{field:'type',title:'类型',width:80,templet:'#typeTpl'},
{field:'token_price',title:'发行价',width:90},
{field:'total_supply',title:'总量',width:100},
{field:'real_sold',title:'已售',width:90},
{field:'fake_progress',title:'展示进度%',width:90},
{field:'min_buy',title:'最低申购',width:90},
{field:'max_buy',title:'最高申购',width:90},
{field:'subscription_limit',title:'限购次数',width:80},
{field:'status',title:'状态',width:80,templet:'#statusTpl'},
{field:'start_time',title:'开始时间',width:150},
{field:'end_time',title:'结束时间',width:150},
{field:'announce_time',title:'公告时间',width:150},
{field:'listing_time',title:'上市时间',width:150},
{field:'unlock_time',title:'解锁时间',width:150},
{fixed:'right',title:'操作',width:200,toolbar:'#actionTpl'}
]]
});
table.on('tool(projectTable)', function(obj){
if(obj.event==='edit') editProject(obj.data);
if(obj.event==='codes') openCodes(obj.data);
if(obj.event==='del'){
layer.confirm('确定删除该项目?',function(i){
$.post('/admin/ieo/project/delete',{id:obj.data.id,_token:'{{csrf_token()}}'},function(r){
layer.close(i); if(r.type=='ok'){layer.msg('删除成功');loadData();}else layer.msg(r.message,{icon:2});
});
});
}
});
window.addProject = function(){ openForm({}); };
window.editProject = function(d){ openForm(d); };
function openForm(d){
var html = '<form class="layui-form" style="padding:20px;">'
+'<div class="layui-form-item"><label class="layui-form-label">项目名称</label><div class="layui-input-block"><input name="name" class="layui-input" value="'+(d.name||'')+'"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">代号(Symbol)</label><div class="layui-input-block"><input name="symbol" class="layui-input" value="'+(d.symbol||'')+'"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">发行价(USDT)</label><div class="layui-input-block"><input name="token_price" class="layui-input" value="'+(d.token_price||'')+'"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">总供应量</label><div class="layui-input-block"><input name="total_supply" class="layui-input" value="'+(d.total_supply||'')+'"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">最低申购额</label><div class="layui-input-block"><input name="min_buy" class="layui-input" value="'+(d.min_buy||100)+'"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">最高申购额</label><div class="layui-input-block"><input name="max_buy" class="layui-input" value="'+(d.max_buy||10000)+'"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">限购次数</label><div class="layui-input-block"><input name="subscription_limit" class="layui-input" value="'+(d.subscription_limit||0)+'" placeholder="0=不限次数"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">开始时间</label><div class="layui-input-block"><input id="dt_start" name="start_time" class="layui-input" value="'+(d.start_time||'')+'" placeholder="点击选择时间"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">结束时间</label><div class="layui-input-block"><input id="dt_end" name="end_time" class="layui-input" value="'+(d.end_time||'')+'" placeholder="点击选择时间"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">公告时间</label><div class="layui-input-block"><input id="dt_announce" name="announce_time" class="layui-input" value="'+(d.announce_time||'')+'" placeholder="点击选择时间"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">上市时间</label><div class="layui-input-block"><input id="dt_listing" name="listing_time" class="layui-input" value="'+(d.listing_time||'')+'" placeholder="点击选择时间"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">解锁时间</label><div class="layui-input-block"><input id="dt_unlock" name="unlock_time" class="layui-input" value="'+(d.unlock_time||'')+'" placeholder="点击选择时间"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">类型</label><div class="layui-input-block"><select name="type"><option value="1" '+(d.type==1?'selected':'')+'>申购</option><option value="2" '+(d.type==2?'selected':'')+'>配售</option></select></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">状态</label><div class="layui-input-block"><select name="status"><option value="0" '+(d.status==0?'selected':'')+'>待发行</option><option value="1" '+(d.status==1?'selected':'')+'>发行中</option><option value="2" '+(d.status==2?'selected':'')+'>已结束</option></select></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">展示进度%</label><div class="layui-input-block"><input name="fake_progress" class="layui-input" value="'+(d.fake_progress||0)+'"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">项目描述</label><div class="layui-input-block"><textarea name="description" class="layui-textarea">'+(d.description||'')+'</textarea></div></div>'
+'</form>';
layer.open({
type:1, title:d.id?'编辑项目':'添加项目', area:['560px','700px'], content:html,
success:function(){
['dt_start','dt_end','dt_announce','dt_listing','dt_unlock'].forEach(function(id){
laydate.render({elem:'#'+id, type:'datetime', format:'yyyy-MM-dd HH:mm:ss'});
});
},
btn:['保存','取消'],
yes:function(index,layero){
var form = layero.find('form');
var postData = {};
form.find('input,select,textarea').each(function(){postData[this.name]=this.value;});
if(d.id) postData.id = d.id;
postData._token = '{{csrf_token()}}';
$.post('/admin/ieo/project/save', postData, function(r){
layer.close(index);
if(r.type=='ok'){layer.msg('保存成功');loadData();}else layer.msg(r.message,{icon:2});
});
}
});
}
function openCodes(d){
var html = '<div style="padding:15px;">'
+'<div class="layui-form-item"><label class="layui-form-label">项目</label><div class="layui-input-block"><input class="layui-input" value="'+d.name+' ('+d.symbol+')" readonly></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">生成数量</label><div class="layui-input-block"><input id="gc_count" class="layui-input" value="10" placeholder="要生成多少个配售码"></div></div>'
+'<div class="layui-form-item"><label class="layui-form-label">每码金额(USDT)</label><div class="layui-input-block"><input id="gc_amount" class="layui-input" value="'+(d.min_buy||100)+'" placeholder="每个配售码的金额"></div></div>'
+'<div class="layui-form-item"><div class="layui-input-block">'
+'<button class="layui-btn layui-btn-sm" onclick="doGen('+d.id+')">生成</button>'
+'<button class="layui-btn layui-btn-sm layui-btn-primary" onclick="reloadCodes('+d.id+')">刷新</button>'
+'</div></div>'
+'<table id="codeTable" lay-filter="codeTable"></table>'
+'</div>';
layer.open({
type:1, title:'配售码管理 - '+d.name, area:['800px','600px'], content:html,
success:function(){
layui.use('table', function(){
layui.table.render({
elem:'#codeTable', id:'codeTable',
url:'/admin/ieo/codes?project_id='+d.id, page:true, limit:20,
cols:[[
{field:'id',title:'ID',width:60},
{field:'code',title:'配售码',width:120},
{field:'amount',title:'金额',width:100},
{field:'used_text',title:'状态',width:100,templet:function(d){return d.used?'<span class="layui-badge layui-bg-gray">已使用</span>':'<span class="layui-badge layui-bg-green">可用</span>';}},
{field:'user_phone',title:'用户手机',width:140},
{field:'user_email',title:'用户邮箱'}
]]
});
});
}
});
}
window.doGen = function(pid){
var count = $('#gc_count').val(), amount = $('#gc_amount').val();
$.post('/admin/ieo/generate_codes', {project_id:pid, count:count, amount:amount, _token:'{{csrf_token()}}'}, function(r){
if(r.type=='ok'){ layer.msg(r.message); reloadCodes(pid); }
else layer.msg(r.message,{icon:2});
});
};
window.reloadCodes = function(pid){
layui.table.reload('codeTable', {url:'/admin/ieo/codes?project_id='+pid});
};
});
</script>
@endsection