1
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\Base;
|
||||
/**
|
||||
* @property integer $id 主键(ID) - 无注释
|
||||
* @property integer $user_id 用户ID
|
||||
* @property string $title 名字
|
||||
* @property string $network 网络
|
||||
* @property string $address 账号
|
||||
* @property string $img 图片
|
||||
* @property integer $is_default 是否默认
|
||||
* @property integer $created_at 创建时间
|
||||
* @property integer $updated_at 更新时间
|
||||
* @property integer $status 状态
|
||||
*/
|
||||
class Address extends Base
|
||||
{
|
||||
//protected $name = 'address';
|
||||
|
||||
|
||||
function getNetworkList(){
|
||||
return [
|
||||
"BEP-20"=>"BEP-20",
|
||||
"TRC-20"=>"TRC-20",
|
||||
"WECHAT"=>"微信",
|
||||
"ALIPAY"=>"支付宝"
|
||||
];
|
||||
}
|
||||
function getStatusList(){
|
||||
return [
|
||||
'0' => '禁用',
|
||||
'1' => '启用',
|
||||
];
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('User', 'user_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
use support\think\Db;
|
||||
|
||||
use traits\model\SoftDelete;
|
||||
|
||||
class Archives extends Base
|
||||
{
|
||||
|
||||
//use SoftDelete;// 表名
|
||||
|
||||
protected function getOptions(): array{
|
||||
return array_merge(parent::getOptions(),[
|
||||
'append' => [
|
||||
'status_text'
|
||||
],
|
||||
]);
|
||||
}
|
||||
public static function onAfterInsert(Archives $row)
|
||||
{
|
||||
\support\Log::error(''. json_encode($row));
|
||||
$pk = $row->getPk();
|
||||
self::where($pk, $row->$pk)->update(['weigh' => $row[$pk]]);
|
||||
$changedData = $row->getData();
|
||||
if (isset($changedData['content'])) {
|
||||
//在更新成功后刷新副表
|
||||
$values = array_intersect_key($changedData, array_flip(['content']));
|
||||
$values['id'] = $row['id'];
|
||||
//更新副表
|
||||
Db::name('content')->insert($values, true);
|
||||
}
|
||||
}
|
||||
public static function onAfterUpdate($row)
|
||||
{
|
||||
\support\Log::info('onAfterUpdate'.$row->id. json_encode($row->getChangedData()));
|
||||
$changedData = $row->getChangedData();
|
||||
if (isset($changedData['content'])) {
|
||||
//在更新成功后刷新副表
|
||||
$values = array_intersect_key($row->getData(), array_flip(['content']));
|
||||
//更新副表
|
||||
Db::name('content')->where('id',$row->id)->update($values);
|
||||
}
|
||||
}
|
||||
public static function onAfterDelete($row)
|
||||
{
|
||||
Db::name('content')->where('id',$row->id)->delete();
|
||||
}
|
||||
/**
|
||||
* 批量设置数据
|
||||
* @param $data
|
||||
* @return $this
|
||||
*/
|
||||
public function setAddonData(string|array|object $data)
|
||||
{
|
||||
if (is_object($data)) {
|
||||
$data = get_object_vars($data);
|
||||
}
|
||||
foreach($data as $k=>$v){
|
||||
$this->$k=$v;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStatusList()
|
||||
{
|
||||
return ['1' => '正常', '0' => '隐藏'];
|
||||
}
|
||||
public function getStatusTextAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
|
||||
$list = $this->getStatusList();
|
||||
return isset($list[$value]) ? $list[$value] : '';
|
||||
}
|
||||
public function getCategoryOptions($type='default'){
|
||||
return Category::where('status','1')->where('type',$type)->column('id,title');
|
||||
}
|
||||
function setCreatedAtAttr($v,$row=[]){
|
||||
cp($v);
|
||||
cp($row);
|
||||
}
|
||||
|
||||
|
||||
public function getFlagList()
|
||||
{
|
||||
return Config('site.flagtype');
|
||||
}
|
||||
|
||||
public function category()
|
||||
{
|
||||
return $this->belongsTo('Category', 'category_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
namespace app\model;
|
||||
|
||||
use Symfony\Component\Console\Input\Input;
|
||||
use think\Model;
|
||||
use think\facade\Db;
|
||||
|
||||
class BalanceLog extends Base
|
||||
{
|
||||
|
||||
// 表结构定义(使用时间戳)
|
||||
const TABLE_SCHEMA = [
|
||||
'id' => 'int(11) NOT NULL AUTO_INCREMENT',
|
||||
'user_id' => 'int(11) NOT NULL',
|
||||
'currency' => 'varchar(20) NOT NULL',
|
||||
'amount' => 'decimal(15,2) NOT NULL',
|
||||
'before' => 'decimal(15,2) NOT NULL',
|
||||
'after' => 'decimal(15,2) NOT NULL',
|
||||
'type' => 'varchar(50) NOT NULL',
|
||||
'created_at' => 'int(11) NOT NULL COMMENT \'UNIX timestamp\'', // 改为整型时间戳
|
||||
'memo' => 'varchar(255) DEFAULT NULL',
|
||||
'PRIMARY KEY (`id`)'
|
||||
];
|
||||
function getCreatedAtAttr($v){
|
||||
return $v ? explode('.',$v)[0] : '';
|
||||
}
|
||||
protected function getOptions(): array{
|
||||
return array_merge(parent::getOptions(),[
|
||||
'connection' => 'mongodb',
|
||||
// 'append' => [
|
||||
// 'from_user',
|
||||
// 'to_user'
|
||||
// ],
|
||||
]);
|
||||
}
|
||||
public static function create(array|object $data, array $allowField = [], bool $replace = false):\think\model\contract\Modelable
|
||||
{
|
||||
$model = new static();
|
||||
if(isset($data['currency'])){
|
||||
if(in_array($data['currency'],Config('site.allow_balance_log'))){
|
||||
$data['status']=isset($data['status']) ? $data['status']:1;
|
||||
$data['user_id'] = intval($data['user_id']);
|
||||
$data['amount'] = floatval($data['amount']);
|
||||
$data['before'] = floatval($data['before']);
|
||||
$data['after'] = floatval($data['after']);
|
||||
$data['type'] = $data['type'] instanceof \app\enum\BalanceType ? $data['type']->value : floatval($data['type']);
|
||||
$model->setSuffix('_'.strtolower($data['currency']))->allowField($allowField)
|
||||
->replace($replace)
|
||||
->save($data, true);
|
||||
}
|
||||
}
|
||||
return $model->fetchModel($model);
|
||||
}
|
||||
|
||||
// 创建所有需要的表索引
|
||||
public static function createAllIndexes(): array
|
||||
{
|
||||
$results = [];
|
||||
$allow_balance_log = Config('site.allow_balance_log');
|
||||
foreach ($allow_balance_log as $currency) {
|
||||
$results[$currency] = self::createTableIndexes($currency);
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
// 创建索引(适配时间戳查询)
|
||||
public static function createTableIndexes(string $currency): array
|
||||
{
|
||||
$table = self::getTableName($currency);
|
||||
$results = [];
|
||||
|
||||
try {
|
||||
// 确保归档表存在
|
||||
if (!self::tableExists($table)) {
|
||||
self::createTableStructure($table);
|
||||
}
|
||||
// 主复合索引(使用时间戳)
|
||||
if (!self::indexExists($table, 'idx_user_currency_type_created')) {
|
||||
Db::execute("ALTER TABLE `{$table}` ADD INDEX `idx_user_currency_type_created` (`user_id`, `currency`, `type`, `created_at`)");
|
||||
$results[] = "Created idx_user_currency_type_created on {$table}";
|
||||
}
|
||||
|
||||
// 时间索引(降序优化)
|
||||
if (!self::indexExists($table, 'idx_created_at')) {
|
||||
Db::execute("ALTER TABLE `{$table}` ADD INDEX `idx_created_at` (`created_at` DESC)");
|
||||
$results[] = "Created idx_created_at on {$table}";
|
||||
}
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
$results['error'] = "Error on {$table}: " . $e->getMessage();
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
// 检查索引是否存在
|
||||
protected static function indexExists(string $table, string $indexName): bool
|
||||
{
|
||||
$indexes = Db::query("SHOW INDEX FROM `{$table}` WHERE Key_name = ?", [$indexName]);
|
||||
return !empty($indexes);
|
||||
}
|
||||
|
||||
// 检查表是否存在
|
||||
protected static function tableExists(string $table): bool
|
||||
{
|
||||
try {
|
||||
Db::query("SELECT 1 FROM `{$table}` LIMIT 1");
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 数据归档方法(可在定时任务中调用)
|
||||
public static function archiveData(int $days = 3): array
|
||||
{
|
||||
$results = [];
|
||||
$allow_balance_log = Config('site.allow_balance_log');
|
||||
foreach ($allow_balance_log as $currency) {
|
||||
$results[$currency] = self::archiveCurrencyData($currency, $days);
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
// 归档指定货币的数据
|
||||
protected static function archiveCurrencyData(string $currency, int $days): array
|
||||
{
|
||||
$table = self::getTableName($currency);
|
||||
$archiveTable = $table . '_archive';
|
||||
$cutoffTimestamp = time() - ($days * 86400); // 转为时间戳计算
|
||||
$result = [
|
||||
'table' => $table,
|
||||
'archived' => 0,
|
||||
'messages' => []
|
||||
];
|
||||
|
||||
try {
|
||||
// 确保归档表存在
|
||||
if (!self::tableExists($archiveTable)) {
|
||||
self::createTableStructure($archiveTable);
|
||||
$result['messages'][] = "Created archive table: {$archiveTable}";
|
||||
}
|
||||
|
||||
// 分批归档数据
|
||||
$totalArchived = 0;
|
||||
Db::table($table)
|
||||
->where('created_at', '<=', $cutoffTimestamp)
|
||||
->chunk(1000, function($logs) use ($archiveTable, $table, &$totalArchived) {
|
||||
Db::table($archiveTable)->insertAll($logs);
|
||||
$count = count($logs);
|
||||
Db::table($table)->whereIn('id', array_column($logs, 'id'))->delete();
|
||||
$totalArchived += $count;
|
||||
});
|
||||
|
||||
$result['archived'] = $totalArchived;
|
||||
$result['messages'][] = "Archived {$totalArchived} records from {$table}";
|
||||
|
||||
// 优化表
|
||||
Db::execute("OPTIMIZE TABLE `{$table}`");
|
||||
$result['messages'][] = "Optimized table: {$table}";
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
$result['error'] = $e->getMessage();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// 查询方法(示例)
|
||||
public static function queryLogs($userId, $currency, $type = null, $startTime = null, $endTime = null)
|
||||
{
|
||||
$model = new static;
|
||||
$query = $model->setSuffix('_'.strtolower($currency))->where('currency', $currency)
|
||||
->where('user_id', intval($userId))
|
||||
->order('created_at', 'desc');
|
||||
|
||||
if ($type) {
|
||||
if($type == '99999'){
|
||||
$query->whereIn('type', [
|
||||
\app\enum\BalanceType::OUTPUT_REWARD->value,
|
||||
\app\enum\BalanceType::WITHDRAW_REWARD->value,
|
||||
\app\enum\BalanceType::PRODUCT_INCOME->value,
|
||||
\app\enum\BalanceType::AGENT_COMMISSION->value,
|
||||
\app\enum\BalanceType::DIFFERENTIAL_COMMISSION->value
|
||||
]);
|
||||
}else{
|
||||
$query->where('type', intval($type));
|
||||
}
|
||||
}
|
||||
|
||||
if ($startTime) {
|
||||
// 支持传入时间戳或日期字符串
|
||||
//$startTimestamp = is_numeric($startTime) ? intval($startTime) : strtotime($startTime);
|
||||
$query->where('created_at', '>=', $startTime);
|
||||
}
|
||||
|
||||
if ($endTime) {
|
||||
// 支持传入时间戳或日期字符串
|
||||
//$endTimestamp = is_numeric($endTime) ? intval($endTime) : strtotime($endTime);
|
||||
$query->where('created_at', '<=', $endTime);
|
||||
}
|
||||
$limit = 10;
|
||||
if(request()){
|
||||
$limit = input('limit',10);
|
||||
}
|
||||
return $query->paginate($limit);
|
||||
}
|
||||
|
||||
// 创建表结构
|
||||
protected static function createTableStructure(string $table): bool
|
||||
{
|
||||
if (self::tableExists($table)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
foreach (self::TABLE_SCHEMA as $column => $definition) {
|
||||
if (strpos($definition, 'PRIMARY KEY') === false) {
|
||||
$columns[] = "`{$column}` {$definition}";
|
||||
}
|
||||
}
|
||||
|
||||
$primaryKey = self::TABLE_SCHEMA['PRIMARY KEY'] ?? 'PRIMARY KEY (`id`)';
|
||||
|
||||
$sql = "CREATE TABLE `{$table}` (" .
|
||||
implode(', ', $columns) . ", " .
|
||||
$primaryKey .
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
|
||||
|
||||
Db::execute($sql);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use DateTimeInterface;
|
||||
use support\think\Model;
|
||||
|
||||
class Base extends Model
|
||||
{
|
||||
protected function getOptions(): array{
|
||||
return [
|
||||
'connection' => 'mysql',
|
||||
'createTime' => 'created_at',
|
||||
'updateTime' => 'updated_at',
|
||||
'deleteTime' => 'deleted_at',
|
||||
'autoWriteTimestamp' => 'int',
|
||||
//'dateFormat' => false
|
||||
// query 自定义数据库查询对象类名(默认为空)
|
||||
// type 需要自动转换的字段及类型(数组,默认为空)
|
||||
// autoValidate 是否自动验证(开启后会自动进行数据验证)
|
||||
// validate 对应验证类名或验证规则(字符串或数组,autoValidate参数开启后有效)
|
||||
// strict 是否严格区分字段大小写(默认为true)
|
||||
// disuse 废弃字段(数组,默认为空)
|
||||
// readonly 只读字段(数组,默认为空)
|
||||
// hidden 输出隐藏字段(数组,默认为空)
|
||||
// visible 输出显示字段(数组,默认为空)
|
||||
// append 输出追加字段(数组,默认为空)
|
||||
// mapping 字段映射(数组,默认为空)
|
||||
// autoRelation 自动with关联(数组,默认为空)
|
||||
// insert 自动新增写入(数组,默认为空)
|
||||
// update 自动更新写入(数组,默认为空)
|
||||
// dateFormat 时间输出格式化设置
|
||||
];
|
||||
}
|
||||
/**
|
||||
* 格式化日期
|
||||
*
|
||||
* @param DateTimeInterface $date
|
||||
* @return string
|
||||
*/
|
||||
protected function serializeDate(DateTimeInterface $date)
|
||||
{
|
||||
return $date->format('Y-m-d H:i:s');
|
||||
}
|
||||
function getStatusList(){
|
||||
return [
|
||||
'0' => '隐藏',
|
||||
'1' => '正常',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
/**
|
||||
* @property integer $id 主键(ID) - 无注释
|
||||
* @property integer $user_id 用户ID
|
||||
* @property float $amount 总价
|
||||
* @property integer $type 类型
|
||||
* @property string $title 标题
|
||||
* @property integer $total 总数量
|
||||
* @property integer $used 已使用的数量
|
||||
* @property integer $expires 过期时间
|
||||
* @property integer $days 量
|
||||
* @property integer $created_at 创建时间
|
||||
* @property integer $updated_at 更新时间
|
||||
* @property integer $status 状态
|
||||
*/
|
||||
class Card extends Base
|
||||
{
|
||||
protected $name = 'card';
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
/**
|
||||
* @property integer $id 主键(主键)
|
||||
* @property string $username 用户名
|
||||
* @property string $nickname 昵称
|
||||
* @property string $password 密码
|
||||
* @property string $created_at 创建时间
|
||||
* @property string $updated_at 更新时间
|
||||
* @property integer $status 禁用
|
||||
*/
|
||||
class Category extends Base
|
||||
{
|
||||
protected function getOptions(): array{
|
||||
return array_merge(parent::getOptions(),[
|
||||
'insert' => [
|
||||
'status' => 1
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
/**
|
||||
* Cdkey模型
|
||||
*
|
||||
* @package app\model
|
||||
*
|
||||
* @property integer $id 主键(ID) - 无注释
|
||||
* @property integer $type 标题
|
||||
* @property integer $category_id 分类ID
|
||||
* @property string $account cdkey
|
||||
* @property string $password 密码
|
||||
* @property integer $days 量
|
||||
* @property integer $expires 过期时间
|
||||
* @property integer $is_used 是否使用
|
||||
* @property integer $record_id 使用记录
|
||||
* @property integer $use_time 使用时间
|
||||
* @property integer $created_at 创建时间
|
||||
* @property integer $updated_at 更新时间
|
||||
* @property integer $status 状态
|
||||
*/
|
||||
class Cdkey extends Base
|
||||
{
|
||||
protected $name = 'cdkey';
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\Base;
|
||||
/**
|
||||
* @property integer $id 主键(ID) - 无注释
|
||||
* @property string $content 无注释
|
||||
* @property string $content1 无注释
|
||||
* @property string $content2 无注释
|
||||
*/
|
||||
class Content extends Base
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\Base;
|
||||
/**
|
||||
* @property integer $id 主键(ID) - 无注释
|
||||
* @property string $title 标题
|
||||
* @property string $image 封面
|
||||
* @property string $amounts 面额列表
|
||||
* @property integer $stock 库存
|
||||
* @property integer $sales 銷售量
|
||||
* @property integer $user_quantity 用户累计限购
|
||||
* @property string $memo 备注
|
||||
* @property integer $weight 权重
|
||||
* @property integer $created_at 创建时间
|
||||
* @property integer $updated_at 更新时间
|
||||
* @property integer $status 状态
|
||||
*/
|
||||
/**
|
||||
--
|
||||
-- 表的结构 `wa_gift`
|
||||
--
|
||||
|
||||
CREATE TABLE `wa_gift` (
|
||||
`id` int NOT NULL,
|
||||
`title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '标题',
|
||||
`image` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '封面',
|
||||
`amounts` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '面额列表',
|
||||
`stock` int DEFAULT '0' COMMENT '库存',
|
||||
`sales` int DEFAULT '0' COMMENT '銷售量',
|
||||
`user_quantity` int NOT NULL DEFAULT '0' COMMENT '用户累计限购',
|
||||
`memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
|
||||
`weight` int DEFAULT NULL COMMENT '权重',
|
||||
`created_at` int DEFAULT NULL COMMENT '创建时间',
|
||||
`updated_at` int DEFAULT NULL COMMENT '更新时间',
|
||||
`status` tinyint DEFAULT NULL COMMENT '状态'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `wa_gift`
|
||||
--
|
||||
|
||||
INSERT INTO `wa_gift` (`id`, `title`, `image`, `amounts`, `stock`, `sales`, `user_quantity`, `memo`, `weight`, `created_at`, `updated_at`, `status`) VALUES
|
||||
(12, '京东礼品卡', '/upload/files/20250922/911fabdb0719edcbba3f0f7b84f59f85_68d09e2a8447e.png', '[\"1000\"]', 999, 405, 10, '', NULL, 1749809778, 1758502443, 1),
|
||||
(13, '亚马逊电子礼品卡', '', '[1350.0]', 0, 530, 0, '', NULL, 1749809924, 1757263525, 1),
|
||||
(14, '永辉电子礼品卡', '', '[3.5]', 0, 300, 0, '', NULL, 1749875587, 1757263532, 1),
|
||||
(15, '盒马电子礼品卡', '', '[3.5]', 0, 300, 0, '', NULL, 1749953784, 1757263539, 1),
|
||||
(42, '沃尔玛电子礼品卡', '', '[\"10\",\"22\"]', 99, 2, 0, '', NULL, 1757263545, 1759943587, 1);
|
||||
|
||||
--
|
||||
-- 转储表的索引
|
||||
--
|
||||
|
||||
--
|
||||
-- 表的索引 `wa_gift`
|
||||
--
|
||||
ALTER TABLE `wa_gift`
|
||||
ADD PRIMARY KEY (`id`) USING BTREE;
|
||||
|
||||
--
|
||||
-- 在导出的表使用AUTO_INCREMENT
|
||||
--
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `wa_gift`
|
||||
--
|
||||
ALTER TABLE `wa_gift`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=44;
|
||||
COMMIT;
|
||||
*/
|
||||
class Gift extends Base
|
||||
{
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected function getOptions(): array{
|
||||
return array_merge(parent::getOptions(),[
|
||||
'insert' => [
|
||||
'status' => 1,
|
||||
'amounts' => '[]'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
function setAmountsAttr($v='',$row=[]){
|
||||
if(is_array($v) || is_object($v)){
|
||||
return json_encode($v,JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
if(is_string($v) && substr($v,0,1)!='['){
|
||||
$v = explode(',',$v);
|
||||
return json_encode($v,JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
return '[]';
|
||||
}
|
||||
function getAmountsAttr($v='',$row=[]){
|
||||
if(!$v){return [];}
|
||||
if(is_array($v) || is_object($v)){
|
||||
return $v;
|
||||
}
|
||||
return json_decode($v,true);
|
||||
}
|
||||
function getStatusList(){
|
||||
return [
|
||||
'0' => '禁用',
|
||||
'1' => '启用',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\Base;
|
||||
/**
|
||||
* @property integer $id 主键(ID) - 无注释
|
||||
* @property integer $user_id 用户ID
|
||||
* @property integer $gift_id 产品ID
|
||||
* @property integer $quantity 购买数量
|
||||
* @property float $amount 总价
|
||||
* @property integer $denomination 面值
|
||||
* @property string $cdkey 兑换码
|
||||
* @property string $memo CDKEY
|
||||
* @property integer $status 状态
|
||||
* @property integer $created_at 创建时间
|
||||
* @property integer $updated_at 更新时间
|
||||
*/
|
||||
class GiftOrder extends Base
|
||||
{
|
||||
public function gift()
|
||||
{
|
||||
return $this->belongsTo('Gift', 'gift_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('User', 'user_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
function getStatusList(){
|
||||
return [
|
||||
'0' => '兑换中',
|
||||
'1' => '成功',
|
||||
'-1' => '失败',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\Base;
|
||||
/**
|
||||
* @property integer $id 主键(ID) - 无注释
|
||||
* @property string $code 无注释
|
||||
* @property integer $expire 无注释
|
||||
* @property integer $created_at 无注释
|
||||
* @property integer $updated_at 无注释
|
||||
* @property integer $status 无注释
|
||||
*/
|
||||
class Invitecode extends Base
|
||||
{
|
||||
protected function getOptions(): array{
|
||||
return array_merge(parent::getOptions(),[
|
||||
'insert' => [
|
||||
'status' => 0
|
||||
]
|
||||
]);
|
||||
}
|
||||
function getStatusList(){
|
||||
return [
|
||||
'0' => '隐藏',
|
||||
'1' => '正常',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\Base;
|
||||
/**
|
||||
* 产品模型
|
||||
*
|
||||
* @package app\model
|
||||
* @property integer $id 主键(ID) - 无注释
|
||||
* @property string $title 标题
|
||||
* @property string $image 封面
|
||||
* @property float $price 价格
|
||||
* @property float $accelerate_price 加速包价格
|
||||
* @property integer $min_score 最少获得积分
|
||||
* @property integer $max_score 最多获得积分
|
||||
* @property integer $sales 銷售量
|
||||
* @property integer $total 问卷数量
|
||||
* @property integer $assign_count 每日分配
|
||||
* @property integer $accelerate_assign_times 加速包分配次数
|
||||
* @property integer $accelerate_assign_count 加速包每日分配
|
||||
* @property integer $user_quantity 用户累计限购
|
||||
* @property string $memo 备注
|
||||
* @property integer $weight 权重
|
||||
* @property integer $created_at 创建时间
|
||||
* @property integer $updated_at 更新时间
|
||||
* @property integer $status 状态
|
||||
*/
|
||||
class Product extends Base
|
||||
{
|
||||
function getCycleTypeList(){
|
||||
return [
|
||||
'hour' => '小时',
|
||||
'day' => '天',
|
||||
];
|
||||
}
|
||||
public function getCategoryOptions($type='product'){
|
||||
return Category::where('status','1')->where('type',$type)->column('id,title');
|
||||
}
|
||||
public function category()
|
||||
{
|
||||
return $this->belongsTo('Category', 'category_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
public function questionnaire()
|
||||
{
|
||||
return $this->belongsTo('Questionnaire', 'questionnaire_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
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 '';
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\Base;
|
||||
/**
|
||||
* @property integer $id 主键(主键)
|
||||
* @property integer $user_id 用户ID
|
||||
* @property integer $product_id 产品ID
|
||||
* @property float $price 购买单价
|
||||
* @property integer $quantity 购买数量
|
||||
* @property float $amount 总价
|
||||
* @property integer $accelerate 是否加速
|
||||
* @property integer $accelerate_times 总加速次数
|
||||
* @property integer $accelerate_used 已加速次数
|
||||
* @property integer $assigned 总数量
|
||||
* @property integer $total 已分配数量
|
||||
* @property integer $assigned 已分配数量
|
||||
* @property integer $assigned 已分配数量
|
||||
* @property integer $status 禁用
|
||||
* @property string $created_at 创建时间
|
||||
* @property string $updated_at 更新时间
|
||||
* @property \app\model\Product $product 产品模型
|
||||
* @property \app\model\User $user 用户模型
|
||||
*/
|
||||
|
||||
|
||||
class ProductOrder extends Base
|
||||
{
|
||||
public function product()
|
||||
{
|
||||
return $this->belongsTo('Product', 'product_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('User', 'user_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
// function getStatusList(){
|
||||
// return \app\enum\WithdrawlStatus::toArray();
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
use app\model\Base;
|
||||
/**
|
||||
* 实名认证模型
|
||||
* @property int $user_id
|
||||
* @property string $realname
|
||||
* @property string $idcard
|
||||
* @property int $created_at
|
||||
* @property int $updated_at
|
||||
*/
|
||||
class Realname extends Base
|
||||
{
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('User', 'user_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
use app\model\Base;
|
||||
/**
|
||||
* @property integer $id 主键(ID) - 无注释
|
||||
* @property string $user_id 用户ID
|
||||
* @property float $amount 金额
|
||||
* @property string $network 网络
|
||||
* @property string $address 充值地址
|
||||
* @property string $extra 其他参数
|
||||
* @property string $from 支付地址
|
||||
* @property float $real_amount 实收金额
|
||||
* @property string $txid 凭证
|
||||
* @property integer $pay_time 支付时间
|
||||
* @property integer $confirmations 确认数量
|
||||
* @property string $result 结果
|
||||
* @property string $reason 原因
|
||||
* @property integer $status -1取消,0:创建,1支付中,2完成
|
||||
* @property integer $created_at 创建时间
|
||||
* @property integer $updated_at 更新时间
|
||||
*/
|
||||
class Recharge extends Base
|
||||
{
|
||||
|
||||
protected function getOptions(): array
|
||||
{
|
||||
// 所有的参数配置统一返回
|
||||
return array_merge(parent::getOptions(),[
|
||||
'append' => ['status_text','remaining_sec','usdt_amount']
|
||||
]);
|
||||
}
|
||||
function getStatusTextAttr($v,$row){
|
||||
if($v){
|
||||
return \app\enum\RechargeStatus::tryFromValue($row['status'])->getDescription();
|
||||
}
|
||||
}
|
||||
function getRemainingSecAttr($v,$row){
|
||||
$created_at = $row['created_at'];
|
||||
if(!$created_at){
|
||||
return 0;
|
||||
}
|
||||
if(false !== strpos($created_at,'-')){
|
||||
$created_at = strtotime($created_at);
|
||||
}
|
||||
$v = $created_at + 900 -time() ;
|
||||
return $v <=0 ? 0 : $v;
|
||||
}
|
||||
function getUsdtAmountAttr($v,$row){
|
||||
if(in_array($row['network'],['BEP-20','TRC-20'])){
|
||||
$amount = bcdiv($row['amount'],Config('site.money_to_usdt_rate'),4);
|
||||
//折扣
|
||||
$amount = bcmul($amount,Config('site.usdt_recharge_discount'),4);
|
||||
return formatAmount($amount,4);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function setTransferAtAttr($v){
|
||||
if($v && strpos($v,'-')){
|
||||
return strtotime($v);
|
||||
}
|
||||
return $v;
|
||||
}
|
||||
|
||||
function setCreatedAtAttr($v){
|
||||
if($v && strpos($v,'-')){
|
||||
return strtotime($v);
|
||||
}
|
||||
return $v;
|
||||
}
|
||||
function setUpdatedAtAttr($v){
|
||||
if($v && strpos($v,'-')){
|
||||
return strtotime($v);
|
||||
}
|
||||
return $v;
|
||||
}
|
||||
function getStatusList(){
|
||||
return \app\enum\RechargeStatus::toArray();
|
||||
}
|
||||
|
||||
function getNetworkList(){
|
||||
return [
|
||||
"BEP-20"=>"BEP-20",
|
||||
"TRC-20"=>"TRC-20"
|
||||
];
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('User', 'user_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
use support\think\Db;
|
||||
|
||||
/**
|
||||
* 用户模型
|
||||
* @package app\model\User
|
||||
*
|
||||
* @property integer $id 主键(ID) - 主键
|
||||
* @property integer $role_id 角色ID
|
||||
* @property integer $parent_id 推荐人
|
||||
* @property integer $group 用戶分組
|
||||
* @property string $username 用户名
|
||||
* @property string $nickname 昵称
|
||||
* @property string $password 密码
|
||||
* @property string $trade_password 交易密码
|
||||
* @property string $sex 性别
|
||||
* @property string $avatar 头像
|
||||
* @property string $email 邮箱
|
||||
* @property string $mobile 手机
|
||||
* @property integer $level 等级
|
||||
* @property string $birthday 生日
|
||||
* @property float $money 余额(元)
|
||||
* @property float $score 积分
|
||||
* @property float $currency1 无注释
|
||||
* @property float $currency2 无注释
|
||||
* @property float $currency3 无注释
|
||||
* @property float $currency4 无注释
|
||||
* @property float $currency5 无注释
|
||||
* @property float $currency6 无注释
|
||||
* @property float $currency7 无注释
|
||||
* @property float $currency8 无注释
|
||||
* @property float $currency9 无注释
|
||||
* @property integer $email_verify 邮箱认证
|
||||
* @property integer $mobile_verify 手机认证
|
||||
* @property integer $realname_verify 实名认证
|
||||
* @property string $safe_email 安全邮箱
|
||||
* @property integer $loginfailure 登录失败的次数
|
||||
* @property integer $last_time 登录时间
|
||||
* @property string $last_ip 登录ip
|
||||
* @property integer $join_time 注册时间
|
||||
* @property string $join_ip 注册ip
|
||||
* @property string $totp_secret totp_secret
|
||||
* @property integer $expire_at 过期时间
|
||||
* @property integer $active 激活状态
|
||||
* @property string $invite_code 邀请码
|
||||
* @property integer $created_at 创建时间
|
||||
* @property integer $updated_at 更新时间
|
||||
* @property integer $status 状态
|
||||
* Strings methods
|
||||
* @method static bool money(int $user_id,float $amount, \app\enum\BalanceType $type, string $memo = null)
|
||||
* 用户余额
|
||||
* @method static bool score(int $user_id,float $amount, \app\enum\BalanceType $type, string $memo = null)
|
||||
* 用户积分
|
||||
* @method static bool currency1(int $user_id,float $amount, \app\enum\BalanceType $type, string $memo = null)
|
||||
* 调研币
|
||||
* @method static bool currency2(int $user_id,float $amount, \app\enum\BalanceType $type, string $memo = null)
|
||||
*
|
||||
* @method static bool currency3(int $user_id,float $amount, \app\enum\BalanceType $type, string $memo = null)
|
||||
*
|
||||
* @method static bool currency4(int $user_id,float $amount, \app\enum\BalanceType $type, string $memo = null)
|
||||
*
|
||||
* @method static bool currency5(int $user_id,float $amount, \app\enum\BalanceType $type, string $memo = null)
|
||||
*
|
||||
* @method static bool currency6(int $user_id,float $amount, \app\enum\BalanceType $type, string $memo = null)
|
||||
* 可领取指标
|
||||
* @method static bool currency7(int $user_id,float $amount, \app\enum\BalanceType $type, string $memo = null)
|
||||
* 待分配指标
|
||||
* @method static bool currency8(int $user_id,float $amount, \app\enum\BalanceType $type, string $memo = null)
|
||||
* 已分配指标
|
||||
* @method static bool currency9(int $user_id,float $amount, \app\enum\BalanceType $type, string $memo = null)
|
||||
* 未通过指标
|
||||
* @method static bool transform($from_currency,$to_currency,int $user_id,float $amount, \app\enum\BalanceType $type, string $memo = null)
|
||||
*/
|
||||
class User extends Base
|
||||
{
|
||||
public function role()
|
||||
{
|
||||
return $this->belongsTo('\\app\\model\\UserRole', 'role_id', 'id');//->bind(['name']);
|
||||
}
|
||||
public function realname()
|
||||
{
|
||||
return $this->hasOne('\\app\\model\\Realname', 'id', 'user_id');//->bind(['name']);
|
||||
}
|
||||
/**
|
||||
* 扩展属性
|
||||
* @param int $user_id 用户ID
|
||||
* @return \think\model\relation\BelongsTo 用户扩展关联关系
|
||||
*/
|
||||
public function extend()
|
||||
{
|
||||
return $this->belongsTo('UserExtend', 'user_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
|
||||
// 定义与 UserTeam 的关联关系,假设用户的 id 对应 UserTeam 表中的 ancestor_id
|
||||
public function team()
|
||||
{
|
||||
return $this->hasMany(UserTeam::class, 'ancestor_id', 'id');
|
||||
}
|
||||
|
||||
public static function transform($from_currency,$to_currency,$user_id,$amount,\app\enum\BalanceType $type,$memo=null){
|
||||
|
||||
if(!in_array($from_currency,Config('site.allow_currencys'))){
|
||||
abort(__('Incorrect from_currency:%currency%',['%currency%'=>$from_currency]));
|
||||
}
|
||||
if(!in_array($to_currency,Config('site.allow_currencys'))){
|
||||
abort(__('Incorrect to_currency:%currency%',['%currency%'=>$to_currency]));
|
||||
}
|
||||
$time = time();
|
||||
$user = self::lock(true)->where('id',$user_id)->find();
|
||||
if(!$user){
|
||||
throw new \Exception(__('User not found'));
|
||||
}
|
||||
$from_after = bcadd($user->{$from_currency} , -$amount,4);
|
||||
$to_after = bcadd($user->{$to_currency} , $amount,4);
|
||||
if($to_after<0 || $from_after<0){
|
||||
abort(__('not enougth to currency'));
|
||||
}
|
||||
$from_logData = [
|
||||
'user_id' => $user_id.'',
|
||||
'currency' => $from_currency,
|
||||
'amount' => -$amount.'',
|
||||
'before' => $user->{$from_currency}.'',
|
||||
'after' => $from_after.'',
|
||||
'type' => $type->value,
|
||||
'created_at' => $time.'',
|
||||
'memo' => $memo
|
||||
];
|
||||
$to_logData = [
|
||||
'user_id' => $user_id.'',
|
||||
'currency' => $to_currency,
|
||||
'amount' => $amount.'',
|
||||
'before' => $user->{$to_currency}.'',
|
||||
'after' => $to_after.'',
|
||||
'type' => $type->value,
|
||||
'created_at' => $time.'',
|
||||
'memo' => $memo
|
||||
];
|
||||
$user->{$from_currency} = $from_after;
|
||||
$user->{$to_currency} = $to_after;
|
||||
$user->save();
|
||||
|
||||
// 写入日志
|
||||
BalanceLog::create($to_logData);
|
||||
BalanceLog::create($from_logData);
|
||||
}
|
||||
/**
|
||||
* 变更会员余额
|
||||
* @param int $score 积分
|
||||
* @param int $user_id 会员ID
|
||||
* @param string $memo 备注
|
||||
*/
|
||||
public static function _setBalance($currency,$user_id,$amount,\app\enum\BalanceType $type,$memo=null){
|
||||
//cp($currency,$user_id,$amount,$type->getDescription(),$memo);
|
||||
if(!in_array($currency,Config('site.allow_currencys'))){
|
||||
abort(__('Incorrect currency:%currency%',['%currency%'=>$currency]));
|
||||
}
|
||||
if(!$currency){
|
||||
abort(__('Incorrect currency'));
|
||||
}
|
||||
if(!$user_id){
|
||||
abort(__('Incorrect parameter user'));
|
||||
}
|
||||
if(!$amount){
|
||||
abort(__('Incorrect amount'));
|
||||
}
|
||||
$user = self::lock(true)->where('id',$user_id)->find();
|
||||
$after = bcadd($user->{$currency}, $amount, 8);
|
||||
if($amount < 0 && $after < 0){
|
||||
abort(__('Insufficient user balance'));
|
||||
}
|
||||
$logData = [
|
||||
'user_id' => $user_id.'',
|
||||
'currency' => $currency,
|
||||
'amount' => $amount.'',
|
||||
'before' => '0',
|
||||
'after' => '0',
|
||||
'type' => $type->value,
|
||||
'created_at' => time().'',
|
||||
'memo' => $memo
|
||||
];
|
||||
$logData['before'] = $user->{$currency};
|
||||
$user->{$currency} = $after;
|
||||
$logData['after'] = $user->{$currency};
|
||||
$user->save();
|
||||
|
||||
// 写入日志
|
||||
BalanceLog::create($logData);
|
||||
}
|
||||
|
||||
public static function __callStatic($method, $args)
|
||||
{
|
||||
$currency = strtolower($method);
|
||||
if(in_array($currency,Config('site.allow_currencys'))){
|
||||
return self::_setBalance($currency,$args[0],$args[1],$args[2],$args[3]);
|
||||
}else{
|
||||
return parent::__callStatic($method, $args);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 扩展属性
|
||||
* @param int $user_id 用户ID
|
||||
* @return \think\model\relation\BelongsTo 用户扩展关联关系
|
||||
*/
|
||||
public function referrer()
|
||||
{
|
||||
return $this->belongsTo('User', 'parent_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\Base;
|
||||
/**
|
||||
* @property integer $user_id 用户ID
|
||||
* @property integer $direct_total 直推数量
|
||||
* @property integer $team_total 团队成员数量
|
||||
* @property float $consume 消费统计
|
||||
* @property float $sales 销售额
|
||||
*/
|
||||
class UserExtend extends Base
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?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) : [];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\Base;
|
||||
use support\Model;
|
||||
/**
|
||||
* @property integer $id 主键(主键)
|
||||
* @property string $title 标题
|
||||
* @property string $icon 图标
|
||||
* @property string $key 标识
|
||||
* @property integer $pid 上级菜单
|
||||
* @property string $created_at 创建时间
|
||||
* @property string $updated_at 更新时间
|
||||
* @property string $href url
|
||||
* @property integer $type 类型
|
||||
* @property integer $weight 排序
|
||||
*/
|
||||
class UserRule extends Base
|
||||
{
|
||||
protected function getOptions(): array{
|
||||
return array_merge(parent::getOptions(),[
|
||||
'insert' => [
|
||||
'status' => 1
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace app\model;
|
||||
/**
|
||||
* @property integer $id 主键(ID) - 主键
|
||||
* @property integer $user_id 用户ID
|
||||
* @property string $sign_date 签到日期
|
||||
* @property integer $reward 签到奖励
|
||||
* @property integer $continuous_days 连续签到天数
|
||||
* @property integer $created_at 创建时间
|
||||
*/
|
||||
class UserSignin extends Base
|
||||
{
|
||||
protected $name = 'user_signin';
|
||||
protected $autoWriteTimestamp = true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\Base;
|
||||
/**
|
||||
* @property integer $ancestor_id 上级用户ID
|
||||
* @property integer $descendant_id 下级用户ID
|
||||
* @property integer $depth 层级深度(0表示自己)
|
||||
* @property integer $status 用户有效性状态,0表示无效,1表示有效
|
||||
*/
|
||||
class UserTeam extends Base
|
||||
{
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'descendant_id', 'id');
|
||||
}
|
||||
/**
|
||||
* 根据用户ID向上查询团队成员
|
||||
* @param mixed $user_id
|
||||
* @param mixed $user_field
|
||||
* @return array
|
||||
*/
|
||||
static function getTeamByChild($user_id = 0,$user_field=''){
|
||||
$list = self::alias('ut')
|
||||
->join('user u', 'ut.ancestor_id = u.id')
|
||||
->where('ut.descendant_id', $user_id)
|
||||
//->where('ut.ancestor_id','<>', $data['user_id'])
|
||||
//->where('ut.depth', '<=', 3) // 限制三级内
|
||||
->field('u.id as user_id,u.group, ut.depth')
|
||||
->order('ut.depth ASC')->select();
|
||||
if(!is_array($list)){
|
||||
$list = $list->toArray();
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
/**
|
||||
* 根据用户ID向下查询团队
|
||||
* @param mixed $user_id
|
||||
* @param mixed $user_field
|
||||
* @return array
|
||||
*/
|
||||
static function getTeamByParent($user_id = 0,$user_field=''){
|
||||
$list = self::alias('ut')
|
||||
->join('user u', 'ut.ancestor_id = u.id')
|
||||
//->where('ut.descendant_id', $user_id)
|
||||
->where('ut.ancestor_id','<>', $user_id)
|
||||
//->where('ut.depth', '<=', 3) // 限制三级内
|
||||
->field('u.id as user_id,u.group, ut.depth')
|
||||
->order('ut.depth ASC')->select();
|
||||
if(!is_array($list)){
|
||||
$list = $list->toArray();
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\Base;
|
||||
/**
|
||||
* @property integer $id 主键(ID) - 无注释
|
||||
* @property integer $user_id 用户ID
|
||||
* @property float $deduction_amount 提现金额
|
||||
* @property float $recive_amount 到账金额
|
||||
* @property float $fee 后续费
|
||||
* @property string $title 姓名
|
||||
* @property string $network 方式
|
||||
* @property string $address 地址
|
||||
* @property integer $transfer_at 转账时间
|
||||
* @property string $txid 凭证
|
||||
* @property string $memo 备注
|
||||
* @property integer $created_at 创建时间
|
||||
* @property integer $updated_at 更新时间
|
||||
* @property integer $status 状态
|
||||
*/
|
||||
class Withdrawl extends Base
|
||||
{
|
||||
|
||||
protected function getOptions(): array
|
||||
{
|
||||
// 所有的参数配置统一返回
|
||||
return array_merge(parent::getOptions(),[
|
||||
'append' => ['status_text']
|
||||
]);
|
||||
}
|
||||
function getStatusTextAttr($v,$row){
|
||||
if($v){
|
||||
return \app\enum\WithdrawlStatus::tryFromValue($row['status'])->getDescription();
|
||||
}
|
||||
}
|
||||
function setTransferAtAttr($v){
|
||||
if($v && strpos($v,'-')){
|
||||
return strtotime($v);
|
||||
}
|
||||
}
|
||||
|
||||
function setCreatedAtAttr($v){
|
||||
if($v && strpos($v,'-')){
|
||||
return strtotime($v);
|
||||
}
|
||||
}
|
||||
function setUpdatedAtAttr($v){
|
||||
if($v && strpos($v,'-')){
|
||||
return strtotime($v);
|
||||
}
|
||||
}
|
||||
function getNetworkList(){
|
||||
return [
|
||||
"BEP-20"=>"BEP-20",
|
||||
"TRC-20"=>"TRC-20",
|
||||
"WECHAT"=>"微信",
|
||||
"ALIPAY"=>"支付宝"
|
||||
];
|
||||
}
|
||||
function getStatusList(){
|
||||
return \app\enum\WithdrawlStatus::toArray();
|
||||
}
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('User', 'user_id', 'id');//->setEagerlyType(0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\Base;
|
||||
/**
|
||||
* @property integer $id 主键(ID) - 无注释
|
||||
* @property integer $user_id 用户ID
|
||||
* @property integer $product_id 产品ID
|
||||
* @property integer $questionnaire_id 问卷ID
|
||||
* @property integer $order_id 订单ID
|
||||
* @property array $answer 答案
|
||||
* @property float $income 总收益
|
||||
* @property integer $start_time 开始时间
|
||||
* @property integer $end_time 结束时间
|
||||
* @property string $settings 配置
|
||||
* @property integer $status 状态
|
||||
* @property integer $created_at 创建时间
|
||||
* @property integer $updated_at 更新时间
|
||||
*/
|
||||
class WorkRecord extends Base
|
||||
{
|
||||
protected function getOptions(): array
|
||||
{
|
||||
// 所有的参数配置统一返回
|
||||
return array_merge(parent::getOptions(),[
|
||||
'hidden' => ['settings'],
|
||||
'append' => ['status_text']
|
||||
]);
|
||||
}
|
||||
function getStatusTextAttr($v,$row){
|
||||
return \app\enum\ServerStatus::tryFromValue($row['status']?:0)->getDescription();
|
||||
}
|
||||
public static function onBeforeWrite(&$row)
|
||||
{
|
||||
if(!$row->settings){
|
||||
$step_before_array = [
|
||||
'bootstrap' => rand(10,20),
|
||||
'http_proxy' => rand(10,20),
|
||||
'browser_env' => rand(10,20),
|
||||
'enter_questionnaire' => rand(10,20),
|
||||
'match_virtual_person' => rand(10,20),
|
||||
];
|
||||
//后置耗时
|
||||
$step_after_array = [
|
||||
'submit_result' => rand(5,10),
|
||||
'wait_submit_result' => rand(5,10),
|
||||
'wait_settlement' => 0,
|
||||
];
|
||||
$answer_array=[];
|
||||
/** @var Questionnaire $questionnaire */
|
||||
$questionnaire = Questionnaire::where('id',$row->questionnaire_id)->find();
|
||||
for ($i=0; $i < $questionnaire->total ; $i++) {
|
||||
$answer_array['answer_'.($i+1)] = 30;
|
||||
}
|
||||
$row->settings = array_merge($step_before_array,$answer_array,$step_after_array);
|
||||
}
|
||||
if(!$row->answer){
|
||||
$answer = [];
|
||||
foreach($row->questionnaire->body as $k=>$vo){
|
||||
$answer[$k]= rand(0,count($vo['answer'])-1);
|
||||
}
|
||||
$row->answer = $answer;
|
||||
}
|
||||
// if($row->start_time && !$row->end_time){
|
||||
// $row->end_time = 0;
|
||||
// if(is_array($row->settings)){
|
||||
// $end_time = $row->start_time + array_sum($row->settings);
|
||||
// $row->end_time = $end_time;
|
||||
// }
|
||||
// }
|
||||
//cp('onBeforeWrite');
|
||||
}
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id', 'id');
|
||||
}
|
||||
public function product()
|
||||
{
|
||||
return $this->belongsTo(Product::class, 'product_id', 'id');
|
||||
}
|
||||
public function questionnaire()
|
||||
{
|
||||
return $this->hasOne(Questionnaire::class, 'id', 'questionnaire_id');
|
||||
}
|
||||
/**
|
||||
* 自动写入Settings字段
|
||||
*/
|
||||
function setSettingsAttr($v='',$row=[]){
|
||||
if(is_array($v)){
|
||||
return json_encode($v);
|
||||
}
|
||||
return $v;
|
||||
}
|
||||
/**
|
||||
* Settings自动转为数组
|
||||
*/
|
||||
public function getSettingsAttr($v='',$row=[]){
|
||||
//cp('getSettingsAttr');
|
||||
if(!$v){
|
||||
return [];
|
||||
}
|
||||
if(!is_array($v)){
|
||||
return json_decode($v,true);
|
||||
}
|
||||
return $v;
|
||||
}
|
||||
public function start(){
|
||||
if($this->status != \app\enum\ServerStatus::WAITING->value){
|
||||
return $this->error(__('Server could not start'));
|
||||
}
|
||||
$this->status = \app\enum\ServerStatus::WORKING->value;
|
||||
$this->start_time = time();
|
||||
if(is_array($this->settings)){
|
||||
$end_time = $this->start_time + array_sum($this->settings);
|
||||
$this->end_time = $end_time;
|
||||
}
|
||||
$this->save();
|
||||
addJob(['server_id'=>$this->id,'action'=>'workcomplete'],'Questionnaire',$this->end_time-time());
|
||||
}
|
||||
public function getStep(){
|
||||
if ($this->status != \app\enum\ServerStatus::WORKING->value) {
|
||||
return [
|
||||
'step' => 0,
|
||||
'msg' => \app\enum\ServerStatus::tryFromValue($this->status)->name,
|
||||
'next_time' => null,
|
||||
'remaining_seconds' => 0
|
||||
];
|
||||
}
|
||||
|
||||
$settings = $this->settings;
|
||||
//cp($settings);
|
||||
|
||||
$start_time = $this->start_time; // 使用实际的开始时间
|
||||
//$start_time = time();
|
||||
$current_time = time();
|
||||
//$current_time = $start_time+140;//time(); // 当前时间戳
|
||||
|
||||
if ($current_time < $start_time) {
|
||||
//根据时间判断未开始
|
||||
return [
|
||||
'step' => 0,
|
||||
'msg' => \app\enum\ServerStatus::tryFromValue($this->status)->name,
|
||||
'next_time' => $start_time,
|
||||
'remaining_seconds' => 0
|
||||
];
|
||||
}
|
||||
|
||||
// 计算已经过去的时间
|
||||
$elapsed = $current_time - $start_time;
|
||||
|
||||
// 初始化结果
|
||||
$result = [
|
||||
'step' => 7,
|
||||
'current' => __('bootstrap'),
|
||||
'next_time' => null,
|
||||
'msg' => __('anser'),
|
||||
'remaining_seconds' => 0
|
||||
];
|
||||
|
||||
// 遍历所有阶段
|
||||
$accumulated = 0;
|
||||
$found_current = false;
|
||||
$stepArr = [
|
||||
'bootstrap' => 1,
|
||||
'http_proxy' => 2,
|
||||
'browser_env' => 3,
|
||||
'enter_questionnaire' => 4,
|
||||
'match_virtual_person' => 5,
|
||||
'submit_result' => 7,
|
||||
'wait_submit_result' => 7,
|
||||
'wait_settlement' => 7,
|
||||
];
|
||||
foreach ($settings as $name => $duration) {
|
||||
$accumulated += $duration;
|
||||
|
||||
// 1. 找到当前阶段
|
||||
if (!$found_current && $elapsed < $accumulated) {
|
||||
$found_current = true;
|
||||
if(substr($name,0,7) == 'answer_'){
|
||||
$_name = explode('_',$name);
|
||||
$result['index'] = intval($_name[1]);
|
||||
$result['current'] = __($_name[0].'_%index%',['%index%'=>$result['index']]);
|
||||
$result['step'] = 6;
|
||||
$result['msg'] = 'AI Thinking';
|
||||
}else{
|
||||
$result['step'] = $stepArr[$name];
|
||||
$result['msg'] = __($name);
|
||||
}
|
||||
// 当前阶段剩余时间 = 当前阶段结束时间 - 当前时间
|
||||
$result['remaining_seconds'] = $accumulated - $elapsed;
|
||||
}
|
||||
|
||||
// 2. 找到下一阶段开始时间
|
||||
if ($elapsed < $accumulated) {
|
||||
$result['next_time'] = $start_time + $accumulated;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果已经超过所有阶段
|
||||
if ($elapsed >= $accumulated) {
|
||||
return [
|
||||
'step' => 7,
|
||||
'msg' => \app\enum\ServerStatus::tryFromValue(4)->name,
|
||||
'next_time' => null,
|
||||
'remaining_seconds' => 0
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user