初始化

This commit is contained in:
liut
2021-10-12 11:06:24 +08:00
commit ff0b4d5b12
1270 changed files with 405680 additions and 0 deletions
@@ -0,0 +1,28 @@
<?php
namespace app\common\behavior;
use app\common\model\Setting;
use think\facade\Cache;
use think\facade\Config;
class LoadConfigRun
{
public function run(){
$conf_cache = Cache::get('_setting_config');
if(empty($conf_cache)){
$conf_cache = Setting::select()->toArray();
Cache::set('_setting_config',$conf_cache);
}
// 加载配置
foreach ($conf_cache as $item){
Config::set([$item['set_name'] => $item['set_value']],$item['set_type']);
}
}
}
+89
View File
@@ -0,0 +1,89 @@
<?php
namespace app\common\controller;
use app\admin\controller\User;
use app\common\model\Users;
use think\Controller;
use think\exception\HttpResponseException;
use think\Response;
class Admin extends Controller
{
protected $middleware = ['AdminLoginCheck'];
protected $adminInfo = [];
public function initialize(){
parent::initialize(); // TODO: Change the autogenerated stub
$this->adminInfo = (new Users())->login_info('admin');
}
protected function callModelMethods($model,$methods,...$args){
$class_name = 'app\common\model\\'.$model;
$class = new $class_name;
try {
call_user_func_array([$class,$methods],$args);
}catch (\Throwable $e){
$this->returnError($e->getMessage(),505);
}
}
protected function returnSuccess($msg = '操作成功',$data = []){
$result = [
'code' => 200,
'msg' => $msg,
'time' => time(),
'data' => $data,
];
$type = 'json';
$response = Response::create($result, $type)->header([]);
throw new HttpResponseException($response);
}
protected function returnSuccessLayTable($count,$data = []){
$result = [
'code' => 0,
'msg' => '加载成功',
'count' => $count,
'data' => $data,
];
$type = 'json';
$response = Response::create($result, $type)->header([]);
throw new HttpResponseException($response);
}
protected function returnError($msg = '操作失败,系统错误',$code = 502,$data = []){
$result = [
'code' => $code,
'msg' => $msg,
'time' => time(),
'data' => $data,
];
$type = 'json';
$response = Response::create($result, $type)->header([]);
throw new HttpResponseException($response);
}
protected function getQueryMap($methods,$kw = [],$ql = []){
$map = [];
foreach ($ql as $item){
$value = input($methods.'.'.$item);
if(!empty($value)){
$map[$item] = $value;
}
}
foreach ($kw as $item){
$value = input($methods.'.'.$item);
if(!empty($value)){
$map[$item] = $value;
}
}
return $map;
}
}
+115
View File
@@ -0,0 +1,115 @@
<?php
namespace app\common\controller;
use app\common\model\Groups;
use app\common\model\Policys;
use app\common\model\Users;
use think\Controller;
class Home extends Controller
{
protected $middleware = ['UserLoginCheck'];
protected $userInfo = [];
protected $groupData = [];
protected $vip_info = [];
protected $is_login = 0;
public function initialize(){
parent::initialize(); // TODO: Change the autogenerated stub
$this->userInfo = (new Users())->login_info('default');
// 是否登录
$this->is_login = empty($this->userInfo) ? 0 : 1;
// 用户组信息
if($this->is_login){
// 登录用户组
$this->groupData = Groups::where('id',$this->userInfo['group'])->find();
}else{
// 游客用户组
$this->groupData = Groups::where('id',2)->find();
}
// 获取VIP用户组ID
$vip_group = config('vip.vip_group');
// 获取普通用户组ID
$default_group = config('register.default_group');
// 判断是否VIP
if($this->userInfo['group'] == $vip_group){
// VIP过期
if(intval($this->userInfo['group_expire']) < time()){
Users::where('id',$this->userInfo['id'])->update([
'group' => $default_group,
'group_expire' => 0
]);
$this->vip_info['is_vip'] = 0;
$this->vip_info['expire_time'] = 0;
}else{
$this->vip_info['is_vip'] = 1;
$this->vip_info['expire_time'] = date('Y-m-d',$this->userInfo['group_expire']);
}
}else{
$this->vip_info['is_vip'] = 0;
$this->vip_info['expire_time'] = 0;
}
$this->assign('group',$this->groupData);
$this->assign('info',$this->userInfo);
$this->assign('is_login',$this->is_login);
$this->assign('vip_info',$this->vip_info);
$this->assign('url_path',$this->request->path());
}
protected function getPolicy(): array
{
$policy = Policys::where('id',$this->groupData['policy_id'])->find()->toArray();
return $policy;
}
protected function getPolicyUrl($policy,$param = []): string
{
if($policy['type'] != 'remote'){
return url('upload/file');
}
$data = [
'uid' => $this->userInfo['id'],
'policy_id' => $policy['id'],
'save_dir' => $policy['config']['save_dir']
];
$data = array_merge($data,$param);
$data['sign'] = $this->remote_sign_params($data,$policy['config']['access_token']);
return $policy['config']['server_uri'].'?'.urldecode(http_build_query($data));
}
protected function remote_sign_params($params,$key): string
{
// 过滤参数
$params = array_filter($params,function($key) use ($params){
if(empty($params[$key]) || $key == 'sign'){
return false;
}
return true;
},ARRAY_FILTER_USE_KEY);
// ascii排序
ksort($params);
reset($params);
// 签名
return md5(urldecode(http_build_query($params)) . $key);
}
}
@@ -0,0 +1,11 @@
<?php
namespace app\common\exception;
use think\Exception;
class LoginError extends Exception
{
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace app\common\model;
use think\Model;
class Certify extends Model
{
}
+432
View File
@@ -0,0 +1,432 @@
<?php
namespace app\common\model;
use think\Exception;
class FileManage
{
/**
* 获取上级目录ID
* @param $folder_id
* @param $uid
* @return mixed
*/
public static function getFolderPid($folder_id,$uid){
if(empty($folder_id)){
$folder_id = Folders::where('uid',$uid)->where('parent_folder',$folder_id)->value('id');
}
return $folder_id;
}
/**
* 获取有效的目录ID
* @param $folder_id
* @param $uid
* @return mixed
*/
public static function getFolderAllowPid($folder_id,$uid){
if(empty($folder_id)){
$folder_id = Folders::where('uid',$uid)->where('parent_folder',$folder_id)->value('id');
}else{
$folder_id = Folders::where('uid',$uid)->where('id',$folder_id)->value('id');
}
return $folder_id;
}
/**
* 获取文件列表
* @param $folder_id
* @param $search
* @param $uid
* @param $page
* @param $limit
* @return array|array[]
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function ListFile($folder_id,$search,$uid,$page,$limit): array
{
//获取当前根目录
$folder_id = self::getFolderPid($folder_id,$uid);
$maps = [
['uid','=',$uid],
['parent_folder','=',$folder_id],
['delete_time','null','']
];
$files_sql = db('stores')
->where($maps)
->where('origin_name','like','%'.$search.'%')
->field('id,uid,shares_id,origin_name as name,ext,size,count_down,count_open,update_time')
->fetchSql(true)
->select();
$list = db('folders')
->where($maps)
->where('folder_name','like','%'.$search.'%')
->field('id,uid,shares_id,folder_name as name,ext,size,count_down,count_open,update_time')
->union($files_sql,true)
->page($page,$limit)
->select();
$files_count = db('stores')
->where($maps)
->where('origin_name','like','%'.$search.'%')
->field('id')
->count();
$folder_count = db('folders')
->where($maps)
->where('folder_name','like','%'.$search.'%')
->field('id')
->count();
$data = ['data' => []];
foreach ($list as $item){
$file_item = [
'file_name' => '',
'file_size' => '-',
'url' => '',
'url_pass' => '',
'count_down' => '<font color="#f81" size="4">'.$item['count_down'].'</font>',
'count_open' => $item['count_open'],
'update_time' => date('Y-m-d H:i',$item['update_time'])
];
if($item['ext'] == 755){
$file_item['file_name'] = '
<img class="file-icon" src="'.getFileIcon('dir','index').'" />
<text class="filename folder" id="t'.$item['id'].'" data-id="'.$item['id'].'" data-filename="'.$item['name'].'" data-folder="1">'.$item['name'].'</text>
<div class="gengduo" onclick="clickGengduo(event,'.$item['id'].')">
<span><em class="icon icon-more icon-color" title="更多"></em></span>
</div>';
$share_info = Shares::getShare($item['uid'],$item['id'],1);
}else{
$file_item['file_name'] = '
<img class="file-icon" src="'.getFileIcon($item['ext'],'index').'" />
<text class="filename" id="t'.$item['id'].'" data-id="'.$item['id'].'" data-filename="'.$item['name'].'" data-folder="0">'.$item['name'].'</text>
<div class="gengduo" onclick="clickGengduo(event,'.$item['id'].')">
<span><em class="icon icon-more icon-color" title="更多"></em></span>
</div>';
$share_info = Shares::getShare($item['uid'],$item['id'],0);
$file_item['file_size'] = countSize($item['size']);
}
$is_folder = $item['ext'] == 755 ? 1 : 0;
if(!empty($share_info)){
$share_url = getShareUrl($share_info['code']);
$file_item['url'] = '<a id="'.$item['id'].'-url" data-id="'.$item['id'].'" data-pass="'.$share_info['pwd'].'" data-pass-status="'.$share_info['pwd_status'].'" href="'.$share_url.'" target="_blank">'.$share_url.'</a>';
if(empty($share_info['pwd']) || $share_info['pwd_status'] == 0){
$share_info['pwd'] = '-';
}
$file_item['url_pass'] = '<a id="'.$item['id'].'-pass" onclick="if($(\'#'.$item['id'].'-pass\').html() != \'-\'){CopyText($(\'#'.$item['id'].'-pass\').html(),\'复制提取码成功~\')}else{setPass('.$item['id'].',$(\'#t'.$item['id'].'\').html(),'.$is_folder.')}">'.$share_info['pwd'].'</a>';
}
$data['data'][] = $file_item;
}
//查询上级目录
$data['parent'] = "";
if($folder_id != 0){
$parent_ids = self::getUserDirParents($uid,$folder_id);
if(!empty($parent_ids)){
$folder_parents = Folders::where('id','in',$parent_ids)
->where('uid',$uid)
->field('id,folder_name')
->order('id desc')
->select()->toArray();
$folder_parents = array_reverse($folder_parents);
$data['parent'] = $folder_parents;
}
}
$data['total'] = $files_count + $folder_count;
return $data;
}
public static function ShareListFile($folder_id,$uid){
//获取当前根目录
$folder_id = self::getFolderPid($folder_id,$uid);
$maps = [
['uid','=',$uid],
['parent_folder','=',$folder_id],
['delete_time','null','']
];
$files_sql = db('stores')
->where($maps)
->field('id,uid,shares_id,origin_name as name,ext,size,update_time')
->fetchSql(true)
->select();
$list = db('folders')
->where($maps)
->field('id,uid,shares_id,folder_name as name,ext,size,update_time')
->union($files_sql,true)
->select();
$share_ids = array_column($list,'shares_id');
// 查询分享代码
$share_list = Shares::where('id','in',$share_ids)->column('code','id');
// 返回数据
$data = [];
foreach ($list as $item){
$type = $item['ext'] == 755 ? 'dir' : $item['ext'];
$files = [
'id' => $item['id'],
'type' => $item['ext'] == 755 ? 'dir' : 'file',
'icon' => getFileIcon($type,'index'),
'name' => $item['name'],
'size' => empty($item['size']) ? '-' : countSize($item['size']),
'time' => friendDate($item['update_time'])
];
$code = $share_list[$item['shares_id']] ?? '';
if(empty($code)){
$files['url'] = 'javascript:;';
}else{
$files['url'] = getShareUrl($code);
}
$data[] = $files;
}
return $data;
}
public static function FolderList($folder_id,$uid): array
{
//获取当前根目录
$folder_id = self::getFolderPid($folder_id,$uid);
$maps = [
['uid','=',$uid],
['parent_folder','=',$folder_id],
['delete_time','null','']
];
return Folders::withTrashed()
->where($maps)
->field('id,folder_name')
->select()->each(function($item) use ($uid){
if(Folders::withTrashed()->where('parent_folder',$item['id'])->where('uid',$uid)->count() > 0){
$item['down'] = 1;
}else{
$item['down'] = 0;
}
return $item;
})->toArray();
}
/**
* 回收站文件列表
* @param $search
* @param $uid
* @param $page
* @param $limit
* @return array|array[]
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function RecycleFile($search,$uid,$page,$limit){
$file_sql = db('stores')
->where('uid',$uid)
->where('delete_time','not null')
->where('origin_name','like','%'.$search.'%')
->field('id,uid,shares_id,origin_name as name,ext,size,count_down,count_open,update_time')
->fetchSql(true)
->select();
$list = db('folders')
->where('uid',$uid)
->where('delete_time','not null')
->where('folder_name','like','%'.$search.'%')
->field('id,uid,shares_id,folder_name as name,ext,size,count_down,count_open,update_time')
->union($file_sql,true)
->page($page,$limit)
->select();
$stores_count = db('stores')
->where('uid',$uid)
->where('delete_time','not null')
->where('origin_name','like','%'.$search.'%')
->field('id')
->count();
$folders_count = db('folders')
->where('uid',$uid)
->where('delete_time','not null')
->where('folder_name','like','%'.$search.'%')
->field('id')
->count();
$data = ['data' => []];
foreach ($list as $item){
$file_item = [
'file_name' => '',
'file_size' => '-',
'url' => '',
'url_pass' => '',
'count_down' => '<font color="#f81" size="4">'.$item['count_down'].'</font>',
'count_open' => $item['count_open'],
'update_time' => date('Y-m-d H:i',$item['update_time'])
];
if($item['ext'] == 755){
$file_item['file_name'] = '
<img class="file-icon" src="'.getFileIcon('dir','index').'" />
<text class="filename folder" id="t'.$item['id'].'" data-id="'.$item['id'].'" data-filename="'.$item['name'].'" data-folder="1">'.$item['name'].'</text>
<div class="gengduo" onclick="clickGengduo(event,'.$item['id'].')">
<span><em class="icon icon-more icon-color" title="更多"></em></span>
</div>';
$share_info = Shares::getShare($item['uid'],$item['id'],1);
}else{
$file_item['file_name'] = '
<img class="file-icon" src="'.getFileIcon($item['ext'],'index').'" />
<text class="filename" id="t'.$item['id'].'" data-id="'.$item['id'].'" data-filename="'.$item['name'].'" data-folder="0">'.$item['name'].'</text>
<div class="gengduo" onclick="clickGengduo(event,'.$item['id'].')">
<span><em class="icon icon-more icon-color" title="更多"></em></span>
</div>';
$share_info = Shares::getShare($item['uid'],$item['id'],0);
$file_item['file_size'] = countSize($item['size']);
}
$is_folder = $item['ext'] == 755 ? 1 : 0;
if(!empty($share_info)){
$share_url = getShareUrl($share_info['code']);
$file_item['url'] = '<a id="'.$item['id'].'-url" data-id="'.$item['id'].'" data-pass="'.$share_info['pwd'].'" data-pass-status="'.$share_info['pwd_status'].'" href="'.$share_url.'" target="_blank">'.$share_url.'</a>';
if(empty($share_info['pwd']) || $share_info['pwd_status'] == 0){
$share_info['pwd'] = '-';
}
$file_item['url_pass'] = '<a id="'.$item['id'].'-pass" onclick="if($(\'#'.$item['id'].'-pass\').html() != \'-\'){CopyText($(\'#'.$item['id'].'-pass\').html(),\'复制提取码成功~\')}else{setPass('.$item['id'].',$(\'#t'.$item['id'].'\').html(),'.$is_folder.')}">'.$share_info['pwd'].'</a>';
}
$data['data'][] = $file_item;
}
//查询上级目录
$data['parent'] = "";
$data['total'] = $stores_count + $folders_count;
return $data;
}
/**
* 创建目录
* @throws Exception
*/
public static function createFolder($folder_pid, $folder_name, $folder_desc, $uid){
$folder_name = str_replace(" ","",$folder_name);
$folder_name = str_replace("/","",$folder_name);
//获取当前根目录
$folder_pid = self::getFolderPid($folder_pid,$uid);
if(empty($folder_name)){
throw new Exception('目录名不能为空');
}
// 判断路径
if(Folders::where('id',$folder_pid)->where('uid',$uid)->find() == null){
throw new Exception('文件夹路径不存在');
}
// 是否重复
if(
Folders::where('parent_folder',$folder_pid)
->where('folder_name',$folder_name)
->where('uid',$uid)->find() != null
){
throw new Exception('文件夹已存在');
}
$dir_id = (new Folders)->insertGetId([
'uid' => $uid,
'folder_name' => $folder_name,
'parent_folder' => $folder_pid,
'desc' => $folder_desc,
'create_time' => time(),
'update_time' => time()
]);
$share_id = Shares::addShare($uid,$dir_id,1);
(new Folders)->where('id',$dir_id)->update(['shares_id' => $share_id]);
return $dir_id;
}
/**
* 获取用户上级目录列表
* @param $uid
* @param $folder_id
* @return array
*/
protected static function getUserDirParents($uid,$folder_id): array
{
$folders = self::getUserDirs($uid);
return self::getDirParents($folders,$folder_id);
}
/**
* 递归获取上级目录
* @param $folders
* @param $folder_id
* @return array
*/
protected static function getDirParents($folders,$folder_id): array
{
$ids = [];
foreach ($folders as $item){
if($item['id'] == $folder_id){
if($item['pid']){
$ids[] = $item['id'];
$ids = array_merge(self::getDirParents($folders,$item['pid']),$ids);
}
}
}
return $ids;
}
/**
* 获取用户目录
* @param $uid
* @return array
*/
protected static function getUserDirs($uid): array
{
return Folders::where('uid',$uid)->field('id,parent_folder as pid')->select()->toArray();
}
}
+238
View File
@@ -0,0 +1,238 @@
<?php
namespace app\common\model;
use app\common\model\driver\AliyunOss;
use app\common\model\driver\Local;
use app\common\model\driver\TxyunOss;
use think\Exception;
class FileUpload
{
/**
* @var int 储存策略
*/
protected $policy;
/**
* @var int 上传用户
*/
protected $uid;
/**
* @var array 上传数据
*/
protected $info;
/**
* @var int 最大上传大小
*/
protected $max_size;
/**
* 设置来源信息
* @param $uid
* @param $policy
* @param $max_size
* @return FileUpload
*/
public function source($uid,$policy,$max_size): FileUpload
{
$this->uid = $uid;
$this->policy = $policy;
$this->max_size = $max_size;
return $this;
}
/**
* 检查文件信息
* @throws Exception
*/
protected function check(){
if(empty($this->info['file']['folder'])){
throw new Exception('上传目标文件夹不存在');
}
if(empty($this->info['file']['data'])){
throw new Exception('请选择上传的文件');
}
if(empty($this->info['file']['size'])){
throw new Exception('文件大小异常');
}
if(empty($this->info['file']['name'])){
throw new Exception('上传文件名异常');
}
if($this->policy['type'] == 'remote'){
throw new Exception('您不可以使用该存储策略');
}
if(!empty($this->max_size)){
if($this->info['file']['size'] > $this->max_size){
throw new Exception('单文件最大上传大小'.countSize($this->max_size));
}
}
if(!empty($this->policy['filetype'])){
$file_ext = $this->getFileExt($this->info['file']['name']);
$allow_ext = explode(',',$this->policy['filetype']);
if(!in_array($file_ext,$allow_ext)){
throw new Exception('不允许上传'.$file_ext.'类型的文件');
}
}
if(empty($this->info['chunk']['key'])){
throw new Exception('分片密钥错误');
}
}
/**
* 获取文件后缀名
* @param $filename
* @return string
*/
protected function getFileExt($filename): string
{
return strtolower(pathinfo($filename, PATHINFO_EXTENSION));
}
/**
* 获取随机文件名
* @param int $length
* @return string
*/
protected function getRandomKey(int $length = 16): string
{
$charTable = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$result = "";
for ( $i = 0; $i < $length; $i++ ){
$result .= $charTable[ mt_rand(0, strlen($charTable) - 1) ];
}
return $result;
}
/**
* 获取上传目录
* @param $key
* @return string|string[]
*/
protected function getPath($key)
{
// 目录分割
$ds = DIRECTORY_SEPARATOR;
// 配置目录
$save_dir = str_replace('/',$ds,$this->policy['config']['save_dir']);
// 根目录
$root_path = realpath(env('root_path') . './public') . $save_dir;
// 临时存储目录
$temp_path = realpath(env('root_path') . './public') . str_replace('/',$ds,'/temp/');
// 当前保存目录
$file_path = date('Ymd') . $ds . $this->uid . $ds;
//文件名
$file_name = uniqid( "file_") . time();
$data = [
'root' => $root_path,
'temp' => $temp_path,
'file' => $file_path,
'path' => $root_path . $file_path,
'temp_path' => $temp_path . $file_path,
'name' => $file_name,
'filename' => $file_name .'.'. $this->getFileExt($this->info['file']['name'])
];
if($key == 'all'){
return $data;
}
return $data[$key] ?? '';
}
public function upload(){
// 超时时间5分钟
@set_time_limit(5 * 60);
// 获取有效的目录ID
$this->info['file']['folder'] = FileManage::getFolderAllowPid(input('post.folder_id',0),$this->uid);
// 获取上传文件大小
$this->info['file']['size'] = input('post.size',0);
// 获取上传文件名
$this->info['file']['name'] = input('post.name','');
// 上传文件对象获取
$this->info['file']['data'] = request()->file('file');
// 分片上传
$this->info['chunk']['key'] = input('post.chunks_key');
$this->info['chunk']['chunk'] = input('post.chunk',0);
$this->info['chunk']['chunks'] = input('post.chunks',0);
$this->info['uid'] = $this->uid;
// 参数校验
$this->check();
// 目录
$path = $this->getPath('all');
// 上传驱动
switch ($this->policy['type']){
// 阿里云
case 'aliyunoss':
$upload = new AliyunOss($this->info,$this->policy,$path);
break;
// 腾讯云
case 'txyunoss':
$upload = new TxyunOss($this->info,$this->policy,$path);
break;
// 本地
default:
$upload = new Local($this->info,$this->policy,$path);
break;
}
// 上传文件
$file_object = $upload->upload();
// 插入数据库
if($file_object != 'chunk_file' && $file_object != null){
// 加入数据库
$data = [
'uid' => $this->uid,
'origin_name' => $this->info['file']['name'],
'file_name' => $file_object,
'size' => $this->info['file']['size'],
'ext' => $this->getFileExt($this->info['file']['name']),
'parent_folder' => $this->info['file']['folder'],
'policy_id' => $this->policy['id'],
'create_time' => time(),
'update_time' => time()
];
$file_id = (new Stores)->insertGetId($data);
$share_id = Shares::addShare($this->uid,$file_id,0);
Stores::where('id',$file_id)->update(['shares_id' => $share_id]);
return ['code' => 1,'msg' => '文件上传成功'];
}
return ['code' => 1,'chunks' => 'chunk 文件上传成功'];
}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace app\common\model;
use think\Exception;
use think\Model;
use think\model\concern\SoftDelete;
class Folders extends Model
{
use SoftDelete;
protected $deleteTime = 'delete_time';
protected $autoWriteTimestamp = true;
}
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace app\common\model;
use think\Model;
class Groups extends Model
{
public function addGroup($data){
$data["max_storage"] = $data["max_storage"] * $data["storage_size"];
unset($data["storage_size"]);
self::insert($data);
}
public function editGroup($id,$data){
$data["max_storage"] = $data["max_storage"] * $data["storage_size"];
unset($data["storage_size"]);
self::where('id',$id)->update($data);
}
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace app\common\model;
use think\Model;
class Order extends Model
{
}
+53
View File
@@ -0,0 +1,53 @@
<?php
namespace app\common\model;
use think\Model;
class Policys extends Model
{
public function addPolicy($data){
//基础参数
$keys = ['name','type','filetype'];
// 附加参数
$field = [];
foreach ($data as $key => $item){
if(!in_array($key,$keys)){
$field[$key] = $item;
unset($data[$key]);
}
}
$data['config'] = json_encode($field);
self::insert($data);
}
public function editPolicy($id,$data){
//基础参数
$keys = ['name','type','filetype'];
// 附加参数
$field = [];
foreach ($data as $key => $item){
if(!in_array($key,$keys)){
$field[$key] = $item;
unset($data[$key]);
}
}
$data['config'] = json_encode($field);
self::where('id',$id)->update($data);
}
public function getConfigAttr($value){
return json_decode($value,true);
}
public static function getPolicyAll(): array
{
return self::field('id,name')->select()->toArray();
}
}
+60
View File
@@ -0,0 +1,60 @@
<?php
namespace app\common\model;
use think\Model;
class Profit extends Model
{
public static function record($uid,$file_id,$field,$value = 1): bool
{
$fp = fopen('record_lock.txt', "w+");
if(flock($fp,LOCK_EX | LOCK_NB)){
// 判断今日是否统计
$rec = self::where('uid',$uid)->where('file_id',$file_id)->whereTime('create_time','d')->find();
// 补全字段
$field = 'count_'.$field;
if($field == 'count_view'){
Stores::where('id',$file_id)->where('uid',$uid)->setInc('count_open',1);
}
if($field == 'count_down'){
Stores::where('id',$file_id)->where('uid',$uid)->setInc('count_down',1);
}
if(!empty($rec)){
self::where('uid',$uid)->where('file_id',$file_id)->setInc($field,$value);
flock($fp,LOCK_UN);
return true;
}
// 插入新统计
$data = [
'uid' => $uid,
'file_id' => $file_id,
'create_time' => time(),
$field => $value
];
// 插入统计
self::insert($data);
flock($fp,LOCK_UN);
return true;
} else{
fclose($fp);
return false;
}
}
}
+44
View File
@@ -0,0 +1,44 @@
<?php
namespace app\common\model;
use think\Model;
class Record extends Model
{
public static function addRecord($uid,$type,$source,$money,$remark){
$user = Users::where('id',$uid)->find();
// 操作前金额
$before_money = $user['amount'];
// 操作
if($type){
$after_money = floatval($user['amount']) - floatval($money);
}else{
$after_money = floatval($user['amount']) + floatval($money);
}
if($after_money < 0){
return false;
}
if($type){
Users::where('id',$uid)->setDec('amount',$money);
}else{
Users::where('id',$uid)->setInc('amount',$money);
}
return self::create([
'uid' => $uid,
'type' => $type,
'source' => $source,
'money' => $money,
'before_money' => $before_money,
'after_money' => $after_money,
'remark' => $remark,
'create_time' => time()
]);
}
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace app\common\model;
use think\Model;
class Reports extends Model
{
}
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace app\common\model;
use think\Model;
class Setting extends Model
{
}
+58
View File
@@ -0,0 +1,58 @@
<?php
namespace app\common\model;
use think\Exception;
use think\Model;
class Shares extends Model
{
public static function addShare($uid,$source,$type){
$share_code = '';
for ($i = 0;$i < 5;$i++){
$code = shortUrl($uid.'_'.$source.'_'.$type.time());
if(self::where('code',$code)->count() == 0){
$share_code = $code;
break;
}
}
if(empty($share_code)){
throw new Exception('分享连接生成失败,请稍后重试');
}
$pwd = getRndSharePwd();
$data = [
'uid' => $uid,
'source_id' => $source,
'type' => $type,
'speed' => 0,
'code' => $code,
'pwd' => $pwd,
'pwd_status' => 0
];
return self::insertGetId($data);
}
public static function getShare($uid,$source,$type){
return self::where([
['uid','=',$uid],
['source_id','=',$source],
['type','=',$type]
])->field('id,code,pwd,pwd_status,speed')->find();
}
public function delShare(){
}
public static function updateShare($id,$data){
return self::where('id',$id)->update($data);
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace app\common\model;
use think\Model;
use think\model\concern\SoftDelete;
class Stores extends Model
{
use SoftDelete;
protected $deleteTime = 'delete_time';
protected $autoWriteTimestamp = true;
public function getPolicy(){
$policy = Policys::get($this->policy_id);
if(empty($policy)){
return false;
}
return $policy;
}
public function getLocalSaveFilePath($save_dir,$filename): string
{
return env('root_path').'public'.getSafeDirSeparator($save_dir . $filename);
}
public function getLocalSaveFile($save_dir,$filename){
return str_replace(['/','\\','//','\\\\'],'/',($save_dir.$filename));
}
}
+167
View File
@@ -0,0 +1,167 @@
<?php
namespace app\common\model;
use app\common\exception\LoginError;
use think\Exception;
use think\facade\Session;
use think\Model;
class Users extends Model
{
/**
* 用户注册方法
* @param $username
* @param $email
* @param $password
* @param $group
* @param array $other
* @throws Exception
*/
public function register($username, $email, $password, $group, array $other = [],$group_expire=0){
if(self::where('username',$username)->count() > 0){
throw new Exception('当前帐号已被注册');
}
if(self::where('email',$email)->count() > 0){
throw new Exception('当前安全邮箱已被绑定');
}
$en_password = md5($password . config('app.pass_salt'));
$nickname = ucfirst($username);
if(isset($other['nickname'])){
$nickname = $other['nickname'];
}
$user = [
'nickname' => $nickname,
'username' => $username,
'email' => $email,
'group' => $group,
'password' => $en_password,
'create_time' => time(),
'group_expire' => $group_expire,
'status' => 1
];
self::insert($user);
$user_id = self::getLastInsID();
//添加基础目录
if($group != 1){
Folders::insert([
'uid' => $user_id,
'folder_name' => '根目录',
'parent_folder' => 0,
'create_time' => time()
]);
}
}
/**
* 用户登录登录方法
* @param $username
* @param $password
* @param string $login_type
* @return bool
* @throws LoginError
*/
public function login($username,$password,$login_type = 'default'){
// 登录用户组类型
if($login_type == 'admin'){
$group = 1;
}else{
$group = config('register.default_group') .','.config('vip.vip_group');
}
// 查找用户
$user = self::where('username',$username)->where('group','in',$group)->find();
// 用户不存在
if(empty($user)){
throw new LoginError('登录帐号或者密码错误,请重试');
}
// 加密密码
$password = md5($password . config('app.pass_salt'));
if($user['password'] != $password){
throw new LoginError('登录帐号或者密码错误,请重试');
}
// 不允许登录
if($login_type == 'default' && $user['status'] == 0){
throw new LoginError('登录帐号已被管理员封禁,请联系管理员处理!');
}
// 登录成功
Session::set($login_type .'_uid',$user['id']);
Session::set($login_type .'_lkey',md5($username . $password . $user['status']));
return true;
}
/**
* 退出登录方法
* @param string $type
*/
public function logout(string $type = 'default'){
Session::delete($type .'_uid');
Session::delete($type .'_lkey');
}
/**
*登录验证方法
* @param string $type
* @return bool
*/
public function login_auth(string $type = 'default'): bool
{
$uid = Session::get($type .'_uid');
$key = Session::get($type .'_lkey');
$user = self::where('id',$uid)->find();
if(empty($user)){
return false;
}
if($key != md5($user['username'] . $user['password'] . $user['status'])){
return false;
}
return true;
}
/**
* 获取当前登录用户信息
* @param string $type
* @return Users|false
*/
public function login_info(string $type = 'default'){
$uid = Session::get($type .'_uid');
$user = self::where('id',$uid)->find();
if(empty($user)){
return false;
}
return $user;
}
public function getCertify(){
return Certify::where('uid',$this->id)
->where('status',1)
->field('name,idcard,create_time')
->find();
}
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace app\common\model;
use think\Model;
class Withdraw extends Model
{
}
@@ -0,0 +1,185 @@
<?php
namespace app\common\model\driver;
use OSS\Core\OssException;
use OSS\OssClient;
use think\Exception;
use think\facade\Cache;
class AliyunOss extends PolicyStore
{
public function uploadSimple(){
// 临时文件地址
$temp_file = $this->path['temp_path'] . $this->path['filename'];
// 保存临时文件
$file_info = $this->info['file']['data']->move($this->path['temp_path'],$this->path['filename']);
if(!$file_info){
throw new Exception($this->info['file']['data']->getError());
}
$accessKeyId = $this->policy['config']['access_key'];
$accessKeySecret = $this->policy['config']['access_secret'];
$endpoint = $this->policy['config']['endpoint'];
$bucket = $this->policy['config']['bucket'];
$policy_save_dir = ltrim($this->policy['config']['save_dir'],'/');
$object = getDiyDirSeparator('/',$policy_save_dir. $this->path['file'].$this->path['filename']);
try{
$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
$ossClient->uploadFile($bucket,$object,$temp_file);
// 删除临时文件
@unlink($temp_file);
// 返回文件存储地址
return '/'. $object;
} catch(OssException $e) {
throw new Exception('FAILED'.$e->getMessage());
}
}
public function uploadPart()
{
// 临时文件地址
$temp_file = $this->path['temp_path'] . $this->path['filename'];
// 保存临时文件
$file_info = $this->info['file']['data']->move($this->path['temp_path'],$this->path['filename']);
if(!$file_info){
throw new Exception($this->info['file']['data']->getError());
}
$accessKeyId = $this->policy['config']['access_key'];
$accessKeySecret = $this->policy['config']['access_secret'];
$endpoint = $this->policy['config']['endpoint'];
$bucket = $this->policy['config']['bucket'];
$policy_save_dir = ltrim($this->policy['config']['save_dir'],'/');
// 缓存分片上传地址
$chunks_object_keys = 'aliyun_oss_chunks_'.$this->info['chunk']['key'];
$multi_upload_object = Cache::get($chunks_object_keys);
try {
$client = new OssClient($accessKeyId,$accessKeySecret,$endpoint);
// 缓存防止重复文件地址
if(empty($multi_upload_object)){
$upload_object_path = getDiyDirSeparator('/',$policy_save_dir. $this->path['file'].$this->path['filename']);
$uploadId = $client->initiateMultipartUpload($bucket,$upload_object_path);
$multi_upload_object = [
'object' => $upload_object_path,
'upload_id' => $uploadId
];
Cache::set($chunks_object_keys,$multi_upload_object);
}
// 分片上传配置
$options = [
// 上传文件地址
OssClient::OSS_FILE_UPLOAD => $temp_file,
// 分片号
OssClient::OSS_PART_NUM => $this->info['chunk']['chunk'] + 1,
];
$client->uploadPart($bucket, $multi_upload_object['object'], $multi_upload_object['upload_id'], $options);
// 组合文件
if(($this->info['chunk']['chunk'] + 1) == $this->info['chunk']['chunks']){
// 获取所有分片信息
$listPartsInfo = $client->listParts($bucket, $multi_upload_object['object'], $multi_upload_object['upload_id']);
$uploadParts = [];
foreach ($listPartsInfo->getListPart() as $partInfo) {
$uploadParts[] = [
'PartNumber' => $partInfo->getPartNumber(),
'ETag' => $partInfo->getETag()
];
}
// 合并分片
$client->completeMultipartUpload($bucket, $multi_upload_object['object'], $multi_upload_object['upload_id'], $uploadParts);
// 删除分片缓存信息
Cache::rm($chunks_object_keys);
// 删除临时文件
@unlink($temp_file);
// 返回结果
return '/' . $multi_upload_object['object'];
}
// 删除临时文件
@unlink($temp_file);
return 'chunk_file';
}catch (OssException $e){
throw new Exception('FAILED'.$e->getMessage());
}
}
public function download($stores, $speed, $policy)
{
$accessKeyId = $policy['config']['access_key'];
$accessKeySecret = $policy['config']['access_secret'];
$endpoint = $policy['config']['endpoint'];
$bucket = $policy['config']['bucket'];
$object = ltrim($stores['file_name'],'/');
// 限速下载
if($speed !== ""){
// 下载速度
$down_speed = round(intval($speed) * 8192);
// 最小限速100kb/s
if($down_speed < 819200){
$down_speed = 819200;
}
$options = [
OssClient::OSS_TRAFFIC_LIMIT => $down_speed
];
}
try {
$ossClient = new OssClient($accessKeyId,$accessKeySecret,$endpoint);
$options['response-content-disposition'] = 'attachment; filename='.$stores['origin_name'];
// 120s有效期
$timeout = 120;
$signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "GET", $options);
// 跳转下载地址
return redirect($signedUrl);
}catch (OssException $e){
throw new Exception($e->getMessage());
}
}
}
+125
View File
@@ -0,0 +1,125 @@
<?php
namespace app\common\model\driver;
use think\Exception;
use think\facade\Cache;
class Local extends PolicyStore
{
public function uploadSimple()
{
// 保存文件
$file_info = $this->info['file']['data']->move($this->path['path'],$this->path['name']);
if(!$file_info){
throw new Exception($this->info['file']['data']->getError());
}
$policy_save_dir = $this->policy['config']['save_dir'];
return getDiyDirSeparator('/',$policy_save_dir. $this->path['file'].$this->path['filename']);
}
public function uploadPart()
{
// 分片数据存储名称
$chunks_saveKey = 'chunks_'.$this->info['uid'].'_'.$this->info['chunk']['key'];
// 文件名称
$temp_filename = 'chunks_'.md5($this->info['chunk']['key']).'_'.$this->getRandomKey(4) . '_part_'.$this->info['chunk']['chunk'].'.chunk';
// 临时文件地址
$temp_file = $this->path['temp_path'] . $temp_filename;
// 保存临时文件
$file_info = $this->info['file']['data']->move($this->path['temp_path'],$temp_filename);
if(!$file_info){
throw new Exception('分片创建错误:'.$this->info['file']['data']->getError());
}
// 分片存储列表
$chunk_list = Cache::get($chunks_saveKey) ?? [];
// 加入分片文件
$chunk_list[] = $temp_file;
// 保存分片临时存储列表
Cache::set($chunks_saveKey,$chunk_list);
// 分片上传成功
if($this->info['chunk']['chunk'] == ($this->info['chunk']['chunks'] - 1)){
$save_file = $this->path['path'] . $this->path['filename'];
// 融合文件路径
$fileObj = fopen($save_file,"a+");
// 融合文件
foreach ($chunk_list as $value) {
$chunkObj = fopen($value, "rb");
if(!($fileObj && $chunkObj)){
throw new Exception('分片融合文件创建失败');
}
$content = fread($chunkObj, (2 * 1024 * 1024));
fwrite($fileObj, $content, (2 * 1024 * 1024));
unset($content);
fclose($chunkObj);
// 删除分片文件
unlink($value);
}
// 清空分片临时存储列表
Cache::rm($chunks_saveKey);
$policy_save_dir = $this->policy['config']['save_dir'];
return getDiyDirSeparator('/',$policy_save_dir. $this->path['file'] . $this->path['filename']);
}
return 'chunk_file';
}
protected function getRandomKey($length = 16){
$charTable = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$result = "";
for ( $i = 0; $i < $length; $i++ ){
$result .= $charTable[ mt_rand(0, strlen($charTable) - 1) ];
}
return $result;
}
public function download($stores,$speed,$policy)
{
//存储文件地址
$_file = getSafeDirSeparator(env('root_path').'public'.$stores['file_name']);
// 文件不存在
if(!is_file($_file)){
throw new Exception('文件不存在,可能已被删除');
}
$_file_path = $stores['file_name'];
$_file_limit_size = round(intval($speed) * 1024);
// 启用 nginx X-Accel 下载
header('Content-Type: application/octet-stream');
$encoded_fname = rawurlencode($stores['origin_name']);
header('Content-Disposition: attachment;filename="'.$encoded_fname.'";filename*=utf-8'."''".$encoded_fname);
header('X-Accel-Redirect: '. $_file_path);
header('X-Accel-Buffering: yes');
// 不限速下载
if($speed !== ""){
header('X-Accel-Limit-Rate:'.$_file_limit_size);
}
}
}
@@ -0,0 +1,46 @@
<?php
namespace app\common\model\driver;
abstract class PolicyStore
{
protected $info;
protected $policy;
protected $path;
public function __construct($info,$policy,$path)
{
$this->info = $info;
$this->policy = $policy;
$this->path = $path;
}
public function upload()
{
if(!empty($this->info['chunk']['chunks'])){
return $this->uploadPart();
}else{
return $this->uploadSimple();
}
}
public function uploadSimple()
{
return 0;
}
public function uploadPart()
{
return 0;
}
public function download($stores,$speed,$policy)
{
return 0;
}
}
@@ -0,0 +1,210 @@
<?php
namespace app\common\model\driver;
use Qcloud\Cos\Client;
use Qcloud\Cos\Exception\ServiceResponseException;
use think\Exception;
use think\facade\Cache;
class TxyunOss extends PolicyStore
{
public function uploadSimple(){
$secretId = $this->policy['config']['secret_id'];
$secretKey = $this->policy['config']['secret_key'];
$region = $this->policy['config']['region'];
$bucket = $this->policy['config']['bucket'];
// 文件路径
$file_path = $this->info['file']['data']->getInfo('tmp_name');
$file = fopen($file_path, 'rb');
// 存储路径
$policy_save_dir = ltrim($this->policy['config']['save_dir'],'/');
$object = getDiyDirSeparator('/',$policy_save_dir. $this->path['file'].$this->path['filename']);
try {
// COS对象
$client = new Client([
'region' => $region,
'schema' => 'http',
'credentials' => [
'secretId' => $secretId,
'secretKey' => $secretKey
]
]);
if ($file) {
// 上传文件
$client->putObject([
'Bucket' => $bucket,
'Key' => $object,
'Body' => $file
]);
// 返回文件存储地址
return '/'. $object;
}else{
throw new Exception('上传文件路径错误');
}
}catch (ServiceResponseException $e){
throw new Exception($e->getMessage());
}catch (\Exception $e) {
throw new Exception($e->getMessage());
}
}
public function uploadPart()
{
// 配置信息
$secretId = $this->policy['config']['secret_id'];
$secretKey = $this->policy['config']['secret_key'];
$region = $this->policy['config']['region'];
$bucket = $this->policy['config']['bucket'];
// 分片数据存储名称
$chunks_saveKey = 'txyunoss_chunks_'.$this->info['uid'].'_'.$this->info['chunk']['key'];
// 文件名称
$temp_filename = 'chunks_'.md5($this->info['chunk']['key']).'_'.$this->getRandomKey(4) . '_part_'.$this->info['chunk']['chunk'].'.chunk';
// 临时文件地址
$temp_file = $this->path['temp_path'] . $temp_filename;
// 保存临时文件
$file_info = $this->info['file']['data']->move($this->path['temp_path'],$temp_filename);
if(!$file_info){
throw new Exception('分片创建错误:'.$this->info['file']['data']->getError());
}
// 分片存储列表
$chunk_list = Cache::get($chunks_saveKey) ?? [];
// 加入分片文件
$chunk_list[] = $temp_file;
// 保存分片临时存储列表
Cache::set($chunks_saveKey,$chunk_list);
// 分片上传成功
if($this->info['chunk']['chunk'] == ($this->info['chunk']['chunks'] - 1)){
// COS对象
$client = new Client([
'region' => $region,
'schema' => 'http',
'credentials' => [
'secretId' => $secretId,
'secretKey' => $secretKey
]
]);
$save_file = $this->path['temp_path'] . 'cos_cob_'.substr(md5($this->info['chunk']['key']),0,8).'_t_'.time().'.bak';
// 融合文件路径
$fileObj = fopen($save_file,"a+");
// 融合文件
foreach ($chunk_list as $value) {
$chunkObj = fopen($value, "rb");
if(!($fileObj && $chunkObj)){
throw new Exception('分片融合文件创建失败');
}
$content = fread($chunkObj, (2 * 1024 * 1024));
fwrite($fileObj, $content, (2 * 1024 * 1024));
unset($content);
fclose($chunkObj);
// 删除分片文件
unlink($value);
}
// 清空分片临时存储列表
Cache::rm($chunks_saveKey);
try {
$policy_save_dir = $this->policy['config']['save_dir'];
$upload_object_path = getDiyDirSeparator('/',$policy_save_dir. $this->path['file'].$this->path['filename']);
if ($fileObj) {
// 上传文件
$client->Upload($bucket,$upload_object_path,$fileObj);
// 删除临时组合文件
@unlink($save_file);
return $upload_object_path;
}else{
throw new Exception('上传文件路径错误');
}
}catch (ServiceResponseException $e){
throw new Exception($e->getMessage());
}catch (\Exception $e) {
throw new Exception($e->getMessage());
}
}
return 'chunk_file';
}
protected function getRandomKey($length = 16){
$charTable = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$result = "";
for ( $i = 0; $i < $length; $i++ ){
$result .= $charTable[ mt_rand(0, strlen($charTable) - 1) ];
}
return $result;
}
public function download($stores, $speed, $policy)
{
$secretId = $policy['config']['secret_id'];
$secretKey = $policy['config']['secret_key'];
$region = $policy['config']['region'];
$bucket = $policy['config']['bucket'];
$object = ltrim($stores['file_name'],'/');
// COS对象
$client = new Client([
'region' => $region,
'schema' => 'http',
'credentials' => [
'secretId' => $secretId,
'secretKey' => $secretKey
]
]);
$disposition = 'attachment; filename='.$stores['origin_name'];
$url = $client->getPresignedUrl('GetObject',[
'Bucket' => $bucket,
'Key' => $object
],'+10 minutes')->__toString();
$url .= 'response-content-disposition='.urlencode($disposition).'&';
// 限速下载
if($speed !== ""){
// 下载速度
$down_speed = round(intval($speed) * 8192);
// 最小限速100kb/s
if($down_speed < 819200){
$down_speed = 819200;
}
$url .= 'x-cos-traffic-limit='.$down_speed;
}
// 跳转下载地址
return redirect($url);
}
}