Commit 2c909e78 authored by 董先生's avatar 董先生

Merge branch 'dev' of http://rungit.jxdsy.cn:10000/sugar/stock_new into dev

parents 7cf756d1 3314982f
...@@ -2087,126 +2087,38 @@ if(!function_exists('get_between')) { ...@@ -2087,126 +2087,38 @@ if(!function_exists('get_between')) {
$substr = substr($input, strlen($start) + strpos($input, $start), (strlen($input) - strpos($input, $end)) * (-1)); $substr = substr($input, strlen($start) + strpos($input, $start), (strlen($input) - strpos($input, $end)) * (-1));
return $substr; return $substr;
} }
}
//腾讯数据解析 /*
if(!function_exists('jsonQuotation')) { * 计算佣金
function jsonQuotation($item) { */
$item[0] = isset($item[0])?substr(str_replace('v_','', $item[0]), 0, 2):'';//交易所代号 if (!function_exists('commission')) {
$item[80] = isset($item[30]) ? strtotime($item[30]) : time(); function commission($money,$scale,$min){
return $item; $commission = round(($money * $scale) / 10000, 2);//佣金
} $commission = $commission < $min ? $min : $commission;
} return $commission;
/*
* 通过API接口获取全部股票列表
*/
if(!function_exists('apiStockList')) {
function apiStockList(){
$url = "http://".LOCAL_STOCK_HOST.":".LOCAL_STOCK_PORT."/api/market/getStockList";
$result = curls($url);
$data = json_decode($result, true);
$json = isset($data['data']) ? $data['data'] : [];
return $json;
}
}
/*
* 获取新浪热门行业
*/
if(!function_exists('getSinahy')) {
function getSinahy(){
$output = curl('https://vip.stock.finance.sina.com.cn/q/view/newSinaHy.php');
if($output){
$findme = '{"';
$pos = strpos($output, $findme) + 2;
$output = substr($output, $pos, -2);
$t2 = explode('","', mb_convert_encoding($output, 'utf-8', 'gbk'));
$res = array();
foreach ($t2 as $k => $v) {
$res[$k] = explode(',', substr(explode(':', $v)[1], 1));
}
return $res ?: false;
}else{
return false;
}
}
}
//新浪股票热门行业分类排行
if(!function_exists('getSinaNodeclass')) {
function getSinaNodeclass($node,$page=1,$num=50){
$url = 'https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page='.$page.'&num='.$num.'&sort=symbol&asc=1&node='.$node;
$json = curl($url);
$data = json_decode($json, true);
return $data ?: false;
}
} }
/* }
* 远程访问 /*
*/ * 计算印花税
if (!function_exists('curls')) { */
function curls($url, $data=[]) { if(!function_exists('stamps')) {
$curl = curl_init(); function stamps($money){
curl_setopt($curl, CURLOPT_URL, $url); $stamps = round($money * config('stamp_duty') / 1000, 2);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); return $stamps ?? 0;
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Access-Token:' . LOCAL_TRADING_TOKEN,
'Client-Host:' . RedisUtil::getClientHost(),
));
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
} }
}
/* /*
* 通过API接口获取行情 * 计算过户费
*/ */
if(!function_exists('getApiStock')) { if(!function_exists('transfer')) {
/** function transfer($money){
* @param $code if(!config('transfer_fee') || config('transfer_fee') == 0){ //当该值未设置或值为0时表示关闭,则返回0
* @param string $model return 0;
* @return array|mixed }elseif(config('transfer_fee') > 1){ //当值大于1时表示具体数值,则返回该数值
*/ return config('transfer_fee');
function getApiStock($code, $model='stock'){ }else{
//$recData['data'] = ThirdMarket($code,$model); $transfer = round(($money / 1000) * config('transfer_fee'), 2) ?? 0;
/**********************腾讯证券网********************/
$recData['data'] = TencentMarkets($code);
//$recData['data'] = east_market($code,$model);
switch ($model) {
case 'stock' ://单个股票
$stockData = isset($recData['data']) ? $recData['data'][0] : [];
break;
case 'stocks' ://多个股票
$stockData = isset($recData['data']) ? $recData['data'] : [];
break;
default :
$stockData = isset($recData['data']) ? $recData['data'][0] : [];
break;
}
return $stockData;
}
}
//腾讯数据获取
if(!function_exists('TencentMarkets')) {
function TencentMarkets($code){
$url = 'https://qt.gtimg.cn/q=' . $code;
//print_r($url);exit;
$output = curl($url);
$str = mb_convert_encoding($output, 'utf-8', 'gbk');
$str = str_replace(array("\r\n", "\r", "\n"), "", $str);
$t2 = explode('";', $str);
$json = [];
foreach ($t2 as $key => $val) {
$array = explode("~", $val);
if(isset($array[2])&&isset($array[3])&&isset($array[4])){
$json[] = jsonQuotation(explode("~", $val));
}else{
continue;
}
}
return $json;
} }
return $transfer;
} }
} }
...@@ -242,10 +242,17 @@ if (!function_exists('getEndDay')) { ...@@ -242,10 +242,17 @@ if (!function_exists('getEndDay')) {
} }
if (!function_exists('z_market')) { if (!function_exists('z_market')) {
function z_market($code) function z_market($code,$market="HK")
{ {
$res = \think\Db::name('admin_config')->where(array('name' => 'market_data_in'))->value('value'); $res = \think\Db::name('admin_config')->where(array('name' => 'market_data_in'))->value('value');
//判断股票前缀
if(toMarket($code)){
$market = toMarket($code);
};
$code=strtolower($market).$code;
//判断股票是否
switch ($res) { switch ($res) {
case 1: case 1:
$res = qq_market($code); $res = qq_market($code);
......
...@@ -87,7 +87,7 @@ class Index extends Common ...@@ -87,7 +87,7 @@ class Index extends Common
if ($code === null) { if ($code === null) {
return json(['data' => null, 'status' => 0, 'message' => '缺少参数code,操作失败']); return json(['data' => null, 'status' => 0, 'message' => '缺少参数code,操作失败']);
} }
$data = z_market(strtolower($market).$code); $data = z_market($code,$market);
if (!$data) { if (!$data) {
return json(['data' => $data, 'status' => 0, 'message' => '操作失败']); return json(['data' => $data, 'status' => 0, 'message' => '操作失败']);
} }
......
<?phpdeclare (strict_types = 1);namespace app\market\controller;use app\market\home\Common;use app\market\model\Position;use app\market\model\StockSubAccount;use app\market\model\SubAccountMoney;use app\market\model\StockPosition;use app\market\model\Delivery;use app\market\model\StockSubAccountRisk;use app\market\model\Trust;use app\market\model\StockDealStock;use app\market\model\Borrow;use think\Log;use think\Db;//use util\RedisUtil; class Trade extends Common { protected function _initialize(){ parent::_initialize(); $token = $this->request->param("token"); $mid = isLogin($token); } public function account_info() { $token = $this->request->param("token"); $mid = isLogin($token); if(!$mid) return json(['status' => 0, 'message' => '登陆后才能进行查看']); $subId = $this->request->param("id"); if(!$subId) return json(['status' => 0, 'message' => '缺少参数或参数获取错误']); $subModel = new SubAccountMoney(); $res = $subModel->get_account_money_inf($subId); if(!$res) return json(['status' => 0, 'message' => '操作失败']); $res['available_amount'] >= 0 ? $res['available_amount'] : 0; $res = $subModel->ftoy($res); $pos = Position::where(['sub_id'=>$subId, 'buying'=>0])->order('id desc')->select(); $res['return_money'] = 0; $res['market_value'] = 0; foreach ($pos as $k => $v ) { $data = z_market($v['gupiao_code']); if($data['Price'] == '') continue; $res['return_money'] += ($data['Price'] - $v['buy_average_price']) * $v['stock_count']; $res['market_value'] += $data['Price'] * $v['stock_count']; } // 提盈额度计算 $all = $res['market_value'] + $res['avail']; $profit = bcsub(strval($all),bcadd(strval($res['borrow_money']),strval($res['deposit_money'])),2); if($profit > 0){ $res['available_amount'] = $profit < $res['available_amount'] ? $profit : $res['available_amount']; }else{ $res['available_amount'] = 0; } //$res['available_amount'] = $res['available_amount'] > $res['avail'] ? $res['avail'] : $res['available_amount']; $res['available_amount'] = bcadd(strval($res['available_amount']),'0',2); // 去掉卖出委托的市值 $weituo = 0; $weituo = Db::name('stock_trust')->where(['sub_id'=>$res['stock_subaccount_id'],'flag2'=>'卖出委托','status'=>'已委托'])->sum('amount'); $res['return_money'] = bcadd(strval($res['return_money']),'0', 2); //加法,在原值上加0为了保留小数点后两位 $res['market_value'] = bcsub(strval($res['market_value']),strval($weituo), 2);//减法 $res['total_money'] = bcadd(strval($res['market_value']),bcadd(strval($res['avail']),strval($res['freeze_amount']),2), 2);//加法 return json(['data'=>$res,'status' => 1, 'message' => '操作成功']); } /* * 持仓查询 */ public function position() { $token = $this->request->param("token"); $mid = isLogin($token); if(!$mid) return json(['status' => 0, 'message' => '未登录']); $subid = $this->request->param("subid"); if(!$subid) return json(['status' => 0, 'message' => '参数不正确']); $submodel = new StockSubAccount(); $res = $submodel->get_account_by_id($subid); if (!$res) return json(['status' => 0, 'message' => '不存在的子账号']); if (empty($res['account_id'])) return json(['status' => 0, 'message' => '证券公司不存在']); $data = Position::where(['sub_id' => $subid,'buying' => 0])->where('stock_count','>',0)->order('id desc')->paginate(20, false, ['query' => request()->param()]); if (!$data || count($data) === 0) return ajaxmsg('没有数据',0,$data); foreach ($data as $k => $item){ //查询当天交易的数量 T+1 交易 $todayCount = Delivery::get_delivery_order($subid,$item["gupiao_code"]); $data[$k]['canbuy_count'] = $item['canbuy_count']; //查询股票最新行情 $Qdata = z_market($item["gupiao_code"]); //查询子账户 $data[$k]['sub_account'] = $res['sub_account']; //提取当前价格 $data[$k]['now_price'] = $Qdata['Price']; //市值 = 当前价格*数量 $data[$k]['market_value'] = round((int)$Qdata['Price']*(int)$item['stock_count'],2); //参考成本价 $data[$k]['ck_price'] = Position::calculate($subid,$item["gupiao_code"],'price'); //买入均价 $data[$k]['buy_average_price'] = Position::calculate($subid,$item["gupiao_code"],'average'); //参考盈亏 //$data[$k]['ck_profit'] = $item['stock_count'] > 0 ? round(($Qdata['Price']-$data[$k]['buy_average_price'])*$item['stock_count'], 2) : 0; $data[$k]['ck_profit'] = $item['stock_count'] > 0 ? bcmul(strval((int)$Qdata["Price"]-(int)$data[$k]['buy_average_price']),strval($item['stock_count']),2) : 0;//参考浮动盈亏 //盈亏比例 //$data[$k]['profit_rate'] = $item['stock_count'] > 0 ? round(($data[$k]['ck_profit'] / ($data[$k]['buy_average_price'] * $item['stock_count'])) * 100, 2) : 0; //$data[$k]['profit_rate'] = $item['stock_count'] > 0 ? bcdiv(strval($data[$k]['ck_profit']),strval($data[$k]['buy_average_price']*$item['stock_count']*100),2) : 0;//盈亏比例 //当天可卖数量计算 //$data[$k]['canbuy_count'] = StockPosition::getCanbuyCount($subid,$item["gupiao_code"]); } return ajaxmsg('操作成功',1,$data); } /* * 证券买入 */ public function buy() { if(!$this->token || $this->userId == '') return ajaxmsg('未登录',500); if (!checkTradeTime()) return ajaxmsg('非交易时间',0); if (!sysConfig('site_trade_buy')) return ajaxmsg('系统设置为禁买状态',0); $data = [ "subid" => input('subid','', ['trim', FILTER_SANITIZE_NUMBER_INT]),//子账户ID, "code" => input('code' ,'', ['trim', FILTER_SANITIZE_NUMBER_INT]),//股票代码 "name" => input('name' ,''),//股票名称 "market" => input('market',''),//交易所代码 "count" => input('count', 0, ['trim', FILTER_SANITIZE_NUMBER_INT]),//购买数量 "price" => input('price', 0, ['trim']), 'model' => input('model', 1, ['trim', FILTER_SANITIZE_NUMBER_INT]),//1:是委托状态 ]; //验证数据 $result = $this->validate($data, 'Trade.trade'); if(!$result) return ajaxmsg($result,0); //检查其他买入条件是否符合 $trade_res = Trust::execute($data,'buy'); if(isset($trade_res['status'])&&!$trade_res['status']) return ajaxmsg($trade_res['message'],0); $trade_money = $trade_res['trade_money']; $moneyinfo = $trade_res['moneyinfo']; $price = $trade_res['price']; //计算佣金 commission_scale:佣金比例(单位:万分之几) 如:5 代表万分之五; min_commission:最低佣金(单位:元) $commission = commission($trade_money,$moneyinfo['commission_scale'],$moneyinfo['min_commission']); //计算过户费 $transfer = transfer($trade_money); //写入子账户资金变化表 Db::startTrans(); $effectMoney = $trade_money + $commission + $transfer; /*(子账户ID, 金额*100, 买卖方向[1:买入 2:卖出], 盈亏金额, 实盘相关, 股票代码)*/ $ret = SubAccountMoney::upMoneyLog($data['subid'], $effectMoney, 3, 0, 0, $data['code']); if (!$ret){ Db::rollback(); return ajaxmsg('委托失败!',0); } $Trust_no = mt_rand(101010, 999999) . substr(strval(time()), 1); //添加到委托表 $Trust_res = Trust::add_m_trust($data, $price, $Trust_no); if(!$Trust_res){ Db::rollback(); return ajaxmsg('委托失败!',0); } //持仓数量查询 $position = Db::name('stock_position')->where(['sub_id' => $data['subid'],'gupiao_code' => $data['code'],'buying' => 0])->find(); $amount = empty($position) ? $data['count'] : $position['canbuy_count'] + $data['count']; //提交交易费用信息 $Delivery = new Delivery; $avail = ($moneyinfo['avail']) - $effectMoney; //print_r("佣金: ".$commission." 过户费: ".$transfer." 总计:".$effectMoney);Db::rollback();exit; $del_res = $Delivery->add_m_delivery_order($data['code'], $data['count'], $price, $data['subid'], $commission, $transfer, $Trust_no, $avail, $amount, $data['model']); //print_r($del_res);Db::rollback();exit; if(!$del_res){ Db::rollback(); return ajaxmsg('委托失败',0); }else{ Db::commit(); return ajaxmsg('买入委托已提交',1); } } public function sell() { if(!$this->token || $this->userId == '') return ajaxmsg('未登录',500); if (!checkTradeTime()) return ajaxmsg('非交易时间',0); if (sysConfig('site_trade_sell') == 0) return ajaxmsg('系统设置为不允许卖出股票',0); if (time() <= strtotime(date("Y-m-d 09:30:15"))) { return ajaxmsg('平台设置9点30分15秒后可卖出',0); } $data = [ "subid" => input('subid','', ['trim', FILTER_SANITIZE_NUMBER_INT]),//子账户ID, "code" => input('code' ,'', ['trim', FILTER_SANITIZE_NUMBER_INT]),//股票代码 "name" => input('name' ,''),//股票名称 "market" => input('market', ''),//交易所代码 "count" => input('count', 0, ['trim', FILTER_SANITIZE_NUMBER_INT]),//购买数量 "price" => input('price', 0, ['trim']), 'model' => input('model', 1, ['trim', FILTER_SANITIZE_NUMBER_INT]),//1:是委托状态 ]; //验证数据 $result = $this->validate($data, 'Trade.trade'); if(!$result) return ajaxmsg($result,0); $Trust = new Trust; $trade_res = $Trust->execute($data,'sell'); //print_r($trade_res['message']);exit; if(isset($trade_res['status'])&&!$trade_res['status']) return ajaxmsg($trade_res['message'],0); $trade_money = $trade_res['trade_money']; $moneyinfo = $trade_res['moneyinfo']; $price = $trade_res['price']; //计算佣金 $commission = commission($trade_money,$moneyinfo['commission_scale'],$moneyinfo['min_commission']); //印花税 $stamps = stamps($trade_money); //计算过户费 $transfer = transfer($trade_money); //写入子账户资金变化表 Db::startTrans(); $effectMoney = $trade_money - $transfer - $stamps - $commission; $ret = SubAccountMoney::upMoneyLog($data['subid'], $effectMoney, 4); if(!$ret){ Db::rollback(); return ajaxmsg('委托失败!',0); } $Trust_no = mt_rand(101010, 999999).substr(strval(time()),1); //添加到委托表 $Trust_res = $Trust->sell_m_trust($data, $price, $Trust_no); if(!$Trust_res){ Db::rollback(); return ajaxmsg('委托失败!',0); } //持仓数量查询 $position = Db::name('stock_position')->where(['sub_id' => $data['subid'],'gupiao_code' => $data['code'],'buying' => 0])->find(); $amount = $position['canbuy_count'] - $data['count']; //持仓减少 $pos_res = Db::name('stock_position')->where(['sub_id' => $data['subid'],'gupiao_code' => $data['code'],'buying' => 0])->dec('canbuy_count',intval($data['count']))->update(); $Delivery = new Delivery; $avail = $moneyinfo["avail"] + $effectMoney; $del_res = $Delivery->sell_m_delivery_order($data['code'], $data['count'], $price, $data['subid'], $commission, $transfer, $Trust_no, $stamps, $avail, $amount, $data['model']); if(!$del_res || !$pos_res){ Db::rollback(); return ajaxmsg('委托失败',0); } Db::commit(); return ajaxmsg('卖出委托已提交',1); } /*委托记录*/ public function trust() { if(!$this->token || $this->userId == '') return ajaxmsg('未登录',500); $sub_id = input('sub_id', '', ['trim', FILTER_SANITIZE_NUMBER_INT]); $startDate = input('start_date', ''); $endDate = input('end_date', ''); $page = input('page', 1, ['trim', FILTER_SANITIZE_NUMBER_INT]); $submodel = new StockSubAccount; $res = $submodel->getAccountById($sub_id); if (!$res['account_id']) return ajaxmsg('不存在的子账号',0); $trust = new Trust; //print_r($startDate);print_r($endDate);exit; $data = $trust->get_trust($sub_id,$startDate,$endDate,$page); if(!$data) return ajaxmsg('没有数据',0); return ajaxmsg('操作成功',1,$data); } /* * 获取可撤单委托列表 */ public function cancel_trust() { if(!$this->token || $this->userId == '') return ajaxmsg('未登录',500); $sub_id = input('sub_id', '', ['trim', FILTER_SANITIZE_NUMBER_INT]); $submodel = new StockSubAccount; $res = $submodel->getAccountById($sub_id); if (!$res['account_id']) return ajaxmsg('不存在的子账号',0); $trust = new Trust; $res = $trust->get_cancel_trust($sub_id); if(!$res) return ajaxmsg('没有数据',0); return ajaxmsg('操作成功',1,$res); } /* * 当天撤销委托 */ public function cancel() { if(!$this->token || $this->userId == '') return ajaxmsg('未登录',500); $sub_id = input('sub_id', '', ['trim', FILTER_SANITIZE_NUMBER_INT]); $trust_no = input('trust_no', '', ['trim', FILTER_SANITIZE_NUMBER_INT]); $res = StockSubAccount::getAccountById($sub_id); if (!$res['account_id']) return ajaxmsg('不存在的子账号',0); Db::startTrans(); $yes = false; $tempinfo = Db::name('stock_trust')->where(['trust_no' => $trust_no])->lock(true)->find(); if (!$tempinfo){ Db::rollback(); return ajaxmsg('没找到对应委托,撤单失败',0); } $trust['status'] = '已撤'; $trust['cancel_order_flag'] = '1'; $trust['cancel_order_count'] = $tempinfo['trust_count']; $trust_res = Db::name('stock_trust')->where(['trust_no' => $trust_no])->update($trust); $affect_money = Db::name('stock_delivery_order')->where(array('trust_no' => $trust_no))->value('liquidation_amount'); if ($tempinfo['flag2'] == '买入委托'){ $subm_res = SubAccountMoney::upMoneyLog($sub_id, $affect_money, 8); $position = true; } if ($tempinfo['flag2'] == '卖出委托'){ $position = Db::name('stock_position')->where(['sub_id' => $sub_id,'gupiao_code' => $tempinfo['gupiao_code'],'buying' => 0])->find(); $position['canbuy_count'] = $position['canbuy_count'] + $tempinfo['trust_count']; $position = Db::name('stock_position')->where(['sub_id' => $sub_id,'gupiao_code' => $tempinfo['gupiao_code']])->update($position); $subm_res = SubAccountMoney::upMoneyLog($sub_id, $affect_money, 9); } $delivery = Db::name('stock_delivery_order')->where(array('trust_no' => $trust_no))->delete(); if($trust_res && $subm_res && $position && $delivery){ Db::commit(); return ajaxmsg('撤单成功',1); } Db::rollback(); return ajaxmsg('撤单失败',0); } /* * 成交记录 */ public function deal() { if(!$this->token || $this->userId == '') return ajaxmsg('未登录',500); $sub_id = input('sub_id', '', ['trim', FILTER_SANITIZE_NUMBER_INT]); $startDate = input('start_date', ''); $endDate = input('end_date', ''); $page = input('page', 1, ['trim', FILTER_SANITIZE_NUMBER_INT]); $submodel = new StockSubAccount; $res = $submodel->getAccountById($sub_id); if (!$res['account_id']) return ajaxmsg('不存在的子账号',0); $deal_stack = new StockDealStock; $data = $deal_stack->get_deal_stock($sub_id,$startDate,$endDate,$page); if(!$data) return ajaxmsg('没有数据',0); return ajaxmsg('操作成功',1,$data); } /* * 交割记录 */ public function comp() { if(!$this->token || $this->userId == '') return ajaxmsg('未登录',500); $sub_id = input('sub_id', '', ['trim', FILTER_SANITIZE_NUMBER_INT]); $startDate = input('start_date', ''); $endDate = input('end_date', ''); $page = input('page', 1, ['trim', FILTER_SANITIZE_NUMBER_INT]); $submodel = new StockSubAccount; $res = $submodel->getAccountById($sub_id); if (!$res['account_id']) return ajaxmsg('不存在的子账号',0); $deal_stack = new Delivery; $data = $deal_stack->get_delivery_order($sub_id,$startDate,$endDate,$page); if(!$data) return ajaxmsg('没有数据',0); return ajaxmsg('操作成功',1,$data); } } <?phpdeclare (strict_types = 1); namespace app\market\controller;use app\market\home\Common;use app\market\model\Position;use app\market\model\StockSubAccount;use app\market\model\SubAccountMoney;use app\market\model\StockPosition;use app\market\model\Delivery;use app\market\model\StockSubAccountRisk;use app\market\model\Trust;use app\market\model\StockDealStock;use app\market\model\Borrow;use app\stock\model\Account as AccountModel;use think\Log;use think\Db;//use util\RedisUtil; class Trade extends Common { protected function _initialize(){ parent::_initialize(); $token = $this->request->param("token"); $mid = isLogin($token); } public function account_info() { $token = $this->request->param("token"); $mid = isLogin($token); if(!$mid) return json(['status' => 0, 'message' => '登陆后才能进行查看']); $subId = $this->request->param("id"); if(!$subId) return json(['status' => 0, 'message' => '缺少参数或参数获取错误']); $subModel = new SubAccountMoney(); $res = $subModel->get_account_money_inf($subId); if(!$res) return json(['status' => 0, 'message' => '操作失败']); $res['available_amount'] >= 0 ? $res['available_amount'] : 0; $res = $subModel->ftoy($res); $pos = Position::where(['sub_id'=>$subId, 'buying'=>0])->order('id desc')->select(); $res['return_money'] = 0; $res['market_value'] = 0; foreach ($pos as $k => $v ) { $data = z_market($v['gupiao_code']); if($data['Price'] == '') continue; $res['return_money'] += ($data['Price'] - $v['buy_average_price']) * $v['stock_count']; $res['market_value'] += $data['Price'] * $v['stock_count']; } // 提盈额度计算 $all = $res['market_value'] + $res['avail']; $profit = bcsub(strval($all),bcadd(strval($res['borrow_money']),strval($res['deposit_money'])),2); if($profit > 0){ $res['available_amount'] = $profit < $res['available_amount'] ? $profit : $res['available_amount']; }else{ $res['available_amount'] = 0; } //$res['available_amount'] = $res['available_amount'] > $res['avail'] ? $res['avail'] : $res['available_amount']; $res['available_amount'] = bcadd(strval($res['available_amount']),'0',2); // 去掉卖出委托的市值 $weituo = 0; $weituo = Db::name('stock_trust')->where(['sub_id'=>$res['stock_subaccount_id'],'flag2'=>'卖出委托','status'=>'已委托'])->sum('amount'); $res['return_money'] = bcadd(strval($res['return_money']),'0', 2); //加法,在原值上加0为了保留小数点后两位 $res['market_value'] = bcsub(strval($res['market_value']),strval($weituo), 2);//减法 $res['total_money'] = bcadd(strval($res['market_value']),bcadd(strval($res['avail']),strval($res['freeze_amount']),2), 2);//加法 return json(['data'=>$res,'status' => 1, 'message' => '操作成功']); } /* * 持仓查询 */ public function position() { $token = $this->request->param("token"); $mid = isLogin($token); if(!$mid) return json(['status' => 0, 'message' => '未登录']); $subid = $this->request->param("subid"); if(!$subid) return json(['status' => 0, 'message' => '参数不正确']); $submodel = new StockSubAccount(); $res = $submodel->get_account_by_id($subid); if (!$res) return json(['status' => 0, 'message' => '不存在的子账号']); if (empty($res['account_id'])) return json(['status' => 0, 'message' => '证券公司不存在']); $data = Position::where(['sub_id' => $subid,'buying' => 0])->where('stock_count','>',0)->order('id desc')->paginate(20, false, ['query' => request()->param()]); if (!$data || count($data) === 0) return ajaxmsg('没有数据',0,$data); foreach ($data as $k => $item){ //查询当天交易的数量 T+1 交易 $todayCount = Delivery::get_delivery_order($subid,$item["gupiao_code"]); $data[$k]['canbuy_count'] = $item['canbuy_count']; //查询股票最新行情 $Qdata = z_market($item["gupiao_code"],$item['market']); //查询子账户 $data[$k]['sub_account'] = $res['sub_account']; //提取当前价格 $data[$k]['now_price'] = $Qdata['Price']; //市值 = 当前价格*数量 $data[$k]['market_value'] = round((int)$Qdata['Price']*(int)$item['stock_count'],2); //参考成本价 $data[$k]['ck_price'] = Position::calculate($subid,$item["gupiao_code"],'price'); //买入均价 $data[$k]['buy_average_price'] = Position::calculate($subid,$item["gupiao_code"],'average'); //参考盈亏 //$data[$k]['ck_profit'] = $item['stock_count'] > 0 ? round(($Qdata['Price']-$data[$k]['buy_average_price'])*$item['stock_count'], 2) : 0; $data[$k]['ck_profit'] = $item['stock_count'] > 0 ? bcmul(strval((int)$Qdata["Price"]-(int)$data[$k]['buy_average_price']),strval($item['stock_count']),2) : 0;//参考浮动盈亏 //盈亏比例 //$data[$k]['profit_rate'] = $item['stock_count'] > 0 ? round(($data[$k]['ck_profit'] / ($data[$k]['buy_average_price'] * $item['stock_count'])) * 100, 2) : 0; //$data[$k]['profit_rate'] = $item['stock_count'] > 0 ? bcdiv(strval($data[$k]['ck_profit']),strval($data[$k]['buy_average_price']*$item['stock_count']*100),2) : 0;//盈亏比例 //当天可卖数量计算 //$data[$k]['canbuy_count'] = StockPosition::getCanbuyCount($subid,$item["gupiao_code"]); } return ajaxmsg('操作成功',1,$data); } /* * 证券买入 */ public function buy() { $token = $this->request->param("token"); $mid = isLogin($token); if(!$mid) return json(['status' => 0, 'message' => '登陆后才能进行查看']); if (!yan_time()) return json(['status' => 0, 'message' => '非交易时间']); if (!config('site_trade_buy')) return ajaxmsg('系统设置为禁买状态',0); $data = [ "sub_id" => input('id','', ['trim', FILTER_SANITIZE_NUMBER_INT]),//子账户ID, "code" => input('code' ,'', ['trim', FILTER_SANITIZE_NUMBER_INT]),//股票代码 "name" => input('name' ,''),//股票名称 "market" => input('market',''),//交易所代码 "count" => input('count', 0, ['trim', FILTER_SANITIZE_NUMBER_INT]),//购买数量 "price" => input('price', 0, ['trim']), 'model' => input('model', 1, ['trim', FILTER_SANITIZE_NUMBER_INT]),//1:是委托状态 ]; //验证数据 $result = $this->validate($data, 'Trade.trade'); if(!$result) return ajaxmsg($result,0); //检查其他买入条件是否符合 $Trust = new Trust; $trade_res = $Trust->executeData($data,'buy'); if(isset($trade_res['status'])&&!$trade_res['status']) return ajaxmsg($trade_res['message'],0); $trade_money = $trade_res['trade_money']; $moneyinfo = $trade_res['moneyinfo']; $price = $trade_res['price']; //计算佣金 commission_scale:佣金比例(单位:万分之几) 如:5 代表万分之五; min_commission:最低佣金(单位:元) $commission = commission($trade_money,$moneyinfo['commission_scale'],$moneyinfo['min_commission']); //计算过户费 $transfer = transfer($trade_money); //写入子账户资金变化表 Db::startTrans(); $effectMoney = $trade_money + $commission + $transfer; /*(子账户ID, 金额*100, 买卖方向[1:买入 2:卖出], 盈亏金额, 实盘相关, 股票代码)*/ $ret = SubAccountMoney::up_moneylog($data['subid'], $effectMoney, 3, 0, 0, $data['code']); if (!$ret){ Db::rollback(); return ajaxmsg('委托失败!',0); } $subres = AccountModel::getAccountById($data['sub_id']); $broker = AccountModel::getBroker($subres['account_id']); if (!$subres) return ajaxmsg('子账号或证券公司不存在!',0); $Trust_no = mt_rand(101010, 999999) . substr(strval(time()), 1); //添加到委托表 $Trust_res = $Trust->add_m_trust($data, $data['count'],$data['price'],$data['sub_id'],$broker['lid'],$broker['user'],$broker['stockjobber'],$Trust_no,$broker, $data['model']); if(!$Trust_res){ Db::rollback(); return ajaxmsg('委托失败!',0); } //持仓数量查询 $position = Db::name('stock_position')->where(['sub_id' => $data['subid'],'gupiao_code' => $data['code'],'buying' => 0])->find(); $amount = empty($position) ? $data['count'] : $position['canbuy_count'] + $data['count']; //提交交易费用信息 $Delivery = new Delivery; $avail = ($moneyinfo['avail']) - $effectMoney; //print_r("佣金: ".$commission." 过户费: ".$transfer." 总计:".$effectMoney);Db::rollback();exit; $del_res = $Delivery->add_m_delivery_order($data, $data['count'],$data['price'],$data['sub_id'],$broker['lid'],$broker['user'],$broker['stockjobber'],$commission,$transfer,$Trust_no,$avail,$amount, $data['model']); //print_r($del_res);Db::rollback();exit; if(!$del_res){ Db::rollback(); return ajaxmsg('委托失败',0); }else{ Db::commit(); return ajaxmsg('买入委托已提交',1); } } public function sell() { $token = $this->request->param("token"); $mid = isLogin($token); if(!$mid) return json(['status' => 0, 'message' => '登陆后才能进行查看']); if (!yan_time()) return json(['status' => 0, 'message' => '非交易时间']); if (config('site_trade_sell') == 0) return ajaxmsg('系统设置为不允许卖出股票',0); if (time() <= strtotime(date("Y-m-d 09:30:15"))) { return ajaxmsg('平台设置9点30分15秒后可卖出',0); } $data = [ "sub_id" => input('id','', ['trim', FILTER_SANITIZE_NUMBER_INT]),//子账户ID, "code" => input('code' ,'', ['trim', FILTER_SANITIZE_NUMBER_INT]),//股票代码 "name" => input('name' ,''),//股票名称 "market" => input('market', ''),//交易所代码 "count" => input('count', 0, ['trim', FILTER_SANITIZE_NUMBER_INT]),//购买数量 "price" => input('price', 0, ['trim']), 'model' => input('model', 1, ['trim', FILTER_SANITIZE_NUMBER_INT]),//1:是委托状态 ]; //验证数据 $result = $this->validate($data, 'Trade.trade'); if(!$result) return ajaxmsg($result,0); $Trust = new Trust; $trade_res = $Trust->executeData($data,'sell'); //print_r($trade_res['message']);exit; if(isset($trade_res['status'])&&!$trade_res['status']) return ajaxmsg($trade_res['message'],0); $trade_money = $trade_res['trade_money']; $moneyinfo = $trade_res['moneyinfo']; $price = $trade_res['price']; //计算佣金 $commission = commission($trade_money,$moneyinfo['commission_scale'],$moneyinfo['min_commission']); //印花税 $stamps = stamps($trade_money); //计算过户费 $transfer = transfer($trade_money); //写入子账户资金变化表 Db::startTrans(); $effectMoney = $trade_money - $transfer - $stamps - $commission; $ret = SubAccountMoney::up_moneylog($data['sub_id'], $effectMoney, 4); if(!$ret){ Db::rollback(); return ajaxmsg('委托失败!',0); } $Trust_no = mt_rand(101010, 999999).substr(strval(time()),1); $subres = AccountModel::getAccountById($data['sub_id']); $broker = AccountModel::getBroker($subres['account_id']); if (!$subres) return ajaxmsg('子账号或证券公司不存在!',0); $Trust_no = mt_rand(101010, 999999) . substr(strval(time()), 1); //添加到委托表 $Trust_res = $Trust->sell_m_trust($data, $data['count'],$data['price'],$data['sub_id'],$broker['lid'],$broker['user'],$broker['stockjobber'],$Trust_no,$broker, $data['model']); if(!$Trust_res){ Db::rollback(); return ajaxmsg('委托失败!',0); } //持仓数量查询 $position = Db::name('stock_position')->where(['sub_id' => $data['subid'],'gupiao_code' => $data['code'],'buying' => 0])->find(); $amount = $position['canbuy_count'] - $data['count']; //持仓减少 $pos_res = Db::name('stock_position')->where(['sub_id' => $data['subid'],'gupiao_code' => $data['code'],'buying' => 0])->dec('canbuy_count',intval($data['count']))->update(); $Delivery = new Delivery; $avail = $moneyinfo["avail"] + $effectMoney; $del_res = $Delivery->sell_m_delivery_order($data, $data['count'],$data['price'],$data['sub_id'],$broker['lid'],$broker['user'],$broker['stockjobber'],$commission,$transfer,$Trust_no,$avail,$amount, $data['model']); if(!$del_res || !$pos_res){ Db::rollback(); return ajaxmsg('委托失败',0); } Db::commit(); return ajaxmsg('卖出委托已提交',1); } /*委托记录*/ public function trust() { if(!$this->token || $this->userId == '') return ajaxmsg('未登录',500); $sub_id = input('sub_id', '', ['trim', FILTER_SANITIZE_NUMBER_INT]); $startDate = input('start_date', ''); $endDate = input('end_date', ''); $page = input('page', 1, ['trim', FILTER_SANITIZE_NUMBER_INT]); $submodel = new StockSubAccount; $res = $submodel->getAccountById($sub_id); if (!$res['account_id']) return ajaxmsg('不存在的子账号',0); $trust = new Trust; //print_r($startDate);print_r($endDate);exit; $data = $trust->get_trust($sub_id,$startDate,$endDate,$page); if(!$data) return ajaxmsg('没有数据',0); return ajaxmsg('操作成功',1,$data); } /* * 获取可撤单委托列表 */ public function cancel_trust() { if(!$this->token || $this->userId == '') return ajaxmsg('未登录',500); $sub_id = input('sub_id', '', ['trim', FILTER_SANITIZE_NUMBER_INT]); $submodel = new StockSubAccount; $res = $submodel->getAccountById($sub_id); if (!$res['account_id']) return ajaxmsg('不存在的子账号',0); $trust = new Trust; $res = $trust->get_cancel_trust($sub_id); if(!$res) return ajaxmsg('没有数据',0); return ajaxmsg('操作成功',1,$res); } /* * 当天撤销委托 */ public function cancel() { if(!$this->token || $this->userId == '') return ajaxmsg('未登录',500); $sub_id = input('sub_id', '', ['trim', FILTER_SANITIZE_NUMBER_INT]); $trust_no = input('trust_no', '', ['trim', FILTER_SANITIZE_NUMBER_INT]); $res = StockSubAccount::getAccountById($sub_id); if (!$res['account_id']) return ajaxmsg('不存在的子账号',0); Db::startTrans(); $yes = false; $tempinfo = Db::name('stock_trust')->where(['trust_no' => $trust_no])->lock(true)->find(); if (!$tempinfo){ Db::rollback(); return ajaxmsg('没找到对应委托,撤单失败',0); } $trust['status'] = '已撤'; $trust['cancel_order_flag'] = '1'; $trust['cancel_order_count'] = $tempinfo['trust_count']; $trust_res = Db::name('stock_trust')->where(['trust_no' => $trust_no])->update($trust); $affect_money = Db::name('stock_delivery_order')->where(array('trust_no' => $trust_no))->value('liquidation_amount'); if ($tempinfo['flag2'] == '买入委托'){ $subm_res = SubAccountMoney::upMoneyLog($sub_id, $affect_money, 8); $position = true; } if ($tempinfo['flag2'] == '卖出委托'){ $position = Db::name('stock_position')->where(['sub_id' => $sub_id,'gupiao_code' => $tempinfo['gupiao_code'],'buying' => 0])->find(); $position['canbuy_count'] = $position['canbuy_count'] + $tempinfo['trust_count']; $position = Db::name('stock_position')->where(['sub_id' => $sub_id,'gupiao_code' => $tempinfo['gupiao_code']])->update($position); $subm_res = SubAccountMoney::upMoneyLog($sub_id, $affect_money, 9); } $delivery = Db::name('stock_delivery_order')->where(array('trust_no' => $trust_no))->delete(); if($trust_res && $subm_res && $position && $delivery){ Db::commit(); return ajaxmsg('撤单成功',1); } Db::rollback(); return ajaxmsg('撤单失败',0); } /* * 成交记录 */ public function deal() { if(!$this->token || $this->userId == '') return ajaxmsg('未登录',500); $sub_id = input('sub_id', '', ['trim', FILTER_SANITIZE_NUMBER_INT]); $startDate = input('start_date', ''); $endDate = input('end_date', ''); $page = input('page', 1, ['trim', FILTER_SANITIZE_NUMBER_INT]); $submodel = new StockSubAccount; $res = $submodel->getAccountById($sub_id); if (!$res['account_id']) return ajaxmsg('不存在的子账号',0); $deal_stack = new StockDealStock; $data = $deal_stack->get_deal_stock($sub_id,$startDate,$endDate,$page); if(!$data) return ajaxmsg('没有数据',0); return ajaxmsg('操作成功',1,$data); } /* * 交割记录 */ public function comp() { if(!$this->token || $this->userId == '') return ajaxmsg('未登录',500); $sub_id = input('sub_id', '', ['trim', FILTER_SANITIZE_NUMBER_INT]); $startDate = input('start_date', ''); $endDate = input('end_date', ''); $page = input('page', 1, ['trim', FILTER_SANITIZE_NUMBER_INT]); $submodel = new StockSubAccount; $res = $submodel->getAccountById($sub_id); if (!$res['account_id']) return ajaxmsg('不存在的子账号',0); $deal_stack = new Delivery; $data = $deal_stack->get_delivery_order($sub_id,$startDate,$endDate,$page); if(!$data) return ajaxmsg('没有数据',0); return ajaxmsg('操作成功',1,$data); } }
\ No newline at end of file \ No newline at end of file
......
...@@ -15,6 +15,7 @@ class Trust extends Model{ ...@@ -15,6 +15,7 @@ class Trust extends Model{
protected $table = '__STOCK_TRUST__'; protected $table = '__STOCK_TRUST__';
// 自动写入时间戳 // 自动写入时间戳
protected $autoWriteTimestamp = true; protected $autoWriteTimestamp = true;
/* /*
* 存储委托记录 * 存储委托记录
* $data 持仓数据 * $data 持仓数据
...@@ -224,11 +225,11 @@ class Trust extends Model{ ...@@ -224,11 +225,11 @@ class Trust extends Model{
* 返回子账号当日委托 * 返回子账号当日委托
* $sub_id 子账号 * $sub_id 子账号
*/ */
public function get_trust_day($sub_id){ public function get_trust_day($sub_id){
$time=strtotime(date('y-m-d',time())); $time=strtotime(date('y-m-d',time()));
$res=Db::name('stock_trust')->where(['sub_id'=>$sub_id,'trust_date'=>$time])->select(); $res=Db::name('stock_trust')->where(['sub_id'=>$sub_id,'trust_date'=>$time])->select();
return $res; return $res;
} }
/* /*
* 返回子账号委托 * 返回子账号委托
* $sub_id 子账号 * $sub_id 子账号
...@@ -291,4 +292,180 @@ class Trust extends Model{ ...@@ -291,4 +292,180 @@ class Trust extends Model{
return $result; return $result;
} }
// 买入时检查
public function executeData($data, $trustModel)
{
//检测是否为禁买股票
$res = self::checkStatus($data['code']);
if ($res) return ['status'=>0, 'message'=>'该股票禁止交易'];
//判断购买数量书否正确
if (($data['count'] % 100) != 0) return ['status'=>0, 'message'=>'交易数量必须是100的整数倍'];
$bs_res = Db::name('stock_borrow')->where(array('stock_subaccount_id' => $data['subid']))->find();
if (empty($bs_res)) {
return ['status'=>0, 'message'=>'没有对应的配资'];
}
if ($bs_res['end_time'] <= time()){
return ['status'=>0, 'message'=>'该账户已逾期,请先续期'];
}
if($trustModel == 'buy'){
return self::trustBuy($data,$bs_res);
}
if($trustModel == 'sell'){
return self::trustSell($data);
}
}
public function trustBuy($data,$bs_res)
{
//查询股票最新行情
$Qdata = z_market($data['code'],$data['market']);
$price = $data['price'] <= 0 ? $Qdata['Price'] : $data['price'];
//判断股票价格是否符号购买条件
if (config('stock_buy_price') > 0) {
if ($price < config('stock_buy_price')) {
return ['status'=>0, 'message'=>'系统设定低于'.config('stock_buy_price').'元一股的股票不能购买'];
}
}
//检查卖量是否正常
$trade_money = self::checkTranMoney($Qdata, $data['count'], $price);
if ($trade_money <= 0) return ['status'=>0, 'message'=>'卖量不足或网络错误'];
//判断卖量和股票限额
$res = self::checkPositionSum($Qdata,$data['sub_id'],$data['code'],$trade_money);
if (isset($res['status'])) {
return ['status'=>0, 'message'=>'该股票超过了单支股票最大购买限额'];
}
//检查子账户余额
$moneymodel = new SubAccountMoney();
$moneyinfo = $moneymodel->get_account_money($data['sub_id']);
if ($moneyinfo['avail'] < $trade_money){
return ['status'=>0, 'message'=>'购买资金不足'];
}
// 免息配资结束当天不能买入
if ($bs_res['type'] == 5) {
if($bs_res['end_time'] < time() + 23 * 3600) {
return ['status'=>0, 'message'=>'免息配资结束当天不能买入'];
}
}
// 设置试用配资第二天不能再买入
if ($bs_res['type'] == 4) {
if($bs_res['end_time'] < time() + 23 * 3600) {
return ['status'=>0, 'message'=>'试用配资结束当天不能买入'];
}
}
$risk = new StockSubAccountRisk;
$risk_res = $risk->get_risk($data['sub_id']);
if ($risk_res['prohibit_open'] == 0){
return ['status'=>0, 'message'=>'您被禁止开新仓,请联系管理员咨询原因'];
}
$retData['trade_money'] = $trade_money;
$retData['moneyinfo'] = $moneyinfo;
$retData['price'] = $price;
return $retData;
}
//卖出时检查
public function trustSell($data)
{
//查询股票最新行情
$Qdata = z_market($data['code'],$data['market']);
$price = $data['price'] <= 0 ? $Qdata['Price'] : $data['price'];
if(config('site_trade_sell') == 0) {
return array('status' => 0, 'message' => '系统设置不允许卖出股票');
}
//检测股票可卖数量
$poscount = Position::get_canbuy_count($data['sub_id'], $data['code']);
if ($poscount < $data['count']) {
return ['status'=>0, 'message'=>'可卖股票不足'];
}
//当股票跌停时买一至买五价格为空
if(intval($Qdata["Bp1"]) <= 0 || intval($Qdata['Bv1']*100) < $data['count']){
return ['status'=>0, 'message'=>'当前买盘不足,无法即时成交!'];
}
//检查子账户余额
$moneymodel = new SubAccountMoney();
$moneyinfo = $moneymodel->get_account_money($data['sub_id']);
$trade_money = 0;
if($data['price'] > 0 && $data['model'] == 1){ //model = 1 是委托状态
$trade_money = intval($data['count']) * intval($data['price']);
}else{
$price = $Qdata['Price'];
//如果没有委托价格使用下面的公式
$trade_money = intval($data['count']) * intval($price);
}
$retData['trade_money'] = $trade_money;
$retData['moneyinfo'] = $moneyinfo;
$retData['price'] = $price;
return $retData;
}
/*查询禁买股票列表*/
public function checkStatus($code)
{
$res = Db::name('stock_list')->where(['code' => $code, 'status' => 0])->find();
return $res;
}
/*
* 验证卖量是否正常
*/
public function checkTranMoney($Qdata, $count, $price)
{
$trade_money = 0;
if (!(empty($price))) {
$trade_money = $count * $price;
}else{
$price = 0;
$v_arr[1] = $Qdata['Sv1'] * 100;
$v_arr[2] = $Qdata['Sv2'] * 100;
$v_arr[3] = $Qdata['Sv3'] * 100;
$v_arr[4] = $Qdata['Sv4'] * 100;
$v_arr[5] = $Qdata['Sv5'] * 100;
$p_arr[1] = $Qdata['Sp1'];
$p_arr[2] = $Qdata['Sp2'];
$p_arr[3] = $Qdata['Sp3'];
$p_arr[4] = $Qdata['Sp4'];
$p_arr[5] = $Qdata['Sp5'];
$tmd = 0;
foreach ($v_arr as $key => $v ){
$tmd = $tmd + $v;
if ($count <= $tmd){
$sum_money = 0;
$sum_count = $count;
for ($i = 1; $i < $key; $i++){
$sum_money += $v_arr[$i] * $p_arr[$i];
$sum_count -= $v_arr[$i];
}
$trade_money = $sum_money + ($sum_count * $p_arr[$key]);
$price = round($trade_money / $count, 2);
$trade_money = $count * $price;
break;
}
}
}
return $trade_money ?? 0;
}
/*
* 返回子账号单只股票持仓数量
* $subid 子账号 $code 股票代码
*/
public function checkPositionSum($Qdata,$subid,$code,$trade_money)
{
$res = Db::name('stock_list')->where(['code' => $code, 'status' => 1])->find();
//判断是否超过该只股票限额
$pos = Db::name('stock_position')->where(['sub_id' => $subid,'gupiao_code' => $code,'buying' => 0])->sum('stock_count');
if (isset($res['quota']) && ($res['quota'] < (($pos * $Qdata['Price']) + $trade_money))) {
return ['status'=>0, 'message'=>'该股票超过了单支股票最大购买限额'];
}
return;
}
} }
\ No newline at end of file
<?php
namespace app\apicom\validate;
use think\Validate;
class Trade extends Validate
{
protected $rule = [
'id' => 'require|number',
'code' => 'require|number|length:6',
'market' => 'require|in:SH,SZ,BJ',
'count' => 'require|number|gt:0',
'price' => 'require',
];
protected $message = [
'id.require' => '参数格式错误',
'code.require' => '参数格式错误',
'code.number' => '参数格式错误',
'code.length' => '参数格式错误',
'count.require' => '请填写委托股数',
'count.number' => '委托股数格式错误',
'count.gt' => '委托股数格式错误',
'market.require' => '参数格式错误',
'market.in' => '参数格式错误',
];
protected $scene = [
'trade' => ['id', 'code', 'market', 'count', 'price'],
];
}
<?php <?php
namespace app\member\model;
use think\helper\Hash; namespace app\member\model;
use app\member\model\Role as RoleModel;
use think\model; use think\helper\Hash;
use think\Db; use app\member\model\Role as RoleModel;
use think\model;
class Member extends Model use think\Db;
class Member extends Model
{
// 设置当前模型对应的完整数据表名称
protected $table = '__MEMBER__';
// 自动写入时间戳
protected $autoWriteTimestamp = true;
// 对密码进行加密
public function setPasswdAttr($value)
{ {
return Hash::make((string)$value);
// 设置当前模型对应的完整数据表名称 }
protected $table = '__MEMBER__';
// 自动写入时间戳
protected $autoWriteTimestamp = true;
// 对密码进行加密
public function setPasswdAttr($value)
{
return Hash::make((string)$value);
}
public function setPaywdAttr($value)
{
return Hash::make((string)$value);
}
// 获取注册ip public function setPaywdAttr($value)
public function setAddIpAttr() {
{ return Hash::make((string)$value);
return get_client_ip(1); }
}
/** // 获取注册ip
* 自动登录 public function setAddIpAttr()
* @param object $member 用户对象 {
* @author 路人甲乙 <4853332099@qq.com> return get_client_ip(1);
* @return bool|int }
*/
public function autoLogin($member)
{
// 记录登录SESSION和COOKIES
$auth = array(
'mid' => $member->id,
'mobile' => $member->mobile,
'last_login_time' => $member->last_login_time,
'last_login_ip' => get_client_ip(1),
);
session('member_auth', $auth);
session('member_auth_sign', data_auth_sign($auth));
return $member->id;
}
/** /**
* 用户登录 * 自动登录
* @param string $mobile 手机号 * @param object $member 用户对象
* @param string $password 密码 * @author 路人甲乙 <4853332099@qq.com>
* @author 张继立 <404851763@qq.com> * @return bool|int
* @return bool|mixed */
*/ public function autoLogin($member)
public function login($mobile = '', $password = '') {
{ // 记录登录SESSION和COOKIES
$mobile = trim($mobile); $auth = array(
$password = trim($password); 'mid' => $member->id,
'mobile' => $member->mobile,
if (preg_match("/^1\d{10}$/", $mobile)) { 'last_login_time' => $member->last_login_time,
// 手机号登录 'last_login_ip' => get_client_ip(1),
$map['mobile'] = $mobile; );
} else { session('member_auth', $auth);
$this->error = '请用手机号码登录'; session('member_auth_sign', data_auth_sign($auth));
return false; return $member->id;
} }
/**
* 用户登录
* @param string $mobile 手机号
* @param string $password 密码
* @author 张继立 <404851763@qq.com>
* @return bool|mixed
*/
public function login($mobile = '', $password = '')
{
$mobile = trim($mobile);
$password = trim($password);
$map['status'] = 1; if (preg_match("/^1\d{10}$/", $mobile)) {
$map['is_del'] = 0; // 手机号登录
$map['mobile'] = $mobile;
} else {
$this->error = '请用手机号码登录';
return false;
}
// 查找用户 $map['status'] = 1;
$member = $this::get($map); $map['is_del'] = 0;
if (!$member) {
$this->error = '用户不存在或被禁用!'; // 查找用户
$member = $this::get($map);
if (!$member) {
$this->error = '用户不存在或被禁用!';
} else {
if (!Hash::check((string)$password, $member['passwd'])) {
$this->error = '用户名或密码错误!';
} else { } else {
if (!Hash::check((string)$password, $member['passwd'])) { $mid = $member['id'];
$this->error = '用户名或密码错误!'; // 更新登录信息
$member['last_login_time'] = request()->time();
$member['last_login_ip'] = get_client_ip(1);
if ($member->save()) {
// 自动登录
return $this->autoLogin($this::get($mid));
} else { } else {
$mid = $member['id']; // 更新登录信息失败
// 更新登录信息 $this->error = '登录信息更新失败,请重新登录!';
$member['last_login_time'] = request()->time(); return false;
$member['last_login_ip'] = get_client_ip(1);
if ($member->save()) {
// 自动登录
return $this->autoLogin($this::get($mid));
} else {
// 更新登录信息失败
$this->error = '登录信息更新失败,请重新登录!';
return false;
}
} }
} }
return false;
} }
return false;
}
/** /**
* 根据会员ID获取会员基本信息 * 根据会员ID获取会员基本信息
* @param array $id 会员ID * @param array $id 会员ID
* @author 路人甲乙 * @author 路人甲乙
* @return mixed * @return mixed
*/ */
public static function getMemberInfoByID($id=null) public static function getMemberInfoByID($id = null)
{ {
$where['m.id'] = $id;//会员ID $where['m.id'] = $id; //会员ID
$where['m.status'] = 1;//会员状态 $where['m.status'] = 1; //会员状态
$data = self::view('member m', true) $data = self::view('member m', true)
->view("money", 'account,freeze,operate_account,bond_account', 'money.mid=m.id', 'left') ->view("money", 'account,freeze,operate_account,bond_account', 'money.mid=m.id', 'left')
->where($where) ->where($where)
->find(); ->find();
return $data; return $data;
} }
/** /**
* 根据会员手机号获取会员基本信息 * 根据会员手机号获取会员基本信息
* @param array $id 会员ID * @param array $id 会员ID
* @author 路人甲乙 * @author 路人甲乙
* @return mixed * @return mixed
*/ */
public static function getMemberInfoByMobile($mobile=null) public static function getMemberInfoByMobile($mobile = null)
{ {
$where['m.mobile'] = $mobile;//会员手机号 $where['m.mobile'] = $mobile; //会员手机号
$where['m.status'] = 1;//会员状态 $where['m.status'] = 1; //会员状态
$data = self::view('member m', true) $data = self::view('member m', true)
->view("money", 'account,freeze,operate_account,bond_account', 'money.mid=m.id', 'left') ->view("money", 'account,freeze,operate_account,bond_account', 'money.mid=m.id', 'left')
->where($where) ->where($where)
->find(); ->find();
return $data; return $data;
}
/**
* 保存注册数据
* @param [type] $data [description]
* @return [type] [description]
* @author 张继立 <404851763@qq.com>
*/
public static function saveData($data)
{
$sdata['mobile'] = $data['mobile'];
$sdata['passwd'] = $data['password'];
$sdata['paywd'] = substr($data['mobile'], -6, 6);
$sdata['pid'] = 0;
$sdata['agent_far'] = intval($data['agent_far']);
$sdata['create_ip'] = get_client_ip(1);
$sdata['create_time'] = time();
$result = self::create($sdata);
if ($result->id) {
Db('money')->insert(['mid' => $result->id]);
$sdata['id'] = $result->id;
return ['status' => 1, 'message' => '注册成功', 'data' => $sdata];
} else {
return ['status' => 0, 'message' => '注册失败'];
} }
/** }
* 保存注册数据
* @param [type] $data [description] /**
* @return [type] [description] * 获取用户列表(下拉选择时使用)
* @author 张继立 <404851763@qq.com> * @param
*/ * @author 路人甲乙
public static function saveData($data) * @return mixed
{ */
$sdata['mobile'] = $data['mobile']; public static function getMemberList()
$sdata['passwd'] = $data['password']; {
$sdata['paywd'] = substr($data['mobile'],-6,6); $list = [];
$sdata['pid'] = 0; $where['status'] = 1;
$sdata['agent_far'] = intval($data['agent_far']); $data_list = Db::name('member')->where($where)->column(true, 'id');
$sdata['create_ip'] = get_client_ip(1); if (!is_null($data_list)) {
$sdata['create_time'] = time(); foreach ($data_list as $v) {
$list[$v['id']] = $v['mobile'];
$result = self::create($sdata);
if($result->id){
Db('money')->insert(['mid'=>$result->id]);
$sdata['id']=$result->id;
return ['status'=>1, 'message'=>'注册成功','data'=>$sdata];
}else{
return ['status'=>0, 'message'=>'注册失败'];
} }
} else {
$list = [];
} }
return $list;
} }
?> }
...@@ -5,8 +5,10 @@ namespace app\money\admin; ...@@ -5,8 +5,10 @@ namespace app\money\admin;
use app\admin\controller\Admin; use app\admin\controller\Admin;
use app\common\builder\ZBuilder; use app\common\builder\ZBuilder;
use app\money\model\EsopPlan as EsopPlanModel; use app\money\model\EsopPlan as EsopPlanModel;
use app\member\model\Member as MemberModel;
use app\stock\model\StockList as StockListModel;
use think\Db; use think\Db;
use think\Hook; use think\Hook;
use think\Cache; use think\Cache;
/** /**
...@@ -21,108 +23,124 @@ class Esopplan extends Admin ...@@ -21,108 +23,124 @@ class Esopplan extends Admin
*/ */
public function index() public function index()
{ {
cookie('__forward__', $_SERVER['REQUEST_URI']); cookie('__forward__', $_SERVER['REQUEST_URI']);
// 获取查询条件 // 获取查询条件
$map = $this->getMap(); $map = $this->getMap();
$order = $this->getOrder(); $order = $this->getOrder();
empty($order) && $order = 'id desc'; empty($order) && $order = 'id desc';
// 数据列表 // 数据列表
$data_list = EsopPlanModel::getAll($map, $order); $data_list = EsopPlanModel::getAll($map, $order);
// 分页数据 // 分页数据
$page = $data_list->render(); $page = $data_list->render();
if(empty($_SERVER["QUERY_STRING"])){ if (empty($_SERVER["QUERY_STRING"])) {
$excel_url=substr(http().$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"],0,- $excel_url = substr(http() . $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"], 0, -5) . "_export";
5)."_export"; } else {
}else{ $excel_url = substr(http() . $_SERVER["SERVER_NAME"] . $_SERVER["PHP_SELF"], 0, -5) . "_export?" . $_SERVER["QUERY_STRING"];
$excel_url=substr(http().$_SERVER["SERVER_NAME"].$_SERVER["PHP_SELF"],0,-
5)."_export?".$_SERVER["QUERY_STRING"];
} }
$btn_excel = [ $btn_excel = [
'title' => '导出EXCEL表', 'title' => '导出EXCEL表',
'icon' => 'fa fa-fw fa-download', 'icon' => 'fa fa-fw fa-download',
'href' => url($excel_url,'','') 'href' => url($excel_url, '', '')
]; ];
return ZBuilder::make('table') return ZBuilder::make('table')
->setSearch(['mid'=>'用户ID','member.name' => '姓名', 'member.mobile' => '手机号']) // 设置搜索框 ->setSearch(['mid' => '用户ID', 'member.name' => '姓名', 'member.mobile' => '手机号']) // 设置搜索框
->addColumns([ // 批量添加数据列 ->addColumns([ // 批量添加数据列
['id', 'ID'], ['id', 'ID'],
['mobile', '手机号'], ['mobile', '手机号'],
['name', '姓名'], ['name', '姓名'],
['title','股票'], ['title', '股票'],
['account', '可用期权'], ['account', '可用期权'],
['plan_account', '期权总值'], ['plan_account', '期权总值'],
['remain_account', '待释放'], ['remain_account', '待释放'],
['release_account', '已释放'], ['release_account', '已释放'],
['duration','总释放天数'], ['duration', '总释放天数'],
['days', '已释放天数'], ['days', '已释放天数'],
['release_time','开始释放时间'], ['release_time', '开始释放时间'],
['create_time', '创建时间'], ['create_time', '创建时间'],
['status', '状态', 'switch'], ['status', '状态', 'switch'],
]) ])
->hideCheckbox() ->hideCheckbox()
->setTableName('plan') ->setTableName('esop_plan')
->addTopButton('custem',$btn_excel) ->addTopButton('custem', $btn_excel)
->addRightButtons(['edit']) // 批量添加右侧按钮 ->addTopButtons('add')
->addRightButton('edit')
->addRightButton('delete')
->addOrder('id,create_time,release_time') ->addOrder('id,create_time,release_time')
->setRowList($data_list) ->setRowList($data_list)
->fetch(); // 渲染模板 ->fetch(); // 渲染模板
} }
/**
public function index_export(){ * 新增
// 获取查询条件 * @return mixed
$map = $this->getMap(); */
$order = $this->getOrder(); public function add()
empty($order) && $order = 'id desc';
// 数据列表
$xlsData = EsopPlanModel::getAll($map, $order);
$title="期权计划列表";
$arrHeader = array('ID','手机号','姓名','股票','可用期权','期权总值','待释放', '已释放','总释放天数', '已释放天数','开始释放时间', '创建时间', '状态');
$fields = array('id','mobile','name','title','account','plan_account','remain_account','release_account','duration','days','release_time','create_time','status');
export($arrHeader,$fields,$xlsData,$title);
}
public function quickEdit($record = [])
{ {
$id = input('post.pk', ''); // 保存数据
$field = input('post.name', ''); if ($this->request->isPost()) {
$value = input('post.value', ''); $data = $this->request->post();
$table = input('post.table', ''); $data['create_time'] = time();
$type = input('post.type', ''); $data['plan_account'] = $data['plan_account'] * 100;
if(in_array($field, array('account', 'plan_account','remain_account','release_account')) ){ //业务逻辑处理
$value *= 100; $result_up = Db::name("esop_plan")->insert($data);
if ($result_up === 1) {
$this->success('添加成功', 'index');
} else {
$this->error($result_up);
}
} }
// 使用ZBuilder快速创建表单
$mid = EsopPlanModel::where('id', $id)->value('mid'); return ZBuilder::make('form')
$old_value = EsopPlanModel::where('id', $id)->value($field); ->setPageTitle('新增') // 设置页面标题
$mobile = Db('member')->where('id',$mid)->value('mobile'); ->addFormItems([ // 批量添加表单项
$details = $mobile.' 字段(' . $field . '),原值:('.$old_value.')新值:(' . $value . ')'; ['select:5', 'mid', '请选择用户', '', MemberModel::getMemberList(), '', url('get_mid'), 'mid'],
['select:5', 'stock_id', '请选择股票', '', StockListModel::getStockList(), '', url('get_stock_id'), 'stock_id'],
['number', 'plan_account', '期权总值', '期权总的价值(港元)', '0'],
['number', 'duration', '总释放天数', '总释放天数', '1000'],
['datetime', 'release_time', '开始时间', '从哪天开始释放期权', '', 'YYYY-MM-DD HH:mm:ss'],
])
->fetch();
}
switch ($type) { // 根据所有用户ID
// 日期时间需要转为时间戳 public function get_mid($mid)
case 'release_time': {
$value = strtotime($value); $arr = [];
break; $where['status'] = 1;
// 开关 $where['id'] = $mid;
case 'switch': $data_list = Db::name('member')->where($where)->find();
$value = $value == 'true' ? 1 : 0; if (!is_null($data_list)) {
break; $arr['code'] = '1'; //判断状态
$arr['msg'] = '请求成功'; //回传信息
$result[$data_list['id']] = $data_list['id'];
$arr['list'] = format_linkage($result); //将一维数组转成联动需要的数据格式
} else {
$arr['code'] = '0'; //判断状态
$arr['msg'] = '数据请求失败'; //回传信息
$arr['list'] = []; //将一维数组转成联动需要的数据格式
} }
$pk = Db('esop_plan')->getPk(); return json($arr);
$result = Db('esop_plan')->where($pk, $id)->setField($field, $value); }
// 根据所有股票ID
if (false !== $result) { public function get_stock_id($stock_id)
Cache::clear(); {
// 记录行为日志 $arr = [];
if (!empty($member_mobile)) { $where['status'] = 1;
call_user_func_array('action_log', ['esop_plan_edit', 'esop_plan', $id, UID, $details]); $where['id'] = $stock_id;
} $data_list = Db::name('stock_list')->where($where)->find();
$this->success('操作成功'); if (!is_null($data_list)) {
$arr['code'] = '1'; //判断状态
$arr['msg'] = '请求成功'; //回传信息
$result[$data_list['id']] = $data_list['id'];
$arr['list'] = format_linkage($result); //将一维数组转成联动需要的数据格式
} else { } else {
$this->error('操作失败'); $arr['code'] = '0'; //判断状态
$arr['msg'] = '数据请求失败'; //回传信息
$arr['list'] = []; //将一维数组转成联动需要的数据格式
} }
return json($arr);
} }
} }
\ No newline at end of file
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
{ {
$data_list = self::view('esop_plan p', true) $data_list = self::view('esop_plan p', true)
->view('member', 'mobile, name, id_card', 'member.id=p.mid', 'left') ->view('member', 'mobile, name, id_card', 'member.id=p.mid', 'left')
->view('stock', 'title', 'stock.id=p.stock_id', 'left') ->view('stock_list', 'title', 'stock_list.id=p.stock_id', 'left')
->where($map) ->where($map)
->order($order) ->order($order)
->paginate() ->paginate()
......
...@@ -8,11 +8,35 @@ ...@@ -8,11 +8,35 @@
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | @author menghui // | @author menghui
namespace app\stock\model; namespace app\stock\model;
use think\model; use think\model;
use think\Db; use think\Db;
class StockList extends Model{
class StockList extends Model
{
// 设置当前模型对应的完整数据表名称 // 设置当前模型对应的完整数据表名称
protected $table = '__STOCK_LIST__'; protected $table = '__STOCK_LIST__';
// 自动写入时间戳 // 自动写入时间戳
protected $autoWriteTimestamp = true; protected $autoWriteTimestamp = true;
}
\ No newline at end of file /**
* 获取股票列表(下拉选择时使用)
* @param
* @author 路人甲乙
* @return mixed
*/
public static function getStockList()
{
$list = [];
$where['status'] = 1;
$data_list = Db::name('stock_list')->where($where)->column(true, 'id');
if (!is_null($data_list)) {
foreach ($data_list as $v) {
$list[$v['id']] = $v['title'];
}
} else {
$list = [];
}
return $list;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment