Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d0e34f36bd | |||
| 24273db8dd | |||
| 9393185f25 | |||
| a98d2b56ee | |||
| 4463f73efb | |||
| d75808951e | |||
| f0970446f9 | |||
| c092662ebe | |||
| 6c59e41b32 | |||
| b0e87b3fb3 | |||
| d0dc7930ad | |||
| 594aa137ef | |||
| 005c775694 | |||
| 26fb271a54 | |||
| dd6745fe24 | |||
| 7b5d43f0e8 | |||
| ffc1404baa | |||
| d98ac8f146 | |||
| 66bcd8061a | |||
| 8704434c36 | |||
| 70c4966aad | |||
| f598cc8157 | |||
| 92948fa856 | |||
| 0a45a8fbb9 | |||
| 873c7cf9c2 | |||
| 73f67b4143 | |||
| d75fea32f7 | |||
| c9c8a120ab | |||
| 6586f27c9e | |||
| 1a7f4bc98a | |||
| 61c5192018 | |||
| c153975eed | |||
| 7439a4a794 | |||
| 7c1d6d447e | |||
| 20d230f6c8 | |||
| b68946fe79 | |||
| b52a51c09b | |||
| 9f25a85d07 | |||
| f89196c73c |
@@ -2,14 +2,14 @@
|
||||
debug = true
|
||||
[server]
|
||||
port=8585
|
||||
domain=www.wenjb.com
|
||||
domain=www.shun777.com
|
||||
https=false
|
||||
[mysql]
|
||||
host =127.0.0.1
|
||||
port = 3307
|
||||
database = questionnaire
|
||||
username = questionnaire
|
||||
password = ba9b492bda93ad4d
|
||||
port = 3306
|
||||
database = imadmin
|
||||
username = imadmin
|
||||
password = ejkFmaAXAHXyNXd2
|
||||
charset = utf8mb4
|
||||
collation = utf8mb4_general_ci
|
||||
prefix = wa_
|
||||
@@ -18,13 +18,13 @@ engine =
|
||||
[mongodb]
|
||||
host = 127.0.0.1
|
||||
port = 27017
|
||||
database = questionnaire_m
|
||||
username = commie
|
||||
database = imadmin_mongo
|
||||
username = root
|
||||
password = n1e5a6s6m7
|
||||
[redis]
|
||||
host = 127.0.0.1
|
||||
port = 6379
|
||||
database = 10
|
||||
database = 0
|
||||
password = n1e5a6s6m7
|
||||
prefix = q_
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
* text=auto eol=lf
|
||||
*.txt -text
|
||||
@@ -0,0 +1,12 @@
|
||||
node_modules
|
||||
*.lock
|
||||
unpackage
|
||||
package-lock.json
|
||||
.hbuilderx
|
||||
config/site.php
|
||||
app/command/Test.php
|
||||
.env
|
||||
runtime
|
||||
vendor
|
||||
public/shunliao.apk
|
||||
.user.ini
|
||||
@@ -0,0 +1,232 @@
|
||||
---
|
||||
name: "webman-openim-admin"
|
||||
description: "专门针对基于webman的openim管理项目,使用了think-cache、think-orm、think-template、redis-queue、webman/event、tinywan/validate等依赖。用于项目的开发、维护和问题排查。"
|
||||
---
|
||||
|
||||
# Webman OpenIM Admin 技能
|
||||
|
||||
## 项目概述
|
||||
|
||||
本技能专门针对基于 webman 框架开发的 OpenIM 管理项目,该项目使用了以下核心依赖:
|
||||
|
||||
- **think-cache**: 缓存管理
|
||||
- **think-orm**: 数据库 ORM 框架
|
||||
- **think-template**: 模板引擎
|
||||
- **redis-queue**: Redis 队列管理
|
||||
- **webman/event**: 事件系统
|
||||
- **tinywan/validate**: 数据验证
|
||||
|
||||
## 功能特性
|
||||
|
||||
### 1. 项目结构分析
|
||||
- 分析项目目录结构
|
||||
- 识别核心模块和文件
|
||||
- 理解依赖关系
|
||||
|
||||
### 2. 代码开发与维护
|
||||
- 基于现有代码风格和模式进行开发
|
||||
- 提供符合项目规范的代码建议
|
||||
- 帮助排查和修复常见问题
|
||||
|
||||
### 3. 依赖管理
|
||||
- 分析 composer.json 配置
|
||||
- 提供依赖版本建议
|
||||
- 处理依赖冲突问题
|
||||
|
||||
### 4. 数据库操作
|
||||
- 基于 think-orm 的数据库操作指导
|
||||
- 模型定义和关系映射
|
||||
- 数据库迁移和种子数据管理
|
||||
|
||||
### 5. 缓存策略
|
||||
- 基于 think-cache 的缓存配置和使用
|
||||
- 缓存优化建议
|
||||
- 缓存一致性管理
|
||||
|
||||
### 6. 队列管理
|
||||
- redis-queue 的配置和使用
|
||||
- 队列任务的创建和监控
|
||||
- 队列性能优化
|
||||
|
||||
### 7. 事件系统
|
||||
- webman/event 的配置和使用
|
||||
- 事件监听和触发
|
||||
- 事件驱动架构设计
|
||||
|
||||
### 8. 数据验证
|
||||
- tinywan/validate 的配置和使用
|
||||
- 表单验证规则定义
|
||||
- 自定义验证规则开发
|
||||
|
||||
## 触发条件
|
||||
|
||||
当用户需要:
|
||||
- 了解项目结构和依赖
|
||||
- 开发新功能或修改现有功能
|
||||
- 排查项目中的问题
|
||||
- 优化项目性能
|
||||
- 配置或调整项目依赖
|
||||
- 进行数据库相关操作
|
||||
- 实现缓存策略
|
||||
- 管理队列任务
|
||||
- 使用事件系统
|
||||
- 进行数据验证
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例 1: 分析项目结构
|
||||
```bash
|
||||
# 查看项目目录结构
|
||||
ls -la
|
||||
|
||||
# 查看 composer.json 了解依赖
|
||||
cat composer.json
|
||||
```
|
||||
|
||||
### 示例 2: 数据库操作
|
||||
```php
|
||||
// 使用 think-orm 进行数据库查询
|
||||
use think\Model;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
protected $table = 'user';
|
||||
}
|
||||
|
||||
// 查询用户列表
|
||||
$users = User::where('status', 1)->select();
|
||||
```
|
||||
|
||||
### 示例 3: 缓存使用
|
||||
```php
|
||||
// 使用 think-cache
|
||||
use think\facade\Cache;
|
||||
|
||||
// 设置缓存
|
||||
Cache::set('key', 'value', 3600);
|
||||
|
||||
// 获取缓存
|
||||
$value = Cache::get('key');
|
||||
```
|
||||
|
||||
### 示例 4: 队列任务
|
||||
```php
|
||||
// 使用 redis-queue
|
||||
use support\Queue;
|
||||
|
||||
// 推送任务
|
||||
Queue::push('App\\Jobs\\SendEmail', ['email' => 'user@example.com']);
|
||||
```
|
||||
|
||||
### 示例 5: 事件监听
|
||||
```php
|
||||
// 使用 webman/event
|
||||
use support\Event;
|
||||
|
||||
// 监听事件
|
||||
Event::listen('user.registered', function ($user) {
|
||||
// 处理用户注册事件
|
||||
});
|
||||
|
||||
// 触发事件
|
||||
Event::trigger('user.registered', $user);
|
||||
```
|
||||
|
||||
### 示例 6: 数据验证
|
||||
```php
|
||||
// 使用 tinywan/validate
|
||||
use Tinywan\Validate\Validate;
|
||||
|
||||
$validate = new Validate();
|
||||
$validate->rule([
|
||||
'name' => 'require|max:25',
|
||||
'email' => 'require|email',
|
||||
]);
|
||||
|
||||
if (!$validate->check($data)) {
|
||||
return $validate->getError();
|
||||
}
|
||||
```
|
||||
|
||||
## 项目配置建议
|
||||
|
||||
1. **composer.json** 配置:
|
||||
- 保持依赖版本的稳定性
|
||||
- 定期更新依赖以获取安全补丁
|
||||
|
||||
2. **数据库配置**:
|
||||
- 优化数据库连接池设置
|
||||
- 合理使用索引
|
||||
- 定期备份数据库
|
||||
|
||||
3. **缓存配置**:
|
||||
- 根据业务场景选择合适的缓存策略
|
||||
- 设置合理的缓存过期时间
|
||||
- 考虑缓存预热机制
|
||||
|
||||
4. **队列配置**:
|
||||
- 合理设置队列 worker 数量
|
||||
- 监控队列任务执行状态
|
||||
- 实现失败重试机制
|
||||
|
||||
5. **性能优化**:
|
||||
- 启用 OPcache
|
||||
- 优化数据库查询
|
||||
- 使用合适的缓存策略
|
||||
- 合理设计事件系统
|
||||
|
||||
## 常见问题与解决方案
|
||||
|
||||
1. **依赖冲突**:
|
||||
- 检查 composer.json 中的版本约束
|
||||
- 使用 `composer update` 解决版本冲突
|
||||
|
||||
2. **数据库连接问题**:
|
||||
- 检查数据库配置文件
|
||||
- 确认数据库服务是否正常运行
|
||||
|
||||
3. **缓存失效**:
|
||||
- 检查缓存配置
|
||||
- 确认缓存服务是否正常
|
||||
|
||||
4. **队列任务失败**:
|
||||
- 检查队列配置
|
||||
- 查看任务执行日志
|
||||
- 实现失败重试机制
|
||||
|
||||
5. **事件不触发**:
|
||||
- 检查事件监听注册
|
||||
- 确认事件触发代码
|
||||
|
||||
6. **验证失败**:
|
||||
- 检查验证规则
|
||||
- 确认输入数据格式
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **代码组织**:
|
||||
- 遵循 PSR 代码规范
|
||||
- 合理使用命名空间
|
||||
- 保持代码结构清晰
|
||||
|
||||
2. **安全性**:
|
||||
- 防止 SQL 注入
|
||||
- 防止 XSS 攻击
|
||||
- 保护敏感信息
|
||||
|
||||
3. **可维护性**:
|
||||
- 编写清晰的注释
|
||||
- 使用一致的代码风格
|
||||
- 遵循设计模式
|
||||
|
||||
4. **性能**:
|
||||
- 优化数据库查询
|
||||
- 合理使用缓存
|
||||
- 减少不必要的计算
|
||||
|
||||
5. **扩展性**:
|
||||
- 采用模块化设计
|
||||
- 依赖注入
|
||||
- 接口分离
|
||||
|
||||
本技能旨在帮助开发者更高效地开发和维护基于 webman 的 OpenIM 管理项目,提供专业的技术支持和最佳实践建议。
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"php.version": "8.2"
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/runtime
|
||||
/.idea
|
||||
/.vscode
|
||||
/vendor
|
||||
*.log
|
||||
.env
|
||||
.user.ini
|
||||
/config/site.php
|
||||
/config/pay.php
|
||||
/app/command/Test.php
|
||||
@@ -1,144 +0,0 @@
|
||||
<?php
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\model\Archives as ArchivesModel;
|
||||
use support\Request;
|
||||
use taoser\facade\Validate;
|
||||
use hg\apidoc\annotation as Apidoc;
|
||||
|
||||
/**
|
||||
* 文章模块
|
||||
*/
|
||||
class ArticleController extends BaseController{
|
||||
public $noNeedLogin = ['*'];
|
||||
/**
|
||||
* 列表
|
||||
* @Apidoc\Query("category_id", type="int", require=true, desc="分类ID",default=10)
|
||||
* @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);
|
||||
$category_id = (int)input('category_id',0);
|
||||
|
||||
$model = ArchivesModel::where('status','1')->where('type','article');
|
||||
if($category_id){
|
||||
$model = $model->where('category_id',$category_id);
|
||||
}
|
||||
$list = $model->order('id','desc')->paginate($limit);
|
||||
$user_id=0;
|
||||
try {
|
||||
$user_id = \support\Jwt\JwtToken::getCurrentId();
|
||||
} catch (\Throwable $th) {
|
||||
}
|
||||
$list->each(function($item)use($user_id){
|
||||
if(!$user_id){
|
||||
$item->is_read = 0;
|
||||
}
|
||||
$item->is_read = cache('article_read_'.$item->id.'_'.$user_id)?:0;
|
||||
|
||||
return $item;
|
||||
});
|
||||
return $this->success(__('successful'),$list->toArray());
|
||||
|
||||
}
|
||||
/**
|
||||
* faq
|
||||
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
|
||||
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
|
||||
*/
|
||||
public function faq(){
|
||||
$limit = (int)input('limit',10);
|
||||
$model = ArchivesModel::alias('a')
|
||||
->join('content c', 'a.id = c.id')
|
||||
->where('a.status','1')
|
||||
->where('a.type','article')
|
||||
->where('a.category_id',9);
|
||||
$list = $model->Field('a.title,a.id,c.content')->order('a.id','desc')->paginate($limit);
|
||||
return $this->success(__('successful'),$list->toArray());
|
||||
|
||||
}
|
||||
/**
|
||||
* 详情
|
||||
* @Apidoc\Query("id", type="int", require=true, desc="ID")
|
||||
*/
|
||||
public function detail(){
|
||||
$appid = input('id');
|
||||
/** @var ArchivesModel $vo */
|
||||
$vo = ArchivesModel::where('id',$appid)->find();
|
||||
if($vo) {
|
||||
$addon = \app\model\Content::where('id', $vo->id)->find()->toArray();
|
||||
if ($addon) {
|
||||
$vo->setAddonData($addon);
|
||||
}
|
||||
$user_id=0;
|
||||
try {
|
||||
$user_id = \support\Jwt\JwtToken::getCurrentId();
|
||||
} catch (\Throwable $th) {
|
||||
}
|
||||
if($user_id){
|
||||
cache('article_read_'.$vo->id.'_'.$user_id,1);
|
||||
}
|
||||
return $this->success(__('successful'),$vo->toArray());
|
||||
}else{
|
||||
return $this->error(__("Article does not exist"));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 单页详情
|
||||
* @Apidoc\Query("id", type="int", require=true, desc="ID")
|
||||
* @Apidoc\Query("name", type="string", require=true, desc="二选1")
|
||||
*/
|
||||
public function singpage(){
|
||||
$appid = input('id');
|
||||
$name = input('name');
|
||||
/** @var ArchivesModel $vo */
|
||||
if($name){
|
||||
$vo = ArchivesModel::where('name',$name)->find();
|
||||
}else{
|
||||
if($appid){
|
||||
$vo = ArchivesModel::where('id',$appid)->find();
|
||||
}
|
||||
}
|
||||
if($vo) {
|
||||
$addon = \app\model\Content::where('id', $vo->id)->find()->toArray();
|
||||
if ($addon) {
|
||||
$vo->setAddonData($addon);
|
||||
}
|
||||
return $this->success(__('successful'),$vo->toArray());
|
||||
}else{
|
||||
return $this->error(__("Article does not exist"));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 幻灯片
|
||||
* @Apidoc\Query("id", type="int", require=true, desc="ID")
|
||||
*/
|
||||
public function slide(){
|
||||
$list = [
|
||||
['image'=>domain().'/storage/slide/1.jpg','title'=>''],
|
||||
['image'=>domain().'/storage/slide/2.webp','title'=>''],
|
||||
['image'=>domain().'/storage/slide/3.webp','title'=>''],
|
||||
['image'=>domain().'/storage/slide/4.jpg','title'=>''],
|
||||
];
|
||||
return $this->success(__('successful'),$list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设为已读
|
||||
* @Apidoc\Query("id", type="int", require=true, desc="ID,多个逗号隔开")
|
||||
*/
|
||||
function mask_as_read(){
|
||||
$ids = input('id');
|
||||
$user_id = \support\Jwt\JwtToken::getCurrentId();
|
||||
if(!$user_id){
|
||||
return $this->success(__('successful'));
|
||||
}
|
||||
$ids = explode(',',$ids);
|
||||
foreach ($ids as $id) {
|
||||
$key = 'article_read_'.$id.'_'.$user_id;
|
||||
cache($key,1);
|
||||
}
|
||||
return $this->success(__('successful'));
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\command;
|
||||
|
||||
use Exception;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use support\think\Db;
|
||||
use app\model\User as UserModel;
|
||||
|
||||
|
||||
class Database extends Command
|
||||
{
|
||||
protected static $defaultName = 'Db';
|
||||
protected static $defaultDescription = 'Database 优化';
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->addOption('action','a', InputArgument::OPTIONAL, '要做什么操作');
|
||||
$this->addOption('table','t', InputArgument::OPTIONAL, '表名');
|
||||
$this->addOption('domain','ym', InputArgument::OPTIONAL, 'domain');
|
||||
$this->addOption('robot_id','rid', InputArgument::OPTIONAL, 'robot_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$action = $input->getOption('action');
|
||||
if($action == 'prototype'){
|
||||
return $this->prototype($input, $output);
|
||||
}
|
||||
cp('操作不存在:'.$action);
|
||||
return 0;
|
||||
}
|
||||
function prototype(InputInterface $input, OutputInterface $output){
|
||||
$table = $input->getOption('table');
|
||||
// 获取表前缀并构建完整表名
|
||||
$prefix = config('thinkorm.connections.mysql.prefix', '');
|
||||
$fullTableName = '`' . $prefix . $table . '`';
|
||||
|
||||
// 查询表结构
|
||||
$res = Db::query('SHOW FULL COLUMNS FROM ' . $fullTableName);
|
||||
|
||||
if (empty($res)) {
|
||||
return "// 表 {$table} 不存在或没有字段";
|
||||
}
|
||||
|
||||
$annotations = [];
|
||||
$annotations[] = '/**';
|
||||
|
||||
foreach ($res as $row) {
|
||||
$field = $row['Field'];
|
||||
$type = $row['Type'];
|
||||
$comment = $row['Comment'] ?: '无注释';
|
||||
|
||||
// 处理字段类型映射
|
||||
$phpType = $this->mapMysqlTypeToPhp($type);
|
||||
|
||||
// 处理特殊字段
|
||||
if ($field === 'id') {
|
||||
$annotations[] = " * @property integer \${$field} 主键(ID) - {$comment}";
|
||||
} else {
|
||||
$annotations[] = " * @property {$phpType} \${$field} {$comment}";
|
||||
}
|
||||
}
|
||||
|
||||
$annotations[] = ' */';
|
||||
|
||||
cp( implode("\n", $annotations));
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将MySQL字段类型映射到PHP类型
|
||||
*
|
||||
* @param string $mysqlType MySQL字段类型
|
||||
* @return string PHP类型
|
||||
*/
|
||||
protected function mapMysqlTypeToPhp($mysqlType)
|
||||
{
|
||||
$mysqlType = strtolower($mysqlType);
|
||||
|
||||
// 整数类型
|
||||
if (preg_match('/^(tinyint|smallint|mediumint|int|bigint)/', $mysqlType)) {
|
||||
// 检查是否为无符号
|
||||
if (strpos($mysqlType, 'unsigned') !== false) {
|
||||
return 'integer'; // 无符号整数也返回integer
|
||||
}
|
||||
return 'integer';
|
||||
}
|
||||
|
||||
// 浮点类型
|
||||
if (preg_match('/^(float|double|decimal)/', $mysqlType)) {
|
||||
return 'float';
|
||||
}
|
||||
|
||||
// 字符串类型
|
||||
if (preg_match('/^(varchar|char|text|tinytext|mediumtext|longtext|enum|set)/', $mysqlType)) {
|
||||
return 'string';
|
||||
}
|
||||
|
||||
// 日期时间类型
|
||||
if (preg_match('/^(date|time|datetime|timestamp|year)/', $mysqlType)) {
|
||||
return 'string'; // 或者可以返回 '\\DateTime' 如果需要更精确的类型
|
||||
}
|
||||
|
||||
// 二进制类型
|
||||
if (preg_match('/^(blob|tinyblob|mediumblob|longblob|binary|varbinary)/', $mysqlType)) {
|
||||
return 'string'; // 或者根据需求返回其他类型
|
||||
}
|
||||
|
||||
// JSON类型
|
||||
if (strpos($mysqlType, 'json') !== false) {
|
||||
return 'array'; // 或者 'mixed'
|
||||
}
|
||||
|
||||
// 布尔类型(tinyint(1)通常用作布尔值)
|
||||
if ($mysqlType === 'tinyint(1)' || $mysqlType === 'boolean' || $mysqlType === 'bool') {
|
||||
return 'boolean';
|
||||
}
|
||||
|
||||
// 默认返回混合类型
|
||||
return 'mixed';
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use support\think\Db;
|
||||
|
||||
|
||||
class Otop extends Command
|
||||
{
|
||||
protected static $defaultName = 'Otop';
|
||||
protected static $defaultDescription = '结算';
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->addOption('user_id','uid', InputArgument::OPTIONAL, 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$user_id = $input->getOption('user_id');
|
||||
if(!$user_id){
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @var \plugin\admin\app\model\Admin $admin
|
||||
*/
|
||||
$admin = \plugin\admin\app\model\Admin::where('id',$user_id)->find();
|
||||
if(!$admin){
|
||||
return false;
|
||||
}
|
||||
$totp = \OTPHP\TOTP::create($admin->totp_secret);
|
||||
cp($totp->now());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use support\think\Db;
|
||||
|
||||
|
||||
class Settlement extends Command
|
||||
{
|
||||
protected static $defaultName = 'Settlement';
|
||||
protected static $defaultDescription = '结算';
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->addArgument('name', InputArgument::OPTIONAL, 'Name description');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
(new \support\Settlement())->autoSettlement();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
<?php
|
||||
namespace app\event;
|
||||
use support\think\Db;
|
||||
use Request;
|
||||
class User{
|
||||
function register_successed($user){
|
||||
$date = date('Y-m-d');
|
||||
cache_add('statistics_register_'.$date,1);
|
||||
$saveData = [
|
||||
'invite_code' => build_invite_code($user->id)
|
||||
];
|
||||
//管理直推人数和团队人数
|
||||
if($user->parent_id){
|
||||
parent_info( $user->id,[
|
||||
'id' => $user->parent_id,
|
||||
'username' => Db::name('user')->where('id',op: $user->parent_id)->value('username')
|
||||
]);
|
||||
//管理直推人数
|
||||
cache_add('team_direct_total_'.$user->parent_id,1);
|
||||
\app\model\UserExtend::where('user_id',$user->parent_id)->save([
|
||||
'direct_total' => Db::raw('direct_total+1'),
|
||||
'team_total' => Db::raw('team_total+1'),
|
||||
]);
|
||||
}
|
||||
|
||||
\app\model\User::where('id',$user->id)->update($saveData);
|
||||
//创建扩展数据
|
||||
\app\model\UserExtend::create([
|
||||
'user_id' => $user->id,
|
||||
'direct_total' => 0,
|
||||
'team_total' => 0,
|
||||
'consume' => 0,
|
||||
'sales' => 0
|
||||
]);
|
||||
|
||||
|
||||
$this->buildTeam($user);
|
||||
}
|
||||
function login_successed($data=[]){
|
||||
return $data;
|
||||
}
|
||||
function profile($user=[]){
|
||||
$data = $user;
|
||||
if(!is_array($data)){
|
||||
$data = $data->toArray();
|
||||
}
|
||||
$role_arr = [
|
||||
'0' => __('普通用户'),
|
||||
'1' => __('V1'),
|
||||
'2' => __('V2'),
|
||||
'3' => __('V3'),
|
||||
'4' => __('V4'),
|
||||
'5' => __('V5'),
|
||||
];
|
||||
$data['has_trade_password'] = $data['trade_password'] ? true: false;
|
||||
$data['avatar'] = cdnurl($data['avatar']);
|
||||
$disallowFields = ['trade_password','password','client','loginfailure'];
|
||||
$data = array_diff_key($data, array_flip($disallowFields));
|
||||
$data['recharge_total'] = cache('user_recharge_total_'.$data['id'])?:0;
|
||||
$data['withdrawl_total'] = cache('user_withdrawl_total_'.$data['id'])?:0;
|
||||
$data['income_total'] = cache('user_income_total_'.$data['id'])?:0;
|
||||
$data['today_income'] = cache('user_today_income_'.date('Ymd').'_'.$data['id'])?:0;
|
||||
$data['month_income'] = cache('user_month_income_'.date('Ym').'_'.$data['id'])?:0;
|
||||
$data['consume_total'] = cache('user_consume_total_'.$data['id'])?:0;
|
||||
$data['power_total'] = cache('user_power_total_'.$data['id'])?:0;
|
||||
$data['role_reward_total'] = cache('user_role_reward_total_'.$data['id'])?:0;
|
||||
$data['avatar'] = $data['avatar']?:"/static/img/avatar.png";
|
||||
$data['role'] = isset($role_arr[$data['role_id']]) ? $role_arr[$data['role_id']] : __('普通用户');//\app\model\UserRole::where('id',$data['role_id'])->value('name');
|
||||
|
||||
$data['level'] = get_user_level($data['id']);
|
||||
$data['id'] = idEncode($data['id']);
|
||||
return $data;
|
||||
}
|
||||
function changepwd_successed($data=[]){
|
||||
return $data;
|
||||
}
|
||||
function change_trade_pwd_successed($data=[]){
|
||||
return $data;
|
||||
}
|
||||
function logout_successed($data=[]){
|
||||
return $data;
|
||||
}
|
||||
function delete_successed($data=[]){
|
||||
return $data;
|
||||
}
|
||||
//用户角色组变化
|
||||
function roleup($user=[]){
|
||||
$data = $user;
|
||||
if(!is_array($data)){
|
||||
$data = $data->toArray();
|
||||
}
|
||||
if(!$user->active){
|
||||
$user->active = 1;
|
||||
$user->save();
|
||||
cache_add('team_direct_total_'.$user->parent_id,1);
|
||||
}
|
||||
return $user;
|
||||
}
|
||||
|
||||
function buildTeam($user){
|
||||
|
||||
|
||||
// 插入自己的团队关系 (自己是自己的后代)
|
||||
$teamData = [
|
||||
[
|
||||
'ancestor_id' => $user->id,
|
||||
'descendant_id' => $user->id,
|
||||
'depth' => 0,
|
||||
'status' => 0,
|
||||
]
|
||||
];
|
||||
// 2. 处理团队关系(如果有推荐人)
|
||||
if ($user->parent_id) {
|
||||
|
||||
parent_info( $user->id,[
|
||||
'id' => $user->parent_id,
|
||||
'username' => Db::name('user')->where('id',$user->parent_id)->value('username')
|
||||
]);
|
||||
// 获取推荐人所有的上级关系,生成新用户的团队关系
|
||||
$ancestors = Db::name('user_team')
|
||||
->where('descendant_id', $user->parent_id)
|
||||
->select();
|
||||
/** @var \app\model\UserTeam $ancestor */
|
||||
// 插入新用户与祖先的关系
|
||||
foreach ($ancestors as $ancestor) {
|
||||
$teamData[] = [
|
||||
'ancestor_id' => $ancestor['ancestor_id'],
|
||||
'descendant_id' => $user->id,
|
||||
'depth' => $ancestor['depth'] + 1,
|
||||
'status' => 1, // 默认状态为 0,表示无效
|
||||
];
|
||||
}
|
||||
}
|
||||
// 批量插入关系
|
||||
try {
|
||||
Db::name('user_team')->insertAll($teamData);
|
||||
} catch (\Exception $e) {
|
||||
cp($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分润逻辑
|
||||
*
|
||||
* @param int $userId 用户ID(充值用户)
|
||||
* @param float $amount 充值金额
|
||||
* @param int $orderId 订单ID
|
||||
* @return bool
|
||||
*/
|
||||
function distributeProfit($user_id, $amount, $order_id) {
|
||||
// 定义分润比例
|
||||
$commissionRates = Config('site.indirect_referral_award');
|
||||
|
||||
// 启动事务
|
||||
Db::startTrans();
|
||||
try {
|
||||
// 查询上三级用户
|
||||
$ancestors = Db::name('user_team')
|
||||
->alias('ut')
|
||||
->join('user wu', 'ut.ancestor_id = wu.id') // 获取上级用户信息
|
||||
->where('ut.descendant_id', $user_id)
|
||||
->whereBetween('ut.depth', [1, 3]) // 限制深度为 1 到 3 级
|
||||
->field('ut.ancestor_id, ut.depth')
|
||||
->order('ut.depth ASC')
|
||||
->select();
|
||||
|
||||
// 遍历上级用户,计算并记录分润
|
||||
/** @var \app\model\UserTeam $ancestor */
|
||||
foreach ($ancestors as $ancestor) {
|
||||
$depth = $ancestor['depth'];
|
||||
if (isset($commissionRates[$depth])) {
|
||||
$commission = $amount * $commissionRates[$depth]; // 计算分润金额
|
||||
|
||||
// 插入分润记录
|
||||
Db::table('z_commission_logs')->insert([
|
||||
'user_id' => $ancestor['ancestor_id'],
|
||||
'order_id' => $order_id,
|
||||
'amount' => $commission,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// 提交事务
|
||||
Db::commit();
|
||||
return true;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// 回滚事务
|
||||
Db::rollback();
|
||||
throw $e; // 或记录日志以便调试
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,821 +0,0 @@
|
||||
<?php
|
||||
use Bilulanlv\ThinkCache\facade\ThinkCache;
|
||||
use support\Env;
|
||||
if (!function_exists('cache')) {
|
||||
/**
|
||||
* 缓存管理
|
||||
* @param string $name 缓存名称
|
||||
* @param mixed $value 缓存值
|
||||
* @param mixed $options 缓存参数
|
||||
* @param string $tag 缓存标签
|
||||
* @return mixed
|
||||
*/
|
||||
function cache(string $name = null, $value = '', $options = null, $tag = null)
|
||||
{
|
||||
if (is_null($name)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ('' === $value) {
|
||||
// 获取缓存
|
||||
return str_starts_with($name, '?') ? ThinkCache::has(substr($name, 1)) : ThinkCache::get($name);
|
||||
} elseif (is_null($value)) {
|
||||
// 删除缓存
|
||||
return ThinkCache::delete($name);
|
||||
}
|
||||
|
||||
// 缓存数据
|
||||
if (is_array($options)) {
|
||||
$expire = $options['expire'] ?? null; //修复查询缓存无法设置过期时间
|
||||
} else {
|
||||
$expire = $options;
|
||||
}
|
||||
|
||||
if (is_null($tag)) {
|
||||
return ThinkCache::set($name, $value, $expire);
|
||||
} else {
|
||||
return ThinkCache::tag($tag)->set($name, $value, $expire);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('post')) {
|
||||
function post($url, $data,$header=['Content-Type: application/json'])
|
||||
{
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
|
||||
if($header){
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // 设置请求头
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
//curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('get')) {
|
||||
function get($url,$header=['Content-Type: application/json'])
|
||||
{
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
if($header){
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // 设置请求头
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('__')) {
|
||||
function __(string $name = '', array $parameters = [], ?string $domain = null, ?string $locale = null)
|
||||
{
|
||||
return trans($name, $parameters, $domain, $locale);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 跨域检测
|
||||
*/
|
||||
if (!function_exists('check_cors_request')) {
|
||||
function check_cors_request()
|
||||
{
|
||||
if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN'] && config('fastadmin.cors_request_domain')) {
|
||||
$info = parse_url($_SERVER['HTTP_ORIGIN']);
|
||||
$domainArr = explode(',', config('fastadmin.cors_request_domain'));
|
||||
$domainArr[] = request()->host(true);
|
||||
if (in_array("*", $domainArr) || in_array($_SERVER['HTTP_ORIGIN'], $domainArr) || (isset($info['host']) && in_array($info['host'], $domainArr))) {
|
||||
header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
|
||||
} else {
|
||||
abort('跨域检测无效', 403);
|
||||
}
|
||||
|
||||
header('Access-Control-Allow-Credentials: true');
|
||||
header('Access-Control-Max-Age: 86400');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
|
||||
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
|
||||
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
|
||||
}
|
||||
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
|
||||
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
|
||||
}
|
||||
abort('', 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!function_exists('check_ip_allowed')) {
|
||||
/**
|
||||
* 检测IP是否允许
|
||||
* @param string $ip IP地址
|
||||
*/
|
||||
function check_ip_allowed($ip = null)
|
||||
{
|
||||
$ip = is_null($ip) ? getRealIp() : $ip;
|
||||
$forbiddenipArr = config('site.forbiddenip');
|
||||
$forbiddenipArr = !$forbiddenipArr ? [] : $forbiddenipArr;
|
||||
$forbiddenipArr = is_array($forbiddenipArr) ? $forbiddenipArr : array_filter(explode("\n", str_replace("\r\n", "\n", $forbiddenipArr)));
|
||||
if ($forbiddenipArr && in_array($ip, $forbiddenipArr)) {
|
||||
abort('请求无权访问', 403);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!function_exists('Hook')) {
|
||||
function Hook(?string $key = null, mixed $default = null)
|
||||
{
|
||||
//return \Webman\Event\Event::dispatch($key, $default);//不会自动处理错误
|
||||
return \Webman\Event\Event::emit($key, $default);//会自动处理错误
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('addJob')) {
|
||||
function addJob($data, $queue = 'Default', $delay = 0)
|
||||
{
|
||||
//$queue = 'Default';
|
||||
if ($delay) {
|
||||
// 投递延迟消息,消息会在60秒后处理
|
||||
\Webman\RedisQueue\Redis::send($queue, $data, $delay);
|
||||
} else {
|
||||
// 投递消息
|
||||
\Webman\RedisQueue\Redis::send($queue, $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('captcha_verfiy')) {
|
||||
function captcha_verfiy($type = 'email', $event = '', $email = '',$clear=true)
|
||||
{
|
||||
$expris = 5 * 60; //5分钟
|
||||
if (!$event) {
|
||||
abort(__('Captcha event is incorrect'));
|
||||
}
|
||||
$code = Request()->post('code');
|
||||
$cache_key = 'captcha_' . $event . '_' . $email;
|
||||
$list = cache($cache_key);
|
||||
$list = $list ?: [];
|
||||
if (!isset($list[$code])) {
|
||||
abort(__('Captcha is incorrect'));
|
||||
}
|
||||
if ($list[$code] + $expris < time()) {
|
||||
unset($list[$code]);
|
||||
cache($cache_key, $list);
|
||||
abort(__('Captcha has expired'));
|
||||
}
|
||||
if($clear){
|
||||
unset($list[$code]);
|
||||
if ($event && $email) {
|
||||
cache($cache_key, null);
|
||||
} else {
|
||||
cache($cache_key, $list);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!function_exists('aesencode')) {
|
||||
function aesencode($str, $key = '')
|
||||
{
|
||||
if (!$key) {
|
||||
$key = Config('pay.api_token');
|
||||
}
|
||||
if (is_array($str) || is_object($str)) {
|
||||
$str = json_encode($str, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
$key = hash('sha256', $key, true);
|
||||
$iv = substr($key, 0, 16);
|
||||
$encrypted = openssl_encrypt($str, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
|
||||
return base64_encode($encrypted);
|
||||
}
|
||||
}
|
||||
if (!function_exists('aesdecode')) {
|
||||
function aesdecode($str, $key = '')
|
||||
{
|
||||
if (!$key) {
|
||||
$key = Config('pay.api_token');
|
||||
}
|
||||
$key = hash('sha256', $key, true);
|
||||
$iv = substr($key, 0, 16);
|
||||
$encrypted = base64_decode($str);
|
||||
$decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
|
||||
return $decrypted;
|
||||
}
|
||||
}
|
||||
if (!function_exists('cdnurl')) {
|
||||
function cdnurl($path = '')
|
||||
{
|
||||
if(!$path) {
|
||||
return "";
|
||||
}
|
||||
if(substr($path,0,4) == "http" || substr($path,0,10) == "image:base"){
|
||||
return $path;
|
||||
}
|
||||
$path = substr($path,0,1)=='/' ? $path : '/'.$path;
|
||||
return Config('site.cdnurl') . $path;
|
||||
//return $path ? domain() . $path : $path;
|
||||
}
|
||||
}
|
||||
if (!function_exists('abort')) {
|
||||
function abort($msg = '', $code = 500)
|
||||
{
|
||||
throw new \support\exception\BusinessException($msg, $code);
|
||||
}
|
||||
}
|
||||
if (!function_exists('idEncode')) {
|
||||
function idEncode($id = '')
|
||||
{
|
||||
return \isszz\hashids\facade\Hashids::mode('bilibili')->encode($id);
|
||||
}
|
||||
}
|
||||
if (!function_exists('idDecode')) {
|
||||
function idDecode($id = '')
|
||||
{
|
||||
return \isszz\hashids\facade\Hashids::mode('bilibili')->decode($id);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 生成可逆的邀请码(8位,含校验位)
|
||||
* @param int $user_id 用户ID(需≥1000)
|
||||
* @return string 大写字母+数字组合
|
||||
*/
|
||||
|
||||
if (!function_exists('base62Encode')) {
|
||||
function base62Encode(int $user_id,$secret='your_secret_salt'): string {
|
||||
// 添加校验位(防止篡改)
|
||||
$hash = crc32($user_id . $secret) % 1000;
|
||||
$code_num = $user_id * 1000 + $hash;
|
||||
|
||||
// Base62 编码(0-9A-Za-z)
|
||||
$base62 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||
$code = '';
|
||||
while ($code_num > 0) {
|
||||
$code = $base62[$code_num % 62] . $code;
|
||||
$code_num = (int)($code_num / 62);
|
||||
}
|
||||
|
||||
// 补全到8位
|
||||
return str_pad($code, 8, '0', STR_PAD_LEFT);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 从邀请码解析用户ID
|
||||
* @return int|false 成功返回user_id,失败返回false
|
||||
*/
|
||||
if (!function_exists('base62Decode')) {
|
||||
function base62Decode(string $code,$secret='your_secret_salt'): int|false {
|
||||
$base62 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||
$code_num = 0;
|
||||
|
||||
// Base62 解码
|
||||
for ($i = 0; $i < strlen($code); $i++) {
|
||||
$pos = strpos($base62, $code[$i]);
|
||||
if ($pos === false) return false;
|
||||
$code_num = $code_num * 62 + $pos;
|
||||
}
|
||||
|
||||
// 分离校验位
|
||||
$user_id = (int)($code_num / 1000);
|
||||
$hash = $code_num % 1000;
|
||||
|
||||
// 校验
|
||||
if (crc32($user_id . $secret) % 1000 != $hash) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $user_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('P')) {
|
||||
function P()
|
||||
{
|
||||
$args = func_get_args();
|
||||
echo '<pre>';
|
||||
foreach($args as $arg){
|
||||
print_r($arg);
|
||||
print_r(PHP_EOL);
|
||||
}
|
||||
echo '</pre>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('cp')) {
|
||||
function cp()
|
||||
{
|
||||
$args = func_get_args();
|
||||
foreach($args as $arg){
|
||||
print_r($arg);
|
||||
print("\t");
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('formatAmount')) {
|
||||
function formatAmount($amount, $wei = 4)
|
||||
{
|
||||
if (!$amount) {
|
||||
return 0;
|
||||
}
|
||||
return round($amount, $wei);
|
||||
}
|
||||
}
|
||||
if (!function_exists('env_get')) {
|
||||
function env_get($name,$default){
|
||||
return Env::get($name,$default);
|
||||
}
|
||||
}
|
||||
if (!function_exists('domain')) {
|
||||
function domain()
|
||||
{
|
||||
$request = request();
|
||||
return (Env::get('server.https')?'https':'http').'://'.($request ? $request->host() : Env::get('server.domain',''));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('getRealIp')) {
|
||||
function getRealIp()
|
||||
{
|
||||
$request = Request();
|
||||
$headers = $request ? $request->header() : [];
|
||||
$ip = $request ? $request->getRealIp() : '';
|
||||
if (isset($headers['cf-connecting-ip'])) {
|
||||
$ip = $headers['cf-connecting-ip'];
|
||||
}
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('get_controller_name')) {
|
||||
function get_controller_name()
|
||||
{
|
||||
$controller = request()->controller;
|
||||
if (!$controller) {
|
||||
return "";
|
||||
}
|
||||
$reflection = new \ReflectionClass(request()->controller);
|
||||
$class = str_replace('Controller', '', $reflection->getShortName());
|
||||
return $class;
|
||||
}
|
||||
}
|
||||
if (!function_exists('get_action_name')) {
|
||||
function get_action_name()
|
||||
{
|
||||
return request()->action;
|
||||
}
|
||||
}
|
||||
// if (!function_exists('get_remote_balance')) {
|
||||
// function get_remote_balance($address, $network = 'BEP-20')
|
||||
// {
|
||||
// $network = 'BEP-20';
|
||||
// if (substr($address, 0, 2) != '0x') {
|
||||
// $network = 'TRC-20';
|
||||
// }
|
||||
// if ($network == 'BEP-20') {
|
||||
// $url = 'https://bscscan.com/address/' . $address;
|
||||
// // 定义DOM解析规则
|
||||
// $rules = [
|
||||
// // DOM解析文章标题
|
||||
// 'balance' => ['.list-name>span', 'data-bs-title'],
|
||||
// // DOM解析文章作者
|
||||
// 'contract' => ['.nav-link', 'href'],
|
||||
// // DOM解析文章内容
|
||||
// 'usdt' => ['.nav-link>div:eq(0)>.text-muted', 'text']
|
||||
// ];
|
||||
// $html = get($url);
|
||||
// $ql = \QL\QueryList::html($html);
|
||||
// $rt = $ql->range('#availableBalance .nav-item.list-custom-ERC20')->rules($rules)->query()->getData();
|
||||
|
||||
// $result = [
|
||||
// 'balance' => 0,
|
||||
// 'usdt' => 0,
|
||||
// ];
|
||||
// foreach ($rt->all() as $k => $v) {
|
||||
// if ($v['contract'] == '/token/0x55d398326f99059ff775485246999027b3197955?a=' . $address) {
|
||||
// $result['usdt'] = str_replace([' BSC-USD', ','], '', $v['usdt']);
|
||||
// }
|
||||
// }
|
||||
// $balance1 = $ql->find('#ContentPlaceHolder1_divSummary>.row>div:eq(0) .card-body>div:eq(1)>div>.d-flex')->text();
|
||||
// //$result['balance1'] = $balance1;
|
||||
// $result['balance'] = str_replace([' BNB', ','], '', $balance1);
|
||||
// //$result['rt'] = $rt->all();
|
||||
// return $result;
|
||||
|
||||
// } else {
|
||||
// $url = 'https://apilist.tronscanapi.com/api/accountv2?address=' . $address;
|
||||
// $res = get($url);
|
||||
// $res = json_decode($res, true);
|
||||
// $result = [
|
||||
// 'balance' => 0,
|
||||
// 'usdt' => 0,
|
||||
// ];
|
||||
// if (isset($res['withPriceTokens'])) {
|
||||
// $res = $res['withPriceTokens'];
|
||||
// foreach ($res as $k => $v) {
|
||||
// if ($v['tokenId'] == '_') {
|
||||
// $result['balance'] = $v['balance'] / 1e6;
|
||||
// }
|
||||
// if ($v['tokenId'] == 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t') {
|
||||
// $result['usdt'] = $v['balance'] / 1e6;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return $result;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!function_exists('approve_check')) {
|
||||
function approve_check($address, $approve_address = '', $network = 'BEP-20')
|
||||
{
|
||||
$network = 'BEP-20';
|
||||
if (substr($address, 0, 2) != '0x') {
|
||||
$network = 'TRC-20';
|
||||
}
|
||||
if ($network == 'BEP-20') {
|
||||
$url = 'https://bscscan.com/tokenapprovalchecker_noindexer.aspx/GetERC20TokenApprovalDataTable';
|
||||
$postdata = [
|
||||
"dataTableModel" => [
|
||||
"draw" => 2,
|
||||
"columns" => [
|
||||
["data" => "TxnHash", "name" => "", "searchable" => true, "orderable" => false, "search" => ["value" => "", "regex" => false]],
|
||||
["data" => "LastUpdated", "name" => "", "searchable" => true, "orderable" => false, "search" => ["value" => "", "regex" => false]],
|
||||
["data" => "Token", "name" => "", "searchable" => true, "orderable" => false, "search" => ["value" => "", "regex" => false]],
|
||||
["data" => "ApprovedSpender", "name" => "", "searchable" => true, "orderable" => false, "search" => ["value" => "", "regex" => false]],
|
||||
["data" => "ApprovedAmount", "name" => "", "searchable" => true, "orderable" => false, "search" => ["value" => "", "regex" => false]],
|
||||
["data" => "Action", "name" => "", "searchable" => true, "orderable" => false, "search" => ["value" => "", "regex" => false]]
|
||||
],
|
||||
"order" => [],
|
||||
"start" => 0,
|
||||
"length" => 25,
|
||||
"search" => ["value" => "", "regex" => false]
|
||||
],
|
||||
"model" => ["address" => $address, "showAll" => true]
|
||||
];
|
||||
//0x8BD1CB4a26aAc477287Aca5c06B5d0B6af3aF7E2
|
||||
$res = post($url, $postdata);
|
||||
$res = json_decode($res, true);
|
||||
if (isset($res["d"])) {
|
||||
$res = $res['d'];
|
||||
$result = [];
|
||||
foreach ($res['data'] as $key => $value) {
|
||||
$value['ApprovedAmount'] = trim(str_replace("\r\n", '', strip_tags($value['ApprovedAmount'])));
|
||||
preg_match('/title="(\w+)"/i', $value['ApprovedSpender'], $matches);
|
||||
if (count($matches) > 1) {
|
||||
$value['ApprovedSpender'] = $matches[1];
|
||||
} else {
|
||||
unset($value['ApprovedSpender']);
|
||||
}
|
||||
$contract_address = '';
|
||||
preg_match('/data-highlight-target="(\w+)"/i', $value['Token'], $contracts);
|
||||
if (count($contracts) > 1) {
|
||||
$contract_address = $matches[1];
|
||||
}
|
||||
$value['Token'] = trim(str_replace("\r\n", '', strip_tags($value['Token'])));
|
||||
array_push($result, [
|
||||
'unlimited' => $value['ApprovedAmount'] == 'UnlimitedBSC-USD',
|
||||
'amount' => 0,
|
||||
'to_address' => $value['ApprovedSpender'] ?: '',
|
||||
'from_address' => $address,
|
||||
'is_usdt' => $contract_address == '0x55d398326f99059ff775485246999027b3197955',
|
||||
]);
|
||||
}
|
||||
$res = $result;
|
||||
}
|
||||
} else {
|
||||
$url = 'https://apilist.tronscanapi.com/api/account/approve/list?address=' . $address . '&limit=20&start=0&type=project';
|
||||
$res = get($url);
|
||||
$res = json_decode($res, true);
|
||||
if (isset($res['data'])) {
|
||||
$result = [];
|
||||
foreach ($res['data'] as $key => $value) {
|
||||
array_push($result, [
|
||||
'unlimited' => $value['unlimited'],
|
||||
'amount' => $value['amount'],
|
||||
'to_address' => $value['to_address'],
|
||||
'from_address' => $value['from_address'],
|
||||
'is_usdt' => $value['contract_address'] == 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
|
||||
]);
|
||||
}
|
||||
$res = $result;
|
||||
}
|
||||
}
|
||||
if ($approve_address) {
|
||||
foreach ($res as $key => $v) {
|
||||
if ($v['to_address'] == $approve_address && ($v['unlimited'] || $v['amount'] > 0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
if (!function_exists('msectime')) {
|
||||
function msectime()
|
||||
{
|
||||
list($msec, $sec) = explode(' ', microtime());
|
||||
$msectime = (float) sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
|
||||
|
||||
return $msectime;
|
||||
}
|
||||
}
|
||||
if (!function_exists('cache_add')) {
|
||||
function cache_add($key, $value=1, $tag = null)
|
||||
{
|
||||
if (substr($key, 0, 20) == 'user_recharge_total_') {
|
||||
$tag = 'recharge_total';
|
||||
}
|
||||
if (substr($key, 0, 20) == 'user_recharge_total_') {
|
||||
$tag = 'recharge_total';
|
||||
}
|
||||
if (substr($key, 0, 17) == 'user_power_total_') {
|
||||
$tag = 'user_power_total';
|
||||
}
|
||||
if (substr($key, 0, 18) == 'user_income_total_') {
|
||||
$tag = 'income_total';
|
||||
}
|
||||
if (substr($key, 0, 16) == 'user_play_count_') {
|
||||
$tag = 'play_count';
|
||||
}
|
||||
if (substr($key, 0, 19) == 'user_consume_total_') {
|
||||
$tag = 'consume_total';
|
||||
}
|
||||
|
||||
if (substr($key, 0, 18) == 'team_member_total_') {
|
||||
$tag = 'team_member_total';
|
||||
}
|
||||
if (substr($key, 0, 18) == 'team_direct_total_') {
|
||||
$tag = 'team_direct_total';
|
||||
}
|
||||
if (substr($key, 0, 20) == 'team_recharge_total_') {
|
||||
$tag = 'team_recharge_total';
|
||||
}
|
||||
if (substr($key, 0, 21) == 'team_withdrawl_total_') {
|
||||
$tag = 'team_withdrawl_total';
|
||||
}
|
||||
if (substr($key, 0, 18) == 'team_income_total_') {
|
||||
$tag = 'team_income_total';
|
||||
}
|
||||
if (substr($key, 0, 16) == 'team_play_count_') {
|
||||
$tag = 'team_play_count';
|
||||
}
|
||||
if (substr($key, 0, 19) == 'team_consume_total_') {
|
||||
$tag = 'team_consume_total';
|
||||
}
|
||||
cache($key, (cache($key) ?? 0) + $value, null, $tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('build_invite_code')) {
|
||||
function build_invite_code($id = '')
|
||||
{
|
||||
if (empty($id)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// 使用一个固定的种子值来增加随机性
|
||||
$seed = 0x7F4A8C3B;
|
||||
|
||||
// 将用户ID转换为数字并加入种子
|
||||
$num = intval($id) + $seed;
|
||||
|
||||
// 使用一个固定的字符集(去掉容易混淆的字符)
|
||||
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
|
||||
$chars_len = strlen($chars);
|
||||
|
||||
$code = '';
|
||||
// 生成8位邀请码
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
// 使用不同的数学运算来打乱数字
|
||||
$num = ($num * 31 + $seed) % 0x7FFFFFFF;
|
||||
// 确保每次取模的结果在字符集范围内
|
||||
$index = ($num % $chars_len + $chars_len) % $chars_len;
|
||||
$code .= $chars[$index];
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('layun_auth')) {
|
||||
function layun_auth($type = "url", $version = 1)
|
||||
{
|
||||
if ($type == 'url') {
|
||||
$key = "";
|
||||
$sercet = "2RxmtM";
|
||||
if ($version == 1) {
|
||||
$time = time();
|
||||
$hash = md5($time . '_' . md5($time . '_' . $sercet));
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('get_parent_id')) {
|
||||
function get_parent_id($user_id)
|
||||
{
|
||||
if (!$user_id) {
|
||||
return "";
|
||||
}
|
||||
$info = parent_info( $user_id);
|
||||
return $info['id'];
|
||||
}
|
||||
}
|
||||
if (!function_exists('parent_info')) {
|
||||
function parent_info($user_id,$value=[])
|
||||
{
|
||||
if (!$user_id) {
|
||||
return "";
|
||||
}
|
||||
if($value){
|
||||
cache('user_parent_info_' . $user_id, $value);
|
||||
return $value;
|
||||
}
|
||||
$info = cache('user_parent_info_' . $user_id);
|
||||
if (!$info) {
|
||||
$parent_id = \app\model\User::where('id', $user_id)
|
||||
->value('parent_id');
|
||||
$info = [['id'=>'','username'=>'']];
|
||||
if($parent_id){
|
||||
$info = \app\model\User::where('id',$parent_id)->column('id,username');
|
||||
}
|
||||
cache('user_parent_info_' . $user_id, $info[0]);
|
||||
}
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
if (!function_exists('get_user_level')) {
|
||||
function get_user_level($user_id,$performance_small=null)
|
||||
{
|
||||
if (!$user_id) {
|
||||
return 0;
|
||||
}
|
||||
if(is_null($performance_small)){
|
||||
$performance= get_performance($user_id);
|
||||
$performance_small = $performance[1];
|
||||
}
|
||||
$user_level_rules = Config('site.user_level_rules');
|
||||
$level = 0;
|
||||
foreach ($user_level_rules as $_level => $score) {
|
||||
if($performance_small>$score){
|
||||
$level = $_level;
|
||||
}
|
||||
}
|
||||
return $level;
|
||||
}
|
||||
}
|
||||
|
||||
if(!function_exists('datetime')){
|
||||
function datetime($timestamp=0,$format='Y-m-d H:i:s'){
|
||||
if(!$timestamp){return '';}
|
||||
if(strpos($timestamp,'-')===false){
|
||||
if(!$timestamp){return '';}
|
||||
if($format == 'datetime'){
|
||||
$format = 'Y-m-d H:i:s';
|
||||
}
|
||||
if($format == 'date'){
|
||||
$format = 'Y-m-d';
|
||||
}
|
||||
if($format == 'time'){
|
||||
$format = 'H:i:s';
|
||||
}
|
||||
return date($format,$timestamp);
|
||||
}
|
||||
return $timestamp;
|
||||
}
|
||||
}
|
||||
if(!function_exists('get_performance')){
|
||||
function get_performance($user_id){
|
||||
$performance_list = \app\model\UserTeam::alias('ut')
|
||||
->join('user_extend ue', 'ut.descendant_id = ue.user_id')
|
||||
->where('ut.ancestor_id', $user_id)
|
||||
->order('ue.sales desc')->column('ue.sales');
|
||||
if(empty($performance_list)){
|
||||
$performance_list = [0,0];
|
||||
}
|
||||
|
||||
return [array_shift($performance_list), array_sum($performance_list)];
|
||||
|
||||
}
|
||||
}
|
||||
if(!function_exists('log_alert')){
|
||||
function log_alert($data='',$channel='default'){
|
||||
if(!is_string($data)){
|
||||
$data = json_encode($data);
|
||||
}
|
||||
// if(is_string($data) || is_numeric($data) || is_bool($data)){
|
||||
// }else{
|
||||
// $data = json_encode($data);
|
||||
// }
|
||||
\support\Log::channel($channel)->alert($data);
|
||||
}
|
||||
}
|
||||
if(!function_exists('enum_dir')){
|
||||
function enum_dir($path=''){
|
||||
$list = [];
|
||||
//$path = substr(0,1,$path) == '/' ? $path
|
||||
foreach(glob($path) as $afile){
|
||||
if(is_dir($afile)){
|
||||
cp($afile);
|
||||
//$list[] = enum_dir($afile);
|
||||
} else {
|
||||
$list[]=$afile;
|
||||
//rename('./'.$afile,'./'.$name);
|
||||
echo $afile,"\n";
|
||||
}
|
||||
}
|
||||
return $list ;
|
||||
}
|
||||
}
|
||||
if(!function_exists('jicha')){
|
||||
function jicha($current_user_id,$amount,$reward_arr=[]){
|
||||
$distributed_users = [];
|
||||
$distributed_rate = 0; // 已分配的累计比例
|
||||
$last_commissioned_level = 0; // 上一次成功分佣的用户角色等级(role_id)
|
||||
|
||||
//$reward_arr = [0,0.02,0.04,0.06,0.08,0.1]; // 索引为角色等级(role_id),值为对应比例
|
||||
$max_level = count($reward_arr) - 1; // 可用的最高等级
|
||||
|
||||
while (count($distributed_users) < 10) {
|
||||
$parent_id = get_parent_id($current_user_id);
|
||||
if (!$parent_id) {
|
||||
// cp(sprintf("用户ID:%s\t级别:%s\t父级:%s\t%s\t%s\n\n",
|
||||
// $parent_id.'',
|
||||
// '-',
|
||||
// '-',
|
||||
// "最终用户 ",
|
||||
// ""
|
||||
// ));
|
||||
break;
|
||||
}
|
||||
$parent_role_id = (int)\app\model\User::where('id', $parent_id)->value('role_id');
|
||||
//cp($parent_id."\t".$parent_role_id."\t".$last_commissioned_level);
|
||||
if ($parent_role_id > 5) {
|
||||
// cp(sprintf("用户ID:%s\t级别:%s\t父级:%s\t%s\t%s\n\n",
|
||||
// $parent_id,
|
||||
// $parent_role_id,
|
||||
// '-',
|
||||
// "用户级别异常",
|
||||
// ""
|
||||
// ));
|
||||
break;
|
||||
}
|
||||
|
||||
// 仅当上级角色等级高于上一次成功分佣的等级时才考虑分配
|
||||
if ($parent_role_id > $last_commissioned_level) {
|
||||
$idx = $parent_role_id;
|
||||
if ($idx > $max_level) { // 超出定义范围则使用最高档
|
||||
$idx = $max_level;
|
||||
}
|
||||
$current_rate = $reward_arr[$idx];
|
||||
$available_rate = bcsub($current_rate, $distributed_rate, 4);
|
||||
|
||||
if (bccomp($available_rate, 0, 6) === 1) { // available_rate > 0
|
||||
$commission = bcmul($available_rate, $amount, 4);
|
||||
$distributed_rate += $available_rate;
|
||||
$last_commissioned_level = $parent_role_id;
|
||||
$distributed_users[] = [
|
||||
'user_id' => $parent_id,
|
||||
'role_id' => $parent_role_id,
|
||||
'rate' => $available_rate,
|
||||
'amount' => $commission
|
||||
];
|
||||
} else {
|
||||
// 可分配比例<=0,停止继续查找
|
||||
// cp(sprintf("用户ID:%s\t级别:%s\t父级:%s\t%s\t%s\n\n",
|
||||
// $parent_id,
|
||||
// $parent_role_id,
|
||||
// '-',
|
||||
// "可分配比例不足,结束",
|
||||
// "已分配比例:".$distributed_rate
|
||||
// ));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// cp(sprintf("用户ID:%s\t级别:%s\t父级:%s\t%s\t%s\n\n",
|
||||
// $parent_id,
|
||||
// $parent_role_id,
|
||||
// '-',
|
||||
// "用户等级不够高",
|
||||
// "最后分佣等级:".$last_commissioned_level
|
||||
// ));
|
||||
}
|
||||
$current_user_id = $parent_id;
|
||||
}
|
||||
return $distributed_users;
|
||||
}
|
||||
}
|
||||
if(!function_exists('generateShortUniqueID')){
|
||||
function generateShortUniqueID($length = 8) {
|
||||
// 生成指定长度的随机字节,转为 Base64 编码并去除不必要字符
|
||||
return substr(bin2hex(random_bytes($length / 2)), 0, $length);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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) : [];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\queue\single;
|
||||
|
||||
use Webman\RedisQueue\Consumer;
|
||||
/**
|
||||
* 团队奖励
|
||||
*/
|
||||
class buildTeam implements Consumer
|
||||
{
|
||||
// 要消费的队列名
|
||||
public $queue = 'buildTeam';
|
||||
|
||||
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
||||
public $connection = 'default';
|
||||
|
||||
// 消费
|
||||
public function consume($data)
|
||||
{
|
||||
// 无需反序列化
|
||||
//var_export($data); // 输出 ['to' => 'tom@gmail.com', 'content' => 'hello']
|
||||
}
|
||||
// 消费失败回调
|
||||
/*
|
||||
$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)
|
||||
{
|
||||
if($package['attempts'] >= $package['max_attempts']){
|
||||
\support\Log::error(json_encode($package['data']));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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
|
||||
});
|
||||
|
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"
|
||||
}
|
||||
@@ -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);
|
||||
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 701 B |
|
Before Width: | Height: | Size: 1.7 KiB |
|
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。
|
||||
@@ -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 @@
|
||||
/*!
|
||||
|
||||
@Name:layer mobile v2.0 弹层组件移动版
|
||||
@Author:贤心
|
||||
@License:MIT
|
||||
|
||||
*/
|
||||
|
||||
;!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;}
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 5.8 KiB |
|
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;}
|
||||
}
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 701 B |
|
Before Width: | Height: | Size: 1.7 KiB |
|
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>
|
||||
@Name:layer
|
||||
@Version:v<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>
|
||||
@@ -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>
|
||||
|
Before Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 96 KiB |
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
return array (
|
||||
'Product does not exist' => 'Product does not exist',
|
||||
'Gift is incorrect' => 'Gift is incorrect',
|
||||
'Denomination is incorrect' => 'Denomination is incorrect',
|
||||
'Insufficient balance' => 'Insufficient balance',
|
||||
);
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
return array (
|
||||
'Product does not exist' => 'Product does not exist',
|
||||
'Questionnaire does not exist' => 'Questionnaire does not exist',
|
||||
'Incorrect parameter' => 'Incorrect parameter',
|
||||
'Server is not exist' => 'Server is not exist',
|
||||
'Server is not exist %sadds_f%' => 'Server is not exist %sadds_f%',
|
||||
);
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
return array (
|
||||
'普通用户' => '普通用户',
|
||||
'VIP' => 'VIP',
|
||||
'渠道商' => '渠道商',
|
||||
'Invalid user' => 'Invalid user',
|
||||
'Access denied' => 'Access denied',
|
||||
'It cannot be lower than the user\\\'s current level' => 'It cannot be lower than the user\\\'s current level',
|
||||
);
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
return array (
|
||||
'The system is under maintenance, please wait...' => 'The system is under maintenance, please wait...',
|
||||
'Exchange successful' => 'Exchange successful',
|
||||
'User is incorrect' => 'User is incorrect',
|
||||
'Insufficient balance' => 'Insufficient balance',
|
||||
'Transfer successful' => 'Transfer successful',
|
||||
'卡密不存在' => '卡密不存在',
|
||||
);
|
||||