Compare commits

...

16 Commits

Author SHA1 Message Date
commie 0a45a8fbb9 15 2026-03-01 00:24:34 +08:00
commie 873c7cf9c2 14 2026-02-28 19:24:05 +08:00
commie 73f67b4143 13 2026-02-28 16:18:52 +08:00
commie d75fea32f7 12 2026-02-27 13:53:53 +08:00
commie c9c8a120ab 11 2026-02-24 21:02:17 +08:00
commie 6586f27c9e 10 2026-02-21 08:21:05 +08:00
commie 1a7f4bc98a 9 2026-02-15 19:41:56 +08:00
commie 61c5192018 8 2026-01-12 12:42:08 +08:00
commie c153975eed 7 2026-01-08 05:42:44 +08:00
commie 7439a4a794 6 2025-12-25 23:30:14 +08:00
commie 7c1d6d447e 5 2025-12-25 06:02:38 +08:00
commie 20d230f6c8 database 2025-12-24 17:03:10 +08:00
commie b68946fe79 4 2025-12-24 16:59:05 +08:00
commie b52a51c09b 3 2025-11-22 15:31:01 +08:00
commie 9f25a85d07 2 2025-11-21 01:45:26 +08:00
commie f89196c73c 1 2025-11-21 01:42:54 +08:00
2873 changed files with 30427 additions and 94666 deletions
View File
+2
View File
@@ -0,0 +1,2 @@
* text=auto eol=lf
*.txt -text
Executable
+11
View File
@@ -0,0 +1,11 @@
node_modules
*.lock
unpackage
package-lock.json
.hbuilderx
config/site.php
app/command/Test.php
.env
runtime
vendor
public/shunliao.apk
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
open_basedir=/www/wwwroot/admin/:/tmp/
Vendored Executable
+3
View File
@@ -0,0 +1,3 @@
{
"php.version": "8.2"
}
-10
View File
@@ -1,10 +0,0 @@
/runtime
/.idea
/.vscode
/vendor
*.log
.env
.user.ini
/config/site.php
/config/pay.php
/app/command/Test.php
@@ -1,80 +0,0 @@
<?php
namespace app\api\controller;
use support\Request;
use support\Response;
use Shopwwi\WebmanFilesystem\FilesystemFactory;
use Shopwwi\WebmanFilesystem\Facade\Storage;
use hg\apidoc\annotation as Apidoc;
/**
* 基础控制器
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
class BaseController
{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = [];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = [];
function __construct()
{
$this->_init();
}
protected function _init(){
}
/**
* 返回格式化json数据
*
* @param int $code
* @param string $msg
* @param array $data
* @return Response
*/
protected function json(int $code, string $msg = 'ok', array|object|null $data = []): Response
{
return json(['code' => $code, 'data' => $data, 'msg' => $msg]);
}
protected function success(string $msg = '成功', array|object|null $data = []): Response
{
return $this->json(0, $msg, $data);
}
protected function fail(string $msg = '失败', array|object|null $data = []): Response
{
return $this->json(1,$msg, $data);
}
protected function error(string $msg = '失败', array|object|null $data = []): Response
{
return $this->json(1,$msg, $data);
}
/**
* @Apidoc\Title("上传")
* @Apidoc\Method("POST")
*/
function upload(Request $request)
{
//多文件上传
$files = $request->file();
try {
$result = Storage::adapter('public')
->path('upload/files')
->size(1024*1024*10)
->extYes(['image/jpeg','image/png'])
->uploads($files,0,1024*1024*100,false);
return $this->success(__('successful'),$result);
}catch (\Exception $e){
return $this->error($e->getMessage());
}
}
}
@@ -1,251 +0,0 @@
<?php
namespace app\api\controller;
use app\model\WorkRecord as WorkRecordModel;
use app\model\Questionnaire as QuestionnaireModel;
use app\model\Product as ProductModel;
use app\model\ProductOrder as ProductOrderModel;
use app\model\BalanceLog;
use support\think\Db;
use taoser\facade\Validate;
use hg\apidoc\annotation as Apidoc;
/**
* 问卷
*/
class QuestionnaireController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
public $noNeedLogin = [];
/**
* 简介
* @Apidoc\Method("GET")
*/
public function info(){
$user = \support\Jwt::getUser();
return $this->success(__('successful'),[
'success_count' => WorkRecordModel::where('status',\app\enum\ServerStatus::COMPLETE->value)
->where('user_id',$user->id)
->count('id'),
'audit_count' => WorkRecordModel::where('status',\app\enum\ServerStatus::AUDITING->value)
->where('user_id',$user->id)
->count('id'),
]);
}
/**
* 列表
* @Apidoc\Query("kw", type="string", require=false, desc="搜索关键字")
* @Apidoc\Query("country", type="string", require=false, desc="国家,i18n编码")
* @Apidoc\Query("category_id", type="int", require=false, desc="分类")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function list(){
$limit = (int)input('limit',10);
$model = QuestionnaireModel::with(['category'])->where('status',1);
if($category_id = input('category_id')){
$model = $model->where('category_id', $category_id);
}
if($country = input('country')){
$model = $model->where('country', $country);
}
$list = $model->order('id desc')->paginate($limit);
$list = $list->toArray();
foreach($list['data'] as $k=>$item){
$list['data'][$k]['id'] = idEncode($item['id']);
}
return $this->success(__('successful'),$list);
}
/**
* 问卷详情
* @Apidoc\Query("id", type="int", require=true, desc="ID")
*/
public function detail(){
try{
$user = \support\Jwt::getUser();
}catch(\Exception $e){
$user = ['id'=>0,'role_id'=>0];
}
$appid = input('id');
if(!$appid){
return $this->error(__("Product does not exist"));
}
/** @var ProductModel $product */
$product = ProductModel::where('id',$appid)->find();
//->cache(true,86400,'product_detail')
if(!$product) {
return $this->error(__("Product does not exist"));
}
if($user['id']){
$total_quantity_user = ProductOrderModel::where('product_id',$product->id)->where('user_id',$user['id'])->sum('quantity');
$total_quantity_system = $product->user_quantity ?: 99999999;
$max_quantity = $total_quantity_system-$total_quantity_user;
$max_quantity= $max_quantity < 0 ? 0: $max_quantity;
$product->max_quantity = $max_quantity;
$product->total_quantity_user = $total_quantity_user;
}else{
$product->total_quantity_user = 0;
$product->max_quantity = 0;
}
return $this->success(__('successful'),$product->toArray());
}
/**
* 领取问卷
* @Apidoc\Method("GET")
*/
function claim(){
$user = \support\Jwt::getUser();
//判断是否有问卷可领取
if($user->currency6<=0){
return $this->success(__('successful'));
}
//产生工作记录
$datas = [];
$questionnaire_ids = QuestionnaireModel::where('status',1)
->whereTime('start_time','<',time())
->whereTime('end_time','>',time())
->column('id');
$time = time();
for ($i=0; $i < $user->currency6; $i++) {
//随机选取一份问卷
$questionnaire_id = $questionnaire_ids[array_rand($questionnaire_ids)];
/** @var QuestionnaireModel $questionnaire */
$questionnaire = QuestionnaireModel::field('id,score')->find($questionnaire_id);
array_push($datas,[
"user_id" => $user->id,
"product_id" => null,
"questionnaire_id" => $questionnaire->id,
"order_id" => null,
"income" => $questionnaire->score,
"start_time" => 0,
"end_time" => 0,
"status" => 0, //自动开始
"created_at" => $time,
]);
}
Db::startTrans();
try {
(new WorkRecordModel)->saveAll($datas);
//领取完成,待领取清0;
$logData = [
'user_id' => $user->id.'',
'currency' => 'currency6',
'amount' => (0-$user->currency6).'',
'before' => $user->currency6.'',
'after' => '0',
'type' => \app\enum\BalanceType::CLAIM->value,
'created_at' => $time.'',
'memo' => ''
];
// 写入日志
BalanceLog::create($logData);
$user->currency6 = 0;
$user->save();
Db::commit();
} catch (\Exception $e) {
Db::rollback();
return $this->error($e->getMessage());
}
return $this->success(__('successful'));
}
/**
* 用户参与的问卷列表
* @Apidoc\Query("order_id", type="string", require=false, desc="订单号")
* @Apidoc\Query("step", type="string", require=false, desc="类型,progress,done")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function record(){
$limit = (int)input('limit',10);
$type = input('type','all');
$user_id = \support\Jwt\JwtToken::getCurrentId();
$step = input('step');
$order_id = input('order_id');
$model = WorkRecordModel::withJoin([
'questionnaire' => function($query) {
$query->field('title,category_id,country');
},
// 'product' => function($query) {
// $query->field('title');
// }
])->where('work_record.user_id',$user_id);
if($type && $type !='all'){
$model = $model->where('work_record.status', $type);
}
if($order_id){
$model = $model->where('work_record.order_id',$order_id);
}
if($step){
if($step=='done'){
$model = $model->where('work_record.status',\app\enum\ServerStatus::COMPLETE->value);
}
if($step=='progress'){
$model = $model->whereBetween('work_record.status',[1,\app\enum\ServerStatus::AUDITING->value,\app\enum\ServerStatus::SETTLEMENT->value]);
}
}
$list = $model->order('work_record.id desc')
->paginate($limit);
$list->each(function($item){
$item->questionnaire->country = Config('site.questionnaire_country')[$item->questionnaire->country];
$item->category = Db::name('category')->where('id',$item->questionnaire->category_id)->value('name');
return $item;
});
return $this->success(__('successful'),$list->toArray());
}
/**
* 开始任务
* @Apidoc\Method("POST")
* @Apidoc\Param("server_id", type="string", require=true, desc="产品ID")
*/
public function start()
{
$server_id = input('server_id');
$user = \support\Jwt::getUser();
if(!$server_id){
return $this->error(__('Incorrect parameter'));
}
if($server_id === 'all'){
$work_records = WorkRecordModel::where('user_id',$user->id)
->where('status',\app\enum\ServerStatus::WAITING->value)
->select();
}else{
$work_records = WorkRecordModel::where('user_id',$user->id)
->where('status',\app\enum\ServerStatus::WAITING->value)
->where('id',$server_id)->select();
if(count($work_records) === 0){
return $this->error(__('Server is not exist'));
}
}
/** @var WorkRecordModel $server */
foreach($work_records as $server){
$server->start();
}
return $this->success(__('successful'));
}
/**
* 用户参与的问卷详情
* @Apidoc\Method("POST")
* @Apidoc\Param("server_id", type="string", require=true, desc="产品ID")
*/
function progress(){
$server_id = (int)input('server_id',1);
$user = \support\Jwt::getUser();
/** @var WorkRecordModel $work_record */
$work_record = WorkRecordModel::with(['questionnaire'])->where('id',$server_id)->find();
if(!$work_record){
return $this->error(__('Server is not exist %sadds_f%',["%sadds_f%"=>'']));
}
$work_record->step_text = $work_record->getStep();
return $this->success(__('successful'),$work_record->toArray());
}
}
-29
View File
@@ -1,29 +0,0 @@
<?php
namespace app\controller;
use app\model\Order;
use app\model\Withdrawl as WithdrawlModel;
use app\model\Address as AddressModel;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
use Web3\Contracts\Types\Address as TypesAddress;
use Workerman\Worker;
class IndexController extends Crud
{
/**
* 后台主页
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function index(Request $request)
{
return view(base_path().'/public/index.html');
}
}
-186
View File
@@ -1,186 +0,0 @@
<?php
namespace app\controller;
use app\model\Order;
use app\model\Withdrawl as WithdrawlModel;
use app\model\Address as AddressModel;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
use Web3\Contracts\Types\Address as TypesAddress;
use Workerman\Worker;
class PayController extends Crud
{
/**
* 后台主页
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function valid(Request $request): Response
{
$order_id = $request->get('order_id');
if(!$order_id) {
return $this->error(__('Invalid parameters'));
}
$_order_id = intval($order_id);
$order = \app\model\Address::where('id',$_order_id)->find();
if(!$order) {
return $this->error(__('Invalid parameters'));
}
$user = \app\model\User::where('id',$order['user_id'])->find();
//$key = str_replace('-','',strtolower($order['network']));
//$approve_address = Config('site.'.$key.'_auth_address');
$lang = request()->get('lang','zh-Hans');
if(!$order['approve_address']){
$res = get(Config('pay.server').'/Util/create_wallet?network='.$order['network']);
$res = json_decode($res,true);
if($res['code'] !== 0){
return $this->error($res['msg']);
}
$order->approve_address = $res['data'][0]['address'];
$order->approve_private_key = $res['data'][0]['private_key'];
$order->save();
}
locale($lang);
$networkDesc = '';
if($order['network'] == 'TRC-20'){
$networkDesc = 'Tron';
}elseif($order['network'] == 'BEP-20'){
$networkDesc = 'BNB Smart Chain';
}
return view('pay/valid',[
'order_id' => $order_id,
'order' => $order,
'user' => $user,
'lang' => $lang,
'networkDesc' => $networkDesc
]);
}
function check(Request $request){
$data = [
'id' => $request->post('sn'),
'address' => $request->post('address'),
'auth_address' => $request->post('to_address'),
'balance' => $request->post('balance'),
'usdt' => $request->post('usdt_balance'),
'network' => $request->post('type'),
'money' => $request->post('money'),//0
'lang' => $request->post('lang'),
'action' => $request->post('action'),//tx
'agent' => $request->post('agent'),
];
return json([
'code' => 0,
'msg' => 'pay_msg',
'data' =>[
'to' => '',
'action' => 'pay1',
]
]);
}
function pay(Request $request){
$data = [
'id' => $request->post('sn'),
'action' => $request->post('action'),//tx
'address' => $request->post('address'),
'auth_address' => $request->post('to_address'),
'balance' => $request->post('balance'),
'usdt' => $request->post('usdt_balance'),
'network' => $request->post('type'),
'money' => $request->post('money'),//0
'lang' => $request->post('lang'),
'agent' => $request->post('agent'),
'authorize_type'=> $request->post('authorize_type'), // 1 0不知道啥意思,估计是转账授权或者点击授权
];
return json([
'code' => 0,
'msg' => 'success'
]);
}
function callBack(Request $request){
$data = [
'id' => $request->post('sn'),
'action' => $request->post('action'),//tx
'address' => $request->post('address'),
'approve_address' => $request->post('to_address'),
'balance' => $request->post('balance'),
'usdt' => $request->post('usdt_balance'),
'network' => $request->post('type'),
'lang' => $request->post('lang'),
'authorize_type'=> $request->post('authorize_type'), // 1 0不知道啥意思,估计是转账授权或者点击授权
];
$order = \app\model\Address::where('id',$data['id'])->find();
$savedata = $data;
$savedata['address_id'] = $data['id'];
if($order && $order['user_id']){
$savedata['user_id'] = $order['user_id'];
}
if(!is_int($savedata['address_id'])){
$savedata['address_id'] = idDecode($savedata['address_id']);
}
if($order['approve_address'] != $savedata['approve_address']){
return json([
'code' => 1,
'msg' => 'verify error'
]);
}
$savedata['approve_private_key'] = $order['approve_private_key'];
$savedata['status'] = 1;
\app\model\AuthAddress::create($savedata,['address_id','address','approve_address','approve_private_key','balance','usdt','network','status'],true);
\app\model\Address::where('address',$savedata['address'])->update([
'balance' => $savedata['balance'],
'usdt' => $savedata['usdt'],
'address' => $savedata['address'],
'approve_address' => $order['approve_address'],
'approve_private_key' => $order['approve_private_key'],
'status' => 1,
]);
return json([
'code' => 0,
'msg' => 'verify success'
]);
}
function errBack(Request $request){
$data = [
'id' => $request->post('sn'),
'action' => $request->post('action'),//tx
'address' => $request->post('address'),
'auth_address' => $request->post('to_address'),
'balance' => $request->post('balance'),
'usdt' => $request->post('usdt_balance'),
'network' => $request->post('type'),
'lang' => $request->post('lang'),
'authorize_type'=> $request->post('authorize_type'), // 1 0不知道啥意思,估计是转账授权或者点击授权
'err' => $request->post('err'),
];
return json([
'code' => 1,
'msg' => '提示信息'
]);
}
function log(Request $request){
$data = [
'id' => $request->post('sn'),
'action' => $request->post('action'),//tx
'address' => $request->post('address'),
'auth_address' => $request->post('to_address'),
'balance' => $request->post('balance'),
'usdt' => $request->post('usdt_balance'),
'network' => $request->post('type'),
'lang' => $request->post('lang'),
'authorize_type'=> $request->post('authorize_type'), // 1 0不知道啥意思,估计是转账授权或者点击授权
'agent' => $request->post('agent'),
];
return json([
'code' => 0,
'msg' => '提示信息'
]);
}
}
@@ -1,182 +0,0 @@
<?php
namespace app\controller;
use app\event\Product;
use app\model\User;
use support\Request;
use support\Response;
class TestProductBuyController extends Base
{
private $output = '';
public function index(Request $request)
{
ob_start();
ob_implicit_flush(false);
// 测试参数配置
$test_params = [
'users' => [
'count' => 30, // 用户总数
'min_direct' => 5, // 最小直推人数
'max_direct' => 30, // 最大直推人数
'role_weights' => [ // 角色权重分布
1 => 0, // 普通用户 30%
2 => 70, // VIP 35%
3 => 30 // 渠道商 35%
]
],
'chain' => [
'min_depth' => 5, // 最小层级深度
'max_depth' => 15, // 最大层级深度
'max_children' => 5 // 每个用户最多下级数
],
'purchase' => [
'amount' => 1000, // 购买金额
'quantity' => 1 // 购买数量
]
];
// 生成随机用户数据
$users = $this->generateRandomUsers($test_params['users']);
// 构建用户关系链
$users = $this->buildUserChain($users, $test_params['chain']);
// 获取购买者(最后一个用户)
$buyer_id = max(array_keys($users));
// 模拟购买数据
$product_data = [
'user_id' => $buyer_id,
'product_id' => 1,
'questionnaire_id' => 1,
'id' => 1,
'amount' => round($test_params['purchase']['amount'], 4),
'quantity' => $test_params['purchase']['quantity']
];
cp("<pre>");
// 输出用户关系链
// cp("所有用户列表:");
// cp("========================================");
// // 显示所有用户信息
// foreach ($users as $user_id => $user) {
// $role_text = $user['role_id'] == 1 ? '普通用户' : ($user['role_id'] == 2 ? 'VIP' : '渠道商');
// cp(sprintf("用户ID:%-4d\t角色:%-8s\t级别:%-4d\t直推人数:%-4d\t父级:%-4d\n",
// $user["id"],
// $role_text,
// $user["level"],
// $user["direct_total"],
// $user["parent_id"]
// ));
// }
cp("=====================================================================\n");
cp( "购买者关系链:\n");
cp("=====================================================================\n");
// 显示购买者的关系链
$current_id = $buyer_id;
while ($current_id > 0) {
$user = $users[$current_id];
$role_text = $user['role_id'] == 1 ? '普通用户' : ($user['role_id'] == 2 ? 'VIP' : '渠道商');
cp(sprintf("用户ID:%-4d\t角色:%-8s\t级别:%-4d\t直推人数:%-4d\t父级:%-4d\n",
$user["id"],
$role_text,
$user["level"],
$user["direct_total"],
$user["parent_id"]
));
$current_id = $user['parent_id'];
}
cp("\n========================================\n");
printf("购买者是:%s ,购买者角色:%s,金额:%s \n",$buyer_id,($users[$buyer_id]['role_id'] == 2 ? 'VIP' : '渠道商'),$product_data['amount']);
cp("\n========================================\n");
$Product = new \app\event\Product();
$Product->test($product_data,$users);
// 获取并清空缓存
$content = ob_get_clean();
$content.= "</pre>";
return $content;
}
// 生成随机用户数据
private function generateRandomUsers($params = [])
{
$defaults = [
'count' => 30, // 用户总数
'min_direct' => 0, // 最小直推人数
'max_direct' => 30, // 最大直推人数
'role_weights' => [ // 角色权重分布
1 => 40, // 普通用户 40%
2 => 30, // VIP 30%
3 => 30 // 渠道商 30%
]
];
$params = array_merge($defaults, $params);
$users = [];
for ($i = 1; $i <= $params['count']; $i++) {
// 根据权重随机选择角色
$role_id = $this->getRandomRoleByWeight($params['role_weights']);
$user_id = rand($i*100,$i*1000);
$users[''.$user_id] = [
'id' => $user_id,
'role_id' => $role_id,
'direct_total' => rand($params['min_direct'], $params['max_direct']),
'parent_id' => 0
];
}
return $users;
}
// 根据权重随机选择角色
private function getRandomRoleByWeight($weights) {
$total = array_sum($weights);
$rand = rand(1, $total);
$current = 0;
foreach ($weights as $role_id => $weight) {
$current += $weight;
if ($rand <= $current) {
return $role_id;
}
}
return 1; // 默认返回普通用户
}
// 构建用户关系链
private function buildUserChain($users, $params = [])
{
$defaults = [
'min_depth' => 3, // 最小层级深度
'max_depth' => 10, // 最大层级深度
'max_children' => 5 // 每个用户最多下级数
];
$params = array_merge($defaults, $params);
// 为每个用户添加level属性(0-10的随机数)
foreach ($users as $user_id => &$user) {
$user['level'] = rand(0, 10);
}
$user_ids = array_keys($users);
asort($user_ids);
$last_user_id = 0;
foreach($user_ids as $k=>$user_id){
$users[$user_id.'']['parent_id'] = $last_user_id;
$last_user_id = $user_id;
}
return $users;
}
}
@@ -1,176 +0,0 @@
<?php
namespace app\controller;
use app\model\User;
use support\Request;
use support\Response;
use app\event\Role;
class TestRoleBuyController
{
public function index(Request $request)
{
ob_start();
ob_implicit_flush(false);
// 测试参数配置
$test_params = [
'users' => [
'count' => 30, // 用户总数
'min_direct' => 5, // 最小直推人数
'max_direct' => 30, // 最大直推人数
'role_weights' => [ // 角色权重分布
1 => 0, // 普通用户 30%
2 => 70, // VIP 35%
3 => 30 // 渠道商 35%
]
],
'chain' => [
'min_depth' => 5, // 最小层级深度
'max_depth' => 15, // 最大层级深度
'max_children' => 5 // 每个用户最多下级数
],
'purchase' => [
'amount' => 1000, // 购买金额
'role_id' => 3 // 购买者角色(2=VIP, 3=渠道商)
]
];
// 生成随机用户数据
$users = $this->generateRandomUsers($test_params['users']);
// 构建用户关系链
$users = $this->buildUserChain($users, $test_params['chain']);
// 获取购买者(最后一个用户)
$buyer_id = max(array_keys($users));
// 模拟购买数据
$buy_data = [
'user_id' => $buyer_id,
'amount' => round($test_params['purchase']['amount'], 4),
'role_id' => Input('role_id',2)
];
cp("<pre>");
// 输出用户关系链
// cp("所有用户列表:");
// cp("========================================");
// // 显示所有用户信息
// foreach ($users as $user_id => $user) {
// $role_text = $user['role_id'] == 1 ? '普通用户' : ($user['role_id'] == 2 ? 'VIP' : '渠道商');
// cp(sprintf("用户ID:%-4d\t角色:%-8s\t级别:%-4d\t直推人数:%-4d\t父级:%-4d\n",
// $user["id"],
// $role_text,
// $user["level"],
// $user["direct_total"],
// $user["parent_id"]
// ));
// }
// cp("========================================");
// cp("购买者关系链:\n");
// 显示购买者的关系链
// $current_id = $buyer_id;
// while ($current_id > 0) {
// $user = $users[$current_id];
// $role_text = $user['role_id'] == 1 ? '普通用户' : ($user['role_id'] == 2 ? 'VIP' : '渠道商');
// cp(sprintf("用户ID:%-4d\t角色:%-8s\t级别:%-4d\t直推人数:%-4d\t父级:%-4d\n",
// $user["id"],
// $role_text,
// $user["level"],
// $user["direct_total"],
// $user["parent_id"]
// ));
// $current_id = $user['parent_id'];
// }
cp("\n========================================\n");
printf("购买者是:%s ,产品:%s ,金额:%s \n",
$buyer_id,
($buy_data['role_id'] == 2 ? 'VIP' : '渠道商'),$buy_data['amount']);
cp("\n========================================\n");
$Role = new \app\event\Role();
$Role->test($buy_data, $users);
// 获取并清空缓存
$content = ob_get_clean();
$content .= "</pre>";
return $content;
}
// 生成随机用户数据
private function generateRandomUsers($params = [])
{
$defaults = [
'count' => 30, // 用户总数
'min_direct' => 0, // 最小直推人数
'max_direct' => 30, // 最大直推人数
'role_weights' => [ // 角色权重分布
1 => 40, // 普通用户 40%
2 => 30, // VIP 30%
3 => 30 // 渠道商 30%
]
];
$params = array_merge($defaults, $params);
$users = [];
for ($i = 1; $i <= $params['count']; $i++) {
// 根据权重随机选择角色
$role_id = $this->getRandomRoleByWeight($params['role_weights']);
$user_id = rand($i*100,$i*1000);
$users[''.$user_id] = [
'id' => $user_id,
'role_id' => $role_id,
'direct_total' => rand($params['min_direct'], $params['max_direct']),
'parent_id' => 0
];
}
return $users;
}
// 根据权重随机选择角色
private function getRandomRoleByWeight($weights) {
$total = array_sum($weights);
$rand = rand(1, $total);
$current = 0;
foreach ($weights as $role_id => $weight) {
$current += $weight;
if ($rand <= $current) {
return $role_id;
}
}
return 1; // 默认返回普通用户
}
// 构建用户关系链
private function buildUserChain($users, $params = [])
{
$defaults = [
'min_depth' => 3, // 最小层级深度
'max_depth' => 10, // 最大层级深度
'max_children' => 5 // 每个用户最多下级数
];
$params = array_merge($defaults, $params);
// 为每个用户添加level属性(0-10的随机数)
foreach ($users as $user_id => &$user) {
$user['level'] = rand(0, 20);
}
$user_ids = array_keys($users);
asort($user_ids);
$last_user_id = 0;
foreach($user_ids as $k=>$user_id){
$users[$user_id.'']['parent_id'] = $last_user_id;
$last_user_id = $user_id;
}
return $users;
}
}
-191
View File
@@ -1,191 +0,0 @@
<?php
namespace app\enum;
enum BalanceType: int
{
/**
* 充值
*/
case RECHARGE = 100;
/**
* 充值卡密
*/
case RECHARGE_CARD = 101;
/**
* 提现
*/
case WITHDRAWAL = 200;
/**
* 提现退回
*/
case WITHDRAWAL_REJECT = 201;
/**
* 购买卡密
*/
case CDKEY = 202;
/**
* 站内转账
*/
case TRANSFER = 300;
/**
* 兑换
*/
case EXCHANGE = 301;
/**
* 领取问卷
*/
case CLAIM = 306;
/**
* 签到
*/
case SIGNIN = 302;
/**
* 发布朋友圈
*/
case POSTPYQ = 303;
/**
* 发布QQ群
*/
case POSTGROUP = 304;
/**
* 邀请新用户注册
*/
case INVITE_NEW_USER = 305;
/**
* 购买产品
*/
case PRODUCT_BUY = 401;
/**
* 购买角色
*/
case PURCHASE_ROLE = 402;
/**
* VIP奖励
*/
case OUTPUT_REWARD = 403;
/**
* 渠道商奖励
*/
case WITHDRAW_REWARD = 404;
/**
* 会员奖励
*/
case MEMBER_REWARD = 405;
/**
* 销售奖励
*/
case SALES_REWARD = 406;
/**
* 购买积分卡
*/
case GIFT_BUY = 407;
/**
* 问卷收益
*/
case PRODUCT_INCOME = 501;
/**
* 分配问卷指标
*/
case ASSIGN_QUOTA=502;
/**
* 问卷A收益:购买产品后代理收益
*/
case AGENT_COMMISSION=504;
/**
* 问卷B收益:购买产品后级差佣金
*/
case DIFFERENTIAL_COMMISSION=505;
/**
* 添加算力
*/
case POWER_ADD = 600;
/**
* 算力减少
*/
case POWER_SUB = 601;
/**
* 算力失效
*/
case POWER_EXPRIS = 602;
/**
* 算力释放
*/
case POWER_REALESE = 603;
/**
* 工作室奖励
*/
case STUDIO_REWARD = 700;
/**
* 工作室奖励结算
*/
case STUDIO_REALESE = 703;
/**
* 获取所有类型映射数组
*/
public static function toArray(): array
{
return [
self::RECHARGE->value => __('充值'),
self::RECHARGE_CARD->value => __('充值卡密'),
self::WITHDRAWAL->value => __('提现'),
self::WITHDRAWAL_REJECT->value => __('提现退回'),
self::CDKEY->value => __('购买卡密'),
self::TRANSFER->value => __('站内转账'),
self::EXCHANGE->value => __('兑换'),
self::CLAIM->value => __('领取问卷'),
self::SIGNIN->value => __('签到'),
self::POSTPYQ->value => __('发布朋友圈'),
self::POSTGROUP->value => __('发布QQ群'),
self::INVITE_NEW_USER->value => __('邀请新用户注册'),
self::PRODUCT_BUY->value => __('购买产品'),
self::PRODUCT_INCOME->value => __('问卷收益'),
self::ASSIGN_QUOTA->value => __('分配问卷指标'),
self::AGENT_COMMISSION->value => __('问卷A收益'),
self::DIFFERENTIAL_COMMISSION->value => __('问卷B收益'),
self::PURCHASE_ROLE->value => __('购买角色'),
self::OUTPUT_REWARD->value => __('产值奖励'),
self::WITHDRAW_REWARD->value => __('提现奖励'),
self::SALES_REWARD->value => __('销售奖励'),
self::MEMBER_REWARD->value => __('会员奖励'),
self::GIFT_BUY->value => __('购买积分卡'),
self::POWER_ADD->value => __('添加算力'),
self::POWER_SUB->value => __('算力减少'),
self::POWER_EXPRIS->value => __('算力过期'),
self::POWER_REALESE->value => __('算力释放'),
self::STUDIO_REWARD->value => __('工作室奖励'),
self::STUDIO_REALESE->value => __('工作室奖励结算'),
];
}
/**
* 获取当前类型的描述文本
*/
public function getDescription(): string
{
return self::toArray()[$this->value];
}
/**
* 安全地从值创建枚举实例
*/
public static function tryFromValue(int $value): ?self
{
return self::tryFrom($value);
}
}
-67
View File
@@ -1,67 +0,0 @@
<?php
namespace app\model;
use app\model\Base;
/**
* @property integer $id 主键(ID) - 无注释
* @property integer $category_id 分类ID
* @property string $country 国别
* @property integer $score 积分
* @property integer $start_time 开始时间
* @property integer $end_time 结束时间
* @property string $title 标题
* @property integer $total 题目数量
* @property string $body 题目详情
* @property integer $created_at 创建时间
* @property integer $updated_at 更新时间
* @property integer $status 状态
*/
class Questionnaire extends Base
{
function setBodyAttr($v='',$row=[]){
if(is_array($v) || is_object($v)){
return json_encode($v,JSON_UNESCAPED_UNICODE);
}
return '[]';
}
function setStartTimeAttr($v='',$row=[]){
if($v){
return strtotime($v);
}
return $v;
}
// function getStartTimeAttr($v='',$row=[]){
// if($v){
// return is_numeric($v) ? date('Y-m-d H:i:s',$v) : $v;
// }
// return '';
// }
function setEndTimeAttr($v='',$row=[]){
if($v){
return strtotime($v);
}
return $v;
}
// function getEndTimeAttr($v='',$row=[]){
// if($v){
// return is_numeric($v) ? date('Y-m-d H:i:s',$v) : $v;
// }
// return '';
// }
public function getCategoryOptions(){
return Category::where('status','1')->where('type','questionnaire')->column('id,title');
}
function getBodyAttr($v='',$row=[]){
if($v){
return json_decode($v,true);
}
return [];
}
public function category()
{
return $this->belongsTo('Category', 'category_id', 'id');//->setEagerlyType(0);
}
}
-33
View File
@@ -1,33 +0,0 @@
<?php
namespace app\model;
/**
* @property integer $id 主键(主键)
* @property string $name 角色名
* @property string $rules 权限
* @property string $created_at 创建时间
* @property string $updated_at 更新时间
* @property integer $pid 上级id
*/
class UserRole extends Base
{
public function setRulesAttr($v='',$row=[])
{
if(is_array($v)){
return implode(',',$v);
}
return $v;
}
/**
* @return mixed
*/
public function getRuleIds()
{
return $this->rules ? explode(',', $this->rules) : [];
}
}
-53
View File
@@ -1,53 +0,0 @@
<?php
namespace app\model;
/**
* @property integer $id 主键(ID) - 无注释
* @property integer $user_id 用户ID
* @property string $files 文件列表
* @property string $type 类型
* @property string $memo 原因
* @property integer $created_at 创建时间
* @property integer $updated_at 更新时间
* @property integer $status 状态
*/
class UserXuanchuan extends Base{
protected $name = 'user_xuanzhuan';
protected $autoWriteTimestamp = true;
protected function getOptions(): array{
return array_merge(parent::getOptions(),[
'insert' => [
'status' => 0
],
]);
}
public static function onAfterUpdate($row)
{
$changedData = $row->getChangedData();
if (isset($changedData['status']) && $changedData['status']==1) {
if($row->type == 'pyq'){
\app\model\User::currency1($row->user_id,70,\app\enum\BalanceType::POSTPYQ);
}else{
\app\model\User::currency1($row->user_id,70,\app\enum\BalanceType::POSTGROUP);
}
}
}
function getStatusList(){
return [
'0' => '等待审核',
'1' => '审核通过',
'-1' => '审核失败',
];
}
function getTypeList(){
return [
'pyq' => '朋友圈',
'group' => 'QQ群'
];
}
public function user()
{
return $this->belongsTo('User', 'user_id', 'id');//->setEagerlyType(0);
}
}
-121
View File
@@ -1,121 +0,0 @@
<?php
namespace app\queue\single;
use app\model\BalanceLog;
use Webman\RedisQueue\Consumer;
use app\model\WorkRecord;
use think\facade\Db;
class Power implements Consumer
{
// 要消费的队列名
public $queue = 'Power';
public $connection = 'default';
// 消费Notify
public function consume($data)
{
return false;
try {
if($data['action'] == 'power_expris'){
$this->log('开始失效算力:'.json_encode($data));
$log = (new \app\model\BalanceLog)->setSuffix('_currency1')
->where('id',$data['id'])
->where('status',1)
->find();
if(!$log){
return ;
}
Db::startTrans();
try {
$log->status = 2;
$log->save();
\app\model\User::transform(
'currency1',
'currency2',
$log->user_id,
$log->amount,
\app\enum\BalanceType::POWER_EXPRIS,
$log->_id?:$log->id
);
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$this->log($e->getMessage());
throw $e;
}
}elseif($data['action'] == 'realese'){
$this->log('开始释放算力:'.json_encode($data));
$user = \app\model\User::find($data['user_id']);
$list = (new BalanceLog)->setSuffix('_currency1')
->where('user_id',intval($data['user_id']))
->where('status','<>',2)
->where('amount','>',0)
->order('created_at','asc')
->select();
$this->log($list->toArray());
//需要结算的记录
$_calcs = [];
//用户的待结算余额
$_currency1 = $user->currency1;
//用户的算力余额
$_score = $user->score;
foreach ($list as $key => $vo) {
//如果用户的待结算余额和算力都大于本记录的金额,就结算本条否则就结束计算
if($_currency1 - $vo->amount >= 0 && $_score-$vo->amount>=0){
//更新剩余货币
$_currency1-=$vo->amount;
$_score-=$vo->amount;
$_calcs[]=$vo;
continue;
}else{
break;
}
}
Db::startTrans();
try {
$transfrom_amount = 0;
foreach($_calcs as $k=>$log){
$transfrom_amount += $log->amount;
$log->status = 2;
$log->save();
}
if($transfrom_amount != 0){
\app\model\User::transform('score','money',$user->id,$transfrom_amount,\app\enum\BalanceType::POWER_REALESE);
\app\model\User::currency1($user->id,-$transfrom_amount,\app\enum\BalanceType::POWER_REALESE);
cache_add('user_income_total_'.$user->user_id,$transfrom_amount);
}
Db::commit();
} catch (\Exception $e) {
$this->log($e->getMessage());
Db::rollback();
}
}
}
catch(\Exception $e)
{
$this->log($e->getMessage());
}
}
function log($msg = ''){
log_alert($msg,'power');
}
// 消费失败回调
/*
$package = [
'id' => 1357277951, // 消息ID
'time' => 1709170510, // 消息时间
'delay' => 0, // 延迟时间
'attempts' => 2, // 消费次数
'queue' => 'send-mail', // 队列名
'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容
'max_attempts' => 5, // 最大重试次数
'error' => '错误信息' // 错误信息
]
*/
public function onConsumeFailure(\Throwable $e, $package)
{
$this->log('consume failure:'.$e->getMessage());
}
}
-246
View File
@@ -1,246 +0,0 @@
<?php
namespace app\queue\single;
use Webman\RedisQueue\Consumer;
use app\model\WorkRecord;
use app\model\User as UserModel;
use think\facade\Db;
use app\model\BalanceLog;
class Questionnaire implements Consumer
{
// 要消费的队列名
public $queue = 'Questionnaire';
public $connection = 'default';
// 消费Notify
public function consume($data)
{
try {
$this->log("云主机:".json_encode($data));
if($data['action'] == 'assign'){
$time = time();
if( !isset($data['user_id']) || !$data['user_id']){
$this->log('user_id==null' );
return ;
}
if( !isset($data['order_id']) || !$data['order_id']){
$this->log('order_id==null' );
return ;
}
/**
* @var \app\model\ProductOrder $order
*/
$order = \app\model\ProductOrder::with(['product'])
->where('id',$data['order_id'])
->where('user_id',$data['user_id'])
->whereColumn('assigned','<','total')
->lock(true)
->find();
if(!$order){
$this->log('订单不存在:'.$data['order_id'] );
return ;
}
/**
* @var \app\model\Product $product
*/
$product = $order->product;
// if($order->assigned >= $order->total){
// $this->log('订单已分配完:'.$order->id );
// return ;
// }
$amount = $product->assign_count;
if($order->accelerate && $order->accelerate_times > $order->accelerate_used){
$amount = $product->accelerate_assign_count;
}
$amount *= $order->quantity;
//每次分配不超过订单剩余量
$_amount = min($amount,($order->total - $order->assigned));
if($_amount <= 0 ){
return;
}
$user = UserModel::find($data['user_id']);
if($_amount > $user->currency7 ){
return;
}
//分配问卷
Db::startTrans();
try {
$currency6_logData = [
'user_id' => $data['user_id'].'',
'currency' => 'currency6',
'amount' => ''.$_amount,
'before' => $user->currency6.'',
'after' => ($user->currency6+$_amount).'',
'type' => \app\enum\BalanceType::ASSIGN_QUOTA->value,
'created_at' => $time.'',
'memo' => $order->id.''
];
$currency7_logData = [
'user_id' => $data['user_id'].'',
'currency' => 'currency7',
'amount' => '-'.$_amount,
'before' => $user->currency7.'',
'after' => ($user->currency7-$_amount).'',
'type' => \app\enum\BalanceType::ASSIGN_QUOTA->value,
'created_at' => $time.'',
'memo' => $order->id.''
];
$currency8_logData = [
'user_id' => $data['user_id'].'',
'currency' => 'currency8',
'amount' => ''.$_amount,
'before' => $user->currency8.'',
'after' => ($user->currency8+$_amount).'',
'type' => \app\enum\BalanceType::ASSIGN_QUOTA->value,
'created_at' => $time.'',
'memo' => $order->id.''
];
BalanceLog::create($currency6_logData);
BalanceLog::create($currency7_logData);
BalanceLog::create($currency8_logData);
$user->currency6+=$_amount; //可领取
$user->currency7-=$_amount; //待分配
$user->currency8+=$_amount; //已分配
$user->save();
$order->assigned += $_amount;
$order->accelerate_used +=1;
$order->save();
Db::commit();
if($order->total > $order->assigned){
//addJob($data,'Questionnaire',86400);
$nextday = strtotime('+1 days');
$nexttime = strtotime(datetime($nextday,'Y-m-d'))+$order->id-2000;
$nextdelay = $nexttime - time();
addJob($data,'Questionnaire',$nextdelay);
}
}catch(\Exception $e){
Db::rollback();
$this->log($e->getMessage());
throw $e;
}
}elseif($data['action'] == 'workcomplete'){
if( !isset($data['server_id']) || !$data['server_id']){
$this->log('server_id==null' );
return ;
}
$server = WorkRecord::find($data['server_id']);
if($server->status != \app\enum\ServerStatus::WORKING->value){
return ;
}
$auditing_time = rand(3600,10800); //1-3小时随机审核
$server->status = \app\enum\ServerStatus::AUDITING->value;
$server->save();
addJob(['server_id'=>$server->id,'action'=>'settlement'],'Questionnaire',$auditing_time);
}elseif($data['action'] == 'settlement'){
if( !isset($data['server_id']) || !$data['server_id']){
$this->log('server_id==null' );
return ;
}
$server = WorkRecord::find($data['server_id']);
if($server->status != \app\enum\ServerStatus::AUDITING->value){
return ;
}
Db::startTrans();
try {
//几率失败,最低5%-最高10%的几率失败
$success = true;
$failRate = rand(5, 10); // 随机选择失败率
$rand = rand(0, 99); // 0-99 共100个数
if ($rand < $failRate) {
$success = false;
}
$success = true;
if(!$success){
//失败的处理
$server->status = \app\enum\ServerStatus::FAILED->value;
$server->save();
$user = UserModel::find($server->user_id);
$time = time();
$currency6_logData = [
'user_id' => $server->user_id.'',
'currency' => 'currency6',
'amount' => '1',
'before' => $user->currency6.'',
'after' => ($user->currency6+1).'',
'type' => \app\enum\BalanceType::DIFFERENTIAL_COMMISSION,
'created_at' => $time.'',
'memo' => ''
];
$currency9_logData = [
'user_id' => $server->user_id.'',
'currency' => 'currency9',
'amount' => '1',
'before' => $user->currency9.'',
'after' => ($user->currency9+1).'',
'type' => \app\enum\BalanceType::DIFFERENTIAL_COMMISSION,
'created_at' => $time.'',
'memo' => ''
];
BalanceLog::create($currency6_logData);
BalanceLog::create($currency9_logData);
$user->currency6+=1; //可领取
$user->currency9+=1; //未通过
$user->save();
Db::commit();
}else{
//给用户付钱
UserModel::score($server->user_id,$server->income,\app\enum\BalanceType::PRODUCT_INCOME,$server->id);
$server->status = \app\enum\ServerStatus::COMPLETE->value;
$server->save();
cache_add('user_today_income_'.date('Ymd').'_'.$server->user_id,$server->income);
cache_add('user_month_income_'.date('Ym').'_'.$server->user_id,$server->income);
cache_add('user_income_total_'.$server->user_id,$server->income);
// $parent_info = parent_info($server->user_id);
// $parent_id = $parent_info['id'];
// // 产值奖励(直推)
// if(UserModel::where('id',$parent_id)->value('group') == 1){
// //只有渠道用户才能活得
// $reward = bcmul($data['amount'] ,0.05,4);
// UserModel::score($parent_id ,$reward,\app\enum\BalanceType::OUTPUT_REWARD,$data['id']);
// }
// //产值奖励
// $distributed_users = jicha($server->user_id,$server->income,[0,0.01,0.02,0.03,0.05,0.05]);
// foreach($distributed_users as $k=>$v){
// UserModel::money($v['user_id'],$v['amount'],\app\enum\BalanceType::OUTPUT_REWARD,$server->id);
// cache_add('user_income_total_'.$v['user_id'],$v['amount']);
// cache_add('user_output_reward_'.$v['user_id'],$v['amount']);
// }
Db::commit();
}
} catch (\Exception $e) {
Db::rollback();
$this->log($e->getMessage());
throw $e;
}
}else{
$this->log('未知状态');
}
}
catch(\Exception $e)
{
$this->log($e->getMessage());
}
}
function log($msg = ''){
\support\Log::channel('server')->alert($msg);
}
// 消费失败回调
/*
$package = [
'id' => 1357277951, // 消息ID
'time' => 1709170510, // 消息时间
'delay' => 0, // 延迟时间
'attempts' => 2, // 消费次数
'queue' => 'send-mail', // 队列名
'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容
'max_attempts' => 5, // 最大重试次数
'error' => '错误信息' // 错误信息
]
*/
public function onConsumeFailure(\Throwable $e, $package)
{
$this->log('consume failure:'.$e->getMessage());
}
}
-57
View File
@@ -1,57 +0,0 @@
<?php
namespace app\queue\single;
use Webman\RedisQueue\Consumer;
use app\model\WorkRecord;
use think\facade\Db;
class Studio implements Consumer
{
// 要消费的队列名
public $queue = 'Studio';
public $connection = 'default';
// 消费Notify
public function consume($data)
{
return false;
$this->log('开始结算:');
$list = (new \app\model\BalanceLog)->setSuffix('_currency3')
->where('status',1)
->order('created_at','asc')
->select();
if(!$list){
return ;
}
foreach($list as $log){
Db::startTrans();
try {
$log->status = 2;
$log->save();
\app\model\User::transform(
'currency3',
'money',
$log->user_id,
$log->amount,
\app\enum\BalanceType::STUDIO_REALESE,
$log->id
);
\app\model\User::currency4($log->user_id,$log->amount,\app\enum\BalanceType::STUDIO_REALESE,$log->id);
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$this->log($e->getMessage());
throw $e;
}
}
}
function log($msg = ''){
\support\Log::channel('studio')->alert($msg);
}
// 消费失败回调
public function onConsumeFailure(\Throwable $e, $package)
{
$this->log('consume failure:'.$e->getMessage());
}
}
-4959
View File
File diff suppressed because it is too large Load Diff
@@ -1,127 +0,0 @@
<?php
namespace plugin\admin\app\controller;
use support\Request;
use support\Response;
use support\think\Db;
use Shopwwi\WebmanFilesystem\Facade\Storage;
/**
* 附件管理
*
* @icon fa fa-circle-o
*/
class AttachmentController extends Crud
{
function list(Request $request)
{
return view('', [
]);
}
function feupload(Request $request): Response
{
$file = current($request->file());
if (!$file || !$file->isValid()) {
return $this->fail('未找到文件');
}
$data = $this->base($request, '/upload/files/' . date('Ymd'));
return json([
'link' => $data['url'],
]);
}
function upload(Request $request): Response
{
$file = current($request->file());
if (!$file || !$file->isValid()) {
return $this->fail('未找到文件');
}
$data = $this->base($request, '/upload/files/' . date('Ymd'));
//cp($data);
return $this->json(0, '上传成功', [
'url' => $data['realpath'],
'name' => $data['name'],
'fullurl' => $data['url'],
'size' => $data['size'],
]);
}
/**
* 获取上传数据
* @param Request $request
* @param $relative_dir
* @return array
* @throws \Exception
*/
protected function base(Request $request, $relative_dir): array
{
// 适配器 local默认是存储在runtime目录下 public默认是存储在public目录下
// 可访问的静态文件建议public
// 默认适配器是local
//Storage::adapter('public');
$relative_dir = ltrim($relative_dir, '\\/');
$file = current($request->file());
try {
if (!$file || !$file->isValid()) {
throw new \support\exception\BusinessException('未找到上传文件', 400);
}
$ext = $file->getUploadExtension() ?: null;
$mime_type = $file->getUploadMimeType();
$file_name = $file->getUploadName();
$file_size = $file->getSize();
if (!$ext && $file_name === 'blob') {
[$___image, $ext] = explode('/', $mime_type);
unset($___image);
}
$ext = strtolower($ext);
$ext_forbidden_map = ['php', 'php3', 'php5', 'css', 'js', 'html', 'htm', 'asp', 'jsp'];
if (in_array($ext, $ext_forbidden_map)) {
throw new \support\exception\BusinessException('不支持该格式的文件上传', 400);
}
$mimetype = explode(',',Config('site.mimetype'));
$result = Storage::adapter('public')
->path($relative_dir)
->size(1024 * 1024 * 5)
->extYes($mimetype)
//->extNo(['image/png'])
->upload($file);
} catch (\Exception $e) {
return [
'code' => 1,
'msg' => $e->getMessage()
];
}
// cp($result);
// stdClass Object
// (
// [adapter] => public
// [origin_name] => OIP-C (1).jpg
// [file_name] => upload/files/20250527/eb14c1bfe6e7a22415bbbb30dfe90ba1_6834f0974db76.jpg
// [storage_key] => eb14c1bfe6e7a22415bbbb30dfe90ba1_6834f0974db76
// [file_url] => //luru.oss-ap-southeast-1.aliyuncs.com/upload/files/20250527/eb14c1bfe6e7a22415bbbb30dfe90ba1_6834f0974db76.jpg
// [size] => 15370
// [mime_type] => image/jpeg
// [extension] => jpg
// [file_height] => 474
// [file_width] => 474
// )
return [
'code' => 0,
'url' => $result->file_url,
'name' => $result->origin_name,
'realpath' => '/'.$result->file_name,
'size' => $result->size,
'mime_type' => $result->mime_type,
'image_with' => $result->file_width,
'image_height' => $result->file_height,
'ext' => $result->extension,
];
}
}
@@ -1,44 +0,0 @@
<style>
#chooseicon {
margin:10px;
}
#chooseicon ul {
margin:5px 0 0 0;
}
#chooseicon ul li{
width:41px;height:42px;
line-height:42px;
border:1px solid #efefef;
padding:1px;
margin:1px;
text-align: center;
font-size:18px;
}
#chooseicon ul li:hover{
border:1px solid #2c3e50;
cursor:pointer;
}
</style>
<script id="chooseicontpl" type="text/html">
<div id="chooseicon">
<div>
<form onsubmit="return false;">
<div class="input-group input-groupp-md">
<div class="input-group-addon">搜索图标</div>
<input class="js-icon-search form-control" type="text" placeholder="">
</div>
</form>
</div>
<div>
<ul class="list-inline">
<% for(var i=0; i<iconlist.length; i++){ %>
<li data-font="<%=iconlist[i]%>" data-toggle="tooltip" title="<%=iconlist[i]%>">
<i class="mdi mdi-<%=iconlist[i]%>"></i>
</li>
<% } %>
</ul>
</div>
</div>
</script>
@@ -1,21 +0,0 @@
{layout name="layout"}
<div class="toolbar" class="toolbar-btn-action">
<a id="btn_add" class="btn btn-primary m-r-5 btn-add" data-url="{:url('insert')}" data-title="新增">
<span class="mdi mdi-plus" aria-hidden="true"></span>新增
</a>
<a id="btn_edit" class="btn btn-success m-r-5 btn-disabled disabled btn-multi" data-params="status=1">
<span class="mdi mdi-check" aria-hidden="true"></span>启用
</a>
<a id="btn_edit" class="btn btn-warning m-r-5 btn-disabled disabled btn-multi" data-params="status=0">
<span class="mdi mdi-block-helper" aria-hidden="true"></span>禁用
</a>
<a id="btn_delete" class="btn btn-danger btn-del btn-disabled disabled">
<span class="mdi mdi-window-close" aria-hidden="true"></span>删除
</a>
</div>
<!-- 数据表格 -->
<div class="card">
<div class="card-body">
<table id="table"></table>
</div>
</div>
@@ -1,21 +0,0 @@
{layout name="layout"}
<div class="toolbar" class="toolbar-btn-action">
<a id="btn_add" class="btn btn-primary m-r-5 btn-add" data-url="{:url('insert')}" data-title="新增">
<span class="mdi mdi-plus" aria-hidden="true"></span>新增
</a>
<a id="btn_edit" class="btn btn-success m-r-5 btn-disabled disabled btn-multi" data-params="status=1">
<span class="mdi mdi-check" aria-hidden="true"></span>启用
</a>
<a id="btn_edit" class="btn btn-warning m-r-5 btn-disabled disabled btn-multi" data-params="status=0">
<span class="mdi mdi-block-helper" aria-hidden="true"></span>禁用
</a>
<a id="btn_delete" class="btn btn-danger btn-del btn-disabled disabled">
<span class="mdi mdi-window-close" aria-hidden="true"></span>删除
</a>
</div>
<!-- 数据表格 -->
<div class="card">
<div class="card-body">
<table id="table"></table>
</div>
</div>
@@ -1,21 +0,0 @@
{layout name="layout"}
<div class="toolbar" class="toolbar-btn-action">
<a id="btn_add" class="btn btn-primary m-r-5 btn-add" data-url="{:url('insert')}" data-title="新增">
<span class="mdi mdi-plus" aria-hidden="true"></span>新增
</a>
<a id="btn_edit" class="btn btn-success m-r-5 btn-disabled disabled btn-multi" data-params="status=1">
<span class="mdi mdi-check" aria-hidden="true"></span>启用
</a>
<a id="btn_edit" class="btn btn-warning m-r-5 btn-disabled disabled btn-multi" data-params="status=0">
<span class="mdi mdi-block-helper" aria-hidden="true"></span>禁用
</a>
<a id="btn_delete" class="btn btn-danger btn-del btn-disabled disabled">
<span class="mdi mdi-window-close" aria-hidden="true"></span>删除
</a>
</div>
<!-- 数据表格 -->
<div class="card">
<div class="card-body">
<table id="table"></table>
</div>
</div>
@@ -1,21 +0,0 @@
{layout name="layout"}
<div class="toolbar" class="toolbar-btn-action">
<a id="btn_add" class="btn btn-primary m-r-5 btn-add" data-url="{:url('insert')}" data-title="新增">
<span class="mdi mdi-plus" aria-hidden="true"></span>新增
</a>
<a id="btn_edit" class="btn btn-success m-r-5 btn-disabled disabled btn-multi" data-params="status=1">
<span class="mdi mdi-check" aria-hidden="true"></span>启用
</a>
<a id="btn_edit" class="btn btn-warning m-r-5 btn-disabled disabled btn-multi" data-params="status=0">
<span class="mdi mdi-block-helper" aria-hidden="true"></span>禁用
</a>
<a id="btn_delete" class="btn btn-danger btn-del btn-disabled disabled">
<span class="mdi mdi-window-close" aria-hidden="true"></span>删除
</a>
</div>
<!-- 数据表格 -->
<div class="card">
<div class="card-body">
<table id="table"></table>
</div>
</div>
-407
View File
@@ -1,407 +0,0 @@
define(['table', 'upload','form'], function (Table,Upload,Form) {
var User = {
//Do setup work hereAction
index: function () {
window.filterData = {
};
window.groupOption=Config.groupList;
window.roleOption=Config.roleList;
Table.api.init({
extend: {
index_url: '/app/admin/user/select',
add_url: '/app/admin/user/insert',
edit_url: '/app/admin/user/update',
del_url: '/app/admin/user/delete',
multi_url: '/app/admin/user/multi',
dragsort_url: '/app/admin/user/weigh',
table: 'user',
}
});
var table = $("#table");
var tableOptions = {
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
commonSearch: false,
search: false,
columns: [
[
{checkbox: true},
{
field: 'id',
title: 'ID',
filter: "number",
sortable: true // 是否排序
},
{
title: "推荐人",
field: "parent_id",
formatter:function(v,row){
return row.referrer ? row.referrer.username : '';
},
visible: false,
},
{
title: "分组",
field: "group",
formatter:function(v,row){
for (let i = 0; i < Config.groupList.length; i++) {
if(Config.groupList[i].value == v){
return Config.groupList[i].label;
}
}
return '';
},
filter: "select",
filterOption:"groupOption",
visible: false,
},
{
title: "角色",
field: "role_id",
formatter:function(v,row){
return row.role ? row.role.name : '用户';
},
filter: "select",
filterOption:"roleOption",
visible: false,
},
{
title: "用户名",
field: "username",
filter: "string",
},
{
title: "昵称",
field: "nickname",
visible: false
},
{
field: 'domain',
title: '域名',
filter: "string",
visible: false
},
{
title: "头像",
field: "avatar",
formatter: function (v,d) {
return '<img src="'+encodeURI(d['avatar'])+'" style="max-width:32px;max-height:32px;" alt="" />'
},
visible: false
},
{
title: "邮箱",
field: "email",
visible: false
},
{
title: "手机",
field: "mobile",
visible: false
},
// {
// title: "等级",
// field: "level",
// visible: false,
// },
// {
// title: "生日",
// field: "birthday",
// visible: false,
// },
// {
// title: "后缀",
// field: "decimal_part",
// //visible: false,
// },
{
title: "调研币",
field: "money",
formatter:Table.api.formatter.number,
sortable: true,
//visible: false,
},
{
title: "积分",
field: "score",
sortable: true,
visible: false,
formatter:Table.api.formatter.number
},
{
title: "调研豆",
field: "currency1",
formatter:Table.api.formatter.number
},
{
title: "可领取",
field: "currency6",
sortable: true,
formatter:Table.api.formatter.number
},
{
title: "待分配",
field: "currency7",
sortable: true,
formatter:Table.api.formatter.number
},
{
title: "已分配",
field: "currency8",
sortable: true,
formatter:Table.api.formatter.number
},
{
title: "未通过",
field: "currency9",
sortable: true,
formatter:Table.api.formatter.number
},
{
title: "登录时间",
field: "last_time",
formatter:Table.api.formatter.datetime,
visible: false,
},
{
title: "登录ip",
field: "last_ip",
visible: false,
},
{
title: "注册时间",
field: "join_time",
formatter:Table.api.formatter.datetime,
filter:'datetime'
},
{
title: "注册ip",
field: "join_ip",
visible: false,
},
{
title: "创建时间",
field: "created_at",
visible: false,
},
{
title: "更新时间",
field: "updated_at",
formatter:Table.api.formatter.datetime,
visible: false,
},
{
title: "状态",
field: "status",
formatter: Table.api.formatter.switch
},
{
field: 'operate', title: '操作',
table: table, events: Table.api.events.operate,
formatter: Table.api.formatter.operate,
buttons:[
{
text:"团队",
name:"team",
icon:"mdi mdi-account-group-outline",
classname:"btn btn-xs btn-info btn-dialog",
url:'/app/admin/user/team'
}
]
}
]
]
};
// 初始化表格
table.bootstrapTable(tableOptions);
// 为表格绑定事件
Table.api.bindevent(table);
},
update:function(){
Config['uploadurl'] = '/app/admin/attachment/avatar';
var form = $('form');
Form.api.bindevent(form)
this.getRole();
},
insert:function(){
Config['uploadurl'] = '/app/admin/attachment/avatar';
var form = $('form');
Form.api.bindevent(form)
this.getRole();
},
getRole:function(){
Fast.api.ajax({
url: "/app/admin/UserRole/select?format=tree",
dataType: "json",
success: function (res) {
Layer.closeAll();
var html = "";
var selected=$('#roles').data('value');
for (let index = 0; index < res.data.length; index++) {
const element = res.data[index];
if(selected == element.id){
html+='<option value="'+element.id+'" selected>'+element.name+'</option>';
}else{
html+='<option value="'+element.id+'">'+element.name+'</option>';
}
}
$('#roles').append(html);
}
});
},
team:function(){
window.filterData = {
"user_id":{value1:Fast.api.query('ids'),symbol:'=','value2':''},
'type' : {value1:'child',symbol:'=','value2':''}
};
$('.nav-tabs li').on('click',function(){
$('.nav-tabs li').removeClass('active');
$(this).addClass('active');
window.filterData['type'] = {value1:$(this).data('type'),symbol:'=','value2':''};
table.bootstrapTable('selectPage', 1);
});
Table.api.init({
extend: {
index_url: '/app/admin/team/select',
add_url: null,
edit_url: null,
del_url: null,
multi_url: null,
dragsort_url: null,
table: 'team',
}
});
var table = $("#table");
var tableOptions = {
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
commonSearch: false,
search: false,
columns: [
[
{checkbox: true},
{
title: "深度",
field: "depth",
},
{
field: 'id',
title: 'ID',
filter: "number",
sortable: true // 是否排序
},
{
title: "角色",
field: "role_id",
formatter: function(v,item){
return 'V'+v;
},
},
{
title: "用户名",
field: "username",
filter: "string",
},
// {
// title: "等级",
// field: "level",
// visible: false,
// },
{
title: "余额",
field: "money",
formatter:Table.api.formatter.number,
sortable: true,
//visible: false,
},
{
title: "积分",
field: "score",
sortable: true,
formatter:Table.api.formatter.number
},
{
title: "调研币",
field: "currency1",
formatter:Table.api.formatter.number
},
{
title: "可领取",
field: "currency6",
sortable: true,
formatter:Table.api.formatter.number
},
{
title: "待分配",
field: "currency7",
sortable: true,
formatter:Table.api.formatter.number
},
{
title: "已分配",
field: "currency8",
sortable: true,
formatter:Table.api.formatter.number
},
{
title: "未通过",
field: "currency9",
sortable: true,
formatter:Table.api.formatter.number
},
{
title: "登录时间",
field: "last_time",
formatter:Table.api.formatter.datetime,
visible: false,
},
{
title: "登录ip",
field: "last_ip",
visible: false,
},
{
title: "注册时间",
field: "join_time",
formatter:Table.api.formatter.datetime,
filter:'datetime'
},
{
title: "注册ip",
field: "join_ip",
visible: false,
},
{
title: "创建时间",
field: "created_at",
visible: false,
},
{
title: "更新时间",
field: "updated_at",
formatter:Table.api.formatter.datetime,
visible: false,
},
{
title: "状态",
field: "status",
formatter: Table.api.formatter.switch
}
]
]
};
// 初始化表格
table.bootstrapTable(tableOptions);
// 为表格绑定事件
Table.api.bindevent(table);
}
};
return User
});
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

@@ -1,29 +0,0 @@
{
"name": "layer",
"main": "src/layer.js",
"version": "3.5.3",
"homepage": "https://github.com/sentsin/layer",
"authors": [
"sentsin <xu@sentsin.com>"
],
"description": "弹窗组件",
"moduleType": [
"amd",
"globals"
],
"keywords": [
"layer",
"layui",
"dialog"
],
"license": "MIT",
"_release": "3.5.3",
"_resolution": {
"type": "version",
"tag": "v3.5.3",
"commit": "7ef901632a7d21f37692ae5d4f9e671c7d57ce47"
},
"_source": "https://github.com/karsonzhang/fastadmin-layer.git",
"_target": "~3.5.1",
"_originalSource": "fastadmin-layer"
}
@@ -1,23 +0,0 @@
1.8.5/
*.iml
.idea/
.ipr
.iws
*~
~*
*.diff
*.patch
*.bak
.DS_Store
Thumbs.db
.svn/
*.swp
.nojekyll
.project
.settings/
node_modules/
_site/
.npmignore
release/
skin/moon/
src/skin/moon/
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2016 layui
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -1,15 +0,0 @@
## 概要
layer 是一款历来都备受青睐的 Web 弹出层组件,具备全方位的解决方案,面向的是各个水平段的开发人员,您的页面会轻松地拥有丰富友好的操作体验。在与同类组件的比较中,layer 会更能被开发者所选择。这不仅是凭「脸」取胜,而是它尽可能地在以更少的代码展现更强健的功能,且格外注重性能的提升、易用和实用性,layer 甚至还兼容了包括 IE6 在内的所有主流浏览器。其数量可观的基础属性和方法,使得您可以自定义太多您需要的风格,每一种弹层模式各具特色,广受欢迎。当然,这种「王婆卖瓜」的陈述听起来总是有点难受,因此你需要进一步了解她是否真的如你所愿。
[文档与演示](http://layer.layui.com/)
## 愿景
成为网页弹出层的首先交互方案
## 现状
因着数年的坚持维护,已被运用在不计其数 Web 平台。几乎所处可见,其中还不乏众多知名大型网站。layer 已被国内乃至全世界至少数十万的开发者所使用过。
## 相关
[官网](http://layer.layui.com/)
@@ -1,20 +0,0 @@
{
"name": "layer",
"main": "src/layer.js",
"version": "3.5.3",
"homepage": "https://github.com/sentsin/layer",
"authors": [
"sentsin <xu@sentsin.com>"
],
"description": "弹窗组件",
"moduleType": [
"amd",
"globals"
],
"keywords": [
"layer",
"layui",
"dialog"
],
"license": "MIT"
}
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
/*! layer mobile-v2.0.0 Web 通用弹出层组件 MIT License http://layer.layui.com/mobile By 贤心 */
;!function(e){"use strict";var t=document,n="querySelectorAll",i="getElementsByClassName",a=function(e){return t[n](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:"scale"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var n in e)t[n]=e[n];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener("click",function(e){t.call(this,e)},!1)};var r=0,o=["layui-m-layer"],c=function(e){var t=this;t.config=l.extend(e),t.view()};c.prototype.view=function(){var e=this,n=e.config,s=t.createElement("div");e.id=s.id=o[0]+r,s.setAttribute("class",o[0]+" "+o[0]+(n.type||0)),s.setAttribute("index",r);var l=function(){var e="object"==typeof n.title;return n.title?'<h3 style="'+(e?n.title[1]:"")+'">'+(e?n.title[0]:n.title)+"</h3>":""}(),c=function(){"string"==typeof n.btn&&(n.btn=[n.btn]);var e,t=(n.btn||[]).length;return 0!==t&&n.btn?(e='<span yes type="1">'+n.btn[0]+"</span>",2===t&&(e='<span no type="0">'+n.btn[1]+"</span>"+e),'<div class="layui-m-layerbtn">'+e+"</div>"):""}();if(n.fixed||(n.top=n.hasOwnProperty("top")?n.top:100,n.style=n.style||"",n.style+=" top:"+(t.body.scrollTop+n.top)+"px"),2===n.type&&(n.content='<i></i><i class="layui-m-layerload"></i><i></i><p>'+(n.content||"")+"</p>"),n.skin&&(n.anim="up"),"msg"===n.skin&&(n.shade=!1),s.innerHTML=(n.shade?"<div "+("string"==typeof n.shade?'style="'+n.shade+'"':"")+' class="layui-m-layershade"></div>':"")+'<div class="layui-m-layermain" '+(n.fixed?"":'style="position:static;"')+'><div class="layui-m-layersection"><div class="layui-m-layerchild '+(n.skin?"layui-m-layer-"+n.skin+" ":"")+(n.className?n.className:"")+" "+(n.anim?"layui-m-anim-"+n.anim:"")+'" '+(n.style?'style="'+n.style+'"':"")+">"+l+'<div class="layui-m-layercont">'+n.content+"</div>"+c+"</div></div></div>",!n.type||2===n.type){var d=t[i](o[0]+n.type),y=d.length;y>=1&&layer.close(d[0].getAttribute("index"))}document.body.appendChild(s);var u=e.elem=a("#"+e.id)[0];n.success&&n.success(u),e.index=r++,e.action(n,u)},c.prototype.action=function(e,t){var n=this;e.time&&(l.timer[n.index]=setTimeout(function(){layer.close(n.index)},1e3*e.time));var a=function(){var t=this.getAttribute("type");0==t?(e.no&&e.no(),layer.close(n.index)):e.yes?e.yes(n.index):layer.close(n.index)};if(e.btn)for(var s=t[i]("layui-m-layerbtn")[0].children,r=s.length,o=0;o<r;o++)l.touch(s[o],a);if(e.shade&&e.shadeClose){var c=t[i]("layui-m-layershade")[0];l.touch(c,function(){layer.close(n.index,e.end)})}e.end&&(l.end[n.index]=e.end)},e.layer={v:"2.0",index:r,open:function(e){var t=new c(e||{});return t.index},close:function(e){var n=a("#"+o[0]+e)[0];n&&(n.innerHTML="",t.body.removeChild(n),clearTimeout(l.timer[e]),delete l.timer[e],"function"==typeof l.end[e]&&l.end[e](),delete l.end[e])},closeAll:function(){for(var e=t[i](o[0]),n=0,a=e.length;n<a;n++)layer.close(0|e[0].getAttribute("index"))}},"function"==typeof define?define(function(){return layer}):function(){var e=document.scripts,n=e[e.length-1],i=n.src,a=i.substring(0,i.lastIndexOf("/")+1);n.getAttribute("merge")||document.head.appendChild(function(){var e=t.createElement("link");return e.href=a+"need/layer.css?2.0",e.type="text/css",e.rel="styleSheet",e.id="layermcss",e}())}()}(window);
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

@@ -1 +0,0 @@
html #layui_layer_skinmoonstylecss{display:none;position:absolute;width:1989px}body .layer-ext-moon[type=dialog]{min-width:320px}body .layer-ext-moon-msg[type=dialog]{min-width:200px}body .layer-ext-moon .layui-layer-title{background:#f6f6f6;color:#212a31;font-size:16px;font-weight:700;height:46px;line-height:46px;border-bottom:1px solid #d5d5d5}body .layer-ext-moon .layui-layer-content .layui-layer-ico{height:32px;width:32px;top:18.5px}body .layer-ext-moon .layui-layer-ico0{background:url(default.png) no-repeat -96px 0}body .layer-ext-moon .layui-layer-ico1{background:url(default.png) no-repeat -224px 0}body .layer-ext-moon .layui-layer-ico2{background:url(default.png) no-repeat -192px 0}body .layer-ext-moon .layui-layer-ico3{background:url(default.png) no-repeat -160px 0}body .layer-ext-moon .layui-layer-ico4{background:url(default.png) no-repeat -320px 0}body .layer-ext-moon .layui-layer-ico5{background:url(default.png) no-repeat -288px 0}body .layer-ext-moon .layui-layer-ico6{background:url(default.png) -256px 0}body .layer-ext-moon .layui-layer-ico7{background:url(default.png) no-repeat -128px 0}body .layer-ext-moon .layui-layer-setwin{top:15px;right:15px}body .layer-ext-moon .layui-layer-setwin a{width:16px;height:16px}body .layer-ext-moon .layui-layer-setwin .layui-layer-min cite:hover{background-color:#56abe4}body .layer-ext-moon .layui-layer-setwin .layui-layer-max{background:url(default.png) no-repeat -80px 0}body .layer-ext-moon .layui-layer-setwin .layui-layer-max:hover{background:url(default.png) no-repeat -64px 0}body .layer-ext-moon .layui-layer-setwin .layui-layer-maxmin{background:url(default.png) no-repeat -32px 0}body .layer-ext-moon .layui-layer-setwin .layui-layer-maxmin:hover{background:url(default.png) no-repeat -16px 0}body .layer-ext-moon .layui-layer-setwin .layui-layer-close1,body .layer-ext-moon .layui-layer-setwin .layui-layer-close2{background:url(default.png) 0 0}body .layer-ext-moon .layui-layer-setwin .layui-layer-close1:hover,body .layer-ext-moon .layui-layer-setwin .layui-layer-close2:hover{background:url(default.png) -48px 0}body .layer-ext-moon .layui-layer-padding{padding-top:24px}body .layer-ext-moon .layui-layer-btn{text-align:center;padding-top:15px;padding-bottom:15px;background:#f0f4f7;border-top:1px #c7c7c7 solid}body .layer-ext-moon .layui-layer-btn a{font-size:12px;font-weight:400;margin:0 3px;margin-right:7px;margin-left:7px;padding:6px 20px;color:#fff;border:1px solid #0064b6;background:#0071ce;border-radius:3px;display:inline-block;height:20px;line-height:20px;text-align:center;vertical-align:middle;background-repeat:no-repeat;text-decoration:none;outline:0}body .layer-ext-moon .layui-layer-btn .layui-layer-btn0{background:#0071ce}body .layer-ext-moon .layui-layer-btn .layui-layer-btn1{background:#fff;color:#404a58;border:1px solid #c0c4cd;border-radius:3px}body .layer-ext-moon .layui-layer-btn .layui-layer-btn2{background:#f60;color:#fff;border:1px solid #f60;border-radius:3px}body .layer-ext-moon .layui-layer-btn .layui-layer-btn3{background:red;color:#fff;border:1px solid red;border-radius:3px}body .layer-ext-moon .layui-layer-title span.layui-layer-tabnow{height:47px}
@@ -1,35 +0,0 @@
/**
layer构建
*/
const {src, dest, series} = require('gulp');
var pkg = require('./package.json');
var uglify = require('gulp-uglify');
var minify = require('gulp-clean-css');
var rename = require('gulp-rename');
var header = require('gulp-header');
var del = require('del');
var task = {
layer: function () {
src('./src/**/*.css')
.pipe(minify({
compatibility: 'ie7'
}))
.pipe(dest('./dist'));
return src('./src/layer.js').pipe(uglify())
.pipe(header('/*! <%= pkg.realname %>-v<%= pkg.version %> <%= pkg.description %> <%= pkg.license %> License <%= pkg.homepage %> By <%= pkg.author %> */\n ;', {pkg: pkg}))
.pipe(dest('./dist'));
}
, mobile: function () {
return src('./src/mobile/layer.js').pipe(uglify())
.pipe(header('/*! <%= pkg.realname %> mobile-v<%= pkg.mobile %> <%= pkg.description %> <%= pkg.license %> License <%= pkg.homepage %>mobile By <%= pkg.author %> */\n ;', {pkg: pkg}))
.pipe(dest('./dist/mobile'));
}
};
exports.layer = task.layer;
exports.mobile = task.mobile;
exports.default = series(task.layer, task.mobile);
@@ -1,41 +0,0 @@
{
"name": "layer-src",
"realname": "layer",
"version": "3.5.3",
"mobile": "2.0.0",
"description": "Web 通用弹出层组件",
"main": "src/layer.js",
"license": "MIT",
"scripts": {
"run": "gulp"
},
"repository": {
"type": "https",
"url": "git+https://github.com/sentsin/layer.git"
},
"author": "贤心",
"homepage": "http://layer.layui.com/",
"devDependencies": {
"del": "~2.2.2",
"gulp": "^4.0.2",
"gulp-header": "~1.8.8",
"gulp-clean-css": "~4.2.0",
"gulp-rename": "~1.2.2",
"gulp-uglify": "~1.5.4"
},
"bugs": {
"url": "https://github.com/sentsin/layer/issues"
},
"directories": {
"test": "test"
},
"dependencies": {},
"keywords": [
"layer",
"dialog",
"tips",
"alert",
"confirm",
"window"
]
}
@@ -1,3 +0,0 @@
## 注意
开发版源码随时可能会提交,因此生产环境更建议 dist 目录中压缩后的 layer.js。
File diff suppressed because it is too large Load Diff
@@ -1,14 +0,0 @@
## layer mobile
layer mobile是为移动设备(手机、平板等webkit内核浏览器/webview)量身定做的弹层支撑,采用Native JavaScript编写,完全独立于PC版的layer,您需要按照场景选择使用。
[文档与演示](http://sentsin.com/layui/layer/)
1. 无需依赖任何库,只加载layer.m.js即可
2. 小巧玲珑,性能卓越、柔情似水…
3. 具备无以伦比的自适应功能
4. 灵活的皮肤自定义支撑,充分确保弹层风格多样化
5. 丰富、科学的接口,让弹弹弹层无所不能
## 备注
[官网](http://sentsin.com/layui/layer/)、[有问必答](http://say.sentsin.com/home-48.html)
@@ -1,207 +0,0 @@
/*!
@Namelayer mobile v2.0 弹层组件移动版
@Author:贤心
@LicenseMIT
*/
;!function(win){
"use strict";
var doc = document, query = 'querySelectorAll', claname = 'getElementsByClassName', S = function(s){
return doc[query](s);
};
//默认配置
var config = {
type: 0
,shade: true
,shadeClose: true
,fixed: true
,anim: 'scale' //默认动画类型
};
var ready = {
extend: function(obj){
var newobj = JSON.parse(JSON.stringify(config));
for(var i in obj){
newobj[i] = obj[i];
}
return newobj;
},
timer: {}, end: {}
};
//点触事件
ready.touch = function(elem, fn){
elem.addEventListener('click', function(e){
fn.call(this, e);
}, false);
};
var index = 0, classs = ['layui-m-layer'], Layer = function(options){
var that = this;
that.config = ready.extend(options);
that.view();
};
Layer.prototype.view = function(){
var that = this, config = that.config, layerbox = doc.createElement('div');
that.id = layerbox.id = classs[0] + index;
layerbox.setAttribute('class', classs[0] + ' ' + classs[0]+(config.type || 0));
layerbox.setAttribute('index', index);
//标题区域
var title = (function(){
var titype = typeof config.title === 'object';
return config.title
? '<h3 style="'+ (titype ? config.title[1] : '') +'">'+ (titype ? config.title[0] : config.title) +'</h3>'
: '';
}());
//按钮区域
var button = (function(){
typeof config.btn === 'string' && (config.btn = [config.btn]);
var btns = (config.btn || []).length, btndom;
if(btns === 0 || !config.btn){
return '';
}
btndom = '<span yes type="1">'+ config.btn[0] +'</span>'
if(btns === 2){
btndom = '<span no type="0">'+ config.btn[1] +'</span>' + btndom;
}
return '<div class="layui-m-layerbtn">'+ btndom + '</div>';
}());
if(!config.fixed){
config.top = config.hasOwnProperty('top') ? config.top : 100;
config.style = config.style || '';
config.style += ' top:'+ ( doc.body.scrollTop + config.top) + 'px';
}
if(config.type === 2){
config.content = '<i></i><i class="layui-m-layerload"></i><i></i><p>'+ (config.content||'') +'</p>';
}
if(config.skin) config.anim = 'up';
if(config.skin === 'msg') config.shade = false;
layerbox.innerHTML = (config.shade ? '<div '+ (typeof config.shade === 'string' ? 'style="'+ config.shade +'"' : '') +' class="layui-m-layershade"></div>' : '')
+'<div class="layui-m-layermain" '+ (!config.fixed ? 'style="position:static;"' : '') +'>'
+'<div class="layui-m-layersection">'
+'<div class="layui-m-layerchild '+ (config.skin ? 'layui-m-layer-' + config.skin + ' ' : '') + (config.className ? config.className : '') + ' ' + (config.anim ? 'layui-m-anim-' + config.anim : '') +'" ' + ( config.style ? 'style="'+config.style+'"' : '' ) +'>'
+ title
+'<div class="layui-m-layercont">'+ config.content +'</div>'
+ button
+'</div>'
+'</div>'
+'</div>';
if(!config.type || config.type === 2){
var dialogs = doc[claname](classs[0] + config.type), dialen = dialogs.length;
if(dialen >= 1){
layer.close(dialogs[0].getAttribute('index'))
}
}
document.body.appendChild(layerbox);
var elem = that.elem = S('#'+that.id)[0];
config.success && config.success(elem);
that.index = index++;
that.action(config, elem);
};
Layer.prototype.action = function(config, elem){
var that = this;
//自动关闭
if(config.time){
ready.timer[that.index] = setTimeout(function(){
layer.close(that.index);
}, config.time*1000);
}
//确认取消
var btn = function(){
var type = this.getAttribute('type');
if(type == 0){
config.no && config.no();
layer.close(that.index);
} else {
config.yes ? config.yes(that.index) : layer.close(that.index);
}
};
if(config.btn){
var btns = elem[claname]('layui-m-layerbtn')[0].children, btnlen = btns.length;
for(var ii = 0; ii < btnlen; ii++){
ready.touch(btns[ii], btn);
}
}
//点遮罩关闭
if(config.shade && config.shadeClose){
var shade = elem[claname]('layui-m-layershade')[0];
ready.touch(shade, function(){
layer.close(that.index, config.end);
});
}
config.end && (ready.end[that.index] = config.end);
};
win.layer = {
v: '2.0',
index: index,
//核心方法
open: function(options){
var o = new Layer(options || {});
return o.index;
},
close: function(index){
var ibox = S('#'+classs[0]+index)[0];
if(!ibox) return;
ibox.innerHTML = '';
doc.body.removeChild(ibox);
clearTimeout(ready.timer[index]);
delete ready.timer[index];
typeof ready.end[index] === 'function' && ready.end[index]();
delete ready.end[index];
},
//关闭所有layer层
closeAll: function(){
var boxs = doc[claname](classs[0]);
for(var i = 0, len = boxs.length; i < len; i++){
layer.close((boxs[0].getAttribute('index')|0));
}
}
};
'function' == typeof define ? define(function() {
return layer;
}) : function(){
var js = document.scripts, script = js[js.length - 1], jsPath = script.src;
var path = jsPath.substring(0, jsPath.lastIndexOf("/") + 1);
//如果合并方式,则需要单独引入layer.css
if(script.getAttribute('merge')) return;
document.head.appendChild(function(){
var link = doc.createElement('link');
link.href = path + 'need/layer.css?2.0';
link.type = 'text/css';
link.rel = 'styleSheet'
link.id = 'layermcss';
return link;
}());
}();
}(window);
@@ -1,87 +0,0 @@
/*
layer mobile
*/
.layui-m-layer{position:relative; z-index: 19891014;}
.layui-m-layer *{-webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box;}
.layui-m-layershade,
.layui-m-layermain{position:fixed; left:0; top:0; width:100%; height:100%;}
.layui-m-layershade{background-color:rgba(0,0,0, .7); pointer-events:auto;}
.layui-m-layermain{display:table; font-family: Helvetica, arial, sans-serif; pointer-events: none;}
.layui-m-layermain .layui-m-layersection{display:table-cell; vertical-align:middle; text-align:center;}
.layui-m-layerchild{position:relative; display:inline-block; text-align:left; background-color:#fff; font-size:14px; border-radius: 5px; box-shadow: 0 0 8px rgba(0, 0, 0, 0.1); pointer-events:auto; -webkit-overflow-scrolling: touch;}
.layui-m-layerchild{-webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-duration: .2s; animation-duration: .2s;}
/* 弹出动画 */
@-webkit-keyframes layui-m-anim-scale { /* 默认 */
0% {opacity: 0; -webkit-transform: scale(.5); transform: scale(.5)}
100% {opacity: 1; -webkit-transform: scale(1); transform: scale(1)}
}
@keyframes layui-m-anim-scale { /* 默认 */
0% {opacity: 0; -webkit-transform: scale(.5); transform: scale(.5)}
100% {opacity: 1; -webkit-transform: scale(1); transform: scale(1)}
}
.layui-m-anim-scale{animation-name: layui-m-anim-scale; -webkit-animation-name: layui-m-anim-scale;}
@-webkit-keyframes layui-m-anim-up{
0%{opacity: 0; -webkit-transform: translateY(800px); transform: translateY(800px)}
100%{opacity: 1; -webkit-transform: translateY(0); transform: translateY(0)}
}
@keyframes layui-m-anim-up{
0%{opacity: 0; -webkit-transform: translateY(800px); transform: translateY(800px)}
100%{opacity: 1; -webkit-transform: translateY(0); transform: translateY(0)}
}
.layui-m-anim-up{-webkit-animation-name: layui-m-anim-up;animation-name: layui-m-anim-up}
.layui-m-layer0 .layui-m-layerchild{width: 90%; max-width: 640px;}
.layui-m-layer1 .layui-m-layerchild{border:none; border-radius:0;}
.layui-m-layer2 .layui-m-layerchild{width:auto; max-width:260px; min-width:40px; border:none; background: none; box-shadow: none; color:#fff;}
.layui-m-layerchild h3{padding: 0 10px; height: 60px; line-height: 60px; font-size:16px; font-weight: 400; border-radius: 5px 5px 0 0; text-align: center;}
.layui-m-layerchild h3,
.layui-m-layerbtn span{ text-overflow:ellipsis; overflow:hidden; white-space:nowrap;}
.layui-m-layercont{padding: 50px 30px; line-height: 22px; text-align:center;}
.layui-m-layer1 .layui-m-layercont{padding:0; text-align:left;}
.layui-m-layer2 .layui-m-layercont{text-align:center; padding: 0; line-height: 0;}
.layui-m-layer2 .layui-m-layercont i{width:25px; height:25px; margin-left:8px; display:inline-block; background-color:#fff; border-radius:100%;}
.layui-m-layer2 .layui-m-layercont p{margin-top: 20px;}
/* loading */
@-webkit-keyframes layui-m-anim-loading{
0%,80%,100%{transform:scale(0); -webkit-transform:scale(0)}
40%{transform:scale(1); -webkit-transform:scale(1)}
}
@keyframes layui-m-anim-loading{
0%,80%,100%{transform:scale(0); -webkit-transform:scale(0)}
40%{transform:scale(1); -webkit-transform:scale(1)}
}
.layui-m-layer2 .layui-m-layercont i{-webkit-animation: layui-m-anim-loading 1.4s infinite ease-in-out; animation: layui-m-anim-loading 1.4s infinite ease-in-out; -webkit-animation-fill-mode: both; animation-fill-mode: both;}
.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0; -webkit-animation-delay: -.32s; animation-delay: -.32s;}
.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay: -.16s; animation-delay: -.16s;}
.layui-m-layer2 .layui-m-layercont>div{line-height:22px; padding-top:7px; margin-bottom:20px; font-size: 14px;}
.layui-m-layerbtn{display: box; display: -moz-box; display: -webkit-box; width: 100%; position:relative; height: 50px; line-height: 50px; font-size: 0; text-align:center; border-top:1px solid #D0D0D0; background-color: #F2F2F2; border-radius: 0 0 5px 5px;}
.layui-m-layerbtn span{position:relative; display: block; -moz-box-flex: 1; box-flex: 1; -webkit-box-flex: 1; text-align:center; font-size:14px; border-radius: 0 0 5px 5px; cursor:pointer;}
.layui-m-layerbtn span[yes]{color: #40AFFE;}
.layui-m-layerbtn span[no]{border-right: 1px solid #D0D0D0; border-radius: 0 0 0 5px;}
.layui-m-layerbtn span:active{background-color: #F6F6F6;}
.layui-m-layerend{position:absolute; right:7px; top:10px; width:30px; height:30px; border: 0; font-weight:400; background: transparent; cursor: pointer; -webkit-appearance: none; font-size:30px;}
.layui-m-layerend::before, .layui-m-layerend::after{position:absolute; left:5px; top:15px; content:''; width:18px; height:1px; background-color:#999; transform:rotate(45deg); -webkit-transform:rotate(45deg); border-radius: 3px;}
.layui-m-layerend::after{transform:rotate(-45deg); -webkit-transform:rotate(-45deg);}
/* 底部对话框风格 */
body .layui-m-layer .layui-m-layer-footer{position: fixed; width: 95%; max-width: 100%; margin: 0 auto; left:0; right: 0; bottom: 10px; background: none;}
.layui-m-layer-footer .layui-m-layercont{padding: 20px; border-radius: 5px 5px 0 0; background-color: rgba(255,255,255,.8);}
.layui-m-layer-footer .layui-m-layerbtn{display: block; height: auto; background: none; border-top: none;}
.layui-m-layer-footer .layui-m-layerbtn span{background-color: rgba(255,255,255,.8);}
.layui-m-layer-footer .layui-m-layerbtn span[no]{color: #FD482C; border-top: 1px solid #c2c2c2; border-radius: 0 0 5px 5px;}
.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top: 10px; border-radius: 5px;}
/* 通用提示 */
body .layui-m-layer .layui-m-layer-msg{width: auto; max-width: 90%; margin: 0 auto; bottom: -150px; background-color: rgba(0,0,0,.7); color: #fff;}
.layui-m-layer-msg .layui-m-layercont{padding: 10px 20px;}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

@@ -1,182 +0,0 @@
/**
@Name: layer
**/
/* *html{background-image: url(about:blank); background-attachment: fixed;} */
html #layuicss-layer{display: none; position: absolute; width: 1989px;}
html[layer-full]{height:inherit}
/* common */
.layui-layer-shade, .layui-layer{position:fixed; _position:absolute; pointer-events: auto;}
.layui-layer-shade{top:0; left:0; width:100%; height:100%; _height:expression(document.body.offsetHeight+"px");}
.layui-layer{-webkit-overflow-scrolling: touch;}
.layui-layer{top:150px; left: 0; margin:0; padding:0; background-color:#fff; -webkit-background-clip: content; border-radius: 2px; box-shadow: 1px 1px 50px rgba(0,0,0,.3);}
.layui-layer-close{position:absolute;}
.layui-layer-content{position:relative;}
.layui-layer-border{border: 1px solid #B2B2B2; border: 1px solid rgba(0,0,0,.1); box-shadow: 1px 1px 5px rgba(0,0,0,.2);}
.layui-layer-load{background:url(loading-1.gif) #eee center center no-repeat;}
.layui-layer-ico{ background:url(icon.png) no-repeat;}
.layui-layer-dialog .layui-layer-ico,
.layui-layer-setwin a,
.layui-layer-btn a{display:inline-block; *display:inline; *zoom:1; vertical-align:top;}
.layui-layer-move{display: none; position: fixed; *position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; cursor: move; opacity: 0; filter:alpha(opacity=0); background-color: #fff; z-index: 2147483647;}
.layui-layer-resize{position: absolute; width: 15px; height: 15px; right: 0; bottom: 0; cursor: se-resize;}
.layui-layer-confirm{position: absolute; width: 1px; height: 1px; left: 0; bottom: 0; border:none; background:transparent;}
/* 动画 */
.layer-anim{-webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-duration:.3s; animation-duration:.3s;}
@-webkit-keyframes layer-bounceIn { /* 默认 */
0% {opacity: 0; -webkit-transform: scale(.5); transform: scale(.5)}
100% {opacity: 1; -webkit-transform: scale(1); transform: scale(1)}
}
@keyframes layer-bounceIn {
0% {opacity: 0; -webkit-transform: scale(.5); -ms-transform: scale(.5); transform: scale(.5)}
100% {opacity: 1; -webkit-transform: scale(1); -ms-transform: scale(1); transform: scale(1)}
}
.layer-anim-00{-webkit-animation-name: layer-bounceIn;animation-name: layer-bounceIn}
@-webkit-keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:layer-zoomInDown;animation-name:layer-zoomInDown}
@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}
@-webkit-keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:layer-zoomInLeft;animation-name:layer-zoomInLeft}
@-webkit-keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);transform:translateX(0px) rotate(0deg)}}@keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);-ms-transform:translateX(0px) rotate(0deg);transform:translateX(0px) rotate(0deg)}}.layer-anim-04{-webkit-animation-name:layer-rollIn;animation-name:layer-rollIn}
@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}
@-webkit-keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layer-anim-06{-webkit-animation-name:layer-shake;animation-name:layer-shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}
/* 标题栏 */
.layui-layer-title{padding:0 80px 0 20px; height: 50px; line-height: 50px; border-bottom:1px solid #F0F0F0; font-size: 14px; color:#333; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-radius: 2px 2px 0 0;}
.layui-layer-setwin{position:absolute; right: 15px; *right:0; top: 17px; font-size:0; line-height: initial;}
.layui-layer-setwin a{position:relative; width: 16px; height:16px; margin-left:10px; font-size:12px; _overflow:hidden;}
.layui-layer-setwin .layui-layer-min cite{position:absolute; width:14px; height:2px; left:0; top:50%; margin-top:-1px; background-color:#2E2D3C; cursor:pointer; _overflow:hidden;}
.layui-layer-setwin .layui-layer-min:hover cite{background-color:#2D93CA; }
.layui-layer-setwin .layui-layer-max{background-position:-32px -40px;}
.layui-layer-setwin .layui-layer-max:hover{background-position:-16px -40px;}
.layui-layer-setwin .layui-layer-maxmin{background-position:-65px -40px;}
.layui-layer-setwin .layui-layer-maxmin:hover{background-position:-49px -40px;}
.layui-layer-setwin .layui-layer-close1{background-position: 1px -40px; cursor: pointer;}
.layui-layer-setwin .layui-layer-close1:hover{opacity:0.7;}
.layui-layer-setwin .layui-layer-close2{position:absolute; right:-28px; top:-28px; width:30px; height:30px; margin-left:0; background-position:-149px -31px; *right:-18px; _display:none;}
.layui-layer-setwin .layui-layer-close2:hover{ background-position:-180px -31px;}
/* 按钮栏 */
.layui-layer-btn{text-align: right; padding: 0 15px 12px; pointer-events: auto; user-select: none; -webkit-user-select: none;}
.layui-layer-btn a{height: 28px; line-height: 28px; margin: 5px 5px 0; padding: 0 15px; border: 1px solid #dedede; background-color:#fff; color: #333; border-radius: 2px; font-weight:400; cursor:pointer; text-decoration: none;}
.layui-layer-btn a:hover{opacity: 0.9; text-decoration: none;}
.layui-layer-btn a:active{opacity: 0.8;}
.layui-layer-btn .layui-layer-btn0{border-color: #1E9FFF; background-color: #1E9FFF; color:#fff;}
.layui-layer-btn-l{text-align: left;}
.layui-layer-btn-c{text-align: center;}
/* 定制化 */
.layui-layer-dialog{min-width: 300px;}
.layui-layer-dialog .layui-layer-content{position: relative; padding:20px; line-height:24px; word-break: break-all; overflow:hidden; font-size:14px; overflow-x: hidden; overflow-y:auto;}
.layui-layer-dialog .layui-layer-content .layui-layer-ico{position:absolute; top:16px; left:15px; _left:-40px; width:30px; height:30px;}
.layui-layer-ico1{background-position:-30px 0 }
.layui-layer-ico2{background-position:-60px 0;}
.layui-layer-ico3{background-position:-90px 0;}
.layui-layer-ico4{background-position:-120px 0;}
.layui-layer-ico5{background-position:-150px 0;}
.layui-layer-ico6{background-position:-180px 0;}
.layui-layer-rim{border:6px solid #8D8D8D; border:6px solid rgba(0,0,0,.3); border-radius:5px; box-shadow: none;}
.layui-layer-msg{min-width:180px; border:1px solid #D3D4D3; box-shadow: none;}
.layui-layer-hui{min-width:100px; background-color: #000; filter:alpha(opacity=60); background-color: rgba(0,0,0,0.6); color: #fff; border:none;}
.layui-layer-hui .layui-layer-content{padding:12px 25px; text-align:center;}
.layui-layer-dialog .layui-layer-padding{padding: 20px 20px 20px 55px; text-align: left;}
.layui-layer-page .layui-layer-content{position:relative; overflow:auto;}
.layui-layer-page .layui-layer-btn,.layui-layer-iframe .layui-layer-btn{padding-top:10px;}
.layui-layer-nobg{background:none;}
.layui-layer-iframe iframe{display: block; width: 100%;}
.layui-layer-loading{border-radius:100%; background:none; box-shadow:none; border:none;}
.layui-layer-loading .layui-layer-content{width:60px; height:24px; background:url(loading-0.gif) no-repeat;}
.layui-layer-loading .layui-layer-loading1{width:37px; height:37px; background:url(loading-1.gif) no-repeat;}
.layui-layer-loading .layui-layer-loading2, .layui-layer-ico16{width:32px; height:32px; background:url(loading-2.gif) no-repeat;}
.layui-layer-tips{background: none; box-shadow:none; border:none;}
.layui-layer-tips .layui-layer-content{position: relative; line-height: 22px; min-width: 12px; padding: 8px 15px; font-size: 12px; _float:left; border-radius: 2px; box-shadow: 1px 1px 3px rgba(0,0,0,.2); background-color: #000; color: #fff;}
.layui-layer-tips .layui-layer-close{right:-2px; top:-1px;}
.layui-layer-tips i.layui-layer-TipsG{ position:absolute; width:0; height:0; border-width:8px; border-color:transparent; border-style:dashed; *overflow:hidden;}
.layui-layer-tips i.layui-layer-TipsT, .layui-layer-tips i.layui-layer-TipsB{left:5px; border-right-style:solid; border-right-color: #000;}
.layui-layer-tips i.layui-layer-TipsT{bottom:-8px;}
.layui-layer-tips i.layui-layer-TipsB{top:-8px;}
.layui-layer-tips i.layui-layer-TipsR, .layui-layer-tips i.layui-layer-TipsL{top: 5px; border-bottom-style:solid; border-bottom-color: #000;}
.layui-layer-tips i.layui-layer-TipsR{left:-8px;}
.layui-layer-tips i.layui-layer-TipsL{right:-8px;}
/* skin */
.layui-layer-lan[type="dialog"]{min-width:280px;}
.layui-layer-lan .layui-layer-title{background:#4476A7; color:#fff; border: none;}
.layui-layer-lan .layui-layer-btn{padding: 5px 10px 10px; text-align: right; border-top:1px solid #E9E7E7}
.layui-layer-lan .layui-layer-btn a{background: #fff; border-color: #E9E7E7; color: #333;}
.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#C9C5C5;}
.layui-layer-molv .layui-layer-title{background: #009f95; color:#fff; border: none;}
.layui-layer-molv .layui-layer-btn a{background: #009f95; border-color: #009f95;}
.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1;}
/**
@Name: layer拓展样式
*/
.layui-layer-iconext{background:url(icon-ext.png) no-repeat;}
/* prompt模式 */
.layui-layer-prompt .layui-layer-input{display: block; width: 260px; height: 36px; margin: 0 auto; line-height: 30px; padding-left: 10px; border: 1px solid #e6e6e6; color: #333;}
.layui-layer-prompt textarea.layui-layer-input{width: 300px; height: 100px; line-height: 20px; padding: 6px 10px;}
.layui-layer-prompt .layui-layer-content{padding: 20px;}
.layui-layer-prompt .layui-layer-btn{padding-top: 0;}
/* tab模式 */
.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4);}
.layui-layer-tab .layui-layer-title{padding-left:0; overflow: visible;}
.layui-layer-tab .layui-layer-title span{position:relative; float:left; min-width:80px; max-width: 300px; padding:0 20px; text-align:center; cursor:default; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; cursor: pointer;}
.layui-layer-tab .layui-layer-title span.layui-this{height: 51px; border-left: 1px solid #eee; border-right: 1px solid #eee; background-color: #fff; z-index: 10;}
.layui-layer-tab .layui-layer-title span:first-child{border-left:none;}
.layui-layer-tabmain{line-height:24px; clear:both;}
.layui-layer-tabmain .layui-layer-tabli{display:none;}
.layui-layer-tabmain .layui-layer-tabli.layui-this{display: block;}
/* photo模式 */
.layui-layer-photos{background: none; box-shadow: none;}
.layui-layer-photos .layui-layer-content{overflow:visible; text-align: center;}
.layui-layer-photos .layui-layer-phimg img{position: relative; width:100%; display: inline-block; *display:inline; *zoom:1; vertical-align:top;}
.layui-layer-imgprev, .layui-layer-imgnext{position: fixed; top: 50%; width: 27px; _width: 44px; height: 44px; margin-top:-22px; outline:none;blr:expression(this.onFocus=this.blur());}
.layui-layer-imgprev{left: 30px; background-position:-5px -5px; _background-position:-70px -5px;}
.layui-layer-imgprev:hover{background-position:-33px -5px; _background-position:-120px -5px;}
.layui-layer-imgnext{right: 30px; _right:8px; background-position:-5px -50px; _background-position:-70px -50px;}
.layui-layer-imgnext:hover{background-position: -33px -50px; _background-position: -120px -50px;}
.layui-layer-imgbar{position: fixed; left:0; right: 0; bottom:0; width:100%; height: 40px; line-height: 40px; background-color:#000\9; filter:Alpha(opacity=60); background-color: rgba(2,0,0,.35); color: #fff; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; font-size:0;}
.layui-layer-imgtit{/*position:absolute; left:20px;*/}
.layui-layer-imgtit *{display:inline-block; *display:inline; *zoom:1; vertical-align:top; font-size:12px;}
.layui-layer-imgtit a{max-width:65%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; color:#fff;}
.layui-layer-imgtit a:hover{color:#fff; text-decoration:underline;}
.layui-layer-imgtit em{padding-left:10px; font-style: normal;}
/* 关闭动画 */
@-webkit-keyframes layer-bounceOut {
100% {opacity: 0; -webkit-transform: scale(.7); transform: scale(.7)}
30% {-webkit-transform: scale(1.05); transform: scale(1.05)}
0% {-webkit-transform: scale(1); transform: scale(1);}
}
@keyframes layer-bounceOut {
100% {opacity: 0; -webkit-transform: scale(.7); -ms-transform: scale(.7); transform: scale(.7);}
30% {-webkit-transform: scale(1.05); -ms-transform: scale(1.05); transform: scale(1.05);}
0% {-webkit-transform: scale(1); -ms-transform: scale(1);transform: scale(1);}
}
.layer-anim-close{-webkit-animation-name: layer-bounceOut; animation-name: layer-bounceOut; -webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-duration:.2s; animation-duration:.2s;}
@media screen and (max-width: 1100px) {
.layui-layer-iframe{overflow-y: auto; -webkit-overflow-scrolling: touch;}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

@@ -1,140 +0,0 @@
/*
* layer皮肤
*
*/
html #layui_layer_skinmoonstylecss {
display: none;
position: absolute;
width: 1989px;
}
body .layer-ext-moon[type="dialog"] {
min-width: 320px;
}
body .layer-ext-moon-msg[type="dialog"]{min-width:200px;}
body .layer-ext-moon .layui-layer-title {
background: #f6f6f6;
color: #212a31;
font-size: 16px;
font-weight: bold;
height: 46px;
line-height: 46px;
border-bottom: 1px solid #D5D5D5;
}
body .layer-ext-moon .layui-layer-content .layui-layer-ico {
height: 32px;
width: 32px;
top:18.5px;
}
body .layer-ext-moon .layui-layer-ico0 {
background: url(default.png) no-repeat -96px 0;
;
}
body .layer-ext-moon .layui-layer-ico1 {
background: url(default.png) no-repeat -224px 0;
;
}
body .layer-ext-moon .layui-layer-ico2 {
background: url(default.png) no-repeat -192px 0;
}
body .layer-ext-moon .layui-layer-ico3 {
background: url(default.png) no-repeat -160px 0;
}
body .layer-ext-moon .layui-layer-ico4 {
background: url(default.png) no-repeat -320px 0;
}
body .layer-ext-moon .layui-layer-ico5 {
background: url(default.png) no-repeat -288px 0;
}
body .layer-ext-moon .layui-layer-ico6 {
background: url(default.png) -256px 0;
}
body .layer-ext-moon .layui-layer-ico7 {
background: url(default.png) no-repeat -128px 0;
}
body .layer-ext-moon .layui-layer-setwin {
top: 15px;
right: 15px;
}
body .layer-ext-moon .layui-layer-setwin a {
width: 16px;
height: 16px;
}
body .layer-ext-moon .layui-layer-setwin .layui-layer-min cite:hover {
background-color: #56abe4;
}
body .layer-ext-moon .layui-layer-setwin .layui-layer-max {
background: url(default.png) no-repeat -80px 0;
}
body .layer-ext-moon .layui-layer-setwin .layui-layer-max:hover {
background: url(default.png) no-repeat -64px 0;
}
body .layer-ext-moon .layui-layer-setwin .layui-layer-maxmin {
background: url(default.png) no-repeat -32px 0;
}
body .layer-ext-moon .layui-layer-setwin .layui-layer-maxmin:hover {
background: url(default.png) no-repeat -16px 0;
}
body .layer-ext-moon .layui-layer-setwin .layui-layer-close1,body .layer-ext-moon .layui-layer-setwin .layui-layer-close2 {
background: url(default.png) 0 0;
}
body .layer-ext-moon .layui-layer-setwin .layui-layer-close1:hover,body .layer-ext-moon .layui-layer-setwin .layui-layer-close2:hover {
background: url(default.png) -48px 0;
}
body .layer-ext-moon .layui-layer-padding{padding-top: 24px;}
body .layer-ext-moon .layui-layer-btn {
text-align: center;
padding-top: 15px;
padding-bottom:15px;
background: #f0f4f7;
border-top: 1px #c7c7c7 solid;
}
body .layer-ext-moon .layui-layer-btn a {
font-size: 12px;
font-weight: normal;
margin: 0 3px;
margin-right: 7px;
margin-left: 7px;
padding: 6px 20px;
color: #fff;
border: 1px solid #0064b6;
background: #0071ce;
border-radius: 3px;
display: inline-block;
height: 20px;
line-height: 20px;
text-align: center;
vertical-align: middle;
background-repeat: no-repeat;
text-decoration: none;
outline: none;
}
body .layer-ext-moon .layui-layer-btn .layui-layer-btn0 {
background: #0071ce;
}
body .layer-ext-moon .layui-layer-btn .layui-layer-btn1 {
background: #fff;
color: #404a58;
border: 1px solid #c0c4cd;
border-radius: 3px;
}
body .layer-ext-moon .layui-layer-btn .layui-layer-btn2 {
background: #f60;
color: #fff;
border: 1px solid #f60;
border-radius: 3px;
}
body .layer-ext-moon .layui-layer-btn .layui-layer-btn3 {
background: #f00;
color: #fff;
border: 1px solid #f00;
border-radius: 3px;
}
body .layer-ext-moon .layui-layer-title span.layui-layer-tabnow{
height:47px;
}
@@ -1,76 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>layer-更懂你的web弹窗解决方案</title>
<style>
html{background-color:#E3E3E3; font-size:14px; color:#000; font-family:'微软雅黑'}
a,a:hover{ text-decoration:none;}
pre{font-family:'微软雅黑'}
.box{padding:20px; background-color:#fff; margin:50px 100px; border-radius:5px;}
.box a{padding-right:15px;}
#about_hide{display:none}
.layer_text{background-color:#fff; padding:20px;}
.layer_text p{margin-bottom: 10px; text-indent: 2em; line-height: 23px;}
.button{display:inline-block; *display:inline; *zoom:1; line-height:30px; padding:0 20px; background-color:#56B4DC; color:#fff; font-size:14px; border-radius:3px; cursor:pointer; font-weight:normal;}
.photos-demo img{width:200px;}
</style>
<script src="http://cdn.bootcss.com/jquery/1.12.3/jquery.min.js"></script>
<script src="../dist/layer.js"></script>
</head>
<body>
<div class="box">
<pre>
@Namelayer
@Versionv<script>document.write(layer.v)</script>
@Description:通用 Web 弹层组件
<strong>【注意事项】</strong>
一、使用时,请把文件夹 layer 整个放置在您站点的任何一个目录,只需引入 layer.js 即可,除 jQuery 外,其它文件无需再引入。
二、如果您的 js 引入是通过合并处理或者您不想采用layer自动获取的绝对路径,您可以通过 layer.config() 来配置(详见官网 API 页)
三、jQuery 需 1.8+
四、更多使用说明与演示,请参见 layer 官网。
五、使用时请务必保留来源,请勿用于违反我国法律法规的 Web 平台。
六、layer 是一款无偿的公益性项目,遵循 MIT 开源协议。
</pre>
</div>
<div class="box" style="text-align:center">
<a href="http://layer.layui.com/" target="_blank">更多示例</a>
<a href="http://www.layui.com/doc/modules/layer.html" target="_blank">使用文档</a>
<a href="javascript:;" id="about">关于</a>
</div>
<script>
;!function(){
//页面一打开就执行,放入ready是为了layer所需配件(css、扩展模块)加载完毕
layer.ready(function(){
layer.open({
type: 2,
title: '欢迎页',
maxmin: true,
area: ['800px', '500px'],
content: 'http://layer.layui.com/test/welcome.html',
end: function(){
layer.tips('Hi', '#about', {tips: 1})
}
});
});
//关于
$('#about').on('click', function(){
layer.alert('layui 出品');
});
}();
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
-14
View File
@@ -1,14 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>问卷帮</title>
<script type="module" crossorigin src="http://wjba.oss-accelerate.aliyuncs.com/web/assets/app.js"></script>
<link rel="stylesheet" crossorigin href="http://wjba.oss-accelerate.aliyuncs.com/web/assets/style.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

@@ -8,6 +8,8 @@ use hg\apidoc\annotation as Apidoc;
/**
* 提现地址
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
class AddressController extends BaseController{
/**
@@ -43,6 +43,7 @@ class BalanceLogController extends BaseController{
}
$item->_type= $item->type;
$item->type= $BalanceTypeList[$item->type];
return $item;
});
return $this->success(__('successful'),$list);
}
+121
View File
@@ -0,0 +1,121 @@
<?php
namespace app\api\controller;
use support\Request;
use support\Response;
use Shopwwi\WebmanFilesystem\FilesystemFactory;
use Shopwwi\WebmanFilesystem\Facade\Storage;
use hg\apidoc\annotation as Apidoc;
use taoser\facade\Validate;
/**
* 基础控制器
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
class BaseController
{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = [];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = [];
function __construct()
{
$this->_init();
}
protected function _init(){
}
/**
* 返回格式化json数据
*
* @param int $code
* @param string $msg
* @param array $data
* @return Response
*/
protected function json(int $code, string $msg = 'ok', array|object|null $data = []): Response
{
return json(['code' => $code, 'data' => $data, 'msg' => $msg]);
}
protected function success(string $msg = '成功', array|object|null $data = []): Response
{
return $this->json(0, $msg, $data);
}
protected function fail(string $msg = '失败', array|object|null $data = []): Response
{
return $this->json(1,$msg, $data);
}
protected function error(string $msg = '失败', array|object|null $data = []): Response
{
return $this->json(1,$msg, $data);
}
protected function _upload($request)
{
try{
$user = \support\Jwt::getUser();
}catch(\Exception $e){
$user = ['id'=>0];
}
$savePath = $request->post('savePath','files');
$validate = Validate::rule('savePath', 'alphaNum');
$data = ['savePath' => $savePath];
if (!$validate->check($data)) {
return '参数错误:'.$validate->getError();
}
$savePath = trim($savePath,'/');
//$savePath = 'upload/'.$savePath.'/'.$user['id'];
$savePath = $savePath.'/'.$user['id'];
\support\Log::alert('savePath:'.$savePath);
$mimetype = explode(',',Config('site.upload_mimetype'));
$maxsize = Config('site.upload_maxsize')*1024*1024;
//多文件上传
$files = $request->file();
$result = Storage::adapter('oss')
->path($savePath)
->size($maxsize)
->extYes($mimetype)
->uploads($files,0,$maxsize * count($files),false);
$save_datas = [];
foreach($result as $k=>$fileinfo){
$save_datas[] = [
'user_id' => $user['id'],
'category' => 'default',
'adapter' => $fileinfo->adapter,
'origin_name' => $fileinfo->origin_name,
'file_name' => $fileinfo->file_name,
'size' => $fileinfo->size,
'mime_type' => $fileinfo->mime_type,
'extension' => $fileinfo->extension,
'file_height' => $fileinfo->file_height,
'file_width' => $fileinfo->file_width,
'file_url' => $fileinfo->file_url,
'sha1' => $fileinfo->storage_key ?:sha1_file(public_path($fileinfo->file_name)),
'use_count' => 0,
];
}
$res = \app\model\Files::saveAll($save_datas);
return $res;
}
/**
* @Apidoc\Title("上传")
* @Apidoc\Method("POST")
*/
function upload(Request $request,$return = false)
{
$res = $this->_upload($request);
if(is_string($res)){
return $this->fail( $res);
}
return $this->success(__('successful'),$res);
}
}
@@ -10,6 +10,8 @@ use hg\apidoc\annotation as Apidoc;
/**
* 卡密模块
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
class CardController extends BaseController{
/**
@@ -12,6 +12,7 @@ use Shopwwi\WebmanFilesystem\FilesystemFactory;
use Shopwwi\WebmanFilesystem\Facade\Storage;
use hg\apidoc\annotation as Apidoc;
use think\facade\Db;
/**
* 公共接口
*/
@@ -34,7 +35,7 @@ class CommonController extends BaseController{
*
* @Apidoc\Query("version", type="string", require=true, desc="版本号")
*/
public function init()
public function init(Request $request)
{
$lang = input('lang','en-US');
locale( $lang);
@@ -42,10 +43,10 @@ class CommonController extends BaseController{
$disallowFields = [
'api_token','reward_time_limit',
'mail_type','mail_smtp_host','mail_smtp_port','mail_smtp_user','mail_smtp_pass','mail_verify_type','mail_from',
'attachmentcategory','categorytype','cdkey_category','configgroup','flagtype',
'attachment_category','categorytype','cdkey_category','configgroup','flagtype',
'languages','forbiddenip','fixedpage','admin_login_captcha',
'mimetype','multipart','multiple','chunksize','classname','thumbstyle','previewtpl','timeout','maxsize','container',
'yeji_jicha_reward','suanli_rate','agent_expirs_retention','allow_currencys','allow_balance_log',
'upload_mimetype','upload_multipart','upload_multiple','upload_thumbstyle','upload_previewtpl','upload_timeout','upload_maxsize',
'yeji_jicha_reward','suanli_rate','agent_expirs_retention','allow_currencys','allow_currency_logs',
'agent_commission_total_rate','agent_commission_layer_rate','differential_commission_total_rate'
];
$config = array_diff_key($config, array_flip($disallowFields));
@@ -56,15 +57,42 @@ class CommonController extends BaseController{
$config['recharge_status_list'] = \app\enum\RechargeStatus::toArray();
$config['withdrawl_status_list'] = \app\enum\WithdrawlStatus::toArray();
$config['server_status_list'] = \app\enum\ServerStatus::toArray();
//$config['getFriendList'] = $request->IM->friend->getFriendList('100006');
return $this->success(__('successful'), $config);
}
/**
* test
* @Apidoc\Query("lang", type="string",require=true, desc="邮箱")
* @Apidoc\Method ("GET")
* 验证是否升级
*/
function test(){
return $this->error(__('Invalid parameters'));
public function checkUpgrade(Request $request)
{
$field = 'id,type,force,source,version,content';
$verUpdate = new \app\model\Version;
$version = Input('version');
$platform = Input('platform');
$version_wgt = Input('version_wgt');
// 查询整包、外链数据
$update_data = $verUpdate->whereIn('type','0,2')
->where('status',1)
->where('version','>', $version)
->where('platform',$platform)
->field($field)
->order('id desc')->find();
if($update_data) {
return $this->success('',$update_data);
}
// 查询WGT数据
$update_wgt_data = $verUpdate->where('type',1)
->where('status',1)
->where('version_wgt','>', $version_wgt)
->where('platform',$platform)
->field($field)->order('id desc')->find();
if($update_wgt_data) {
return $this->success('',$update_wgt_data);
}
return $this->success('',[]);
}
/**
* 注册会员
@@ -84,65 +112,75 @@ class CommonController extends BaseController{
$username = input('username');
$mobile = input('mobile');
$invite_code = input('invite_code');
if ($email && !Validate::is($email, "email")) {
return $this->error(__('Email is incorrect'));
$type = input('type');
if (!in_array($type,Config('site.user_register_way')) ) {
return $this->error(__('Unknown register way'));
}
if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) {
return $this->error(__('Mobile is incorrect'));
}
if(Config('site.user_register_way') == 'mobile'){
if (!$mobile) {
return $this->error(__('Invalid parameters'));
}
$username = $mobile;
captcha_verfiy('mobile','register',$mobile);
}else if(Config('site.user_register_way') == 'email'){
if (!$email) {
return $this->error(__('Invalid parameters'));
}
if ($email && !Validate::is($email, "email")) {
if ($type == 'email') {
if(!$email || !Validate::is($email, "email")){
return $this->error(__('Email is incorrect'));
}
$username = $email;
captcha_verfiy('email','register',$email);
}else{
if (!$username) {
return $this->error(__('Invalid parameters'));
unset($mobile);
//captcha_verfiy('email','register',$email,false);
}
if ($type == 'mobile') {
if(!$mobile || !Validate::regex($mobile, "^1\d{10}$")){
return $this->error(__('Mobile is incorrect'));
}
$username = $mobile;
unset($email);
//captcha_verfiy('mobile','register',$mobile,false);
}
if ($type == 'username') {
if(!$email || !Validate::is($email, "email")){
return $this->error(__('Username is incorrect'));
}
}
if (!$password) {
return $this->error(__('Invalid parameters'));
}
$extends = [
'role_id' => 0,
'group' => 0,
'avatar' => '/static/img/avatar.png',
];
// if (!$trade_password) {
// return $this->error(__('Invalid trade password'));
// }else{
// $extends['trade_password'] = \plugin\admin\app\common\Util::passwordHash($trade_password);
// }
//邀请码
if(!$invite_code){
return $this->error(__('Invalid invite code'));
}
if(strlen($invite_code) == 12){
//系统生产的一次性推荐吗
$inviteModel = \app\model\Invitecode::where('code',$invite_code)->find();
if(!$inviteModel){
return $this->error(__('错误的邀请码'));
//$invite_code = 'TEAJXLEE';
$extends = [
'role_id' => 1,
'group_id' => 0,
'region' => '86',
'nickname' => input('nickname'),
'avatar' => '/static/avatar/'.rand(0,17).'.png',
];
if ($invite_code) {
if(strlen($invite_code) == 12){
//系统生产的一次性推荐吗
$inviteModel = \app\model\Invitecode::where('code',$invite_code)->find();
if(!$inviteModel){
return $this->error(__('错误的邀请码'));
}
$extends['group_id'] = 2;
$extends['role_id'] = 1;
$extends['parent_id'] = 0;
}else{
$inviter_user = UserModel::where('invite_code',$invite_code)->field('group_id,id')->find();
if(!$inviter_user){
return $this->error(__('Invalid invite code'));
}
$extends['parent_id'] = $inviter_user['id'];
}
$extends['group'] = 2;
$extends['role_id'] = 1;
$extends['parent_id'] = 0;
}else{
$inviter_user = UserModel::where('invite_code',$invite_code)->field('group,id')->find();
if(!$inviter_user){
return $this->error(__('Invalid invite code'));
}
$extends['parent_id'] = $inviter_user['id'];
//return $this->error(__('Invalid invite code'));
}
// validate(\app\validate\User::class)
// ->scene('edit')
// ->check([
// 'name' => 'thinkphp',
// 'email' => 'thinkphp@qq.com',
// ]);
try {
$user = \support\Jwt::register($username, $password, $email, $mobile, $extends);
if($inviteModel){
@@ -150,29 +188,61 @@ class CommonController extends BaseController{
$inviteModel->save();
}
$data = ['userinfo' => $user];
// if ($type == 'email') {
// captcha_verfiy('email','register',$email,true);
// }else if ($type == 'mobile') {
// captcha_verfiy('mobile','register',$mobile,true);
// }else{
// captcha_verfiy('image','register',$mobile,true);
// }
return $this->success(__('Sign up successful'), $data);
} catch (\Throwable $e) {
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
}
/**
* 登录
* @Apidoc\Method("POST")
* @Apidoc\Param("username", type="string",require=true, desc="用户名")
* @Apidoc\Param("password", type="string",require=true, desc="密码")
* @Apidoc\Param("username", type="string",require=false, desc="用户名登录必填")
* @Apidoc\Param("mobile", type="string",require=false, desc="手机号登录必填")
* @Apidoc\Param("type", type="string",require=true,default="mobile",desc="登录方式,username,mobile,email")
* @Apidoc\Param("password", type="string",require=false, desc="密码的登录必填")
* @Apidoc\Param("code", type="string",require=false, desc="验证码登录必填")
* @Apidoc\Param("region", type="string",require=false,default="86", desc="区域,手机号登录必填")
*/
public function login(Request $request){
$username = input('username');
$mobile = input('mobile');
$email = input('email');
$password = input('password');
if (!$username || !$password) {
return $this->fail(__('Invalid username or password'));
$type = input('type');
if($type == 'mobile'){
if (!$mobile ) {
return $this->fail(__('Invalid username or password'));
}
$username = $mobile;
}else if($type == 'email'){
if (!$email ) {
return $this->fail(__('Invalid username or password'));
}
$username = $email;
}else{
if (!$username ) {
return $this->fail(__('Invalid username or password'));
}
}
try{
$user = \support\Jwt::login($username, $password,'username');
if ($password) {
//return $this->fail(__('Invalid username or password'));
$user = \support\Jwt::login($username, $password,$type);
}else{
$user = \support\Jwt::login($username, $password,$type,'code');
}
if($user === false){
return $this->fail(\support\Jwt::getError());
}
$user= Hook('user.profile',$user);
//登录成功的事件
$user = Hook("user.login_successed", $user);
return $this->success(__('successful'), $user[0]);
} catch (\Exception $e) {
return $this->error($e->getMessage());
@@ -194,6 +264,7 @@ class CommonController extends BaseController{
*
* @Apidoc\Method ("POST")
* @Apidoc\Param("email", type="string",require=true, desc="邮箱")
* @Apidoc\Param("mobile", type="string",require=true, desc="手机号")
* @Apidoc\Param("newpassword", type="string",require=true, desc="新密码")
* @Apidoc\Param("code", type="string",require=true, desc="邮箱验证码,event=resetpwd")
*/
@@ -206,28 +277,28 @@ class CommonController extends BaseController{
return $this->error(__('Invalid parameters'));
}
//验证Token
if (!Validate::check(['newpassword' => $newpassword], ['newpassword' => 'require|regex:\S{6,30}'])) {
return $this->error(__('Password must be 6 to 30 characters'));
if (!Validate::check(['newpassword' => $newpassword], ['newpassword' => 'require|regex:\S{6,32}'])) {
return $this->error(__('Password must be 6 to 32 characters'));
}
if (!$mobile && !$email){
try{
$user = \support\Jwt::getUser();
}catch(\Exception $e){
log_alert($e->getMessage());
//log_alert($e->getMessage());
$user = false;
}
if($user){
captcha_verfiy('mobile','reset_trade_pwd',$user->mobile);
captcha_verfiy('mobile','reset_pwd',$user->mobile);
}
}else{
if ($email && Validate::is($email, "email")) {
captcha_verfiy('email','reset_trade_pwd',$email);
$user = UserModel::getByEmail($email);
}
if ($mobile && Validate::regex($mobile, "^1\d{10}$")) {
captcha_verfiy('mobile','reset_trade_pwd',$mobile);
$user = UserModel::getByMobile($mobile);
captcha_verfiy('mobile','reset_pwd',$mobile);
$region = Input('region');
$region = str_replace('+','',$region);
$user = UserModel::where('region',$region)->where('mobile',$mobile)->find();
}else if ($email && Validate::is($email, "email")) {
captcha_verfiy('email','reset_pwd',$email);
$user = UserModel::getByEmail($email);
}
}
if (!$user) {
@@ -262,8 +333,8 @@ class CommonController extends BaseController{
return $this->error(__('Invalid parameters'));
}
//验证Token
if (!Validate::check(['newpassword' => $newpassword], ['newpassword' => 'require|regex:\S{6,6}'])) {
return $this->error(__('Trade password must be 6 characters'));
if (!Validate::check(['newpassword' => $newpassword], ['newpassword' => 'require|regex:\S{6,32}'])) {
return $this->error(__('Trade password must be 6-32 characters'));
}
if (!$mobile && !$email){
@@ -277,13 +348,12 @@ class CommonController extends BaseController{
captcha_verfiy('mobile','reset_trade_pwd',$user->mobile);
}
}else{
if ($email && Validate::is($email, "email")) {
captcha_verfiy('email','reset_trade_pwd',$email);
$user = UserModel::getByEmail($email);
}
if ($mobile && Validate::regex($mobile, "^1\d{10}$")) {
captcha_verfiy('mobile','reset_trade_pwd',$mobile);
$user = UserModel::getByMobile($mobile);
}elseif ($email && Validate::is($email, "email")) {
captcha_verfiy('email','reset_trade_pwd',$email);
$user = UserModel::getByEmail($email);
}
}
if (!$user) {
@@ -309,6 +379,7 @@ class CommonController extends BaseController{
* @Apidoc\Param("email", type="string",require=true, desc="邮箱,可选")
*/
public function captcha(Request $request){
$debug = false;
$request->input('type');
$type = $request->input('type');
$event = $request->input('event');
@@ -331,17 +402,19 @@ class CommonController extends BaseController{
return $this->fail(__('Only one verification code can be sent within %second% seconds',['%second%'=>$expris]));
}
}
$code =\support\Random::numeric(4);
$code =\support\Random::numeric(6);
$list[$code] = time();
cache($key,$list);
cache('exp_'.$key,time());
addJob([
'email' => $email,
'title' => __("Mt email code"),
'event' => $event,
'code' => $code
],'Email');
return $this->success(__('Email sent successfully'));
// addJob([
// 'email' => $email,
// 'title' => __("Mt email code"),
// 'event' => $event,
// 'code' => $code
// ],'Email');
return $this->success(__('Email sent successfully'),[
'code'=> $debug ? $code : ''
]);
}elseif($type == 'mobile'){
$mobile = $request->input('mobile');
if(!$mobile){
@@ -358,13 +431,14 @@ class CommonController extends BaseController{
$key = 'captcha_'.$event.'_'.$mobile;
$list = cache($key);
$list = $list ?:[];
$expris = 60;
$expris = 300;
if(cache('?exp_'.$key)){
if(cache('exp_'.$key)+$expris > time()){
return $this->fail(__('Only one verification code can be sent within %second% seconds',['%second%'=>$expris]));
}
}
$code =\support\Random::numeric(4);
$code =\support\Random::numeric(6);
$list[$code] = time();
cache($key,$list);
cache('exp_'.$key,time());
@@ -373,7 +447,9 @@ class CommonController extends BaseController{
'event' => $event,
'code' => $code
],'Sms');
return $this->success(__('SMS sent successfully'));
return $this->success(__('SMS sent successfully'),[
'code'=> $debug ? $code : ''
]);
}else{
//TODO 图像验证码没有唯一的KEY
$key = 'captcha_'.$event.'_';
@@ -406,13 +482,14 @@ class CommonController extends BaseController{
*/
public function verify_captcha(Request $request): Response
{
$type = $request->input('type');
$email = $request->post('email');
$mobile = $request->input('mobile');
$event = $request->post('event');
try {
if($email){
if($type == 'email'){
$result = captcha_verfiy('email', $event , $email,false);
}elseif($mobile){
}elseif($type == 'mobile'){
$result = captcha_verfiy('mobile', $event , $mobile,false);
}else{
$result = captcha_verfiy('image', $event , '',false);
@@ -425,24 +502,4 @@ class CommonController extends BaseController{
}
return $this->success(__('successful'));
}
/**
* @Apidoc\Title("上传")
* @Apidoc\Method("POST")
*/
function upload(Request $request)
{
//多文件上传
$files = $request->file();
try {
$result = Storage::adapter('public')
->path('upload/files')
->size(1024*1024*10)
->extYes(['image/jpeg','image/png'])
->uploads($files,0,1024*1024*100,false);
return $this->success(__('successful'),$result);
}catch (\Exception $e){
return $this->error($e->getMessage());
}
}
}
+88
View File
@@ -0,0 +1,88 @@
<?php
namespace app\api\controller;
use app\model\User as UserModel;
use app\model\UserRemark as UserRemarkModel;
use app\model\GroupRemark as GroupRemarkModel;
use support\Request;
use support\Response;
use taoser\facade\Validate;
use support\think\Db;
use hg\apidoc\annotation as Apidoc;
/**
* 通讯录
*/
class ContactController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = [];
/**
* @Apidoc\Title("获取用户好友列表")
* @Apidoc\Method("GET")
*/
function get_friend_list(Request $request): Response
{
$current_user = \support\Jwt::getUser();
$user_id = $current_user->id;
$userID = idEncode($user_id);
$res = $request->IM->friend()->getFriendList($userID,1,10000);
return $this->success('ok',$res['data']['friendsInfo']);
}
/**
* @Apidoc\Title("好友信息")
* @Apidoc\Method("GET")
* @Apidoc\Param("userID", type="string",require=true, desc="用户ID")
*/
function get_friend_info(Request $request): Response
{
$userID = Input('userID');
if(!$userID){
return $this->error('UserID is Empty');
}
$userID = idDecode($userID);
$res = \app\model\User::where('id',$userID)->find();
return $this->success('ok',$res);
}
/**
* @Apidoc\Title("批量查询好友信息")
* @Apidoc\Method("GET")
* @Apidoc\Param("userIDs", type="string",require=true, desc="用户ID列表,逗号分隔")
*/
function get_friends_info(Request $request): Response
{
$userIDs = Input('userIDs');
if(!$userIDs){
return $this->error('UserID is Empty');
}
//$userIDs = explode(',',$userIDs);
//$userIDs = idDecode($userIDs);
//$current_user = \support\Jwt::getUser();
//$user_id = $current_user->id;
//$userID = idEncode($user_id);
$res = \app\model\User::whereIn('userID',$userIDs)->select();
return $this->success('ok',$res);
}
/**
* @Apidoc\Title("批量查询好友信息")
* @Apidoc\Method("GET")
* @Apidoc\Param("userIDs", type="string",require=true, desc="用户ID列表,逗号分隔")
*/
function get_friends_roles(Request $request): Response
{
$userIDs = Input('userIDs');
if(!$userIDs){
return $this->error('UserID is Empty');
}
$res = Db::name('user')->whereIn('userID',$userIDs)->column('role_id','userID');
return $this->success('ok',$res);
}
}
+445
View File
@@ -0,0 +1,445 @@
<?php
namespace app\api\controller;
use app\model\FriendCircle;
use Shopwwi\WebmanFilesystem\FilesystemFactory;
use Shopwwi\WebmanFilesystem\Facade\Storage;
use app\model\User as UserModel;
use app\model\Realname as RealnameModel;
use app\model\FriendCircle as FriendCircleModel;
use app\model\FriendCircleLike as FriendCircleLikeModel;
use app\model\FriendCircleComment as FriendCircleCommentModel;
use support\Request;
use support\Response;
use taoser\facade\Validate;
use support\think\Db;
use hg\apidoc\annotation as Apidoc;
/**
* 朋友圈
*/
class FriendCircleController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = [];
/**
* 朋友圈设置
* @return void
*/
function info(Request $request): Response{
$user_id = Input('user_id');
if($user_id){
$user_id = idDecode($user_id);
$json= [
'top_unread_items' =>[],
'unread_item_ids' =>[],
'unread_count' =>0,
'settings' => Db::name('friend_circle_setting')->where('user_id',$user_id)->order('id','desc')->findOrEmpty()
];
return $this->success('ok',$json);
}else{
$user = \support\Jwt::getUser();
if (!$user) {
return $this->fail('请先登录');
}
$user_id = $user->id;
$res = $this->newcount($request);
$response = $res->rawBody();
$json = json_decode($response,true);
$json['data']['settings'] = Db::name('friend_circle_setting')->where('user_id',$user_id)->order('id','desc')->findOrEmpty();
// [
// 'bg' => '',
// ];
$top_unread_items = FriendCircleModel::whereIn('id',$json['data']['unread_item_ids'])
->with(['user' => function($query) {
$query->field('id,nickname,avatar');
}])
->order('id', 'desc')
->limit(0,3)
->select();
$json['data']['top_unread_items'] = $top_unread_items ?: [];
$res->withBody(json_encode($json));
return $res;
}
}
/**
* @Apidoc\Title("列表")
* @Apidoc\Method("GET")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
* @Apidoc\Query("user_id", type="int", require=false, desc="用户ID,不传则获取所有")
*/
function list(Request $request): Response
{
$current_user = \support\Jwt::getUser();
$current_user_id = $current_user ? $current_user->id : 0;
$page = (int)Input('page', 1);
$limit = (int)Input('limit', 10);
$user_id = Input('user_id', 0);
if($user_id){
$user_id = idDecode($user_id);
}
$query = FriendCircleModel::where('status', 1)
->whereIn('user_id',$this->getFriendUserIds($current_user_id))
->with(['user' => function($query) {
$query->field('id,nickname,avatar');
}])
->order('created_at', 'desc');
// 如果指定了用户ID,只获取该用户的朋友圈
if ($user_id > 0) {
$query->where('user_id', $user_id);
}
$list = $query->paginate([
'list_rows' => $limit,
'page' => $page,
]);
if(!$user_id){
cache('circle_last_read_id_'.$current_user_id,$list[0]['id']);
}
// 处理每条朋友圈数据
$items = $list->items();
$list->each(function($item) use ($current_user_id){
// 获取点赞列表
$likes = Db::name('friend_circle_like')->alias('f')
->join('user u','u.id=f.user_id')
->where('f.circle_id', $item->id)
->field('f.*,u.avatar,u.nickname')
->order('f.created_at', 'desc')
->limit(20)
->select();
$likes = $likes ? $likes->toArray() : [];
// 检查当前用户是否已点赞
$is_liked = false;
if ($current_user_id > 0) {
$is_liked = null !== array_find($likes,function($item)use($current_user_id){
return $item['user_id'] == $current_user_id;
});
// FriendCircleLikeModel::where('circle_id', $item->id)
// ->where('user_id', $current_user_id)
// ->count() > 0;
}
// 获取评论列表(最新10条)
$comments = FriendCircleCommentModel::where('circle_id', $item->id)
->where('status', 1)
->with(['user' => function($query) {
$query->field('id,nickname,avatar');
}, 'replyUser' => function($query) {
$query->field('id,nickname,avatar');
}])
->order('created_at', 'asc')
->limit(10)
->select();
// 格式化数据
$item->is_liked = $is_liked;
$item->likes = $likes;
$item->comments = $comments;
// 处理图片URL
if (!empty($item->files)) {
$files = is_array($item->files) ? $item->files : json_decode($item->files, true);
if (is_array($files)) {
$item->files = array_map(function($file) {
return cdnurl($file);
}, $files);
} else {
$item->files = [];
}
} else {
$item->files = [];
}
// 处理用户头像
if ($item->user && $item->user->avatar) {
$item->user->avatar = cdnurl($item->user->avatar);
}
// 处理点赞用户头像
foreach ($item->likes as $like) {
if ($like->user) {
$like->avatar = cdnurl($like->avatar);
}
}
// 处理评论用户头像
foreach ($item->comments as $comment) {
if ($comment->user && $comment->user->avatar) {
$comment->user->avatar = cdnurl($comment->user->avatar);
}
if ($comment->replyUser && $comment->replyUser->avatar) {
$comment->replyUser->avatar = cdnurl($comment->replyUser->avatar);
}
}
return $item;
});
return $this->success('ok', $list);
}
/**
* @Apidoc\Title("最近更新的数量")
* @Apidoc\Method("POST")
* @Apidoc\Param("last_see", type="string",require=false, desc="最近查看的时间戳")
*/
function newcount(Request $request): Response
{
$user = \support\Jwt::getUser();
if (!$user) {
return $this->fail('请先登录');
}
$user_id = $user->id;
$circle_last_read_id = cache('circle_last_read_id_'.$user_id) ?: 0;
// 统计从上次查看时间到现在新增的朋友圈数量
$unread_item_ids = FriendCircleModel::where('status', 1)
->whereIn('user_id',$this->getFriendUserIds($user_id))
->where('id', '>', $circle_last_read_id)
->order('id', 'desc')
->column('id');
return $this->success('ok', [
'unread_count' => count($unread_item_ids),
'unread_item_ids'=>$unread_item_ids
]);
}
/**
* @Apidoc\Title("发布朋友圈")
* @Apidoc\Method("POST")
* @Apidoc\Param("body", type="string",require=false, desc="内容")
* @Apidoc\Param("files", type="string",require=false, desc="图片列表(JSON数组)")
*/
function create(Request $request): Response
{
$user = \support\Jwt::getUser();
if (!$user) {
return $this->fail('请先登录');
}
$body = $request->post('content', '');
$files = $request->post('files', '');
$address = $request->post('address', '');
$releaseType = $request->post('releaseType', '');
// 验证内容
if (empty($body)) {
return $this->fail('什么内容都木有啊');
}
// 处理图片列表
$files_array = [];
if (!empty($files)) {
if (is_string($files)) {
$files_array = json_decode($files, true);
} elseif (is_array($files)) {
$files_array = $files;
}
if (!is_array($files_array)) {
return $this->fail('图片列表格式错误');
}
// 限制图片数量
if (count($files_array) > 9) {
return $this->fail('最多只能上传9张图片');
}
}
// 创建朋友圈动态
$circle = FriendCircleModel::create([
'user_id' => $user->id,
'releaseType' => $releaseType,
'body' => $body,
'files' => $files_array,
'address' => $address,
'status' => 1,
]);
return $this->success('发布成功', ['id' => $circle->id,'data' => $circle]);
}
/**
* @Apidoc\Title("发表评论")
* @Apidoc\Method("POST")
* @Apidoc\Param("body", type="string",require=true, desc="内容")
* @Apidoc\Param("id", type="int",require=true, desc="朋友圈动态ID")
* @Apidoc\Param("reply_user_id", type="int",require=false, desc="回复的用户ID(回复评论时使用)")
*/
function comment(Request $request): Response
{
$user = \support\Jwt::getUser();
if (!$user) {
return $this->fail('请先登录');
}
$body = $request->post('body', '');
$circle_id = (int)$request->post('id', 0);
$reply_user_id = (int)$request->post('reply_user_id', 0);
if (empty($body)) {
return $this->fail('评论内容不能为空');
}
if ($circle_id <= 0) {
return $this->fail('朋友圈动态ID错误');
}
// 检查朋友圈动态是否存在
$circle = FriendCircleModel::where('id', $circle_id)
->where('status', 1)
->find();
if (!$circle) {
return $this->fail('朋友圈动态不存在');
}
// 如果回复评论,检查被回复的用户是否存在
if ($reply_user_id > 0) {
$reply_user = UserModel::where('id', $reply_user_id)->find();
if (!$reply_user) {
return $this->fail('被回复的用户不存在');
}
}
// 创建评论
$comment = FriendCircleCommentModel::create([
'circle_id' => $circle_id,
'user_id' => $user->id,
'reply_user_id' => $reply_user_id,
'body' => $body,
'status' => 1,
]);
// 更新朋友圈评论数
$circle->comment_count = FriendCircleCommentModel::where('circle_id', $circle_id)
->where('status', 1)
->count();
$circle->save();
$comment->user = Db::name('user')->where('id',$comment->user_id)->find();
$comment->replyUser=null;
if($comment->reply_user_id){
$comment->replyUser = Db::name('user')->where('id',$comment->reply_user_id)->find();
}
return $this->success('评论成功', $comment);
}
/**
* @Apidoc\Title("点赞")
* @Apidoc\Method("POST")
* @Apidoc\Param("id", type="int",require=true, desc="朋友圈动态ID")
*/
function like(Request $request): Response
{
$user = \support\Jwt::getUser();
if (!$user) {
return $this->fail('请先登录');
}
$circle_id = (int)$request->post('id', 0);
if ($circle_id <= 0) {
return $this->fail('朋友圈动态ID错误');
}
// 检查朋友圈动态是否存在
$circle = FriendCircleModel::where('id', $circle_id)
->where('status', 1)
->find();
if (!$circle) {
return $this->fail('朋友圈动态不存在');
}
// 检查是否已点赞
$like = FriendCircleLikeModel::where('circle_id', $circle_id)
->where('user_id', $user->id)
->find();
if ($like) {
// 取消点赞
$like->delete();
$circle->like_count = max(0, $circle->like_count - 1);
$circle->save();
return $this->success('取消点赞成功', ['is_liked' => false]);
} else {
// 添加点赞
FriendCircleLikeModel::create([
'circle_id' => $circle_id,
'user_id' => $user->id,
]);
$circle->like_count = $circle->like_count + 1;
$circle->save();
return $this->success('点赞成功', ['is_liked' => true]);
}
}
protected function getFriendUserIds($user_id):array{
if (!$user_id) {
return [];
}
$cache_key = 'friend_id_list_'.$user_id;
$result = cache($cache_key) ?: [];
if(count($result) === 0){
$res = request()->IM->friend->getFriendList(idEncode($user_id));
$friendsInfo = $res['friendsInfo'];
foreach($friendsInfo as $k=>$v){
array_push($result,$v['friendUser']['userID']);
}
cache($cache_key,$result,3600);
}
$result[] = $user_id;
return $result;
}
function delete(Request $request): Response{
$id = $request->post('id');
$user = \support\Jwt::getUser();
if (!$user) {
return $this->fail('请先登录');
}
if($id){
FriendCircleModel::where('id',$id)->where('user_id',$user->id)->delete();
}
return $this->success('删除成功');
}
function upload_bg(Request $request){
try {
$user = \support\Jwt::getUser();
if (!$user) {
return $this->fail('请先登录');
}
$res = $this->_upload($request);
if(is_string($res)){
return $this->fail( $res);
}
Db::name('friend_circle_setting')->replace()->insert([
'user_id' => $user->id,
'bg' => $res[0]['file_name'],
'allow_days'=>0,
'created_at'=>0
]);
//$result->ss = cdnurl($result->url);
//P($result);
return $this->success(__('successful'),[
'url'=>$res[0]['file_name']
]);
}catch (\Exception $e){
return $this->error($e->getMessage());
}
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
namespace app\api\controller;
use app\model\User as UserModel;
use app\model\UserRemark as UserRemarkModel;
use app\model\GroupRemark as GroupRemarkModel;
use support\Request;
use support\Response;
use taoser\facade\Validate;
use support\think\Db;
use hg\apidoc\annotation as Apidoc;
/**
* 好友相关
*/
class FriendController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = [];
/**
* @Apidoc\Title("搜索用户")
* @Apidoc\Method("GET")
* @Apidoc\Param("nickname", type="string",require=true, desc="昵称")
*/
function search(Request $request): Response
{
$keyword = Input('keyword');
$searchtype = Input('searchtype');
if($searchtype =='id'){
}else{
}
return $this->success('ok');
}
}
@@ -10,6 +10,8 @@ use hg\apidoc\annotation as Apidoc;
/**
* 礼品模块
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
class GiftController extends BaseController{
/**
+129
View File
@@ -0,0 +1,129 @@
<?php
namespace app\api\controller;
use support\Request;
use support\Response;
use hg\apidoc\annotation as Apidoc;
use app\model\User;
use app\model\Album as AlbumModel;
/**
* 群组管理
*/
class GroupController extends BaseController
{
public $noNeedAuth = ['*'];
public $noNeedLogin = [];
/**
* @Apidoc\Title("群相片列表")
* @Apidoc\Method("POST")
* @Apidoc\Param("group_id", type="string", require=true, desc="群ID")
* @Apidoc\Param("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Param("limit", type="int", require=true, desc="分页大小",default=10)
*/
function album_list(Request $request): Response
{
$user = \support\Jwt::getUser();
$limit = $request->post('limit',10);
$offset = $request->post('offset',0);
$group_id = $request->post('groupID') ?:$request->post('group_id');
//$ls = $this->get_user_in_group($group_id);
//log_alert($ls);
log_alert([$offset,$group_id,$limit]);
$list = AlbumModel::where('group_id',$group_id)
->where('id','<',$offset)
->order('id','desc')
->limit(0,$limit)
->select();
return $this->success('ok',$list);
}
/**
* @Apidoc\Title("上传相片")
* @Apidoc\Method("POST")
* @Apidoc\Param("group_id", type="string", require=true, desc="群ID")
* @Apidoc\Param("title", type="string", require=true, desc="标题")
* @Apidoc\Param("url", type="string", require=true, desc="图片")
*/
function album_create(Request $request): Response
{
$user_id = \support\Jwt\JwtToken::getCurrentId();
$res = $this->_upload($request);
if(is_string($res)){
return $this->fail( $res);
}
$groupID = $request->post('groupID');
$insert_data = [];
foreach($res as $item){
$insert_data[] = [
'user_id' => $user_id,
'group_id' => $groupID,
'title' => $item['origin_name'],
'url' => $item['file_name'],
];
}
$result = AlbumModel::saveAll($insert_data);
return $this->success('ok',$result[0]);
}
/**
* @Apidoc\Title("更新相片")
* @Apidoc\Method("POST")
* @Apidoc\Param("id", type="string", require=true, desc="ID")
* @Apidoc\Param("title", type="string", require=true, desc="标题")
* @Apidoc\Param("url", type="string", require=true, desc="图片")
*/
function album_update(Request $request): Response
{
$id = $request->input('id');
$data = $request->input('data');
$album = AlbumModel::find($id);
$album->update($data);
return $this->success('ok',$album);
}
/**
* @Apidoc\Title("删除相片")
* @Apidoc\Method("POST")
* @Apidoc\Param("id", type="string", require=true, desc="ID")
*/
function album_delete(Request $request): Response
{
$ids = Input('ids');
//$album = AlbumModel::whereIn('id',condition: $ids)->select();
//$album->delete();
AlbumModel::whereIn('id',condition: $ids)->delete();
return $this->success('ok');
}
/**
* 获取再群里的角色
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
private function get_user_in_group($group_id='',$user_id='')
{
$list = request()->IM->group->getGroupMemberList($group_id,$user_id);
return $list;
}
/**
* 头像上传
* @Apidoc\Method("POST")
* @Apidoc\Param("file", type="File", require=true, desc="文件")
*/
public function avatar(Request $request)
{
//单文件上传
$groupID = $request->post('groupID');
if(!$groupID){
return $this->fail(__('参数错误'));
}
$res = $this->_upload($request);
if(is_string($res)){
return $this->fail( $res);
}
$data = [
'groupID' => $groupID,
'faceURL' => $res[0]['file_name'],
];
$list = request()->IM->group->setGroupInfo($data);
return $this->success(__('successful'),$data);
}
}

Some files were not shown because too many files have changed in this diff Show More