test
This commit is contained in:
Submodule digital_doctor/vendor/wanghua/general-utility-tools-php deleted from f31ce1f391
6
digital_doctor/vendor/wanghua/general-utility-tools-php/.gitignore
vendored
Normal file
6
digital_doctor/vendor/wanghua/general-utility-tools-php/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
.idea
|
||||
.git
|
||||
|
||||
/.git
|
||||
/.idea
|
||||
/composer.lock
|
||||
37
digital_doctor/vendor/wanghua/general-utility-tools-php/README.en.md
vendored
Normal file
37
digital_doctor/vendor/wanghua/general-utility-tools-php/README.en.md
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# general_utility_tools_php
|
||||
|
||||
#### Description
|
||||
php常用工具箱
|
||||
general utility tool for php
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
|
||||
|
||||
#### Gitee Feature
|
||||
|
||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
142
digital_doctor/vendor/wanghua/general-utility-tools-php/README.md
vendored
Normal file
142
digital_doctor/vendor/wanghua/general-utility-tools-php/README.md
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
# general_utility_tools_php
|
||||
|
||||
#### 介绍
|
||||
|
||||
[PHP常用通用工具库]
|
||||
|
||||
一、常用验证类库
|
||||
1. 验证手机号是否正确
|
||||
2. 验证邮箱
|
||||
3. 验证身份证号码
|
||||
4. 是否字母或数字
|
||||
5. 是否是小数格式
|
||||
6. 更多功能请参考代码
|
||||
|
||||
二、PHP日期处理工具
|
||||
1. 日期加上N年、月、日、时、分、秒,得到计算后的时间
|
||||
2. 两个日期相减得到天、时、分、秒(没有两个日期相加一说)
|
||||
3. 更多更完善功能敬请期待......
|
||||
|
||||
三、更多类库参考本类库目录
|
||||
1. 每个目录都有使用说明.
|
||||
|
||||
#### 软件架构
|
||||
|
||||
每一种工具独立为一个功能类库。
|
||||
#### 软件要求
|
||||
thinkphp5.0+,PHP7.1+
|
||||
|
||||
|
||||
#### 安装教程
|
||||
composer require wanghua/general-utility-tools-php dev-master
|
||||
|
||||
###### 注意:如果总是安装失败,可切换国内或者国外源;如果是找不到版本则加上dev-master尝试
|
||||
###### 注意:如果总是安装失败,可卸载此包重新安装,卸载指令:composer remove wanghua/general-utility-tools-php
|
||||
###### 注意:如果总是不能提交 vendor下面的一个文件夹(或文件),请参考这篇文章解决:https://blog.csdn.net/qq_15941409/article/details/113184021
|
||||
|
||||
### 一、常用验证类库使用说明
|
||||
##### 初始化
|
||||
|
||||
//静态方法无需实例化直接调用
|
||||
|
||||
##### 验证参数是否是小数格式
|
||||
$str = '1.223';
|
||||
var_dump(Validate::is_float_number($str));
|
||||
|
||||
##### 验证参数是否字母或数字
|
||||
$str = 'qwer#199';
|
||||
var_dump(Validate::is_letter_or_number($str));
|
||||
|
||||
###### 注: 更多功能请参考源码
|
||||
|
||||
### 二、PHP日期处理工具使用说明
|
||||
|
||||
##### 初始化
|
||||
$date = (new Date());
|
||||
$date->date_format = 'Y-m-d H:i:s';//设置格式,默认Y-m-d H:i:s
|
||||
|
||||
##### 日期类型参数(第2个参数)可选项:
|
||||
//分、时、天、周、月、年
|
||||
protected $data_type = [
|
||||
'm' =>'minute',//分钟
|
||||
'minute' =>'minute',//分钟
|
||||
'h' =>'hour',//小时
|
||||
'hour' =>'hour',//小时
|
||||
'd' =>'day',//天
|
||||
'day' =>'day',//天
|
||||
'w' =>'week',//周
|
||||
'week' =>'week',//周
|
||||
'M' =>'month',//月
|
||||
'month' =>'month',//月
|
||||
'y' =>'year',//年
|
||||
'year' =>'year',//年
|
||||
];
|
||||
|
||||
|
||||
##### 在当前时间基础上加3天(第三个参数不传默认使用当前时间)
|
||||
$res = $date->addTime(3, 'd');//支持单词和字母,例如:d表示天,day也表示天
|
||||
dump($res);
|
||||
|
||||
##### 在当前时间基础上加1小时(第三个参数不传默认使用当前时间)
|
||||
$res = $date->addTime(1, 'h');//支持单词和字母,例如:h表示小时,hour也表示小时
|
||||
dump($res);
|
||||
|
||||
##### 在指定时间基础上加1小时
|
||||
$res = $date->addTime(1, 'h', strtotime('2010-10-01 12:00:10'));
|
||||
dump($res);
|
||||
|
||||
##### 在指定时间基础上减1个月 (注意:月是大写M字母,分钟是小写m字母)
|
||||
$res = $date->reduceTime(1, 'M', strtotime('2010-10-01 12:00:10'));
|
||||
dump($res);
|
||||
|
||||
##### 在指定时间基础上减20分钟 (注意:分钟是小写m字母)
|
||||
$res = $date->reduceTime(20, 'm', strtotime('2010-10-01 12:00:10'));
|
||||
dump($res);
|
||||
|
||||
##### 在指定时间基础上减1年
|
||||
$res = $date->reduceTime(1, 'y', strtotime('2010-10-01 12:00:10'));
|
||||
dump($res);
|
||||
|
||||
### 日期时间相减
|
||||
|
||||
//时间相减返回的时间类型 秒、分、时、天 默认返回秒
|
||||
protected $time_type = [
|
||||
's' =>1,//秒
|
||||
'second' =>1,//秒
|
||||
'm' =>60,//分钟
|
||||
'minute' =>60,//分钟
|
||||
'h' =>3600,//小时
|
||||
'hour' =>3600,//小时
|
||||
'd' =>86400,//天
|
||||
'day' =>86400,//天
|
||||
];
|
||||
|
||||
$start_time = '2010-05-01 12:30:00';
|
||||
$end_time = '2010-10-28 12:30:00';
|
||||
|
||||
//结束时间减去开始时间得到秒数 (返回类型参考上方配置)
|
||||
$res = $date->timeReduceTime($end_time, $start_time);
|
||||
dump($res);
|
||||
|
||||
//结束时间减去开始时间得到天数 (返回类型参考上方配置)
|
||||
$res = $date->timeReduceTime($end_time, $start_time, 'day');
|
||||
dump($res);
|
||||
|
||||
###### 注: 更多功能请参考源码
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
|
||||
|
||||
#### 特技
|
||||
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
25
digital_doctor/vendor/wanghua/general-utility-tools-php/composer.json
vendored
Normal file
25
digital_doctor/vendor/wanghua/general-utility-tools-php/composer.json
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"type": "library",
|
||||
"name": "wanghua/general-utility-tools-php",
|
||||
"homepage": "https://gitee.com/drop_drop/general_utility_tools_php.git",
|
||||
"description": "general utility tools for thinkPHP",
|
||||
"license": "Apache-2.0",
|
||||
"version":"1.0.1",
|
||||
"keywords": ["general-utility-tools","php tool","common tool"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "wanghua",
|
||||
"email": "wanghua@qq.com",
|
||||
"homepage": "https://blog.csdn.net/qq_15941409"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "stable",
|
||||
"require": {
|
||||
"ext-json": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"wanghua\\general_utility_tools_php\\": "src/"
|
||||
}
|
||||
}
|
||||
}
|
||||
396
digital_doctor/vendor/wanghua/general-utility-tools-php/src/Date.php
vendored
Normal file
396
digital_doctor/vendor/wanghua/general-utility-tools-php/src/Date.php
vendored
Normal file
@@ -0,0 +1,396 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/10/27} {11:43}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php;
|
||||
|
||||
/**
|
||||
* 日期时间处理类
|
||||
* Class Date
|
||||
* @package libraries
|
||||
*/
|
||||
class Date
|
||||
{
|
||||
//时间默认返回格式
|
||||
public $date_format = 'Y-m-d H:i:s';
|
||||
//分、时、天、周、月、年
|
||||
protected $data_type = [
|
||||
'm' =>'minute',//分钟
|
||||
'minute' =>'minute',//分钟
|
||||
'h' =>'hour',//小时
|
||||
'hour' =>'hour',//小时
|
||||
'd' =>'day',//天
|
||||
'day' =>'day',//天
|
||||
'w' =>'week',//周
|
||||
'week' =>'week',//周
|
||||
'M' =>'month',//月
|
||||
'month' =>'month',//月
|
||||
'y' =>'year',//年
|
||||
'year' =>'year',//年
|
||||
];
|
||||
//秒、分、时、天
|
||||
protected $time_type = [
|
||||
's' =>1,//秒
|
||||
'second' =>1,//秒
|
||||
'm' =>60,//分钟
|
||||
'minute' =>60,//分钟
|
||||
'h' =>3600,//小时
|
||||
'hour' =>3600,//小时
|
||||
'd' =>86400,//天
|
||||
'day' =>86400,//天
|
||||
];
|
||||
/**
|
||||
* desc:日期时间加N
|
||||
*
|
||||
* 【注意】
|
||||
* 请在计算月时使用$date->date_format = 'Y-m'防止跳月份
|
||||
* 例如:2020-03-31月基础上加一个月,在默认$date->date_format='Y-m-d H:i:s'时,会跳到2020-05-01
|
||||
*
|
||||
* author:wh
|
||||
* @param int $times 相加的时间数量 整型
|
||||
* @param string $date_type 要相加的时间类型 可选值:m 分钟;h 小时;d 天;w 周;M 月;y 年
|
||||
* @param int $default_time 时间戳,默认当前时间
|
||||
* @return false|string 返回$this->date_format格式,可根据需要设定格式
|
||||
*/
|
||||
function addTime(int $times, string $date_type, int $default_time=0){
|
||||
return date($this->date_format, strtotime("+{$times} {$this->data_type[$date_type]}", $default_time?$default_time:time()));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:日期时间减N
|
||||
*
|
||||
* 【注意】
|
||||
* 请在计算月时使用$date->date_format = 'Y-m'防止跳月份
|
||||
* 例如:2020-03-31月基础上加一个月,在默认$date->date_format='Y-m-d H:i:s'时,会跳到2020-05-01
|
||||
*
|
||||
* author:wh
|
||||
* @param int $times 减去的时间数量 整型
|
||||
* @param string $date_type 要相减的时间类型 可选值:m 分钟;h 小时;d 天;w 周;M 月;y 年
|
||||
* @param int $default_time 时间戳,默认当前时间
|
||||
* @return false|string 返回$this->date_format格式,可根据需要设定格式
|
||||
*/
|
||||
function reduceTime(int $times, string $date_type, int $default_time=0){
|
||||
return date($this->date_format, strtotime("-{$times} {$this->data_type[$date_type]}", $default_time?$default_time:time()));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:日期时间相减,通常结束时间大于开始时间
|
||||
* author:wh
|
||||
* @param string $end_time 结束时间
|
||||
* @param string $start_time 开始时间
|
||||
* @param string $return_type 日期时间相减后得到的时间类型,可能是小数。可选值:s 秒;m 分钟;h 小时;d;天
|
||||
* @return float|int 返回计算后的天、时、分、秒数
|
||||
*/
|
||||
function timeReduceTime(string $end_time, string $start_time, string $return_type='s'){
|
||||
return (strtotime($end_time) - strtotime($start_time)) / $this->time_type[$return_type];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:日期减日期, 返回月数或年数
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time 开始时间
|
||||
* @param string $end_time 结束时间
|
||||
* @param string $return_type M 返回一共有多少个月,y 返回有多少个年
|
||||
* @return float|int
|
||||
*/
|
||||
function dateCutDate(string $start_time, string $end_time, string $return_type='M'){
|
||||
$e = date_create($end_time);
|
||||
|
||||
$s = date_create($start_time);
|
||||
|
||||
$diff = date_diff($e, $s);
|
||||
|
||||
//计算月份
|
||||
if ($diff->y > 0) {
|
||||
$m = $diff->y * 12 + $diff->m;
|
||||
}else{
|
||||
$m = $diff->m;
|
||||
}
|
||||
return $return_type=='M'?$m:$diff->y;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:日期相减得到月数
|
||||
* 注意:不是计算的时间戳,而是计算的月份差值
|
||||
* author:wh
|
||||
* @param string $start_time
|
||||
* @param string $end_time
|
||||
* @return false|float|int|string
|
||||
*/
|
||||
function dateCutMonth(string $start_time, string $end_time){
|
||||
$start_y = date('Y', strtotime($start_time));
|
||||
$end_y = date('Y', strtotime($end_time));
|
||||
$start_m = date('m', strtotime($start_time));
|
||||
$end_m = date('m', strtotime($end_time));
|
||||
$ym = ($end_y-$start_y) * 12;
|
||||
return $ym - $start_m + $end_m;
|
||||
}
|
||||
/**
|
||||
* desc:日期相减得到年数
|
||||
* 注意:不是计算的时间戳,而是计算的年份差值
|
||||
* author:wh
|
||||
* @param string $start_time
|
||||
* @param string $end_time
|
||||
* @return false|float|int|string
|
||||
*/
|
||||
function dateCutYear(string $start_time, string $end_time){
|
||||
$start_y = date('Y', strtotime($start_time));
|
||||
$end_y = date('Y', strtotime($end_time));
|
||||
return ($end_y-$start_y) * 12;
|
||||
}
|
||||
/**
|
||||
* desc:返回年中第几天
|
||||
* author:wh
|
||||
* @param string $month 指定月份
|
||||
* @param string $day 指定日
|
||||
* @param string $year 指定年份
|
||||
* @return false|string
|
||||
*/
|
||||
function get_day_Year(string $month, string $day, string $year){
|
||||
return date('z',mktime(0,0,0,$month,$day,$year));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:今天的开始时间
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function beginToday(){
|
||||
return date('Y-m-d').' 00:00:00';
|
||||
}
|
||||
/**
|
||||
* desc:今天的结束时间
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function endToday(){
|
||||
return date('Y-m-d').' 23:59:59';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:昨天的开始时间
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function beginYesterday(){
|
||||
return date('Y-m-d', strtotime('-1 day')).' 00:00:00';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:昨天的结束时间
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function endYesterday(){
|
||||
return date('Y-m-d', strtotime('-1 day')).' 23:59:59';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:前天的开始时间
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function beginBeforeYesterday(){
|
||||
return date('Y-m-d', strtotime('-2 day')).' 00:00:00';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:前天的结束时间
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function endBeforeYesterday(){
|
||||
return date('Y-m-d', strtotime('-2 day')).' 23:59:59';
|
||||
}
|
||||
|
||||
/**
|
||||
* 本周的开始日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function beginWeek($His = true)
|
||||
{
|
||||
//此代码会跳周、月、年
|
||||
//$timestamp = mktime(0, 0, 0, date('m'), date('d') - date('w') + 1, date('Y'));
|
||||
//return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
|
||||
|
||||
//改进
|
||||
//$first =1 表示每周星期一为开始日期 0表示每周日为开始日期
|
||||
$first=1;
|
||||
$sdefaultDate = date("Y-m-d");
|
||||
//获取当前周的第几天 周日是 0 周一到周六是 1 - 6
|
||||
$w=date('w',strtotime($sdefaultDate));
|
||||
//是否展示时分秒
|
||||
$week_start = date('Y-m-d',strtotime("$sdefaultDate -".($w ? $w - $first : 6).' days'));
|
||||
//是否展示时分秒
|
||||
if($His){
|
||||
//$week_start
|
||||
return $week_start.' 00:00:00';
|
||||
}
|
||||
//$week_start
|
||||
return $week_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* 本周的结束日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function endWeek($His = true)
|
||||
{
|
||||
//此代码会跳周、月、年
|
||||
//$timestamp = mktime(23, 59, 59, date('m'), date('d') - date('w') + 7, date('Y'));
|
||||
//return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
|
||||
|
||||
//改进
|
||||
//$first =1 表示每周星期一为开始日期 0表示每周日为开始日期
|
||||
$first=1;
|
||||
$sdefaultDate = date("Y-m-d");
|
||||
//获取当前周的第几天 周日是 0 周一到周六是 1 - 6
|
||||
$w=date('w',strtotime($sdefaultDate));
|
||||
//是否展示时分秒
|
||||
$week_start = date('Y-m-d',strtotime("$sdefaultDate -".($w ? $w - $first : 6).' days'));
|
||||
$week_end=date('Y-m-d',strtotime("$week_start +6 days"));
|
||||
//是否展示时分秒
|
||||
return $His?$week_end.' 23:59:59':$week_end;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:上周开始
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function beginBeforeWeek(){
|
||||
$week = $this->beginWeek();
|
||||
$this->date_format = 'Y-m-d';
|
||||
return $this->reduceTime(7,'d',strtotime($week)) . ' 00:00:00';
|
||||
|
||||
//此代码会跳周、月、年
|
||||
//return date('Y-m-d', strtotime('-1 monday', time())).' 00:00:00';//上周一,无论今天几号,-1 monday为上一个有效周未
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:上周结束
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function endBeforeWeek(){
|
||||
|
||||
$week = $this->beginWeek();
|
||||
$this->date_format = 'Y-m-d';
|
||||
return $this->reduceTime(1,'d',strtotime($week)) . ' 23:59:59';
|
||||
|
||||
//此代码会跳周、月、年
|
||||
//return date('Y-m-d', strtotime('-1 sunday', time())).' 23:59:59'; //上一个有效周日,同样适用于其它星期
|
||||
}
|
||||
|
||||
/**
|
||||
* 本月的开始日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function beginMonth($His = true)
|
||||
{
|
||||
return $His ? date('Y-m-').'01 00:00:00' : date('Y-m-').'01';
|
||||
}
|
||||
/**
|
||||
* 本月的结束日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function endMonth($His = true)
|
||||
{
|
||||
$timestamp = mktime(23, 59, 59, date('m'), date('t'), date('Y'));
|
||||
return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:上月开始时间(上月一日)
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function beginBeforeMonth(){
|
||||
return date('Y-m-d', strtotime('-1 month', strtotime(date('Y-m', time()) . '-01 00:00:00'))).' 00:00:00'; //本月一日直接strtotime上减一个月
|
||||
}
|
||||
/**
|
||||
* desc:上月结束时间(上月最后一日)
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function endBeforeMonth(){
|
||||
return date('Y-m-d', strtotime(date('Y-m', time()) . '-01 00:00:00') - 86400).' 23:59:59'; //本月一日减一天即是上月最后一日
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:七天(一周)以内
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function innerWeekDay(){
|
||||
$time = time();
|
||||
//当前时间减去30天
|
||||
$second = $time - 7 * 86400;
|
||||
return date('Y-m-d', $second);
|
||||
}
|
||||
/**
|
||||
* desc:一月以内
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function innerMonth(){
|
||||
$time = time();
|
||||
//当前时间减去30天
|
||||
$second = $time - 30 * 86400;
|
||||
return date('Y-m-d', $second);
|
||||
}
|
||||
/**
|
||||
* desc:一年以内
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function innerYear(){
|
||||
$time = time();
|
||||
//当前时间减去30天
|
||||
$second = $time - 365 * 86400;
|
||||
return date('Y-m-d', $second);
|
||||
}
|
||||
|
||||
/**
|
||||
* 几年的开始日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function beginYear($His = true)
|
||||
{
|
||||
$timestamp = date('Y');
|
||||
return $His ? $timestamp.'-01-01 00:00:00' : $timestamp.'-01-01';
|
||||
}
|
||||
|
||||
/**
|
||||
* 几年的结束日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function endYear($His = true)
|
||||
{
|
||||
$timestamp = date('Y');
|
||||
return $His ? $timestamp.'-12-31 23:59:59' : $timestamp.'-12-31';
|
||||
}
|
||||
}
|
||||
125
digital_doctor/vendor/wanghua/general-utility-tools-php/src/Mmodel.php
vendored
Normal file
125
digital_doctor/vendor/wanghua/general-utility-tools-php/src/Mmodel.php
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/5/1} {21:28}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php;
|
||||
|
||||
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* thinkphp5模型快捷方法库
|
||||
* Class Mmodel
|
||||
* @package wanghua\general_utility_tools_php
|
||||
*/
|
||||
class Mmodel
|
||||
{
|
||||
/**
|
||||
* desc:存在则更新否则插入
|
||||
* author:wh
|
||||
* @param string $table 表名
|
||||
* @param array $where 更新条件(只在更新时有效)
|
||||
* @param array $data 更新或写入数据
|
||||
* @return int 数据主键id
|
||||
*/
|
||||
static function existsUpdateInsert($table,$where,$data){
|
||||
if(empty($where)){
|
||||
return Db::table($table)->insertGetId($data);
|
||||
}
|
||||
$res = Db::table($table)
|
||||
->where($where)
|
||||
->find();
|
||||
if($res){
|
||||
Db::table($table)
|
||||
->where($where)
|
||||
->data($data)
|
||||
->update();
|
||||
return $res['id'];
|
||||
}
|
||||
return Db::table($table)->insertGetId($data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:捕获式函数块
|
||||
*
|
||||
* 无事务处理
|
||||
*
|
||||
* author:wh
|
||||
* @param $fn
|
||||
*/
|
||||
static function catch($fn){
|
||||
try{
|
||||
Tools::log_to_write_txt(['input'=>input()]);
|
||||
return $fn();
|
||||
}catch (\Exception $e){
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail('操作失败.',$e->getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* desc:捕获式函数块
|
||||
*
|
||||
* 无事务处理
|
||||
*
|
||||
* author:wh
|
||||
* @param $fn
|
||||
*/
|
||||
static function catchJson($fn){
|
||||
try{
|
||||
Tools::log_to_write_txt(['input'=>input()]);
|
||||
$res = $fn();
|
||||
return json($res);
|
||||
}catch (\Exception $e){
|
||||
Tools::error_txt_log($e);
|
||||
return json(Tools::set_fail('操作失败.',$e->getMessage()));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* desc:捕获式函数块
|
||||
*
|
||||
* 自动事务处理
|
||||
*
|
||||
* author:wh
|
||||
* @param $fn
|
||||
*/
|
||||
static function catchTrans($fn){
|
||||
Db::startTrans();
|
||||
try{
|
||||
Tools::log_to_write_txt(['input'=>input()]);
|
||||
$res = $fn();
|
||||
Db::commit();
|
||||
return $res;
|
||||
}catch (\Exception $e){
|
||||
Db::rollback();
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail('操作失败.',$e->getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* desc:捕获式函数块
|
||||
*
|
||||
* 自动事务处理
|
||||
*
|
||||
* author:wh
|
||||
* @param $fn
|
||||
*/
|
||||
static function catchTransJson($fn){
|
||||
Db::startTrans();
|
||||
try{
|
||||
Tools::log_to_write_txt(['input'=>input()]);
|
||||
$res = $fn();
|
||||
Db::commit();
|
||||
return json($res);
|
||||
}catch (\Exception $e){
|
||||
Db::rollback();
|
||||
Tools::error_txt_log($e);
|
||||
return json(Tools::set_fail('操作失败.',$e->getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
94
digital_doctor/vendor/wanghua/general-utility-tools-php/src/PinYin.php
vendored
Normal file
94
digital_doctor/vendor/wanghua/general-utility-tools-php/src/PinYin.php
vendored
Normal file
File diff suppressed because one or more lines are too long
50
digital_doctor/vendor/wanghua/general-utility-tools-php/src/SundryConfig.php
vendored
Normal file
50
digital_doctor/vendor/wanghua/general-utility-tools-php/src/SundryConfig.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2023/12/31} {21:56}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* 系统杂项配置
|
||||
*
|
||||
* 读取fa_sundry_config表中的配置
|
||||
*
|
||||
* Class SundryConfig
|
||||
* @package wanghua\general_utility_tools_php
|
||||
*/
|
||||
class SundryConfig
|
||||
{
|
||||
private static $tablename = 'fa_zc_sundry_config';
|
||||
|
||||
/**
|
||||
* desc:获取配置的值,设置配置的值
|
||||
*
|
||||
* 默认缓存值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $key
|
||||
* @param string $val
|
||||
* @return float|mixed|string
|
||||
*/
|
||||
static function val(string $key,string $val=''){
|
||||
$tabname = self::$tablename;
|
||||
if($val){
|
||||
$obj = Db::table($tabname);
|
||||
$obj->where('key',$key);
|
||||
$obj->data(['val'=>$val]);
|
||||
return $obj->update();
|
||||
}
|
||||
$obj = Db::table($tabname);
|
||||
return $obj->where(['key'=>$key])
|
||||
->cache($tabname.'_'.$key,0,$tabname)
|
||||
->value('val');
|
||||
}
|
||||
}
|
||||
360
digital_doctor/vendor/wanghua/general-utility-tools-php/src/Validate.php
vendored
Normal file
360
digital_doctor/vendor/wanghua/general-utility-tools-php/src/Validate.php
vendored
Normal file
@@ -0,0 +1,360 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2019/11/1} {15:09}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php;
|
||||
|
||||
|
||||
class Validate
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:验证手机号是否正确
|
||||
* author:wh
|
||||
* @param $m
|
||||
* @return bool
|
||||
*/
|
||||
static function is_mobile($m) {
|
||||
return preg_match('/^1[3,4,5,6,7,8,9]{1}\d{9}$/', $m) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证邮箱
|
||||
* author:wh
|
||||
* @param $email
|
||||
* @return bool
|
||||
*/
|
||||
static function is_email($email){
|
||||
return preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/",$email)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* [is_IDCard 验证身份证号码]
|
||||
* @Author
|
||||
* @Date 2019-11-26
|
||||
* @param [string] $string [身份证号]
|
||||
* @return boolean [description]
|
||||
*/
|
||||
static function is_IDCard($string){
|
||||
return preg_match("/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/", $string)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* [is_money_times 验证金额是否是100的整数倍]
|
||||
* @Author
|
||||
* @Date 2019-12-12
|
||||
* @param [type] $money [金额]
|
||||
* @return boolean [description]
|
||||
*/
|
||||
static function is_money_times($money){
|
||||
if(!is_numeric($money) || $money <= 0){
|
||||
return false;
|
||||
}
|
||||
return $money%100===0;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是金额
|
||||
* author:wh
|
||||
* @param $money
|
||||
* @return bool
|
||||
*/
|
||||
static function is_money($money){
|
||||
return (preg_match('/^[0-9]+.[0-9]+$/', $money) || preg_match('/^\d+$/', $money))?true:false;
|
||||
}
|
||||
/**
|
||||
* desc:是否是金额,并且最多只有两位小数
|
||||
*
|
||||
* 严格金额格式校验
|
||||
*
|
||||
* author:wh
|
||||
* @param $money
|
||||
* @return bool
|
||||
*/
|
||||
static function is_money_double($money){
|
||||
|
||||
$r = (preg_match('/^[0-9]+.[0-9]+$/', $money) || preg_match('/^\d+$/', $money))?true:false;
|
||||
|
||||
$exp = explode('.',$money);
|
||||
|
||||
if(strpos($money,'.') && preg_match('/^[0-9]+.[0-9]+$/', $money) && strlen($exp[1])>2){
|
||||
//返回false,表示非严格的2位数金额
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是小数格式
|
||||
* author:wh
|
||||
* @param string $num
|
||||
* @return bool
|
||||
*/
|
||||
static function is_float_number(string $num){
|
||||
return preg_match('/^[0-9]+.[0-9]+$/', $num)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是数字
|
||||
* author:wh
|
||||
* @param string $num
|
||||
* @return bool
|
||||
*/
|
||||
static function is_number(string $num){
|
||||
return preg_match('/^\d+$/', $num)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是字母
|
||||
* author: wh
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
static function is_letter(string $str){
|
||||
return preg_match('/^[a-zA-Z]+$/', $str) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否字母或数字
|
||||
* author:wh
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
static function is_letter_or_number(string $str){
|
||||
return preg_match('/^[a-zA-Z|0-9]+$/', $str) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:验证数组是否存在空值
|
||||
* 仅针对基本数据类型
|
||||
* 仅针对一维数组
|
||||
* author:wh
|
||||
* @param $array
|
||||
* @return bool
|
||||
*/
|
||||
static function check_array_val_empty($array){
|
||||
$is_empty = false;
|
||||
foreach ($array as $value){
|
||||
if(($value!==0 && $value !=='0') && empty($value)){
|
||||
$is_empty = true;
|
||||
break;
|
||||
}
|
||||
if(is_int($value) && empty(1*$value)){
|
||||
$is_empty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $is_empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是url
|
||||
* author:wh
|
||||
* @param $v
|
||||
* @return bool
|
||||
*/
|
||||
static function is_url($v){
|
||||
$pattern="#(http|https)://(.*\.)?.*\..*#i";
|
||||
return preg_match($pattern,$v)?true:false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* [是否全部大写]
|
||||
*
|
||||
* @param $str
|
||||
* @return bool
|
||||
* @example
|
||||
* @see
|
||||
* @link
|
||||
*/
|
||||
static function is_upper($str){
|
||||
return preg_match('/^[A-Z]+$/', $str)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* [是否全部小写]
|
||||
*
|
||||
* @param $str
|
||||
* @return bool
|
||||
* @example
|
||||
* @see
|
||||
* @link
|
||||
*/
|
||||
static function is_lower($str){
|
||||
return preg_match('/^[a-z]+$/', $str)?true:false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:验证是微信内还是微信外
|
||||
*
|
||||
* 是否在微信内,是否在微信中
|
||||
*
|
||||
* author:wh
|
||||
* @return bool
|
||||
*/
|
||||
static function is_weixin(){
|
||||
return strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否包含特殊字符
|
||||
* author:wh
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
static function is_special_character(string $str){
|
||||
$res = preg_match ( '/[\Q~!@#$%^&*()+-_=.:?<>\E]/', $str );
|
||||
return $res ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:验证字符串是否全部是中文
|
||||
*
|
||||
* 返回 true表示全部是中文,false表示部分是中文或没有中文
|
||||
*
|
||||
* author:wh
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
static function is_all_chinese(string $str){
|
||||
return preg_match("/^[\x{4e00}-\x{9fa5}]+$/u",$str)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:验证两个浮点数值是否相等
|
||||
*
|
||||
* 例如:
|
||||
* $num1 = 0.1;
|
||||
$num2 = 0.7;
|
||||
|
||||
$res = $num1 + $num2;
|
||||
|
||||
var_dump($res);
|
||||
|
||||
var_dump($res == 0.8);//false 不相等
|
||||
|
||||
var_dump(intval(strval($res)) == intval(strval(0.8)));//true 相等
|
||||
*
|
||||
* author:wh
|
||||
* @param $float_num1
|
||||
* @param $float_num2
|
||||
* @return bool
|
||||
*/
|
||||
static function is_equal_num_val($float_num1, $float_num2){
|
||||
|
||||
return intval(strval($float_num1)) == intval(strval($float_num2));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否包含给定的主域名
|
||||
* author:wh
|
||||
* @param $domain
|
||||
* @param $main_domain
|
||||
* @return bool
|
||||
*/
|
||||
static function is_main_domain($domain,$main_domain){
|
||||
$exp_arr = explode('.',$domain);
|
||||
$str = $exp_arr[count($exp_arr)-2] .'.'. $exp_arr[count($exp_arr)-1];
|
||||
return $str==$main_domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:国内国外IP校验,校验IP来源
|
||||
*
|
||||
* author:wh
|
||||
* @param $ip
|
||||
* @return bool
|
||||
*/
|
||||
static function validate_ip($ip) {
|
||||
$chinaStart = ip2long('1.0.1.0'); // 中国大陆起始IP
|
||||
$chinaEnd = ip2long('254.254.254.254'); // 中国大陆结束IP
|
||||
|
||||
$hongKongStart = ip2long('8.36.0.0'); // 香港起始IP
|
||||
$hongKongEnd = ip2long('8.37.255.255'); // 香港结束IP
|
||||
|
||||
$taiwanStart = ip2long('192.168.0.0'); // 台湾起始IP
|
||||
$taiwanEnd = ip2long('192.168.255.255'); // 台湾结束IP
|
||||
|
||||
$ipLong = ip2long($ip);
|
||||
|
||||
if ($ipLong >= $chinaStart && $ipLong <= $chinaEnd ||
|
||||
$ipLong >= $hongKongStart && $ipLong <= $hongKongEnd ||
|
||||
$ipLong >= $taiwanStart && $ipLong <= $taiwanEnd) {
|
||||
return true; // IP属于国内
|
||||
} else {
|
||||
return false; // IP不属于国内
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否移动端访问访问
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function is_mobile_client()
|
||||
{
|
||||
// 如果有HTTP_X_WAP_PROFILE则一定是移动设备
|
||||
if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
|
||||
if (isset($_SERVER['HTTP_VIA'])) {
|
||||
//找不到为flase,否则为true
|
||||
return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false;
|
||||
}
|
||||
|
||||
//判断手机发送的客户端标志
|
||||
if (isset($_SERVER['HTTP_USER_AGENT'])) {
|
||||
$clientkeywords = [
|
||||
'nokia', 'sony', 'ericsson', 'mot', 'samsung', 'htc', 'sgh', 'lg', 'sharp',
|
||||
'sie-', 'philips', 'panasonic', 'alcatel', 'lenovo', 'iphone', 'ipod', 'blackberry', 'meizu',
|
||||
'android', 'netfront', 'symbian', 'ucweb', 'windowsce', 'palm', 'operamini', 'operamobi',
|
||||
'openwave', 'nexusone', 'cldc', 'midp', 'wap', 'mobile','alipay'
|
||||
];
|
||||
|
||||
// 从HTTP_USER_AGENT中查找手机浏览器的关键字
|
||||
if (preg_match("/(".implode('|', $clientkeywords).")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//协议法,因为有可能不准确,放到最后判断
|
||||
if (isset($_SERVER['HTTP_ACCEPT'])) {
|
||||
// 如果只支持wml并且不支持html那一定是移动设备
|
||||
// 如果支持wml和html但是wml在html之前则是移动设备
|
||||
if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否微信内置浏览器访问
|
||||
* @return bool
|
||||
*/
|
||||
static function is_wx_client()
|
||||
{
|
||||
return strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否支付宝内置浏览器访问
|
||||
* @return bool
|
||||
*/
|
||||
static function is_ali_client()
|
||||
{
|
||||
return strpos($_SERVER['HTTP_USER_AGENT'], 'Alipay') !== false;
|
||||
}
|
||||
}
|
||||
82
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/AlipayLogic.php
vendored
Normal file
82
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/AlipayLogic.php
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/08/24} {10:20}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay;
|
||||
|
||||
|
||||
use app\index\model\AppOrderPayReqRecordModel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 调起支付宝支付
|
||||
*
|
||||
* Class AlipayLogic
|
||||
*
|
||||
* 依赖:
|
||||
* composer require wanghua/general-utility-tools-php dev-master
|
||||
* @deprecated
|
||||
*/
|
||||
class AlipayLogic
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:调起支付
|
||||
* author:wh
|
||||
* @return false|mixed|\SimpleXMLElement|string|\提交表单HTML文本|null
|
||||
* @throws \think\Exception
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
//function pay(string $notify_url,string $return_url=''){
|
||||
|
||||
|
||||
///* *
|
||||
// * 功能:支付宝手机网站支付接口(alipay.trade.wap.pay)接口调试入口页面
|
||||
// * 版本:2.0
|
||||
// * 修改日期:2016-11-01
|
||||
// * 说明:
|
||||
// * 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
|
||||
// 请确保项目文件有可写权限,不然打印不了日志。
|
||||
// */
|
||||
//
|
||||
//header("Content-type: text/html; charset=utf-8");
|
||||
//
|
||||
//
|
||||
//require_once Tools::get_root_path().'library/AlipayTradeWapPay/wappay/service/AlipayTradeService.php';
|
||||
//require_once Tools::get_root_path().'library/AlipayTradeWapPay/wappay/buildermodel/AlipayTradeWapPayContentBuilder.php';
|
||||
////require dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'./../config.php';
|
||||
//$config = config('pay_config.alipay');
|
||||
//if(empty($_POST['WIDout_trade_no']) || trim($_POST['WIDout_trade_no'])=="") return null;
|
||||
////商户订单号,商户网站订单系统中唯一订单号,必填
|
||||
//$out_trade_no = input('WIDout_trade_no');
|
||||
//if(empty($out_trade_no)){
|
||||
// return '参数错误';
|
||||
//}
|
||||
//$order = AppOrderPayReqRecordModel::getOrder($out_trade_no);
|
||||
//if(empty($order)){
|
||||
// return '订单错误';
|
||||
//}
|
||||
////超时时间
|
||||
//$timeout_express="1m";
|
||||
//
|
||||
//$payRequestBuilder = new \AlipayTradeWapPayContentBuilder();
|
||||
//$payRequestBuilder->setBody($order['goods_name']);
|
||||
//$payRequestBuilder->setSubject($order['goods_name']);
|
||||
//$payRequestBuilder->setOutTradeNo($out_trade_no);
|
||||
//$payRequestBuilder->setTotalAmount($order['goods_price']);
|
||||
//$payRequestBuilder->setTimeExpress($timeout_express);
|
||||
//
|
||||
//$payResponse = new \AlipayTradeService($config);
|
||||
|
||||
|
||||
//$result = $payResponse->wapPay($payRequestBuilder,$return_url,$notify_url);
|
||||
//return $result;
|
||||
//}
|
||||
}
|
||||
195
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/pay/AlipayScanPay.php
vendored
Normal file
195
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/pay/AlipayScanPay.php
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/10} {23:15}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay\pay;
|
||||
|
||||
|
||||
use Alipay\EasySDK\Kernel\Config;
|
||||
use Alipay\EasySDK\Kernel\Factory;
|
||||
use app\common\model\TabConf;
|
||||
use app\common\tools\EmailTool;
|
||||
use app\index\logic\AlipayBarcodePayLogic;
|
||||
use app\index\logic\CheckstandLogic;
|
||||
use app\index\model\OrderModel;
|
||||
use app\index\model\PartnerAccountModel;
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 支付宝面对面扫码支付(用户出示付款码)
|
||||
*
|
||||
* 【扫码支付专用】
|
||||
*
|
||||
* 依赖:"alipaysdk/easysdk": "^2.2" || composer require alipaysdk/easysdk
|
||||
*
|
||||
* Class AlipayScanPay
|
||||
* @package wanghua\general_utility_tools_php\alipay\transfer
|
||||
*/
|
||||
class AlipayScanPay
|
||||
{
|
||||
/**
|
||||
* 支付参数配置
|
||||
* @var array
|
||||
*/
|
||||
private array $config = [];
|
||||
|
||||
function __construct($config)
|
||||
{
|
||||
/** 设置支付参数 */
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:面对面扫码支付-(扫用户的付款码)
|
||||
*
|
||||
* 注意:
|
||||
* 免密支付是同步返回支付结果,输入密码支付是异步通知支付结果,
|
||||
* 所以需要处理异步支付结果通知。
|
||||
* @param array $order 订单信息
|
||||
* @param string $auth_code 扫码枪扫描后的授权码
|
||||
* @return array 返回支付结果(一维数组)
|
||||
*/
|
||||
function scanPay($order,$auth_code){
|
||||
if(empty($auth_code)){
|
||||
return Tools::set_res(500,'授权码错误');
|
||||
}
|
||||
try {
|
||||
//1. 设置参数(全局只需设置一次)
|
||||
Factory::setOptions($this->getOptions());
|
||||
//2. 发起API调用(以支付能力下的统一收单交易创建接口为例)
|
||||
$result = Factory::payment()->faceToFace()
|
||||
->optional('scene','bar_code')
|
||||
->pay($order['title'], $order['orderid'], $order['real_amount'], $auth_code);
|
||||
|
||||
if($result->code == 10003){
|
||||
return Tools::set_res(230,'交易进行中(提示用户输入密码)'.$result->msg);
|
||||
}
|
||||
//必须解析json
|
||||
$resp = json_decode($result->httpBody, true);
|
||||
//支付宝面对面扫码支付后续流程
|
||||
return Tools::set_ok('ok',$resp['alipay_trade_pay_response']);//返回支付结果(一维数组)
|
||||
} catch (\Exception $e) {
|
||||
$err_data = [
|
||||
'error'=>'支付宝付款码支付错误'.$e->getMessage(),
|
||||
'error_info'=>$e->getTraceAsString()
|
||||
];
|
||||
Tools::log_to_write_txt($err_data);
|
||||
return Tools::set_fail('错误.'.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:获取支付配置
|
||||
* author:wh
|
||||
* @return Config
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getOptions()
|
||||
{
|
||||
if(empty($this->config)){
|
||||
throw new Exception('支付宝配置错误');
|
||||
}
|
||||
if(empty($this->config['notifyUrl'])){
|
||||
throw new Exception('支付宝配置错误:notifyUrl通知地址字段必须配置(免密支付是同步返回支付结果,输入密码支付是异步通知支付结果)');
|
||||
}
|
||||
$config = $this->config;
|
||||
$options = new Config();
|
||||
$options->protocol = 'https';
|
||||
$options->gatewayHost = 'openapi.alipay.com';
|
||||
$options->signType = $config['sign_type'];
|
||||
|
||||
$options->appId = $config['app_id'];//'<-- 请填写您的AppId,例如:2019022663440152 -->';
|
||||
|
||||
// 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
|
||||
$options->merchantPrivateKey = $config['alipay_app_private_key'];//'<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->';
|
||||
|
||||
$options->alipayCertPath = Tools::get_root_path().$config['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
$options->alipayRootCertPath = Tools::get_root_path().$config['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
$options->merchantCertPath = Tools::get_root_path().$config['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->';
|
||||
|
||||
//注:如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
|
||||
// $options->alipayPublicKey = '<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->';
|
||||
|
||||
//可设置异步通知接收服务地址(可选)
|
||||
$options->notifyUrl = $this->config['notifyUrl'];//request()->domain().'/index/alipay/notify';//"<-- 请填写您的支付类接口异步通知接收服务地址,例如:https://www.test.com/callback -->";
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:支付宝扫码异步通知
|
||||
*
|
||||
* 【通知结果是一维数组】
|
||||
*
|
||||
* {"gmt_create":"2024-06-10 11:53:37","charset":"UTF-8","seller_email":"15023017325",
|
||||
* "subject":"购物消费",
|
||||
* "sign":"oCR3X0ViRrydigLMeOCTrMBNx7O8bSZnEflT0qZYo0gXk2jTI2OVB9mG2UPCkGuSND3wq/pMRFN
|
||||
* ljuz+2r3KMha9a6ArD/ey8w1am3yCKI+FMqUMQSv9TJqfpWdAsc8B45egtr+txBBOA1NMfN41hPnTxM3QzQ82cm
|
||||
* 7VYw6pnYpxJVj/3AsqYxY+wcyMq5+v25eC4TgBo+YJ9pfb3rqaAV91cJBoHRq1Cwh0XEnOzm9zpv7b5cu3r+V0oeW
|
||||
* wTCCi8S1TXW2dfE4H8o63xgASYfJO2fgGIu19YICQdUONkDhu9Tfbf3fFf9SHw3RIw8zrQRqkwAXC32NwfUv4Ru5NqQ==",
|
||||
* "buyer_id":"2088612757425274","invoice_amount":"3258.60","notify_id":"2024061001222115350025271439748729",
|
||||
* "fund_bill_list":"[{\"amount\":\"3258.60\",\"fundChannel\":\"ALIPAYACCOUNT\"}]",
|
||||
* "notify_type":"trade_status_sync","trade_status":"TRADE_SUCCESS","receipt_amount":"3258.60",
|
||||
* "app_id":"2021004136614333","buyer_pay_amount":"3258.60","sign_type":"RSA2",
|
||||
* "seller_id":"2088642975857443","gmt_payment":"2024-06-10 11:53:50",
|
||||
* "notify_time":"2024-06-10 12:07:40","version":"1.0","out_trade_no":"cs25obpv1717991615660",
|
||||
* "total_amount":"3258.60","trade_no":"2024061022001425271426453509","auth_app_id":"2021004136614333",
|
||||
* "buyer_logon_id":"146***@qq.com","point_amount":"0.00"}
|
||||
*
|
||||
* author:wh
|
||||
* param function $fn 传入订单处理逻辑函数 要求返回success、fail
|
||||
* @return string
|
||||
*/
|
||||
function scanPayNotify($fn){
|
||||
Tools::log_to_write_txt([
|
||||
'支付宝异步通知',
|
||||
'input'=>input()
|
||||
]);
|
||||
|
||||
$out_trade_no = input('out_trade_no');
|
||||
if(empty($out_trade_no)){
|
||||
Tools::log_to_write_txt(['error'=>'out_trade_no为空,文件:'.__FILE__.',line:'.__LINE__]);
|
||||
return '';
|
||||
}
|
||||
//$order = Db::table(TabConf::$fa_order)
|
||||
// ->where('orderid',$out_trade_no)
|
||||
// ->find();
|
||||
//if(empty($order)){
|
||||
// Tools::log_to_write_txt(['error'=>'订单不存在,文件:'.__FILE__.',line:'.__LINE__]);
|
||||
// return '';
|
||||
//}
|
||||
//该字段用于判断成功、失败
|
||||
$trade_status = input('trade_status');
|
||||
if(empty($trade_status)){
|
||||
Tools::log_to_write_txt(['error'=>'trade_status为空,文件:'.__FILE__.',line:'.__LINE__]);
|
||||
return '';
|
||||
}
|
||||
if(empty($this->config['seller_id'])){
|
||||
Tools::log_to_write_txt(['error'=>'卖家seller_id为空,文件:'.__FILE__.',line:'.__LINE__]);
|
||||
return '';
|
||||
}
|
||||
|
||||
//判断来源
|
||||
$seller_id = input('seller_id');
|
||||
if($seller_id != $this->config['seller_id']){
|
||||
Tools::log_to_write_txt(['error'=>'支付通知来源错误','seller_id'=>$seller_id,'config'=>$this->config['seller_id']]);
|
||||
return 'fail';
|
||||
}
|
||||
//支付宝面对面扫码支付后续流程
|
||||
$result = input();
|
||||
//异步通知
|
||||
//$res = CheckstandLogic::alipayScanSuccessFlow($result,$order);
|
||||
//if($res['code'] == 200 || $res['code'] == 230){//成功或进行中
|
||||
// return 'success';
|
||||
//}
|
||||
return $fn($result);//要求返回success、fail
|
||||
}
|
||||
}
|
||||
143
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/transfer/AlipayTransfer.php
vendored
Normal file
143
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/transfer/AlipayTransfer.php
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/09/24} {19:43}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay\transfer;
|
||||
|
||||
use Alipay\EasySDK\Kernel\Config;
|
||||
use Alipay\EasySDK\Kernel\Factory;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 支付宝转账(独立且区别于支付,连参数都不能用支付参数)
|
||||
*
|
||||
* 注:换句话说,转账是转账的参数,支付是支付的参数,不能混为一谈(以此备注长记性)。
|
||||
*
|
||||
* 环境要求:PHP7.0+,ThinkPHP5.0+
|
||||
*
|
||||
* 依赖:
|
||||
* composer require alipaysdk/easysdk:^2.0
|
||||
*
|
||||
* composer require wanghua/general-utility-tools-php dev-master
|
||||
*
|
||||
* 重要说明:
|
||||
*
|
||||
* 支付宝开放平台可能有多个应用,可能存在一个默认应用(应用名称:应用2.0签约2020102692466480),转账配置就用此应用的参数,而不是其它应用的配置!
|
||||
*
|
||||
*/
|
||||
class AlipayTransfer
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* desc:转账到支付宝(证书模式)
|
||||
* author:wh
|
||||
* @param array $alipayConfig
|
||||
* @param $transferConfig TransferConfig.php
|
||||
* @return mixed
|
||||
*
|
||||
* 使用案例:
|
||||
*
|
||||
function transfer(array $trans_data){
|
||||
$alipayConfig = \config('pay_config.alipay_transfer');//转账配置
|
||||
|
||||
$trans_config = new TransferConfig();
|
||||
$trans_config->cert_path_alipayCertPublicKey_RSA2 = Tools::get_root_path().$alipayConfig['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
$trans_config->cert_path_alipayRootCert = Tools::get_root_path().$alipayConfig['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
$trans_config->appCertPublicKey = Tools::get_root_path().$alipayConfig['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->'
|
||||
|
||||
|
||||
$order_prefix = 'trs';
|
||||
$order_id = Tools::to_create_order_no($order_prefix);
|
||||
$trans_config->order_id = $order_id;//订单号 必须
|
||||
$trans_config->timestamp = Tools::get_now_date();//请求时间 eg:2020-01-08 10:12:50
|
||||
$trans_config->trans_amount = $trans_data['trans_amount'];//转账金额 必须 且为字符串 最低0.1元 取值范围[0.1,100000000]
|
||||
$trans_config->order_title = $trans_data['order_title'];//订单标题 可选
|
||||
$trans_config->phone = $trans_data['phone'];//支付宝登录手机号 必须
|
||||
$trans_config->name = $trans_data['name'];//支付宝真实姓名 必须
|
||||
$trans_config->remark = $trans_data['remark'];//支付备注 可选
|
||||
|
||||
|
||||
$trans = new AlipayTransfer();
|
||||
Tools::log_to_write_txt(['转账到支付宝,入参:'=>input(), 'trans_config'=>$trans_config]);
|
||||
$pay_res = $trans->alitransfer($alipayConfig, $trans_config);
|
||||
Tools::log_to_write_txt(['转账到支付宝,出参:'=>$pay_res]);
|
||||
//直接返回转账结果,自主验证成功失败的status。code=10000表示操作成功,status=SUCCESS表示转账成功
|
||||
//由于是同步响应,所以不需要对结果验签
|
||||
return $pay_res;
|
||||
}
|
||||
*
|
||||
*/
|
||||
function alitransfer(array $alipayConfig, $transferConfig){
|
||||
//$transferConfig = new TransferConfig();
|
||||
Factory::setOptions($this->getAlipayOptions($alipayConfig, $transferConfig));
|
||||
|
||||
$method = 'alipay.fund.trans.uni.transfer';
|
||||
//公共参数
|
||||
$textParams = [
|
||||
'app_id'=>$alipayConfig['app_id'],
|
||||
'charset'=>'utf-8',
|
||||
'sign_type'=>'RSA2',
|
||||
'timestamp'=>$transferConfig->timestamp,
|
||||
'version'=>'1.0',
|
||||
];
|
||||
|
||||
//请求参数
|
||||
//订单号前缀
|
||||
$biz_content = [
|
||||
'out_biz_no'=>$transferConfig->order_id,//商家支付订单号
|
||||
'trans_amount'=>$transferConfig->trans_amount,
|
||||
'product_code'=>'TRANS_ACCOUNT_NO_PWD',
|
||||
'biz_scene'=>'DIRECT_TRANSFER',
|
||||
'order_title'=>$transferConfig->order_title,
|
||||
'payee_info'=>[
|
||||
'identity'=>$transferConfig->phone,//手机号
|
||||
'identity_type'=>'ALIPAY_LOGON_ID',
|
||||
'name'=>$transferConfig->name,//参与方真实姓名,如果非空,将校验收款支付宝账号姓名一致性。当identity_type=ALIPAY_LOGON_ID时,本字段必填。
|
||||
],
|
||||
'remark'=>$transferConfig->remark,
|
||||
];
|
||||
$pay_res = Factory::util()->generic()->execute($method,$textParams,$biz_content);
|
||||
|
||||
return $pay_res;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:证书模式参数(非证书模式参数需单独获取)
|
||||
* author:wh
|
||||
* @param array $alipayConfig 支付宝转账配置(非支付配置)
|
||||
* @return Config
|
||||
*/
|
||||
protected function getAlipayOptions(array $alipayConfig, $transferConfig)
|
||||
{
|
||||
$options = new Config();
|
||||
$options->protocol = 'https';
|
||||
$options->gatewayHost = 'openapi.alipay.com';
|
||||
$options->signType = 'RSA2';
|
||||
|
||||
//'<-- 请填写您的AppId,例如:2019022663440152 -->'
|
||||
$options->appId = $alipayConfig['app_id'];//'2021002103639985';
|
||||
|
||||
// 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
|
||||
$options->merchantPrivateKey = $alipayConfig['alipay_app_private_key'];//'<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->';
|
||||
|
||||
$options->alipayCertPath = $transferConfig->cert_path_alipayCertPublicKey_RSA2;//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
$options->alipayRootCertPath = $transferConfig->cert_path_alipayRootCert;//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
$options->merchantCertPath = $transferConfig->appCertPublicKey;//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->';
|
||||
|
||||
//注:如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
|
||||
// $options->alipayPublicKey = $alipayConfig['alipay_public_key'];//'<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->';
|
||||
|
||||
//可设置异步通知接收服务地址(可选)
|
||||
$options->notifyUrl = $transferConfig->notifyUrl;//"<-- 请填写您的支付类接口异步通知接收服务地址,例如:https://www.test.com/callback -->";
|
||||
|
||||
//可设置AES密钥,调用AES加解密相关接口时需要(可选)
|
||||
//$options->encryptKey = "<-- 请填写您的AES密钥,例如:aa4BtZ4tspm2wnXLb1ThQA== -->";
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
63
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/transfer/TransferConfig.php
vendored
Normal file
63
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/transfer/TransferConfig.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/09/24} {20:07}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay\transfer;
|
||||
|
||||
|
||||
/**
|
||||
* 调用转账之前请配置此参数
|
||||
*
|
||||
* 配置示例:
|
||||
*
|
||||
$alipayConfig = \config('pay_config.alipay_transfer');//转账配置
|
||||
|
||||
$trans_config = new TransferConfig();
|
||||
$trans_config->cert_path_alipayCertPublicKey_RSA2 = Tools::get_root_path().$alipayConfig['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
$trans_config->cert_path_alipayRootCert = Tools::get_root_path().$alipayConfig['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
$trans_config->appCertPublicKey = Tools::get_root_path().$alipayConfig['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->'
|
||||
|
||||
|
||||
$order_prefix = 'trs';
|
||||
$order_id = Tools::to_create_order_no($order_prefix);
|
||||
$trans_config->order_id = $order_id;//订单号 必须
|
||||
$trans_config->timestamp = Tools::get_now_date();//请求时间 eg:2020-01-08 10:12:50
|
||||
$trans_config->trans_amount = '0.21';//转账金额 必须 且为字符串 最低0.1元 取值范围[0.1,100000000]
|
||||
$trans_config->order_title = '代理提现';//订单标题 可选
|
||||
$trans_config->phone = '18290416033';//支付宝登录手机号 必须
|
||||
$trans_config->name = '王华';//支付宝真实姓名 必须
|
||||
$trans_config->remark = '代理提现到支付宝';//支付备注 可选
|
||||
|
||||
$trans = new AlipayTransfer();
|
||||
$pay_res = $trans->alitransfer($alipayConfig, $trans_config);
|
||||
|
||||
dump($pay_res);
|
||||
*
|
||||
*/
|
||||
class TransferConfig
|
||||
{
|
||||
//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
public $cert_path_alipayCertPublicKey_RSA2 = '';//必须
|
||||
//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
public $cert_path_alipayRootCert = '';//必须
|
||||
//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->'
|
||||
public $appCertPublicKey = '';//必须
|
||||
|
||||
public $notifyUrl = '';//接收异步通知(可选)
|
||||
|
||||
|
||||
//业务参数
|
||||
public $order_id = '';//订单号 必须
|
||||
public $timestamp = '';//请求时间 必须 eg:2020-01-08 10:12:50
|
||||
public $trans_amount = '';//转账金额 必须 且为字符串 最低0.1元 取值范围[0.1,100000000]
|
||||
public $order_title = '';//订单标题 可选
|
||||
public $phone = '';//支付宝登录手机号 必须
|
||||
public $name = '';//支付宝真实姓名 必须
|
||||
public $remark = '';//支付备注 可选
|
||||
|
||||
|
||||
}
|
||||
425
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/Api.php
vendored
Normal file
425
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/Api.php
vendored
Normal file
@@ -0,0 +1,425 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {11:21}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\mysql\lib\Table;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class Api extends BaseLibApi
|
||||
{
|
||||
private $apidir = '';
|
||||
private $namespace = 'app\api\controller';
|
||||
|
||||
private $table_obj = null;
|
||||
|
||||
//一维数组
|
||||
private $functions_arr = [];//要创建的初始方法
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
//默认api目录
|
||||
$this->apidir = Tools::get_root_path().'application/api/controller/';
|
||||
if(!$this->table_obj)
|
||||
$this->table_obj = new Table();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:api目录
|
||||
* author:wh
|
||||
* @param string $dir api创建目录,格式必须按照例子填写 eg: application/api/controller/
|
||||
*/
|
||||
function setapidir(string $dir){
|
||||
$this->apidir = $dir;
|
||||
$nsp = str_replace('application','app',substr($dir,0,strlen($dir)-2));
|
||||
$this->namespace = str_replace('/','\\',$nsp);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:替换表前缀
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @return false|string
|
||||
*/
|
||||
function replaceTablePrefix($tablename){
|
||||
$prefix = config('database.prefix');
|
||||
if($prefix){
|
||||
return substr($tablename,strlen($prefix));
|
||||
}
|
||||
$tmp_prefix = 't_';
|
||||
if(false !== strpos($tablename,$tmp_prefix)){
|
||||
return substr($tablename,strlen($tmp_prefix));
|
||||
}
|
||||
return $tablename;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置方法名称
|
||||
*
|
||||
* author:wh
|
||||
* @param array $functions_arr
|
||||
*/
|
||||
function setApiFunctionsName(array $functions_arr){
|
||||
$this->functions_arr = array_merge($functions_arr,$this->functions_arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:动态创建方法
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
private function syncCreateFunction(array $func_name_arr){
|
||||
$code = '';
|
||||
foreach ($func_name_arr as $func_name=>$func_remark){ //接口方法公共代码模块
|
||||
$commonFunctionCodeModule = $this->commonFunctionCodeModule($func_remark);
|
||||
$code .= <<<EOF
|
||||
|
||||
/**
|
||||
* desc:{$func_remark}
|
||||
*
|
||||
* author:
|
||||
*/
|
||||
function {$func_name}(){
|
||||
{$commonFunctionCodeModule}
|
||||
}
|
||||
EOF;
|
||||
}
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:创建查询接口的代码体
|
||||
*
|
||||
* 本接口只针对简单查询逻辑
|
||||
*
|
||||
* and
|
||||
* like%,%like%,
|
||||
* >, <, >=, <=, !=
|
||||
* between
|
||||
* in
|
||||
*
|
||||
* author:wh
|
||||
* @param array $select_in_params eg:
|
||||
* [
|
||||
* 'gameid'=>['and'],
|
||||
* 'nickname'=>['like%'],
|
||||
* 'reg_time'=>['between'],//时间区间查询
|
||||
* 'audit_time'=>['2015-01-3','eq'],//时间区间查询
|
||||
* ]
|
||||
*
|
||||
*/
|
||||
function setQueryCodeBody(array $select_in_params){
|
||||
$code = '';
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:写入查询接口的代码体
|
||||
*
|
||||
* author:wh
|
||||
* @param array $insert_params
|
||||
* @return string
|
||||
*/
|
||||
function setInsertCodeBody(array $insert_params){
|
||||
$code = '';
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:快速构建api代码
|
||||
*
|
||||
* 本方法不验证接口名称是否重复
|
||||
*
|
||||
* author:wh
|
||||
* @param string $tablename 数据表名称
|
||||
* @param array $func_name_arr 方法名称数组 eg:['getData'=>'获取数据','function_aaa'=>'function_注释aaa']
|
||||
*/
|
||||
function buildApi(string $tablename, array $func_name_arr){
|
||||
//deal table name
|
||||
$tablename = $this->replaceTablePrefix($tablename);
|
||||
|
||||
//基础 start
|
||||
//create base controller
|
||||
$this->buildBaseApiPublicController();//开放控制器
|
||||
$this->buildBaseApiAuthController();//权限控制器
|
||||
$this->errController();//错误控制器
|
||||
//基础 end
|
||||
|
||||
//接口类名
|
||||
$classname = ucfirst(Tools::convertUnderLine($tablename));
|
||||
//接口注释
|
||||
$comment = $this->table_obj->getTableComment($tablename);
|
||||
|
||||
//批量构建方法代码
|
||||
$build_functions_code = $this->syncCreateFunction($func_name_arr);
|
||||
|
||||
//PHP文件名,不含物理路径
|
||||
$file_name = $classname.$this->ext();
|
||||
|
||||
//PHP文件路径和文件名
|
||||
$php_file = $this->apidir.$file_name;
|
||||
|
||||
if(file_exists($php_file)){
|
||||
//追加代码
|
||||
//读取并删除最后的“}”
|
||||
$php_code_str = file_get_contents($php_file);
|
||||
$sub_php_code_str = mb_substr($php_code_str,0,mb_strlen($php_code_str)-2);
|
||||
//追加新的代码
|
||||
$sub_php_code_str .= $build_functions_code ."\n }";
|
||||
//清空代码
|
||||
file_put_contents($php_file,'');
|
||||
//追加
|
||||
$this->createFileExists($php_file,$sub_php_code_str);
|
||||
}else{
|
||||
//创建代码文件
|
||||
$use_tpl = $this->useTpl();
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
{$use_tpl}
|
||||
|
||||
/**
|
||||
* {$comment}
|
||||
* Class {$classname}
|
||||
* @package {$this->namespace}
|
||||
*/
|
||||
class {$classname} extends BaseApiPublicController
|
||||
{
|
||||
|
||||
|
||||
|
||||
{$build_functions_code}
|
||||
|
||||
}
|
||||
EOF;
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:公共方法模块
|
||||
*
|
||||
* author:wh
|
||||
* @param $comment
|
||||
* @return string
|
||||
*/
|
||||
private function commonFunctionCodeModule($comment){
|
||||
$php = <<<EOF
|
||||
try {
|
||||
Tools::log_to_write_txt(['title'=>'{$comment},__IN:','INPUT'=>input()]);
|
||||
//region 校验区 start
|
||||
|
||||
//endregion 校验区 end
|
||||
|
||||
|
||||
|
||||
|
||||
//region 业务逻辑区 start
|
||||
|
||||
//endregion 业务逻辑区 end
|
||||
|
||||
|
||||
|
||||
|
||||
//响应结果处理
|
||||
Tools::log_to_write_txt(['title'=>'{$comment},__OUT:','OUTPUT'=>[]]);
|
||||
return json(Tools::set_res(200,'ok'));
|
||||
}catch (\Exception \$e){
|
||||
Tools::log_to_write_txt([
|
||||
'error'=>'{$comment},API异常。'.\$e->getMessage(),
|
||||
'入参'=>input(),
|
||||
'error_info'=>\$e->getTraceAsString()
|
||||
]);
|
||||
return json(Tools::set_res(500,'系统繁忙'));
|
||||
}
|
||||
EOF;
|
||||
|
||||
return $php;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:api基础开放控制器
|
||||
*
|
||||
* 如果存在则不创建
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
private function buildBaseApiPublicController(){
|
||||
$file_name = 'BaseApiPublicController';
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
|
||||
use think\Controller;
|
||||
|
||||
|
||||
/**
|
||||
* desc:api基础开放架构
|
||||
*
|
||||
* 所有开放接口继承此父类
|
||||
*
|
||||
* author:
|
||||
*/
|
||||
class {$file_name} extends Controller
|
||||
{
|
||||
|
||||
}
|
||||
EOF;
|
||||
|
||||
$php_file = $this->apidir.$file_name.$this->ext();
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:api基础权限控制器
|
||||
*
|
||||
* 如果存在则不创建
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
private function buildBaseApiAuthController(){
|
||||
$file_name = 'BaseApiAuthController';
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
|
||||
use think\Controller;
|
||||
|
||||
|
||||
/**
|
||||
* desc:api基础权限架构
|
||||
*
|
||||
* 所有权限接口继承此父类
|
||||
*
|
||||
* author:
|
||||
*/
|
||||
class {$file_name} extends Controller
|
||||
{
|
||||
|
||||
}
|
||||
EOF;
|
||||
|
||||
$php_file = $this->apidir.$file_name.$this->ext();
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:api底层基础控制器架构
|
||||
*
|
||||
* [按需创建][可单独调用]
|
||||
*
|
||||
* 如果存在则不创建
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function buildBaseApiController(){
|
||||
$file_name = 'BaseApiController';
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
|
||||
use think\Controller;
|
||||
|
||||
|
||||
/**
|
||||
* desc:api底层基础控制器架构
|
||||
*
|
||||
* author:
|
||||
*/
|
||||
class {$file_name} extends Controller
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
EOF;
|
||||
|
||||
$php_file = $this->apidir.$file_name.$this->ext();
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:use模块
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
private function useTpl(){
|
||||
$php = <<<EOF
|
||||
use wanghua\general_utility_tools_php\\tool\Tools;
|
||||
EOF;
|
||||
return $php;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:错误控制器
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function errController(){
|
||||
$file_name = 'Err';
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\\framework\\base\PublicController;
|
||||
use wanghua\general_utility_tools_php\\tool\Tools;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 错误(异常)中转架构
|
||||
*
|
||||
* Class Err
|
||||
* @package app\index\controller
|
||||
*/
|
||||
class {$file_name} extends BaseApiPublicController
|
||||
{
|
||||
/**
|
||||
* desc:校验失败中转
|
||||
*
|
||||
* 场景:内网端口验证未通过时跳转;
|
||||
*
|
||||
* author:wh
|
||||
* @return \\think\\response\\Json
|
||||
*/
|
||||
function checkfailed(){
|
||||
|
||||
return json(Tools::set_res(500,'Permission denied',input()));
|
||||
}
|
||||
}
|
||||
EOF;
|
||||
|
||||
$php_file = $this->apidir.$file_name.$this->ext();
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
}
|
||||
264
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/ApiDocument.php
vendored
Normal file
264
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/ApiDocument.php
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/5/15} {21:40}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* desc:接口文档构建器
|
||||
*
|
||||
* 使用步骤:
|
||||
* (new ApiDocument())->buildDoc();
|
||||
* Class ApiDocument
|
||||
*/
|
||||
class ApiDocument
|
||||
{
|
||||
private $api_cache_arr = [];//缓存所有接口
|
||||
public $api_domain = 'http://127.0.0.1:8080/';//接口域名/ip
|
||||
/**
|
||||
* @var string 接口控制器命名空间
|
||||
*/
|
||||
public $namespace = 'app\\api\\controller';
|
||||
/**
|
||||
* @var string 接口控制器基类,精确到类名,如:app\\common\\controller\\Api
|
||||
* 注意:如果同级目录存在多个基类,则设置直接基类,如果同级目录没有基类,则设置底层基类
|
||||
*/
|
||||
public $extends_base_class = '';
|
||||
//控制器目录物理路径
|
||||
public $controllerDirectory = '';
|
||||
/**
|
||||
* @var string 接口文档保存路径
|
||||
*/
|
||||
public $api_docs_save_dir = 'public/api_docs/';
|
||||
//设置过滤类
|
||||
private $filterClassArr = [];
|
||||
//设置过滤方法
|
||||
private $filterFunctionArr = [];
|
||||
|
||||
public function __construct($api_domain='',$controllerDirectory='')
|
||||
{
|
||||
//默认,如果是tp6,那application就要改为app了,自行传参吧
|
||||
$this->controllerDirectory = Tools::get_root_path().'application/api/controller';
|
||||
if($api_domain){
|
||||
$this->api_domain = $api_domain;
|
||||
}
|
||||
if($controllerDirectory){
|
||||
$this->controllerDirectory = $controllerDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置过滤类(类名)
|
||||
* 过滤场景:
|
||||
* 1、基类
|
||||
* 2、测试类
|
||||
* 3、定时任务类
|
||||
* 4、其它非必要类
|
||||
* author:wh
|
||||
* @param array $filterClassArr
|
||||
*/
|
||||
function setFilterClass(array $filterClassArr=[]){
|
||||
$this->filterClassArr = $filterClassArr;
|
||||
}
|
||||
function setFilterFunction(array $filterArr=[]){
|
||||
$this->filterFunctionArr = $filterArr;
|
||||
}
|
||||
/**
|
||||
* desc:构建接口文档,支持同步到在线文档
|
||||
* author:wh
|
||||
*/
|
||||
function buildDoc(){
|
||||
if(empty($this->extends_base_class)){
|
||||
throw new Exception('请设置接口控制器基类,精确到类名,如:app\\common\\controller\\Api');
|
||||
}
|
||||
$out_path = Tools::get_root_path().$this->api_docs_save_dir;
|
||||
if(!file_exists($out_path)){
|
||||
mkdir($out_path,0777,true);
|
||||
}
|
||||
$outputFile = $out_path.'api_list.md';
|
||||
$controllerClasses = [];
|
||||
|
||||
// 搜索控制器目录下的所有PHP文件
|
||||
foreach (glob($this->controllerDirectory . '/*.php') as $filename) {
|
||||
// 获取文件中的类名
|
||||
$class = basename($filename, '.php');
|
||||
if(in_array($class,$this->filterClassArr)){
|
||||
continue;
|
||||
}
|
||||
// 构建完整的命名空间类名
|
||||
$fullClassName = $this->namespace . '\\' . $class;
|
||||
foreach (explode(',',$this->extends_base_class) as $base_class){
|
||||
// 检查类是否有效并且是think\Controller的子类
|
||||
if (class_exists($fullClassName) && is_subclass_of($fullClassName, $base_class)) {
|
||||
$controllerClasses[] = $fullClassName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建Markdown文件
|
||||
$file = fopen($outputFile, 'w') or die('无法创建文件');
|
||||
|
||||
$head_text = <<<EOF
|
||||
# API 文档
|
||||
## 接口列表
|
||||
###### (ctrl+f 搜索)(如果更改了路由,请根据路由规则定位)
|
||||
##### 请求域名:{$this->api_domain}
|
||||
##### 请求方式:POST(默认)
|
||||
|
||||
EOF;
|
||||
// 写入Markdown文件头部
|
||||
fwrite($file, $head_text);
|
||||
|
||||
foreach ($controllerClasses as $controllerClass) {
|
||||
$reflector = new \ReflectionClass($controllerClass);
|
||||
// 遍历控制器中的公共方法
|
||||
$methods = $reflector->getMethods(\ReflectionMethod::IS_PUBLIC);
|
||||
foreach ($methods as $method) {
|
||||
//过滤方法
|
||||
if(in_array($method->name, $this->filterFunctionArr)){
|
||||
continue;
|
||||
}
|
||||
$exp_class = explode('\\',$controllerClass);
|
||||
//过滤类
|
||||
if(in_array($exp_class[count($exp_class)-1],$this->filterClassArr)){
|
||||
continue;
|
||||
}
|
||||
$comments = $method->getDocComment();
|
||||
if ($comments) {
|
||||
$this->processMethodComment($comments, $controllerClass, $method->name, $outputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose($file);
|
||||
|
||||
//缓存所有接口
|
||||
cache('api_doc_cache_arr',$this->api_cache_arr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:解析方法注释并写入Markdown文件
|
||||
* author:wh
|
||||
* @param $comments
|
||||
* @param $className
|
||||
* @param $methodName
|
||||
* @param $savepath
|
||||
*/
|
||||
private function processMethodComment($comments, $className, $methodName, $savepath) {
|
||||
if($methodName == '__construct'){
|
||||
return '';
|
||||
}
|
||||
$api_url = "/api/{$className}/{$methodName}";
|
||||
$js_api_func_name = "api_{$className}_{$methodName}";
|
||||
$str = <<<EOF
|
||||
|
||||
***
|
||||
```
|
||||
|
||||
EOF;
|
||||
|
||||
$comments_str = mb_substr($comments,0,-2);
|
||||
$class_arr = explode('\\',$className);
|
||||
$className = $class_arr[count($class_arr)-1];
|
||||
$className = $this->camelCaseToUnderscore($className);
|
||||
|
||||
|
||||
$api_name = "api/{$className}/{$methodName}";
|
||||
$doc_txt = <<<EOF
|
||||
* $api_name
|
||||
*/
|
||||
```
|
||||
EOF;
|
||||
$doc_txt= $str.$comments_str.$doc_txt." \r\n";
|
||||
$this->api_cache_arr[] = ['api_name'=>$api_name,'doc_txt'=>$doc_txt];
|
||||
file_put_contents($savepath,$doc_txt, FILE_APPEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:驼峰转下划线
|
||||
* author:wh
|
||||
* @param $string
|
||||
* @return string
|
||||
*/
|
||||
private function camelCaseToUnderscore($string) {
|
||||
$str = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $string));
|
||||
return strpos($str,'_')===0?substr($str,1):$str;
|
||||
}
|
||||
|
||||
function buildApiDocHtml(){
|
||||
$api_doc_cache_arr = cache('api_doc_cache_arr');
|
||||
$htm_str = "";
|
||||
$script_str = "";
|
||||
foreach ($api_doc_cache_arr as $item){
|
||||
$api_name = $item['api_name'];
|
||||
$doc_txt = $item['doc_txt'];
|
||||
|
||||
$function_name = str_replace('/','_',$api_name);
|
||||
$htm_str .= <<<EOF
|
||||
<div id="{$function_name}">
|
||||
<div class="markdown_content">{$doc_txt}</div>
|
||||
<div>
|
||||
按需填写其它接口参数:
|
||||
<textarea name="" id="{$function_name}_textarea" cols="100" rows="3">/{$api_name}</textarea>
|
||||
<a href='JavaScript:;' onclick="DocObject.{$function_name}()">测试</a>
|
||||
</div>
|
||||
<div class="{$function_name}_response_result"></div>
|
||||
|
||||
</div>
|
||||
EOF;
|
||||
$script_str.=<<<EOF
|
||||
{$function_name}(){
|
||||
let url = $('#{$function_name}_textarea').val();
|
||||
$.post(url,{},function(res) {
|
||||
$('.{$function_name}_response_result').html(JSON.stringify(res, null, "\\t"));
|
||||
$('.{$function_name}_response_result').attr('style','color:green');
|
||||
},'json');
|
||||
},
|
||||
EOF;
|
||||
|
||||
|
||||
}
|
||||
$html = <<<EOF
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>接口文档</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
{$htm_str}
|
||||
</div>
|
||||
</body>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script src="/static/common/js/marked.min.js"></script>
|
||||
<script>
|
||||
|
||||
$(function() {
|
||||
//加载markdown
|
||||
DocObject.markdown_content();
|
||||
});
|
||||
|
||||
let DocObject = {
|
||||
markdown_content(){
|
||||
$('.markdown_content').each(function(k,ele) {
|
||||
$(ele).html(marked.parse($(ele).html()));
|
||||
});
|
||||
},
|
||||
$script_str
|
||||
}
|
||||
|
||||
</script>
|
||||
</html>
|
||||
EOF;
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
230
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/BaseApi.php
vendored
Normal file
230
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/BaseApi.php
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/11} {16:14}
|
||||
*/
|
||||
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
use wanghua\general_utility_tools_php\exception\api\ApiException;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* @deprecated 废弃
|
||||
* desc:api交互
|
||||
*
|
||||
* author:wh
|
||||
* Class BaseApi
|
||||
* @package app\apidata
|
||||
*/
|
||||
class BaseApi
|
||||
{
|
||||
protected $post_url = '';
|
||||
private $prefix = 'api_';
|
||||
protected $log_file_name = 'log';
|
||||
protected $__sit__ = '';
|
||||
function __construct(string $url)
|
||||
{
|
||||
$this->post_url = $url;
|
||||
if(empty($this->post_url)) {
|
||||
Tools::log_to_write_txt(['error'=>'API OPERATE: '.ApiException::EMPTY_URL_ERROR], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::EMPTY_URL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置api请求日志文件名称
|
||||
*
|
||||
* 日志保存在runtime中
|
||||
*
|
||||
* author:wh
|
||||
* @param string $log_file_name
|
||||
*/
|
||||
function setLogFileName(string $log_file_name=''){
|
||||
if($log_file_name)$this->log_file_name = $log_file_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc 获取记录日志的文件名
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function getLogFileName(){
|
||||
return $this->prefix.$this->log_file_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置调用位置
|
||||
* author:wh
|
||||
* @param $__file__
|
||||
* @param $__line__
|
||||
*/
|
||||
function setFileDir($__file__, $__line__){
|
||||
$this->__sit__ = $__file__.' > '.$__line__;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:错误位置
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function getErrorSit(){
|
||||
return $this->__sit__;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
*
|
||||
* author:wh
|
||||
* @param array $params
|
||||
*/
|
||||
private function mergeAuthParams(array &$params){
|
||||
$params['nonce'] = Tools::rand_str(10);
|
||||
$params['timestamp'] = time();
|
||||
$token = config('service_framework_config.sign_token');
|
||||
$params['sign'] = Tools::signature($params, $token);
|
||||
}
|
||||
/**
|
||||
* desc:执行post请求, 带权限参数
|
||||
*
|
||||
* 同框架、内部系统推荐
|
||||
*
|
||||
* 返回结果由code 错误码和msg 错误信息组成
|
||||
*
|
||||
* author:wh
|
||||
* @param $param 以表单格式提交数据
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws ApiException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function apiPost($param){
|
||||
$this->mergeAuthParams($param);
|
||||
|
||||
Tools::log_to_write_txt(['API OPERATE, IN',$this->post_url,$param], $this->getLogFileName());
|
||||
$res = Tools::curl_post($this->post_url, $param);
|
||||
Tools::log_to_write_txt(['API OPERATE, OUT',$this->post_url, $res], $this->getLogFileName());
|
||||
|
||||
if(empty($res['data'])) return $res;
|
||||
|
||||
$data = json_decode($res['data'], true);
|
||||
if(empty($data['code'])) {
|
||||
Tools::log_to_write_txt([
|
||||
'error: api操作,错误',
|
||||
'post_url'=>$this->post_url,
|
||||
'error_info'=>ApiException::API_RESPONSE_FORMAT_ERROR,
|
||||
'error_sit'=>$this->getErrorSit(),
|
||||
'result'=>$res,
|
||||
], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::API_RESPONSE_FORMAT_ERROR);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* desc:执行post请求
|
||||
*
|
||||
* 返回结果由code 错误码和msg 错误信息组成
|
||||
*
|
||||
* author:wh
|
||||
* @param $param 以json格式提交数据
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws ApiException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function do($param){
|
||||
|
||||
Tools::log_to_write_txt(['API OPERATE, IN',$this->post_url,$param], $this->getLogFileName());
|
||||
$res = Tools::curl_post($this->post_url, json_encode($param));
|
||||
Tools::log_to_write_txt(['API OPERATE, OUT',$this->post_url, $res], $this->getLogFileName());
|
||||
|
||||
if(empty($res['data'])) return $res;
|
||||
|
||||
$data = json_decode($res['data'], true);
|
||||
if(empty($data['code'])) {
|
||||
Tools::log_to_write_txt([
|
||||
'error: api操作,错误',
|
||||
'post_url'=>$this->post_url,
|
||||
'error_info'=>ApiException::API_RESPONSE_FORMAT_ERROR,
|
||||
'error_sit'=>$this->getErrorSit(),
|
||||
'result'=>$res,
|
||||
], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::API_RESPONSE_FORMAT_ERROR.$this->post_url);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* desc:执行请求
|
||||
*
|
||||
* do 方法的改版,返回结果由state 错误码和err 错误信息组成
|
||||
*
|
||||
* author:wh
|
||||
* @param $param 以json格式提交数据
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws ApiException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function apiDo($param){
|
||||
|
||||
Tools::log_to_write_txt(['API OPERATE, IN',$this->post_url,$param], $this->getLogFileName());
|
||||
$res = Tools::curl_post($this->post_url, json_encode($param));
|
||||
Tools::log_to_write_txt(['API OPERATE, OUT',$this->post_url, $res], $this->getLogFileName());
|
||||
if(empty($res['data'])) return $res;
|
||||
|
||||
|
||||
$data = json_decode($res['data'], true);
|
||||
|
||||
if(is_null($data['state'])) {
|
||||
Tools::log_to_write_txt([
|
||||
'error: api操作,错误',
|
||||
'post_url'=>$this->post_url,
|
||||
'error_info'=>ApiException::API_RESPONSE_FORMAT_ERROR,
|
||||
'error_sit'=>$this->getErrorSit(),
|
||||
'result'=>$res,
|
||||
], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::API_RESPONSE_FORMAT_ERROR);
|
||||
}
|
||||
$data['code'] = isset($data['state'])&&$data['state']==0?200:$data['state'];
|
||||
$data['msg'] = isset($data['err'])?$data['err']:'api接口错误';
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* desc:执行请求
|
||||
*
|
||||
* 同框架、内部系统推荐
|
||||
*
|
||||
* author:wh
|
||||
* @param $param 以表单方式提交数据
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws ApiException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function doPost($param){
|
||||
|
||||
Tools::log_to_write_txt(['API OPERATE, IN',$this->post_url,$param], $this->getLogFileName());
|
||||
$res = Tools::curl_post($this->post_url, $param);
|
||||
Tools::log_to_write_txt(['API OPERATE, OUT',$this->post_url, $res], $this->getLogFileName());
|
||||
|
||||
if(empty($res['data'])) return $res;
|
||||
|
||||
$data = json_decode($res['data'], true);
|
||||
if(empty($data['code'])) {
|
||||
Tools::log_to_write_txt([
|
||||
'error: api操作,错误',
|
||||
'post_url'=>$this->post_url,
|
||||
'error_info'=>ApiException::API_RESPONSE_FORMAT_ERROR,
|
||||
'error_sit'=>$this->getErrorSit(),
|
||||
'result'=>$res,
|
||||
], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::API_RESPONSE_FORMAT_ERROR);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
54
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/BaseLibApi.php
vendored
Normal file
54
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/BaseLibApi.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {15:01}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
|
||||
class BaseLibApi
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:创建目录
|
||||
*
|
||||
* author:wh
|
||||
* @param $apidir
|
||||
*/
|
||||
function createDir($apidir){
|
||||
if(!is_dir($apidir)){
|
||||
mkdir($apidir,0777,true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:文件存在不写入
|
||||
*
|
||||
* author:wh
|
||||
* @param $php_file
|
||||
* @param $php
|
||||
*/
|
||||
function createFile($php_file,$php){
|
||||
if(!file_exists($php_file)){
|
||||
file_put_contents($php_file,$php);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:追加文本
|
||||
*
|
||||
* author:wh
|
||||
* @param $php_file
|
||||
* @param $php
|
||||
*/
|
||||
function createFileExists($php_file,$php){
|
||||
file_put_contents($php_file,$php,FILE_APPEND);
|
||||
}
|
||||
|
||||
function ext(){
|
||||
return '.php';
|
||||
}
|
||||
}
|
||||
193
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/BaseUserLogic.php
vendored
Normal file
193
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/BaseUserLogic.php
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/2/26} {10:54}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class BaseUserLogic
|
||||
{
|
||||
public $user_table = 'fa_users';
|
||||
|
||||
/**
|
||||
* desc:【通用】用户登录逻辑
|
||||
*
|
||||
* 请求端加密,服务端校验
|
||||
*
|
||||
* 签名规则
|
||||
* 请求参数:
|
||||
username //用户名
|
||||
password //密码 md5(md5('a123456')) d477887b0636e5d87f79cc25c99d7dc9
|
||||
timestamp //请求时间戳 2020-01-01 12:34:07
|
||||
noncestr //随机字符串8位
|
||||
sign //签名串,参考全站签名规则
|
||||
|
||||
other_params //其它接口的其它参数
|
||||
* 全站sign规则:
|
||||
1. 对关联数组按照键升序排序
|
||||
2. 拼接成字符串 keyvalkey2val2key3val3
|
||||
3. 再2次md5生成32位小写串
|
||||
4. 与请求参数一起发送到服务器
|
||||
*
|
||||
* author:wh
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
function tologin(){
|
||||
if(!request()->isPost()){
|
||||
return Tools::set_fail('错误');
|
||||
}
|
||||
Tools::log_to_write_txt(['登录入参:'=>input()]);
|
||||
$input_data = input();
|
||||
if(empty($input_data)){
|
||||
return Tools::set_fail('请求参数错误');
|
||||
}
|
||||
if(empty($input_data['username'])){
|
||||
return Tools::set_fail('用户名或密码错误');
|
||||
}
|
||||
if(empty($input_data['password'])){
|
||||
return Tools::set_fail('用户名或密码错误.');
|
||||
}
|
||||
// start 这段代码可放在请求合法性里面校验 Tools::signature
|
||||
if(empty($input_data['timestamp'])){
|
||||
return Tools::set_fail('请求错误..');
|
||||
}
|
||||
if(empty($input_data['noncestr'])){
|
||||
return Tools::set_fail('请求错误...');
|
||||
}
|
||||
if(empty($input_data['sign'])){
|
||||
return Tools::set_fail('请求错误。');
|
||||
}
|
||||
|
||||
$sign = $input_data['sign'];//md5后的字符串
|
||||
unset($input_data['sign']);
|
||||
//验签
|
||||
$signstr = Tools::signature($input_data);
|
||||
//Tools::log_to_write_txt([
|
||||
// '签名日志:',
|
||||
// $signstr,
|
||||
// $sign,
|
||||
// 'input'=>input(),
|
||||
//]);
|
||||
if($signstr != $sign){
|
||||
return Tools::set_fail('非法请求');
|
||||
}
|
||||
|
||||
//请求时间超过有效期 N分钟内有效
|
||||
if(time()-5*60 > strtotime($input_data['timestamp'])){
|
||||
return Tools::set_fail('请求失效');
|
||||
}
|
||||
// end 这段代码可放在请求合法性里面校验 Tools::signature
|
||||
|
||||
$username = $input_data['username'];
|
||||
$user = Db::table($this->user_table)->where('username',$username)->find();
|
||||
if(empty($user)){
|
||||
return Tools::set_fail('账号密码错误!');
|
||||
}
|
||||
//校验密码
|
||||
if($user['password'] != $input_data['password']){
|
||||
return Tools::set_fail('账号密码错误!!');
|
||||
}
|
||||
|
||||
$expires = time()+12*60*60;
|
||||
|
||||
|
||||
|
||||
//返回票据
|
||||
$ticketstr = md5($user['username'].$user['expires']);
|
||||
//保存ticket
|
||||
$user[$ticketstr] = $expires;//N秒后过期
|
||||
//修改有效期
|
||||
Db::table($this->user_table)
|
||||
->data([
|
||||
'ticket'=>$ticketstr,
|
||||
'expires'=>7*86400+time(),//7天
|
||||
])
|
||||
->where('username',$username)
|
||||
->update();
|
||||
session('api_user',$user);//备用(跨环境情况下session不生效)
|
||||
|
||||
return Tools::set_ok('登录成功',['ticket'=>$ticketstr]);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:验证登录,根据提交的ticket来校验是否登录,适用于跨环境登录
|
||||
*
|
||||
* author:wh
|
||||
* @return bool
|
||||
*/
|
||||
function isLogin(){
|
||||
|
||||
$ticket = input('ticket');
|
||||
if(empty($ticket)){
|
||||
Tools::log_to_write_txt(['title'=>'业务ticket字段不存在','input'=>input()]);
|
||||
return false;
|
||||
}
|
||||
$user = Db::table(TabConf::$fa_users)
|
||||
->where('ticket',$ticket)
|
||||
->find();
|
||||
if(empty($user)){
|
||||
Tools::log_to_write_txt(['title'=>'用户未登录']);
|
||||
return false;
|
||||
}
|
||||
//无效票据
|
||||
//if(empty($user[$ticket])){
|
||||
// Tools::log_to_write_txt(['title'=>'未获取到用户ticket',$ticket=>$user]);
|
||||
//
|
||||
// return false;
|
||||
//}
|
||||
//已过期
|
||||
if(time() > $user['expires']){
|
||||
Tools::log_to_write_txt(['title'=>'ticket已过期',$ticket=>$user]);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* desc:用户注册
|
||||
*
|
||||
* 此模块通用性不高,按需使用
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function reg($input_data){
|
||||
try {
|
||||
if(empty($input_data['username'])){
|
||||
return Tools::set_fail('用户名错误');
|
||||
}
|
||||
if(empty($input_data['password'])){
|
||||
return Tools::set_fail('密码错误.');
|
||||
}
|
||||
if(empty($input_data['password2'])){
|
||||
return Tools::set_fail('密码错误!');
|
||||
}
|
||||
if($input_data['password'] != $input_data['password2']){
|
||||
return Tools::set_fail('密码不一致!');
|
||||
}
|
||||
$insert_data = [
|
||||
'username'=>$input_data['username'],
|
||||
'password'=>$input_data['password'],
|
||||
];
|
||||
if(!empty($input_data['phone'])){
|
||||
$insert_data['phone'] = $input_data['phone'];
|
||||
}
|
||||
Db::table($this->user_table)
|
||||
->data($insert_data)
|
||||
->insert();
|
||||
return Tools::set_ok();
|
||||
}catch (\Exception $e){
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
79
digital_doctor/vendor/wanghua/general-utility-tools-php/src/apk/Apk.php
vendored
Normal file
79
digital_doctor/vendor/wanghua/general-utility-tools-php/src/apk/Apk.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/*
|
||||
* description: apk应用安装包信息读取
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {17:16}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\apk;
|
||||
|
||||
|
||||
class Apk
|
||||
{
|
||||
|
||||
/**
|
||||
* 前提:安装PHP ZIP扩展
|
||||
* 扩展下载:https://windows.php.net/downloads/pecl/releases/zip/
|
||||
* desc:读取APK
|
||||
* author:wh
|
||||
* @param string $path 文件地址
|
||||
* @param bool $isRemote 是否远程文件
|
||||
* @param string $proxy 代理
|
||||
* @return array
|
||||
*/
|
||||
function read(string $path, $filename, bool $isRemote=false, $proxy=''){
|
||||
/*解析安卓apk包中的压缩XML文件,还原和读取XML内容
|
||||
|
||||
依赖功能:需要PHP的ZIP包函数支持。*/
|
||||
|
||||
$appObj = new ApkParser();
|
||||
|
||||
$targetFile = $path;//a.apk; apk所在的路径地址
|
||||
// 如果是远程文件,先下载到本地
|
||||
if ($isRemote) {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $path);
|
||||
if ($proxy != '') {
|
||||
curl_setopt($ch, CURLOPT_PROXY, $proxy);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 50);
|
||||
$fileContent = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// 写入临时文件
|
||||
$sys_tmp_path = tempnam(sys_get_temp_dir(), 'DL');
|
||||
$fp = @fopen($sys_tmp_path, 'w+');
|
||||
fwrite($fp, $fileContent);
|
||||
|
||||
$tmp_path = config('app.ROOT_PATH_PRO').'runtime/temp_file';
|
||||
if(!file_exists($tmp_path)){
|
||||
mkdir($tmp_path, 0777, true);
|
||||
}
|
||||
$targetFile = $tmp_path. '/' .time().$filename;
|
||||
$res = move_uploaded_file($sys_tmp_path, $targetFile);
|
||||
dump($res);die;
|
||||
}
|
||||
$result = [
|
||||
'app_name'=>'',// 应用名称
|
||||
'package'=>'',// 应用包名
|
||||
'version_name'=>'',// 版本名称
|
||||
'version_code'=>'',// 版本代码
|
||||
];
|
||||
|
||||
dump($targetFile);die;
|
||||
if(!is_file($targetFile)){
|
||||
return $result;
|
||||
}
|
||||
$appObj->open($targetFile);//$res
|
||||
|
||||
$result = [
|
||||
'app_name'=>$appObj->getAppName(),// 应用名称
|
||||
'package'=>$appObj->getPackage(),// 应用包名
|
||||
'version_name'=>$appObj->getVersionName(),// 版本名称
|
||||
'version_code'=>$appObj->getVersionCode(),// 版本代码
|
||||
];
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
421
digital_doctor/vendor/wanghua/general-utility-tools-php/src/apk/ApkParser.php
vendored
Normal file
421
digital_doctor/vendor/wanghua/general-utility-tools-php/src/apk/ApkParser.php
vendored
Normal file
@@ -0,0 +1,421 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {17:12}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\apk;
|
||||
|
||||
|
||||
use Exception;
|
||||
|
||||
class ApkParser{
|
||||
//----------------------
|
||||
// 公共函数,供外部调用
|
||||
//----------------------
|
||||
public function open($apk_file, $xml_file='AndroidManifest.xml'){
|
||||
$zip = new \ZipArchive();
|
||||
if ($zip->open($apk_file) === TRUE) {
|
||||
$xml = $zip->getFromName($xml_file);
|
||||
$zip->close();
|
||||
if ($xml){
|
||||
try {
|
||||
return $this->parseString($xml);
|
||||
}catch (Exception $e){
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function parseString($xml){
|
||||
$this->xml = $xml;
|
||||
$this->length = strlen($xml);
|
||||
|
||||
$this->root = $this->parseBlock(self::AXML_FILE);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getXML($node=NULL, $lv=-1){
|
||||
if ($lv == -1) $node = $this->root;
|
||||
if (!$node) return '';
|
||||
|
||||
if ($node['type'] == self::END_TAG) $lv--;
|
||||
$xml = @($node['line'] == 0 || $node['line'] == $this->line) ? '' : "\n".str_repeat(' ', $lv);
|
||||
$xml .= $node['tag'];
|
||||
$this->line = @$node['line'];
|
||||
foreach ($node['child'] as $c){
|
||||
$xml .= $this->getXML($c, $lv+1);
|
||||
}
|
||||
return $xml;
|
||||
}
|
||||
|
||||
public function getPackage(){
|
||||
return $this->getAttribute('manifest', 'package');
|
||||
}
|
||||
|
||||
public function getVersionName(){
|
||||
return $this->getAttribute('manifest', 'android:versionName');
|
||||
}
|
||||
|
||||
public function getVersionCode(){
|
||||
return $this->getAttribute('manifest', 'android:versionCode');
|
||||
}
|
||||
|
||||
public function getAppName(){
|
||||
return $this->getAttribute('manifest/application', 'android:name');
|
||||
}
|
||||
|
||||
public function getMainActivity(){
|
||||
for ($id=0; true; $id++){
|
||||
$act = $this->getAttribute("manifest/application/activity[{$id}]/intent-filter/action", 'android:name');
|
||||
if (!$act) break;
|
||||
if ($act == 'android.intent.action.MAIN') return $this->getActivity($id);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public function getActivity($idx=0){
|
||||
$idx = intval($idx);
|
||||
return $this->getAttribute("manifest/application/activity[{$idx}]", 'android:name');
|
||||
}
|
||||
|
||||
public function getAttribute($path, $name){
|
||||
$r = $this->getElement($path);
|
||||
if (is_null($r)) return NULL;
|
||||
|
||||
if (isset($r['attrs'])){
|
||||
foreach ($r['attrs'] as $a){
|
||||
if ($a['ns_name'] == $name) return $this->getAttributeValue($a);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//----------------------
|
||||
// 类型常量定义
|
||||
//----------------------
|
||||
const AXML_FILE = 0x00080003;
|
||||
const STRING_BLOCK = 0x001C0001;
|
||||
const RESOURCEIDS = 0x00080180;
|
||||
const START_NAMESPACE = 0x00100100;
|
||||
const END_NAMESPACE = 0x00100101;
|
||||
const START_TAG = 0x00100102;
|
||||
const END_TAG = 0x00100103;
|
||||
const TEXT = 0x00100104;
|
||||
|
||||
const TYPE_NULL =0;
|
||||
const TYPE_REFERENCE =1;
|
||||
const TYPE_ATTRIBUTE =2;
|
||||
const TYPE_STRING =3;
|
||||
const TYPE_FLOAT =4;
|
||||
const TYPE_DIMENSION =5;
|
||||
const TYPE_FRACTION =6;
|
||||
const TYPE_INT_DEC =16;
|
||||
const TYPE_INT_HEX =17;
|
||||
const TYPE_INT_BOOLEAN =18;
|
||||
const TYPE_INT_COLOR_ARGB8 =28;
|
||||
const TYPE_INT_COLOR_RGB8 =29;
|
||||
const TYPE_INT_COLOR_ARGB4 =30;
|
||||
const TYPE_INT_COLOR_RGB4 =31;
|
||||
|
||||
const UNIT_MASK = 15;
|
||||
private static $RADIX_MULTS = array(0.00390625, 3.051758E-005, 1.192093E-007, 4.656613E-010);
|
||||
private static $DIMENSION_UNITS = array("px","dip","sp","pt","in","mm","","");
|
||||
private static $FRACTION_UNITS = array("%","%p","","","","","","");
|
||||
|
||||
private $xml='';
|
||||
private $length = 0;
|
||||
private $stringCount = 0;
|
||||
private $styleCount = 0;
|
||||
private $stringTab = array();
|
||||
private $styleTab = array();
|
||||
private $resourceIDs = array();
|
||||
private $ns = array();
|
||||
private $cur_ns = NULL;
|
||||
private $root = NULL;
|
||||
private $line = 0;
|
||||
|
||||
//----------------------
|
||||
// 内部私有函数
|
||||
//----------------------
|
||||
private function getElement($path){
|
||||
if (!$this->root) return NULL;
|
||||
$ps = explode('/', $path);
|
||||
$r = $this->root;
|
||||
foreach ($ps as $v){
|
||||
if (preg_match('/([^\[]+)\[([0-9]+)\]$/', $v, $ms)){
|
||||
$v = $ms[1];
|
||||
$off = $ms[2];
|
||||
}else {
|
||||
$off = 0;
|
||||
}
|
||||
foreach ($r['child'] as $c){
|
||||
if ($c['type'] == self::START_TAG && $c['ns_name'] == $v){
|
||||
if ($off == 0){
|
||||
$r = $c; continue 2;
|
||||
}else {
|
||||
$off--;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 没有找到节点
|
||||
return NULL;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
private function parseBlock($need = 0){
|
||||
$o = 0;
|
||||
$type = $this->get32($o);
|
||||
if ($need && $type != $need) throw new Exception('Block Type Error', 1);
|
||||
$size = $this->get32($o);
|
||||
if ($size < 8 || $size > $this->length) throw new Exception('Block Size Error', 2);
|
||||
$left = $this->length - $size;
|
||||
|
||||
$props = false;
|
||||
switch ($type){
|
||||
case self::AXML_FILE:
|
||||
$props = array(
|
||||
'line' => 0,
|
||||
'tag' => '<?xml version="1.0" encoding="utf-8"?>'
|
||||
);
|
||||
break;
|
||||
case self::STRING_BLOCK:
|
||||
$this->stringCount = $this->get32($o);
|
||||
$this->styleCount = $this->get32($o);
|
||||
$o += 4;
|
||||
$strOffset = $this->get32($o);
|
||||
$styOffset = $this->get32($o);
|
||||
$strListOffset = $this->get32array($o, $this->stringCount);
|
||||
$styListOffset = $this->get32array($o, $this->styleCount);
|
||||
$this->stringTab = $this->stringCount > 0 ? $this->getStringTab($strOffset, $strListOffset) : array();
|
||||
$this->styleTab = $this->styleCount > 0 ? $this->getStringTab($styOffset, $styListOffset) : array();
|
||||
$o = $size;
|
||||
break;
|
||||
case self::RESOURCEIDS:
|
||||
$count = $size / 4 - 2;
|
||||
$this->resourceIDs = $this->get32array($o, $count);
|
||||
break;
|
||||
case self::START_NAMESPACE:
|
||||
$o += 8;
|
||||
$prefix = $this->get32($o);
|
||||
$uri = $this->get32($o);
|
||||
|
||||
if (empty($this->cur_ns)){
|
||||
$this->cur_ns = array();
|
||||
$this->ns[] = &$this->cur_ns;
|
||||
}
|
||||
$this->cur_ns[$uri] = $prefix;
|
||||
break;
|
||||
case self::END_NAMESPACE:
|
||||
$o += 8;
|
||||
$prefix = $this->get32($o);
|
||||
$uri = $this->get32($o);
|
||||
|
||||
if (empty($this->cur_ns)) break;
|
||||
unset($this->cur_ns[$uri]);
|
||||
break;
|
||||
case self::START_TAG:
|
||||
$line = $this->get32($o);
|
||||
|
||||
$o += 4;
|
||||
$attrs = array();
|
||||
$props = array(
|
||||
'line' => $line,
|
||||
'ns' => $this->getNameSpace($this->get32($o)),
|
||||
'name' => $this->getString($this->get32($o)),
|
||||
'flag' => $this->get32($o),
|
||||
'count' => $this->get16($o),
|
||||
'id' => $this->get16($o)-1,
|
||||
'class' => $this->get16($o)-1,
|
||||
'style' => $this->get16($o)-1,
|
||||
'attrs' => &$attrs
|
||||
);
|
||||
$props['ns_name'] = $props['ns'].$props['name'];
|
||||
for ($i=0; $i < $props['count']; $i++){
|
||||
$a = array(
|
||||
'ns' => $this->getNameSpace($this->get32($o)),
|
||||
'name' => $this->getString($this->get32($o)),
|
||||
'val_str' => $this->get32($o),
|
||||
'val_type' => $this->get32($o),
|
||||
'val_data' => $this->get32($o)
|
||||
);
|
||||
$a['ns_name'] = $a['ns'].$a['name'];
|
||||
$a['val_type'] >>= 24;
|
||||
$attrs[] = $a;
|
||||
}
|
||||
// 处理TAG字符串
|
||||
$tag = "<{$props['ns_name']}";
|
||||
foreach ($this->cur_ns as $uri => $prefix){
|
||||
$uri = $this->getString($uri);
|
||||
$prefix = $this->getString($prefix);
|
||||
$tag .= " xmlns:{$prefix}=\"{$uri}\"";
|
||||
}
|
||||
foreach ($props['attrs'] as $a){
|
||||
$tag .= " {$a['ns_name']}=\"".
|
||||
$this->getAttributeValue($a).
|
||||
'"';
|
||||
}
|
||||
$tag .= '>';
|
||||
$props['tag'] = $tag;
|
||||
|
||||
unset($this->cur_ns);
|
||||
$this->cur_ns = array();
|
||||
$this->ns[] = &$this->cur_ns;
|
||||
$left = -1;
|
||||
break;
|
||||
case self::END_TAG:
|
||||
$line = $this->get32($o);
|
||||
$o += 4;
|
||||
$props = array(
|
||||
'line' => $line,
|
||||
'ns' => $this->getNameSpace($this->get32($o)),
|
||||
'name' => $this->getString($this->get32($o))
|
||||
);
|
||||
$props['ns_name'] = $props['ns'].$props['name'];
|
||||
$props['tag'] = "</{$props['ns_name']}>";
|
||||
if (count($this->ns) > 1){
|
||||
array_pop($this->ns);
|
||||
unset($this->cur_ns);
|
||||
$this->cur_ns = array_pop($this->ns);
|
||||
$this->ns[] = &$this->cur_ns;
|
||||
}
|
||||
break;
|
||||
case self::TEXT:
|
||||
$o += 8;
|
||||
$props = array(
|
||||
'tag' => $this->getString($this->get32($o))
|
||||
);
|
||||
$o += 8;
|
||||
break;
|
||||
default:
|
||||
throw new Exception('Block Type Error', 3);
|
||||
break;
|
||||
}
|
||||
|
||||
$this->skip($o);
|
||||
$child = array();
|
||||
while ($this->length > $left){
|
||||
$c = $this->parseBlock();
|
||||
if ($props && $c) $child[] = $c;
|
||||
if ($left == -1 && $c['type'] == self::END_TAG){
|
||||
$left = $this->length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($this->length != $left) throw new Exception('Block Overflow Error', 4);
|
||||
if ($props){
|
||||
$props['type'] = $type;
|
||||
$props['size'] = $size;
|
||||
$props['child'] = $child;
|
||||
return $props;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function getAttributeValue($a){
|
||||
$type = &$a['val_type'];
|
||||
$data = &$a['val_data'];
|
||||
switch ($type){
|
||||
case self::TYPE_STRING:
|
||||
return $this->getString($a['val_str']);
|
||||
case self::TYPE_ATTRIBUTE:
|
||||
return sprintf('?%s%08X', self::_getPackage($data), $data);
|
||||
case self::TYPE_REFERENCE:
|
||||
return sprintf('@%s%08X', self::_getPackage($data), $data);
|
||||
case self::TYPE_INT_HEX:
|
||||
return sprintf('0x%08X', $data);
|
||||
case self::TYPE_INT_BOOLEAN:
|
||||
return ($data != 0 ? 'true' : 'false');
|
||||
case self::TYPE_INT_COLOR_ARGB8:
|
||||
case self::TYPE_INT_COLOR_RGB8:
|
||||
case self::TYPE_INT_COLOR_ARGB4:
|
||||
case self::TYPE_INT_COLOR_RGB4:
|
||||
return sprintf('#%08X', $data);
|
||||
case self::TYPE_DIMENSION:
|
||||
return $this->_complexToFloat($data).self::$DIMENSION_UNITS[$data & self::UNIT_MASK];
|
||||
case self::TYPE_FRACTION:
|
||||
return $this->_complexToFloat($data).self::$FRACTION_UNITS[$data & self::UNIT_MASK];
|
||||
case self::TYPE_FLOAT:
|
||||
return $this->_int2float($data);
|
||||
}
|
||||
if ($type >=self::TYPE_INT_DEC && $type < self::TYPE_INT_COLOR_ARGB8){
|
||||
return (string)$data;
|
||||
}
|
||||
return sprintf('<0x%X, type 0x%02X>', $data, $type);
|
||||
}
|
||||
|
||||
private function _complexToFloat($data){
|
||||
return (float)($data & 0xFFFFFF00) * self::$RADIX_MULTS[($data>>4) & 3];
|
||||
}
|
||||
private function _int2float($v) {
|
||||
$x = ($v & ((1 << 23) - 1)) + (1 << 23) * ($v >> 31 | 1);
|
||||
$exp = ($v >> 23 & 0xFF) - 127;
|
||||
return $x * pow(2, $exp - 23);
|
||||
}
|
||||
private static function _getPackage($data){
|
||||
return ($data >> 24 == 1) ? 'android:' : '';
|
||||
}
|
||||
|
||||
private function getStringTab($base, $list){
|
||||
$tab = array();
|
||||
foreach ($list as $off){
|
||||
$off += $base;
|
||||
$len = $this->get16($off);
|
||||
$mask = ($len >> 0x8) & 0xFF;
|
||||
$len = $len & 0xFF;
|
||||
if ($len == $mask){
|
||||
if ($off + $len > $this->length) throw new Exception('String Table Overflow', 11);
|
||||
$tab[] = substr($this->xml, $off, $len);
|
||||
}else {
|
||||
if ($off + $len * 2 > $this->length) throw new Exception('String Table Overflow', 11);
|
||||
$str = substr($this->xml, $off, $len * 2);
|
||||
$tab[] = mb_convert_encoding($str, 'UTF-8', 'UCS-2LE');
|
||||
}
|
||||
}
|
||||
return $tab;
|
||||
}
|
||||
private function getString($id){
|
||||
if ($id > -1 && $id < $this->stringCount){
|
||||
return $this->stringTab[$id];
|
||||
}else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
private function getNameSpace($uri){
|
||||
for ($i=count($this->ns); $i > 0; ){
|
||||
$ns = $this->ns[--$i];
|
||||
if (isset($ns[$uri])){
|
||||
$ns = $this->getString($ns[$uri]);
|
||||
if (!empty($ns)) $ns .= ':';
|
||||
return $ns;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
private function get32(&$off){
|
||||
$int = unpack('V', substr($this->xml, $off, 4));
|
||||
$off += 4;
|
||||
return array_shift($int);
|
||||
}
|
||||
private function get32array(&$off, $size){
|
||||
if ($size <= 0) return NULL;
|
||||
$arr = unpack('V*', substr($this->xml, $off, 4 * $size));
|
||||
if (count($arr) != $size) throw new Exception('Array Size Error', 10);
|
||||
$off += 4 * $size;
|
||||
return $arr;
|
||||
}
|
||||
private function get16(&$off){
|
||||
$int = unpack('v', substr($this->xml, $off, 2));
|
||||
$off += 2;
|
||||
return array_shift($int);
|
||||
}
|
||||
private function skip($size){
|
||||
$this->xml = substr($this->xml, $size);
|
||||
$this->length -= $size;
|
||||
}
|
||||
}
|
||||
103
digital_doctor/vendor/wanghua/general-utility-tools-php/src/coin/Coin.php
vendored
Normal file
103
digital_doctor/vendor/wanghua/general-utility-tools-php/src/coin/Coin.php
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/3/19} {13:57}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\coin;
|
||||
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\http\Curl;
|
||||
|
||||
class Coin
|
||||
{
|
||||
|
||||
public $apiKey = 'f94a2a9c-28be-47c3aaa-9c29-1e83b309d076';
|
||||
public $url = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest';
|
||||
|
||||
|
||||
/**
|
||||
* desc:
|
||||
'limit'=>'1000',
|
||||
'sort'=>'market_cap',
|
||||
'sort_dir'=>'desc',
|
||||
* @param array $params
|
||||
* @return array|bool|int|string
|
||||
*/
|
||||
function getAll(array $params){
|
||||
$params_str = http_build_query($params);
|
||||
$url = $this->url.'?'.$params_str;
|
||||
|
||||
$header = [
|
||||
'X-CMC_PRO_API_KEY:'.$this->apiKey,
|
||||
'accept: application/json',
|
||||
];
|
||||
|
||||
return Curl::curl_get($url,10,$header);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:
|
||||
*
|
||||
*https://coinmarketcap.com/api/documentation/v1/#section/Introduction
|
||||
* 'https://pro-api.coinmarketcap.com/v2/cryptocurrency/ohlcv/historical'
|
||||
* author:wh
|
||||
*/
|
||||
function k(){
|
||||
$url = $this->url;
|
||||
$time_start = input('time_start');
|
||||
$time_end = input('time_end');
|
||||
$type = input('type');
|
||||
|
||||
$header = [
|
||||
'X-CMC_PRO_API_KEY:'.$this->apiKey,
|
||||
];
|
||||
|
||||
$arr = explode('=',$type);
|
||||
$params = [
|
||||
$arr[0]=>$arr[1],//币种
|
||||
'time_start'=>$time_start,
|
||||
'time_end'=>$time_end,
|
||||
'count'=>7,
|
||||
];
|
||||
|
||||
$url = $url.'?'.http_build_query($params);
|
||||
|
||||
return Curl::curl_get($url,10,$header);
|
||||
}
|
||||
|
||||
private function curl_request($url, $method = 'GET',$data=null,$header=array(),$call_back=null)
|
||||
{
|
||||
set_time_limit(30);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
if($header){
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
}
|
||||
if($method == 'POST'){
|
||||
if($data) curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
if($call_back){
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $call_back);
|
||||
}
|
||||
$result = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
return [
|
||||
'status' => 'error',
|
||||
'message' => 'curl 错误信息: ' . curl_error($ch)
|
||||
];
|
||||
}
|
||||
curl_close($ch);
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
390
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/DbCacheUtility.php
vendored
Normal file
390
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/DbCacheUtility.php
vendored
Normal file
@@ -0,0 +1,390 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2019/12/17} {14:30}
|
||||
*/
|
||||
|
||||
namespace wanghua\db\general_utility_tools_php;
|
||||
|
||||
use wanghua\db\general_utility_tools_php\SqlOperateLog;
|
||||
use think\Container;
|
||||
use think\Db;
|
||||
use think\Paginator;
|
||||
|
||||
/**
|
||||
* 环境要求:
|
||||
* ThinkPHP5.1+,PHP7.0+,MySQL8.0+
|
||||
*
|
||||
*
|
||||
* 查询缓存器、监控器
|
||||
* 【使用框架链式操作时,配合此类才能发挥完美效果】
|
||||
* 举例
|
||||
* function getMemberInIds(string $ids){
|
||||
$obj = Db::name($this->table)->whereIn("id",$ids)->where(["is_deleted"=>0]);
|
||||
return DbCacheUtility::getAll($obj);
|
||||
}
|
||||
* Class DbCacheUtility
|
||||
* @package libraries
|
||||
*/
|
||||
class DbCacheUtility
|
||||
{
|
||||
const NoCacheTime = 0;
|
||||
const LowCacheTime = 60 * 1;
|
||||
const NormalCacheTime = 60 * 10;
|
||||
const HighCacheTime = 60 * 60;
|
||||
const LongCacheTime = 60 * 60 * 24;
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $object 查询对象
|
||||
* @param int $cacheDuration
|
||||
* @param bool $is_log
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getOne($object, $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = $object->fetchSql(true)->find();
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'get_one:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = $object->fetchSql(false)->find();
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'get_one', $is_cache);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $object 查询对象
|
||||
* @param int $cacheDuration
|
||||
* @param bool $is_log
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getAll($object, $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = $object->fetchSql(true)->select();
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'get_all:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = $object->fetchSql(false)->select();
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'get_all', $is_cache);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $object
|
||||
* @param int $page
|
||||
* @param int $listRows
|
||||
* @param bool $simple
|
||||
* @param array $config
|
||||
* @param int $cacheDuration
|
||||
* @param bool $is_log
|
||||
* @return mixed
|
||||
*/
|
||||
static function paginates($object, $page=1, $listRows = null, $simple = false, $config = [], $cacheDuration = self::NoCacheTime, $is_log = true){
|
||||
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = $object->limit(abs(1*$page-1) * $listRows, $listRows)->fetchSql(true)->select();
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'paginates:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = $object->fetchSql(false)->paginate($listRows, $simple, $config);
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'paginates', $is_cache);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\BindParamException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
static function queryScalar($sql, $bind = [], $field, $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = self::presetBind($sql, $bind);
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'query_scalar:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = Db::query($sql, $bind);
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'query_scalar', $is_cache);
|
||||
}
|
||||
|
||||
return $result ? $result[0][$field] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\BindParamException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
static function queryOne($sql, $bind = [], $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = self::presetBind($sql, $bind);
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'query_one:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = Db::query($sql, $bind);
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'query_one', $is_cache);
|
||||
}
|
||||
|
||||
return $result ? $result[0] : [];
|
||||
}
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\BindParamException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
static function queryAll($sql, $bind = [], $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = self::presetBind($sql, $bind);
|
||||
//echo $last_sql;die;
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'query_all:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = Db::query($sql, $bind);
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'query_all', $is_cache);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return int
|
||||
* @throws \think\db\exception\BindParamException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
static function execute($sql, $bind = []){
|
||||
return Db::execute($sql, $bind);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
*/
|
||||
static function presetBind($sql, $bind = []){
|
||||
if($bind){
|
||||
foreach ($bind as $key=>$val){
|
||||
$sql = str_replace(':'.$key, $val, $sql);
|
||||
}
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
static function paginate($sql, $bind, $total, $listRows = null, $simple = false, $config = [])
|
||||
{
|
||||
//if (is_int($simple)) {
|
||||
// $total = $simple;
|
||||
// $simple = false;
|
||||
//}
|
||||
|
||||
$paginate = Container::get('config')->pull('paginate');
|
||||
|
||||
if (is_array($listRows)) {
|
||||
$config = array_merge($paginate, $listRows);
|
||||
$listRows = $config['list_rows'];
|
||||
} else {
|
||||
$config = array_merge($paginate, $config);
|
||||
$listRows = $listRows ?: $config['list_rows'];
|
||||
}
|
||||
|
||||
/** @var Paginator $class */
|
||||
$class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\paginator\\driver\\' . ucwords($config['type']);
|
||||
$page = isset($config['page']) ? (int) $config['page'] : call_user_func([
|
||||
$class,
|
||||
'getCurrentPage',
|
||||
], $config['var_page']);
|
||||
|
||||
$page = $page < 1 ? 1 : $page;
|
||||
|
||||
$config['path'] = isset($config['path']) ? $config['path'] : call_user_func([$class, 'getCurrentPath']);
|
||||
|
||||
//if (!isset($total) && !$simple) {
|
||||
//
|
||||
//
|
||||
// unset($this->options['order'], $this->options['limit'], $this->options['page'], $this->options['field']);
|
||||
//
|
||||
// $bind = $this->bind;
|
||||
// $total = $this->count();
|
||||
// $results = $this->options($options)->bind($bind)->page($page, $listRows)->select();
|
||||
//} elseif ($simple) {
|
||||
// $results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select();
|
||||
// $total = null;
|
||||
//} else {
|
||||
// $results = $this->page($page, $listRows)->select();
|
||||
//}
|
||||
|
||||
$results = DbCacheUtility::queryAll($sql, $bind);
|
||||
|
||||
return $class::make($results, $listRows, $page, $total, $simple, $config);
|
||||
}
|
||||
}
|
||||
109
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/RedisUtility.php
vendored
Normal file
109
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/RedisUtility.php
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/5/22} {16:43}
|
||||
*/
|
||||
|
||||
namespace wanghua\db\general_utility_tools_php;
|
||||
|
||||
|
||||
use think\cache\driver\Redis as RedisDriver;
|
||||
use think\Db;
|
||||
use think\facade\Cache;
|
||||
|
||||
/**
|
||||
* Redis操作工具
|
||||
*
|
||||
* 环境要求:
|
||||
* ThinkPHP5.1+,PHP7.0+,MySQL8.0+
|
||||
*
|
||||
*
|
||||
* Class RedisUtility
|
||||
* @package libraries
|
||||
*/
|
||||
class RedisUtility
|
||||
{
|
||||
protected static $redisHandle = null;
|
||||
|
||||
/**
|
||||
* desc:初始化Redis对象
|
||||
* author:wh
|
||||
* @return object|null
|
||||
*/
|
||||
static function redisObject(){
|
||||
if(empty(self::$redisHandle)){
|
||||
//初始化驱动拿到句柄
|
||||
self::$redisHandle = (new RedisDriver(config('cache.redis')))->handler();
|
||||
}
|
||||
return self::$redisHandle;
|
||||
}
|
||||
/**
|
||||
* desc:设置 0 永久有效
|
||||
* author:wh
|
||||
* @param $key_name 键名
|
||||
* @param $value 值 json数据
|
||||
* @return bool
|
||||
*/
|
||||
static function set($key_name, $value){
|
||||
return Cache::store('redis')->set($key_name, json_encode($value, JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:重置
|
||||
* author:wh
|
||||
* @param $key_name
|
||||
* @return bool
|
||||
*/
|
||||
static function reset($key_name){
|
||||
return Cache::store('redis')->set($key_name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置过期时间
|
||||
* author:wh
|
||||
* @param $key_name 键名
|
||||
* @param $value 值 json数据
|
||||
* @param int $expire 过期时间 0 永久有效
|
||||
* @return bool
|
||||
*/
|
||||
static function setExpire($key_name, $value, $expire=0){
|
||||
return Cache::store('redis')->set($key_name, json_encode($value), $expire);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:存储hash类型
|
||||
* author:wh
|
||||
* @param $key
|
||||
* @param $field
|
||||
* @param $value
|
||||
*/
|
||||
static function hSet($key, $field, $value){
|
||||
return self::redisObject()->hSet($key, $field, json_encode($value, JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除指定的键。
|
||||
* author:wh
|
||||
* @param $key
|
||||
* @return mixed
|
||||
*/
|
||||
static function delete($key){
|
||||
return self::redisObject()->delete($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:从存储在键上的哈希中移除一个值。
|
||||
* 如果哈希表不存在,或者键不存在,则返回 FALSE 。
|
||||
* author:wh
|
||||
* @param $key
|
||||
* @param $hashKey1
|
||||
* @return mixed
|
||||
*/
|
||||
static function hDel($key, $hashKey1){
|
||||
return self::redisObject()->hDel($key, $hashKey1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
55
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/SqlOperateLog.php
vendored
Normal file
55
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/SqlOperateLog.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2019/10/31} {9:25}
|
||||
*/
|
||||
|
||||
namespace wanghua\db\general_utility_tools_php;
|
||||
|
||||
|
||||
use think\Db;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 环境要求:
|
||||
* ThinkPHP5.1+,PHP7.0+,MySQL8.0+
|
||||
*
|
||||
* 日志操作类,配合DbCacheUtility.php使用。
|
||||
* 使用前先在系统config.php文件中添加配置:
|
||||
* 1、is_sql_slow_log:是否记录sql慢日志,true or false
|
||||
* 2、新建表(log_sql_operate)字段:action,is_cache,duration_time,type,is_cache,sql,md5_name
|
||||
* 3、如果什么错都没有报,但是程序就是没反应,则去runtime目录中找错误。
|
||||
*
|
||||
* Class SqlOperateLog
|
||||
* @package wanghua\general_utility_tools_php
|
||||
*/
|
||||
class SqlOperateLog
|
||||
{
|
||||
|
||||
static function add($sql,$end_time,$begin_time,$md5_name,$type,$is_cache){
|
||||
$data = [
|
||||
'action'=>request()->baseUrl(),
|
||||
'duration_time'=>$end_time - $begin_time,
|
||||
'type'=>$type,
|
||||
'is_cache'=>$is_cache?1:0,
|
||||
'sql'=>$sql,
|
||||
'md5_name'=>$md5_name,
|
||||
];
|
||||
try{
|
||||
if(config('app.is_sql_slow_log') && ($end_time - $begin_time) >= config('app.is_sql_slow_log')){
|
||||
Db::table('log_sql_operate')->insert($data);
|
||||
}
|
||||
}catch (\Exception $e){
|
||||
//DATABASE BOOM
|
||||
//tp6
|
||||
//Log::error('========[数据库异常:DATABASE BOOM]========'.$e->getTraceAsString());
|
||||
//Log::close();
|
||||
//tp5.1
|
||||
Log::write('========[DATABASE ERROR:DATABASE BOOM]========【'.$e->getMessage().'】'.$e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
262
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/es/Elasticsearch.php
vendored
Normal file
262
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/es/Elasticsearch.php
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/4/26} {9:45}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\db\es;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\Date;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 【es原生操作库】
|
||||
* 【仅支持框架ThinkPHP5+、 PHP7.2+】
|
||||
*
|
||||
* BaseElasticsearch.php类库的替代库
|
||||
*
|
||||
* 使用步骤:
|
||||
* 初始化(设置ip、索引前缀-普通索引请设置为空字符串)
|
||||
* 设置索引范围(例如查询本月,如果索引不是按日期规律设置,请使用普通索引设置方法setIndexNormal,并设置前缀为空字符串)
|
||||
* 设置查询方法(eg: _search)
|
||||
* 设置查询参数(查询条件)
|
||||
* 执行
|
||||
* 返回结果
|
||||
* Class ElasticsearchUtility
|
||||
* @package app\admin\logic
|
||||
*/
|
||||
class Elasticsearch
|
||||
{
|
||||
protected $es_log_file = 'es_log';
|
||||
//最终拼装的请求地址
|
||||
protected $post_url = ''; //eg: $url = 'http://49.4.3.4:9111/qa-item-2021.04/_search';
|
||||
//查询参数
|
||||
protected $query_param = [];
|
||||
//查询方法
|
||||
protected $query_method = '_search';
|
||||
//文档索引
|
||||
protected $index = '';
|
||||
//服务器ip
|
||||
protected $ip = '';
|
||||
//索引前缀(优先设置)
|
||||
protected $index_sign = '';//eg: qa-stat-
|
||||
//设置查询日期格式符号
|
||||
protected $doc_date_sign = '.';
|
||||
//设置是哪个方法调用本es库,用于日志记录
|
||||
protected $exe_func = '';
|
||||
|
||||
|
||||
/**
|
||||
* ElasticsearchUtility constructor.
|
||||
* @param string $ip_port 协议+服务器ip+端口号,必须
|
||||
* @param string $index_sign 当es索引为有规律的日期索引时,可使用前缀并配合日期索引设置方法,体验更佳
|
||||
*/
|
||||
public function __construct(string $ip_port, string $index_sign='')
|
||||
{
|
||||
$this->ip = false===strpos($ip_port,'http')?'http://'.$ip_port:$ip_port;
|
||||
$this->index_sign = $index_sign;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置查询方法,默认_search
|
||||
* author:wh
|
||||
* @param $method_name
|
||||
*/
|
||||
function setQueryMethod($method_name){
|
||||
$this->query_method = $method_name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:根据日期索引查询文档
|
||||
* 注:默认一个月
|
||||
*
|
||||
* eg:'qa-stat-2021.01';
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
* author:wh
|
||||
*/
|
||||
function setIndexDefault(){
|
||||
$this->setRequestIndex(date('Y'.$this->doc_date_sign.'m'));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置要查询的日期文档索引
|
||||
*
|
||||
* 1、按年检索文档[建议5年左右]
|
||||
*
|
||||
* eg: qa-stat-2018.*,qa-stat-2019.*,qa-stat-2020.*,qa-stat-2021.*
|
||||
*
|
||||
* 注意:当索引过长,es会抛出索引太长异常
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time 开始时间 eg:2010-01-01 08:05:55
|
||||
* @param string $end_time 结束时间 eg:2021-12-31 12:05:00
|
||||
* @return string
|
||||
*/
|
||||
function setIndexYearDate(string $start_time, string $end_time){
|
||||
|
||||
//默认查询索引
|
||||
$index = date('Y'.$this->doc_date_sign.'*', strtotime($start_time));
|
||||
|
||||
$sign = ',';//分隔符
|
||||
|
||||
$m = date('Y', strtotime($end_time)) - date('Y', strtotime($start_time));
|
||||
|
||||
//拼装查询索引
|
||||
for ($i=0; $i<$m; $i++){
|
||||
|
||||
$index .= $sign.($this->index_sign.(date('Y', strtotime($start_time))+$i).$this->doc_date_sign.'*');
|
||||
}
|
||||
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置日期索引
|
||||
*
|
||||
* 检索全部日期索引文档
|
||||
*
|
||||
* 例如es设置的索引为:
|
||||
* qa-stat-2021.01
|
||||
qa-stat-2021.02
|
||||
qa-stat-2021.03
|
||||
qa-stat-2021.04
|
||||
*
|
||||
* 实际查询自动设置为:qa-stat-*
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function setIndexAllDate(){
|
||||
|
||||
$this->setRequestIndex('*');
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置普通索引
|
||||
*
|
||||
* 调用此方法,请在初始化时,设置索引前缀index_sign为""空字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $index
|
||||
*/
|
||||
function setIndexNormal(string $index){
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置跨月份索引
|
||||
*
|
||||
* eg: qa-stat-2021.01,qa-stat-2021.02
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time eg:'2020-11'
|
||||
* @param string $end_time eg:'2021-01'
|
||||
* @return string eg: qa-stat-2020.11,qa-stat-2020.12,qa-stat-2021.01
|
||||
*/
|
||||
function setIndexDate(string $start_time, string $end_time){
|
||||
$date = new Date();
|
||||
|
||||
//计算月份
|
||||
$m = $date->dateCutMonth($start_time, $end_time);
|
||||
////解决跨年且不足1个月时,索引设置错误问题
|
||||
//if($m == 0 && (date('Y', strtotime($end_time)) > date('Y', strtotime($start_time)))){
|
||||
// $m = 1;
|
||||
//}
|
||||
//格式
|
||||
$date->date_format = 'Y-m';
|
||||
|
||||
//默认查询索引
|
||||
$index = date('Y'.$this->doc_date_sign.'m', strtotime($start_time));
|
||||
|
||||
$tmp_time = $start_time;
|
||||
$sign = ',';//分隔符
|
||||
|
||||
//拼装查询索引
|
||||
for ($i=0; $i<$m; $i++){
|
||||
$tmp_time = $date->addTime(1, 'M', strtotime($tmp_time));
|
||||
$index .= $sign.$this->index_sign.(date('Y'.$this->doc_date_sign.'m', strtotime($tmp_time)));
|
||||
}
|
||||
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:设置查询参数
|
||||
* author:wh
|
||||
* @param string $query_param_json
|
||||
*/
|
||||
function setQueryParam(string $query_param_json){
|
||||
$this->query_param = $query_param_json;
|
||||
$this->post_url = $this->ip.'/'.$this->index.'/'.$this->query_method;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取查询参数,用于调试
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getQueryParam(){
|
||||
return [
|
||||
'ip'=>$this->ip,
|
||||
'index_sign'=>$this->index_sign,
|
||||
'index'=>$this->index,
|
||||
'query_method'=>$this->query_method,
|
||||
'post_url'=>$this->post_url,
|
||||
'query_param'=>$this->query_param,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:执行es查询
|
||||
* author:wh
|
||||
* @return array|bool|int|string
|
||||
* @throws \Exception
|
||||
*/
|
||||
function execute(){
|
||||
if(empty($this->ip)) throw new \Exception('请设置ip');
|
||||
//if(empty($this->index_sign)) throw new \Exception('请设置索引前缀');
|
||||
if(empty($this->index)) throw new \Exception('请设置索引');
|
||||
if(empty($this->query_method)) throw new \Exception('请设置查询方法');
|
||||
if(empty($this->query_param)) throw new \Exception('请设置查询参数');
|
||||
|
||||
|
||||
|
||||
|
||||
Tools::log_to_write_txt(['exe_func'=>$this->exe_func,'request_url'=>$this->post_url,'IN'=>" | IN: ",'query_params'=>$this->query_param, 'input'=>input()], $this->es_log_file);
|
||||
$result = Tools::curl_post($this->post_url, $this->query_param);
|
||||
Tools::log_to_write_txt(['exe_func'=>$this->exe_func,'OUT'=>" | OUT: ", 'result'=>$result], $this->es_log_file);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置是哪个方法调用本es库,用于日志记录
|
||||
* author:wh
|
||||
* @param string $function
|
||||
*/
|
||||
function setExecuteFunction(string $function){
|
||||
$this->exe_func = $function;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置请求文档索引
|
||||
* author:wh
|
||||
* @param string $index
|
||||
*/
|
||||
protected function setRequestIndex(string $index){
|
||||
$this->index = $this->index_sign.$index;
|
||||
}
|
||||
|
||||
}
|
||||
1340
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/es/README.md
vendored
Normal file
1340
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/es/README.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/mysql/README.MD
vendored
Normal file
6
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/mysql/README.MD
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
## 仅适用于tp5+, php7+
|
||||
|
||||
|
||||
## 表管理
|
||||
|
||||
## 字段管理
|
||||
304
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/mysql/lib/Field.php
vendored
Normal file
304
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/mysql/lib/Field.php
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {10:57}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\db\mysql\lib;
|
||||
|
||||
|
||||
use think\Db;
|
||||
|
||||
class Field
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* desc:创建字段,存在则修改字段
|
||||
* author:wh
|
||||
* @param array $table
|
||||
*/
|
||||
function createfield(array $table){
|
||||
$table_name = $table['tablename'];
|
||||
//新增字段
|
||||
$dec_num = '';
|
||||
|
||||
if(in_array(strtoupper($table['type']), ['TINYINT','SMALLINT','MEDIUMINT','INT','BIGINT','FLOAT','DOUBLE','DECIMAL'])){
|
||||
$table['default'] = '0';//整型默认值 浮点类型自动转为0.00
|
||||
if(in_array(strtoupper($table['type']), ['FLOAT','DOUBLE','DECIMAL'])){
|
||||
$dec_num = ','.$table['decimals_size'];//浮点类型小数位位数
|
||||
}
|
||||
}elseif ($table['type'] == 'enum'){
|
||||
//枚举值不转换
|
||||
}else{
|
||||
$table['default'] = '""';
|
||||
}
|
||||
|
||||
if(in_array(strtolower($table['type']), ['timestamp','datetime','date','time','text','mediumtext','longtext'])){
|
||||
$table['size'] = 0;//重写 默认0
|
||||
$table['default'] = 'null';//重写
|
||||
}
|
||||
//是否可以负数
|
||||
if(in_array(strtolower($table['type']), ['int','tinyint','bigint','smallint', 'double', 'float', 'decimal']) && !empty($post['is_unsigned'])){//不是
|
||||
$is_unsigned = 'unsigned';
|
||||
}else{//是 表单可选值
|
||||
$is_unsigned = '';
|
||||
}
|
||||
|
||||
if (in_array($table['fields_name'], ['create_time', 'update_time'])){
|
||||
if($table['fields_name'] == 'create_time'){
|
||||
$table['default'] = 'CURRENT_TIMESTAMP';
|
||||
}
|
||||
if($table['fields_name'] == 'update_time'){
|
||||
$table['default'] = 'NULL ON UPDATE CURRENT_TIMESTAMP';
|
||||
}
|
||||
}
|
||||
//验证字段是否存在
|
||||
$f = DB::table($table_name)->getTableFields();
|
||||
if(in_array($table['fields_name'], $f)){
|
||||
//枚举类型
|
||||
if ($table['type'] == 'enum'){
|
||||
$enum_str = '';
|
||||
$enum_default = '';
|
||||
//组合枚举值
|
||||
if($table['default']){
|
||||
$enum_str.='ENUM('.$table['default'].')';
|
||||
$enum_default = explode(',', $table['default'])[0];
|
||||
}
|
||||
$sql2 = "ALTER TABLE {$table_name} MODIFY {$table['fields_name']} {$enum_str} NOT NULL DEFAULT {$enum_default} COMMENT '{$table['title']}';";
|
||||
}else{
|
||||
$sql2 = "ALTER TABLE {$table_name} MODIFY COLUMN {$table['fields_name']} {$table['type']}(".$table['size'].$dec_num.") {$is_unsigned} DEFAULT {$table['default']} COMMENT '{$table['title']}';";
|
||||
}
|
||||
}else{
|
||||
|
||||
if(in_array($table['type'], ['text','longtext'])){
|
||||
$sql2 = "ALTER TABLE {$table_name} ADD COLUMN {$table['fields_name']} {$table['type']} COMMENT '{$table['title']}' AFTER id;";
|
||||
}elseif ($table['type'] == 'enum'){//枚举类型
|
||||
$enum_str = '';
|
||||
$enum_default = '';
|
||||
//组合枚举值
|
||||
if($table['default']){
|
||||
$enum_str.='ENUM('.$table['default'].')';
|
||||
$enum_default = explode(',', $table['default'])[0];
|
||||
}
|
||||
$sql2 = "ALTER TABLE {$table_name} ADD {$table['fields_name']} {$enum_str} NOT NULL DEFAULT {$enum_default} COMMENT '{$table['title']}' AFTER id;";
|
||||
}else{
|
||||
$sql2 = "ALTER TABLE {$table_name} ADD COLUMN {$table['fields_name']} {$table['type']}(".$table['size'].$dec_num.") {$is_unsigned} DEFAULT {$table['default']} COMMENT '{$table['title']}' AFTER id;";
|
||||
}
|
||||
}
|
||||
|
||||
DB::execute($sql2);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除字段
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $fieldname
|
||||
*/
|
||||
function dropFieldName($tablename, $fieldname){
|
||||
$sql = "ALTER TABLE {$tablename} DROP COLUMN {$fieldname};";
|
||||
DB::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:改注释
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $comment
|
||||
* @return bool
|
||||
*/
|
||||
function updateComment($tablename,$field, $comment){
|
||||
|
||||
$sql = "ALTER TABLE {$tablename} MODIFY COLUMN {$field} INT COMMENT '{$comment}';";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取数据表中所有字段的数据类型(含其它属性)
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldsDataType(string $dbname,string $tablename){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'";
|
||||
return Db::query($sql);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:获取数据表中某个字段的数据类型(含这个字段的其它属性)
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldDataType(string $dbname,string $tablename,string $fieldname){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'
|
||||
AND COLUMN_NAME='$fieldname'
|
||||
";
|
||||
$ar = Db::query($sql);
|
||||
return $ar[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:获取数据表中某个字段的数据类型
|
||||
*
|
||||
* 不含这个字段的其它属性
|
||||
*
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldDataTypeVal(string $dbname,string $tablename,string $fieldname){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'
|
||||
AND COLUMN_NAME='$fieldname'
|
||||
";
|
||||
$ar = Db::query($sql);
|
||||
return $ar[0]['F_DATATYPE'];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取数据表中某个字段的属性
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldAttrVal(string $dbname,string $tablename,string $fieldname,string $attr){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'
|
||||
AND COLUMN_NAME='$fieldname'
|
||||
";
|
||||
$ar = Db::query($sql);
|
||||
return $ar[0][$attr];
|
||||
}
|
||||
}
|
||||
162
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/mysql/lib/Table.php
vendored
Normal file
162
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/mysql/lib/Table.php
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {10:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\db\mysql\lib;
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class Table
|
||||
{
|
||||
/**
|
||||
* desc:创建表,初始化默认字段
|
||||
* author:wh
|
||||
* @param $data
|
||||
* @return bool
|
||||
*/
|
||||
function createTable($data){
|
||||
$tablename = $data['tablename'];
|
||||
$title = $data['title'];
|
||||
//创建表
|
||||
$sql = "CREATE TABLE IF NOT EXISTS {$tablename}(
|
||||
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
create_time timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
update_time timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY key(id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='{$title}' ;";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:改注释
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $comment
|
||||
* @return bool
|
||||
*/
|
||||
function updateComment($tablename, $comment){
|
||||
$sql = "ALTER TABLE {$tablename} COMMENT '{$comment}';";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:改表名
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $new_table_name
|
||||
* @return bool
|
||||
*/
|
||||
function updateTableName($tablename, $new_table_name){
|
||||
$sql = "ALTER TABLE {$tablename} RENAME TO {$new_table_name}";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:查询当前数据库所有的表名
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
function getTables(){
|
||||
return array_column(Db::query('SHOW TABLES;'), 'Tables_in_'.config('database.database'));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取数据表字所有段名
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @return array
|
||||
*/
|
||||
function getTableFields($tablename){
|
||||
$dbname = config('database.database');
|
||||
$sql = "SELECT COLUMN_NAME column_name,COLUMN_COMMENT column_comment,DATA_TYPE data_type
|
||||
FROM information_schema.columns WHERE TABLE_NAME='{$tablename}' AND table_schema='{$dbname}'";
|
||||
return array_column(Db::query($sql), 'column_name');
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取表的属性
|
||||
* Name:
|
||||
表名称
|
||||
Engine:
|
||||
表的存储引擎
|
||||
Version:
|
||||
版本
|
||||
Row_format:
|
||||
行格式。对于MyISAM引擎,这可能是Dynamic,Fixed或Compressed。动态行的行长度可变,例如Varchar或Blob类型字段。固定行是指行长度不变,例如Char和Integer类型字段
|
||||
Rows:
|
||||
表中的行数。对于MyISAM和其他存储引擎,这个值是精确的,对于innoDB存储引擎,这个值通常是估算的
|
||||
Avg_row_length:
|
||||
平均每行包括的字节数
|
||||
Data_length:
|
||||
整个表的数据量(以字节为单位)
|
||||
Max_data_length:
|
||||
表可以容纳的最大数据量,该值和存储引擎相关
|
||||
Index_length:
|
||||
索引占用磁盘的空间大小(以字节为单位)
|
||||
Data_free:
|
||||
对于MyISAM引擎,表示已经分配,但目前没有使用的空间。这部分空间包含之前被删除的行,以及后续可以被insert利用到的空间
|
||||
Auto_increment:
|
||||
下一个Auto_increment的值
|
||||
Create_time:
|
||||
表的创建时间
|
||||
Update_time:
|
||||
表的最近更新时间
|
||||
Check_time:
|
||||
使用 check table 或myisamchk工具最后一次检查表的时间
|
||||
Collation:
|
||||
表的默认字符集和字符排序规则
|
||||
Checksum:
|
||||
如果启用,保存的是整个表的实时校验和
|
||||
Create_options:
|
||||
创建表时指定的其他选项
|
||||
Comment:
|
||||
包含了其他额外信息,对于MyISAM引擎,保存的是表在创建时带的注释。如果表使用的是innodb引擎 ,保存的是InnoDB表空间的剩余空间。如果是一个视图,注释里面包含了VIEW字样。
|
||||
*
|
||||
* @param $tablename 表名(无表名则查询所有表)
|
||||
*
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
function getTableInfo(string $tablename=''){
|
||||
if($tablename){
|
||||
$sql = "SHOW TABLE STATUS WHERE Name = 'fa_agent';";
|
||||
return Db::query($sql);
|
||||
}
|
||||
$sql = 'show table status;';
|
||||
return Db::query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:检查某个表是否存在
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @return bool
|
||||
*/
|
||||
function isExistTable(string $dbname,string $tablename){
|
||||
$sql = "SELECT TABLE_SCHEMA,TABLE_NAME
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA ='$dbname'
|
||||
AND TABLE_NAME = '$tablename';";
|
||||
return empty(Db::query($sql));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取表注释
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function getTableComment($table){
|
||||
$prefix = config('database.prefix');
|
||||
$table = $prefix.$table;
|
||||
$sql = 'show table status;';
|
||||
$arr = Db::query($sql);
|
||||
$tmp = Tools::key_val_arr($arr,'Name','Comment');
|
||||
return empty($tmp[$table])?'':$tmp[$table];
|
||||
}
|
||||
}
|
||||
15
digital_doctor/vendor/wanghua/general-utility-tools-php/src/douyin/BaseDouYin.php
vendored
Normal file
15
digital_doctor/vendor/wanghua/general-utility-tools-php/src/douyin/BaseDouYin.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/4/5} {10:49}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\douyin;
|
||||
|
||||
|
||||
class BaseDouYin
|
||||
{
|
||||
|
||||
}
|
||||
193
digital_doctor/vendor/wanghua/general-utility-tools-php/src/douyin/DouYinMiniGame.php
vendored
Normal file
193
digital_doctor/vendor/wanghua/general-utility-tools-php/src/douyin/DouYinMiniGame.php
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/4/4} {12:36}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\douyin;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\http\Curl;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class DouYinMiniGame extends BaseDouYin
|
||||
{
|
||||
public $appid = 'tt3c974a2aa3a6ee7c02';
|
||||
public $secret = '5c2414e47a18b9655a164b14ef31ac7cb58179ca';
|
||||
|
||||
|
||||
/**
|
||||
* desc:每2小时更新一次
|
||||
*
|
||||
* https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/server/interface-request-credential/get-access-token
|
||||
*
|
||||
* {"err_no":0,"err_tips":"success","data":{"access_token":"0801121846384c316e52536e5a76396769565145696f597742673d3d","expires_in":7200,"expiresAt":1712208063,"expires_at":1712208063}}
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function getAccessToken(){
|
||||
$url = "https://minigame.zijieapi.com/mgplatform/api/apps/v2/token";
|
||||
$method = 'POST';
|
||||
//$Scope = 'open.ttgame.mgplatform';
|
||||
|
||||
$params = [
|
||||
|
||||
'appid'=>$this->appid,
|
||||
'secret'=>$this->secret,
|
||||
'grant_type'=>'client_credential',
|
||||
];
|
||||
$header = [
|
||||
'Accept: application/json',
|
||||
'content-type: application/json'
|
||||
];
|
||||
$res = Curl::curl_request($url,$method,json_encode($params),$header);
|
||||
|
||||
$json_arr = json_decode($res, true);
|
||||
if($json_arr['err_no']){
|
||||
return Tools::set_res($json_arr['err_no'],$json_arr['err_tips']);
|
||||
}
|
||||
//保存
|
||||
session('ses_dou_yin_access_token',$json_arr['data']);
|
||||
return Tools::set_ok('ok',$json_arr['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:实时获取token
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function realTimeGetAccessToken(){
|
||||
$json_arr = session('ses_dou_yin_access_token');
|
||||
if(empty($json_arr)){
|
||||
return $this->getAccessToken();
|
||||
}
|
||||
if(time() >= $json_arr['expiresAt']){
|
||||
//过期
|
||||
return $this->getAccessToken();
|
||||
}
|
||||
return Tools::set_ok('ok',$json_arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:前端tt.login触发调用
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function jscode2session($code='',$anonymous_code=''){
|
||||
$url = 'https://minigame.zijieapi.com/mgplatform/api/apps/jscode2session';
|
||||
//$Scope = 'open.ttgame.mgplatform';
|
||||
$method = 'GET';
|
||||
|
||||
if(empty($code) && empty($anonymous_code)){
|
||||
return Tools::set_fail('tt.login 接口返回的匿名登录凭证(code 和 anonymous_code 至少要有一个)');
|
||||
}
|
||||
$params = [
|
||||
'appid'=>$this->appid,
|
||||
'secret'=>$this->secret,
|
||||
];
|
||||
if($code){
|
||||
$params['code'] = $code;
|
||||
}
|
||||
if($anonymous_code){
|
||||
$params['anonymous_code'] = $anonymous_code;
|
||||
}
|
||||
$header = [
|
||||
'Accept: application/json',
|
||||
'content-type: application/json'
|
||||
];
|
||||
$url .= '?'.http_build_query($params);
|
||||
//dump($url);
|
||||
Tools::log_to_write_txt(['input'=>$url]);
|
||||
$res = Curl::curl_request($url,$method,[],$header);
|
||||
Tools::log_to_write_txt(['output'=>$res]);
|
||||
//dump($res);
|
||||
$json_arr = json_decode($res, true);
|
||||
//dump($json_arr);die;
|
||||
if($json_arr['error']){
|
||||
return Tools::set_res($json_arr['errcode'],$json_arr['errmsg']);
|
||||
}
|
||||
//保存
|
||||
session('ses_dou_yin_js_code_2_session',$json_arr);
|
||||
return Tools::set_ok('ok',$json_arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:创建二维码
|
||||
* 接口说明
|
||||
* 获取小程序/小游戏的二维码。该二维码可通过任意 app 扫码打开,
|
||||
* 能跳转到开发者指定的对应字节系 app 内拉起小程序/小游戏,并传入开发者指定的参数。
|
||||
* 通过该接口生成的二维码,永久有效,暂无数量限制。
|
||||
*
|
||||
* ⚠ Tip:在使用该功能之前请记得先配置您的默认分享文案和图片,配置方式可参考论坛。
|
||||
* ⚠ Tip:小程序的 path 要 encode 一次,如 pages%3fparam%3dtrue,小游戏的 path 为 JSON 字符串,
|
||||
* 如{"param":true},否则会导致取不到。
|
||||
*
|
||||
* 参数:
|
||||
* code和anonymous_code二选一 必须
|
||||
* appname 可选,目标打开应用名称 默认douyin
|
||||
* background 可选,背景色,rgb格式,英文逗号隔开,默认透明色
|
||||
* path 可选,小程序/小游戏启动参数,小程序则格式为 encode({path}?{query}),小游戏则格式为 JSON 字符串,默认为空
|
||||
* width 宽度 可选,二维码宽度,单位 px,最小 280px,最大 1280px,默认为 430px
|
||||
* line_color 可选,二维码线条颜色,默认为黑色,rgb格式,英文逗号隔开,默认黑色
|
||||
* set_icon 可选,是否展示小程序/小游戏 icon,默认不展示,传yes展示,no不展示,默认no
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function createQRCode($path='',$appname='',$width='',$background='',$line_color='',$set_icon='no'){
|
||||
try {
|
||||
$url = 'https://minigame.zijieapi.com/mgplatform/api/apps/qrcode';
|
||||
//$Scope = 'open.ttgame.mgplatform';
|
||||
$method = 'POST';
|
||||
|
||||
$json_arr = $this->realTimeGetAccessToken();
|
||||
if(empty($json_arr)){
|
||||
return Tools::set_fail('请重新授权');
|
||||
}
|
||||
|
||||
$params = [
|
||||
'access_token'=>$json_arr['data']['access_token'],
|
||||
];
|
||||
if($appname){
|
||||
$params['appname'] = $appname;
|
||||
}
|
||||
if($width){
|
||||
$params['width'] = $width;
|
||||
}
|
||||
//if($path){
|
||||
//小程序/小游戏启动参数,小程序则格式为 encode({path}?{query}),小游戏则格式为 JSON 字符串,默认为空
|
||||
$params['path'] = $path;
|
||||
//}
|
||||
//英文逗号隔开,r,g,b格式
|
||||
if($background){
|
||||
$background_rgb = explode(',',$background);
|
||||
$params['r'] = $background_rgb[0];
|
||||
$params['g'] = $background_rgb[1];
|
||||
$params['b'] = $background_rgb[2];
|
||||
}
|
||||
if($line_color){
|
||||
$line_color_rgb = explode(',',$line_color);
|
||||
$params['r'] = $line_color_rgb[0];
|
||||
$params['g'] = $line_color_rgb[1];
|
||||
$params['b'] = $line_color_rgb[2];
|
||||
}
|
||||
$params['set_icon'] = $set_icon=='yes';
|
||||
|
||||
$header = [
|
||||
'Accept: application/json',
|
||||
'content-type: application/json'
|
||||
];
|
||||
|
||||
Tools::log_to_write_txt(['input'=>input(),'$params'=>$params]);
|
||||
$res = Curl::curl_request($url,$method,json_encode($params),$header);
|
||||
Tools::log_to_write_txt(['output'=>$res]);
|
||||
|
||||
//流
|
||||
return $res;
|
||||
}catch (\Exception $e){
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
88
digital_doctor/vendor/wanghua/general-utility-tools-php/src/encrypt/TripleDES.php
vendored
Normal file
88
digital_doctor/vendor/wanghua/general-utility-tools-php/src/encrypt/TripleDES.php
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/10} {15:51}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\encrypt;
|
||||
|
||||
|
||||
/**
|
||||
* 3DES,三重数据加密算法
|
||||
*
|
||||
* Class TripleDES
|
||||
* @package wanghua\general_utility_tools_php\encrypt
|
||||
*/
|
||||
class TripleDES
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* desc:加密
|
||||
*
|
||||
* author:wh
|
||||
* @param string $value
|
||||
* @param $key
|
||||
* @return string
|
||||
*/
|
||||
public function encrypt(string $value, $key)
|
||||
{
|
||||
$value = self::PaddingPKCS7($value);
|
||||
//AES-128-ECB|不能用 AES-256-CBC|16 AES-128-CBC|16 BF-CBC|8 aes-128-gcm|需要加$tag DES-EDE3-CBC|8
|
||||
$cipher = "DES-EDE3";
|
||||
// if (in_array($cipher, openssl_get_cipher_methods())) {}
|
||||
$result = openssl_encrypt($value, $cipher, $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, "");
|
||||
return base64_encode($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @title 解密
|
||||
*
|
||||
* @param string $str 要传的参数
|
||||
* @param $key
|
||||
* @return bool|false|string
|
||||
*
|
||||
*/
|
||||
public function decrypt(string $str, $key)
|
||||
{
|
||||
$decrypted = openssl_decrypt(base64_decode($str), 'DES-EDE3', $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, "");
|
||||
$ret = self::UnPaddingPKCS7($decrypted);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $data
|
||||
* @return string
|
||||
*/
|
||||
private function PaddingPKCS7($data)
|
||||
{
|
||||
//$block_size = mcrypt_get_block_size('tripledes', 'cbc');//获取长度
|
||||
//$block_size = openssl_cipher_iv_length('tripledes', 'cbc');//获取长度
|
||||
$block_size = 8;
|
||||
$padding_char = $block_size - (strlen($data) % $block_size);
|
||||
$data .= str_repeat(chr($padding_char), $padding_char);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $text
|
||||
* @return false|string
|
||||
*/
|
||||
private function UnPaddingPKCS7($text)
|
||||
{
|
||||
$pad = ord($text{strlen($text) - 1});
|
||||
if ($pad > strlen($text)) {
|
||||
return false;
|
||||
}
|
||||
if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) {
|
||||
return false;
|
||||
}
|
||||
return substr($text, 0, -1 * $pad);
|
||||
}
|
||||
}
|
||||
20
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/AuthError.php
vendored
Normal file
20
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/AuthError.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {19:05}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class AuthError
|
||||
{
|
||||
|
||||
const PERMISSION_DENIED = [60000, '权限拒绝'];
|
||||
|
||||
const ACCESS_REFUSE_ERROR = [60100, '访问被拒绝'];//请求不合法资源
|
||||
|
||||
const ACCESS_TIMES_ERROR = [60200, '访问次数限制'];
|
||||
}
|
||||
84
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/Code.php
vendored
Normal file
84
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/Code.php
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2019/11/12} {21:01}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
/**
|
||||
* 系统级错误, 业务错误代码放在业务层,不要放在此处
|
||||
* Class SystemError
|
||||
* @package errorcode
|
||||
*/
|
||||
class Code
|
||||
{
|
||||
//region 系统级别错误
|
||||
const SUCCESS = [200, 'SUCCESS'];
|
||||
|
||||
const REQUEST_ERROR = [10000, '请求错误'];//一般url资源错误;url错误、敏感参数错误等
|
||||
|
||||
const REQUEST_TYPE_ERROR = [10001, '请求类型错误'];//ajax get post
|
||||
|
||||
const FAILED = [10002, '操作失败'];
|
||||
|
||||
const SOURCE_NOT_FIND = [10003, '资源找不到'];
|
||||
|
||||
const SYSTEM_ERROR = [500, '系统错误'];
|
||||
|
||||
const PERMISSION_DENIED = [10005, '权限拒绝'];
|
||||
|
||||
const ACCESS_REFUSE_ERROR = [10006, '访问被拒绝'];//请求不合法资源
|
||||
|
||||
const ACCESS_TIMES_ERROR = [10007, '访问次数限制'];
|
||||
//endregion 系统级别错误
|
||||
|
||||
|
||||
|
||||
//region 短信错误
|
||||
|
||||
const MESSAGE_SEND_ERROR = [13500, '短信发送失败'];
|
||||
|
||||
const MESSAGE_SEND_ULTRALIMIT = [13600, '短信发送超限'];
|
||||
|
||||
const MESSAGE_VERIFY_FAILED = [13700, '短信验证失败'];
|
||||
|
||||
const MESSAGE_NUM_LITTLE = [13800, '短信余额不足'];
|
||||
|
||||
const MESSAGE_SEND_EXCEPTION = [13900, '短信发送异常'];
|
||||
//endregion
|
||||
|
||||
//region 文件上传
|
||||
const UPLOAD_FAILED = [14000, '上传失败'];
|
||||
|
||||
const UPLOAD_FILE_IS_EMPTY = [14000, '无文件上传'];
|
||||
|
||||
const UPLOAD_FILE_SIZE_EMPTY = [14100, '文件内容为空'];
|
||||
|
||||
const UPLOAD_FILE_SIZE_ERROR = [14200, '文件大小超过限制'];
|
||||
|
||||
const UPLOAD_FILE_MIME_ERROR = [14300, '文件类型错误'];
|
||||
|
||||
const UPLOAD_FILE_EXT_ERROR = [14500, '文件扩展名错误'];
|
||||
|
||||
const FILE_FROM_ERROR = [14520, '来源错误'];
|
||||
//endregion
|
||||
|
||||
|
||||
//region 数据库错误
|
||||
const DATA_IS_EMPTY = [50000, '未获取到相关数据'];
|
||||
|
||||
const UPDATE_ERROR = [50001, '修改异常'];
|
||||
|
||||
const INSERT_ERROR = [50002, '数据保存异常'];
|
||||
|
||||
const SELECT_ERROR = [50003, '查询异常'];
|
||||
|
||||
const DATA_REPEAT_ERROR = [50005, '数据重复'];
|
||||
|
||||
const DATA_INSERT_ERROR = [50006, '数据入库异常'];
|
||||
|
||||
//endregion
|
||||
}
|
||||
30
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/DbError.php
vendored
Normal file
30
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/DbError.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:49}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class DbError
|
||||
{
|
||||
|
||||
|
||||
//region 数据库错误
|
||||
const DATA_IS_EMPTY = [16000, '未获取到相关数据'];
|
||||
|
||||
const UPDATE_ERROR = [16100, '修改异常'];
|
||||
|
||||
const INSERT_ERROR = [16200, '数据保存异常'];
|
||||
|
||||
const SELECT_ERROR = [16300, '查询异常'];
|
||||
|
||||
const DATA_REPEAT_ERROR = [16400, '数据重复'];
|
||||
|
||||
const DATA_INSERT_ERROR = [16500, '数据入库异常'];
|
||||
|
||||
//endregion
|
||||
}
|
||||
19
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/EmailError.php
vendored
Normal file
19
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/EmailError.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:47}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class EmailError
|
||||
{
|
||||
//region 邮件错误
|
||||
const EMAIL_RECEIVER_IS_EMPTY = [23100, '未设置收信人'];
|
||||
|
||||
const EMAIL_SEND_FAILED = [23200, '邮件发送失败'];
|
||||
//endregion
|
||||
}
|
||||
29
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/FileUploadError.php
vendored
Normal file
29
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/FileUploadError.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class FileUploadError
|
||||
{
|
||||
//region 文件上传
|
||||
const UPLOAD_FAILED = [24000, '上传失败'];
|
||||
|
||||
const UPLOAD_FILE_IS_EMPTY = [24100, '无文件上传'];
|
||||
|
||||
const UPLOAD_FILE_SIZE_EMPTY = [24200, '文件内容为空'];
|
||||
|
||||
const UPLOAD_FILE_SIZE_ERROR = [24300, '文件大小超过限制'];
|
||||
|
||||
const UPLOAD_FILE_MIME_ERROR = [24400, '文件类型错误'];
|
||||
|
||||
const UPLOAD_FILE_EXT_ERROR = [24500, '文件扩展名错误'];
|
||||
|
||||
const FILE_SOURCE_ERROR = [24600, '文件来源错误'];
|
||||
//endregion
|
||||
}
|
||||
19
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/LoginError.php
vendored
Normal file
19
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/LoginError.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:59}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class LoginError
|
||||
{
|
||||
|
||||
const OFF_LINE_ERROR = [30100, '未登录'];
|
||||
|
||||
const LOGIN_SESSION_INVALID = [30200, '登录已过期,请重新登录'];
|
||||
|
||||
}
|
||||
27
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/RequestError.php
vendored
Normal file
27
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/RequestError.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/3} {14:14}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class RequestError
|
||||
{
|
||||
//region 请求错误
|
||||
const SUCCESS = [200, 'SUCCESS'];
|
||||
|
||||
const REQUEST_TYPE_ERROR = [50601, '请求类型错误'];//ajax get post
|
||||
|
||||
const SOURCE_NOT_FIND = [50400, '资源找不到'];
|
||||
|
||||
const SYSTEM_ERROR = [50500, '系统错误'];
|
||||
|
||||
const REQUEST_ERROR = [50600, '请求错误'];//一般url资源错误;url错误、敏感参数错误等
|
||||
|
||||
const FAILED = [50602, '请求失败'];
|
||||
//endregion 请求错误
|
||||
}
|
||||
26
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/SmsError.php
vendored
Normal file
26
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/SmsError.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:49}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class SmsError
|
||||
{
|
||||
//region 短信错误
|
||||
|
||||
const MESSAGE_SEND_ERROR = [43500, '短信发送失败'];
|
||||
|
||||
const MESSAGE_SEND_ULTRALIMIT = [43600, '短信发送超限'];
|
||||
|
||||
const MESSAGE_VERIFY_FAILED = [43700, '短信验证失败'];
|
||||
|
||||
const MESSAGE_NUM_LITTLE = [43800, '短信余额不足'];
|
||||
|
||||
const MESSAGE_SEND_EXCEPTION = [43900, '短信发送异常'];
|
||||
//endregion
|
||||
}
|
||||
15
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/SystemError.php
vendored
Normal file
15
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/SystemError.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:50}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class SystemError
|
||||
{
|
||||
|
||||
}
|
||||
264
digital_doctor/vendor/wanghua/general-utility-tools-php/src/es/Elasticsearch.php
vendored
Normal file
264
digital_doctor/vendor/wanghua/general-utility-tools-php/src/es/Elasticsearch.php
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/4/26} {9:45}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\es;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\Date;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* @deprecated 废弃,即将删除
|
||||
*
|
||||
* 【es原生操作库】
|
||||
* 【仅支持框架ThinkPHP5+、 PHP7.2+】
|
||||
*
|
||||
* BaseElasticsearch.php类库的替代库
|
||||
*
|
||||
* 使用步骤:
|
||||
* 初始化(设置ip、索引前缀-普通索引请设置为空字符串)
|
||||
* 设置索引范围(例如查询本月,如果索引不是按日期规律设置,请使用普通索引设置方法setIndexNormal,并设置前缀为空字符串)
|
||||
* 设置查询方法(eg: _search)
|
||||
* 设置查询参数(查询条件)
|
||||
* 执行
|
||||
* 返回结果
|
||||
* Class ElasticsearchUtility
|
||||
* @package app\admin\logic
|
||||
*/
|
||||
class Elasticsearch
|
||||
{
|
||||
protected $es_log_file = 'es_log';
|
||||
//最终拼装的请求地址
|
||||
protected $post_url = ''; //eg: $url = 'http://49.4.3.4:9111/qa-item-2021.04/_search';
|
||||
//查询参数
|
||||
protected $query_param = [];
|
||||
//查询方法
|
||||
protected $query_method = '_search';
|
||||
//文档索引
|
||||
protected $index = '';
|
||||
//服务器ip
|
||||
protected $ip = '';
|
||||
//索引前缀(优先设置)
|
||||
protected $index_sign = '';//eg: qa-stat-
|
||||
//设置查询日期格式符号
|
||||
protected $doc_date_sign = '.';
|
||||
//设置是哪个方法调用本es库,用于日志记录
|
||||
protected $exe_func = '';
|
||||
|
||||
|
||||
/**
|
||||
* ElasticsearchUtility constructor.
|
||||
* @param string $ip_port 协议+服务器ip+端口号,必须
|
||||
* @param string $index_sign 当es索引为有规律的日期索引时,可使用前缀并配合日期索引设置方法,体验更佳
|
||||
*/
|
||||
public function __construct(string $ip_port, string $index_sign='')
|
||||
{
|
||||
$this->ip = false===strpos($ip_port,'http')?'http://'.$ip_port:$ip_port;
|
||||
$this->index_sign = $index_sign;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置查询方法,默认_search
|
||||
* author:wh
|
||||
* @param $method_name
|
||||
*/
|
||||
function setQueryMethod($method_name){
|
||||
$this->query_method = $method_name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:根据日期索引查询文档
|
||||
* 注:默认一个月
|
||||
*
|
||||
* eg:'qa-stat-2021.01';
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
* author:wh
|
||||
*/
|
||||
function setIndexDefault(){
|
||||
$this->setRequestIndex(date('Y'.$this->doc_date_sign.'m'));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置要查询的日期文档索引
|
||||
*
|
||||
* 1、按年检索文档[建议5年左右]
|
||||
*
|
||||
* eg: qa-stat-2018.*,qa-stat-2019.*,qa-stat-2020.*,qa-stat-2021.*
|
||||
*
|
||||
* 注意:当索引过长,es会抛出索引太长异常
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time 开始时间 eg:2010-01-01 08:05:55
|
||||
* @param string $end_time 结束时间 eg:2021-12-31 12:05:00
|
||||
* @return string
|
||||
*/
|
||||
function setIndexYearDate(string $start_time, string $end_time){
|
||||
|
||||
//默认查询索引
|
||||
$index = date('Y'.$this->doc_date_sign.'*', strtotime($start_time));
|
||||
|
||||
$sign = ',';//分隔符
|
||||
|
||||
$m = date('Y', strtotime($end_time)) - date('Y', strtotime($start_time));
|
||||
|
||||
//拼装查询索引
|
||||
for ($i=0; $i<$m; $i++){
|
||||
|
||||
$index .= $sign.($this->index_sign.(date('Y', strtotime($start_time))+$i).$this->doc_date_sign.'*');
|
||||
}
|
||||
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置日期索引
|
||||
*
|
||||
* 检索全部日期索引文档
|
||||
*
|
||||
* 例如es设置的索引为:
|
||||
* qa-stat-2021.01
|
||||
qa-stat-2021.02
|
||||
qa-stat-2021.03
|
||||
qa-stat-2021.04
|
||||
*
|
||||
* 实际查询自动设置为:qa-stat-*
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function setIndexAllDate(){
|
||||
|
||||
$this->setRequestIndex('*');
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置普通索引
|
||||
*
|
||||
* 调用此方法,请在初始化时,设置索引前缀index_sign为""空字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $index
|
||||
*/
|
||||
function setIndexNormal(string $index){
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置跨月份索引
|
||||
*
|
||||
* eg: qa-stat-2021.01,qa-stat-2021.02
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time eg:'2020-11'
|
||||
* @param string $end_time eg:'2021-01'
|
||||
* @return string eg: qa-stat-2020.11,qa-stat-2020.12,qa-stat-2021.01
|
||||
*/
|
||||
function setIndexDate(string $start_time, string $end_time){
|
||||
$date = new Date();
|
||||
|
||||
//计算月份
|
||||
$m = $date->dateCutMonth($start_time, $end_time);
|
||||
////解决跨年且不足1个月时,索引设置错误问题
|
||||
//if($m == 0 && (date('Y', strtotime($end_time)) > date('Y', strtotime($start_time)))){
|
||||
// $m = 1;
|
||||
//}
|
||||
//格式
|
||||
$date->date_format = 'Y-m';
|
||||
|
||||
//默认查询索引
|
||||
$index = date('Y'.$this->doc_date_sign.'m', strtotime($start_time));
|
||||
|
||||
$tmp_time = $start_time;
|
||||
$sign = ',';//分隔符
|
||||
|
||||
//拼装查询索引
|
||||
for ($i=0; $i<$m; $i++){
|
||||
$tmp_time = $date->addTime(1, 'M', strtotime($tmp_time));
|
||||
$index .= $sign.$this->index_sign.(date('Y'.$this->doc_date_sign.'m', strtotime($tmp_time)));
|
||||
}
|
||||
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:设置查询参数
|
||||
* author:wh
|
||||
* @param string $query_param_json
|
||||
*/
|
||||
function setQueryParam(string $query_param_json){
|
||||
$this->query_param = $query_param_json;
|
||||
$this->post_url = $this->ip.'/'.$this->index.'/'.$this->query_method;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取查询参数,用于调试
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getQueryParam(){
|
||||
return [
|
||||
'ip'=>$this->ip,
|
||||
'index_sign'=>$this->index_sign,
|
||||
'index'=>$this->index,
|
||||
'query_method'=>$this->query_method,
|
||||
'post_url'=>$this->post_url,
|
||||
'query_param'=>$this->query_param,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:执行es查询
|
||||
* author:wh
|
||||
* @return array|bool|int|string
|
||||
* @throws \Exception
|
||||
*/
|
||||
function execute(){
|
||||
if(empty($this->ip)) throw new \Exception('请设置ip');
|
||||
//if(empty($this->index_sign)) throw new \Exception('请设置索引前缀');
|
||||
if(empty($this->index)) throw new \Exception('请设置索引');
|
||||
if(empty($this->query_method)) throw new \Exception('请设置查询方法');
|
||||
if(empty($this->query_param)) throw new \Exception('请设置查询参数');
|
||||
|
||||
|
||||
|
||||
|
||||
Tools::log_to_write_txt(['exe_func'=>$this->exe_func,'request_url'=>$this->post_url,'IN'=>" | IN: ",'query_params'=>$this->query_param, 'input'=>input()], $this->es_log_file);
|
||||
$result = Tools::curl_post($this->post_url, $this->query_param);
|
||||
Tools::log_to_write_txt(['exe_func'=>$this->exe_func,'OUT'=>" | OUT: ", 'result'=>$result], $this->es_log_file);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置是哪个方法调用本es库,用于日志记录
|
||||
* author:wh
|
||||
* @param string $function
|
||||
*/
|
||||
function setExecuteFunction(string $function){
|
||||
$this->exe_func = $function;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置请求文档索引
|
||||
* author:wh
|
||||
* @param string $index
|
||||
*/
|
||||
protected function setRequestIndex(string $index){
|
||||
$this->index = $this->index_sign.$index;
|
||||
}
|
||||
|
||||
}
|
||||
1340
digital_doctor/vendor/wanghua/general-utility-tools-php/src/es/README.md
vendored
Normal file
1340
digital_doctor/vendor/wanghua/general-utility-tools-php/src/es/README.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
16
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/BaseException.php
vendored
Normal file
16
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/BaseException.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/14} {10:01}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception;
|
||||
|
||||
use think\Exception;
|
||||
|
||||
class BaseException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
27
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/README.md
vendored
Normal file
27
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/README.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# 系统业务级异常类
|
||||
1. api异常
|
||||
2. 请求异常
|
||||
3. api异常
|
||||
4. 响应异常
|
||||
5. 待扩展......
|
||||
|
||||
|
||||
|
||||
##使用说明
|
||||
例1:
|
||||
|
||||
if(empty($params)){
|
||||
//参数错误,抛出空参数异常
|
||||
throw new RequestException(RequestException::EMPTY_PARAM_ERROR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
例2:
|
||||
|
||||
//假设返回结果格式为:['code'=>200, 'msg'=>'操作成功', 'data'=>[]]
|
||||
if(is_null($result['code'])){
|
||||
//无code字段,抛出响应格式错误
|
||||
throw new ResponseException(ResponseException::RESPONSE_FORMAT_ERROR);
|
||||
}
|
||||
60
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/SystemException.php
vendored
Normal file
60
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/SystemException.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/03/08} {14:17}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception;
|
||||
|
||||
|
||||
use think\exception\Handle;
|
||||
use think\Request;
|
||||
use wanghua\general_utility_tools_php\SundryConfig;
|
||||
use wanghua\general_utility_tools_php\tool\EmailTool;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class SystemException extends Handle
|
||||
{
|
||||
public function render(\Exception $e)
|
||||
{
|
||||
// 参数验证错误
|
||||
//if ($e instanceof ValidateException) {
|
||||
// return json($e->getError(), 422);
|
||||
//}
|
||||
|
||||
// 请求异常
|
||||
//if ($e instanceof HttpException && request()->isAjax()) {
|
||||
// return response($e->getMessage(), $e->getStatusCode());
|
||||
//}
|
||||
|
||||
Tools::log_to_write_txt([
|
||||
'error'=>'系统错误.'.$e->getMessage(),
|
||||
'input'=>Request::instance()->input(),
|
||||
'error_info'=>$e->getTraceAsString()
|
||||
]);
|
||||
|
||||
$title = '新的【系统异常】,请立即处理';
|
||||
//邮件通知管理员
|
||||
$mail_content = '<p>error:'.$e->getMessage().'</p>';
|
||||
$mail_content .= '<p>url:'.request()->url(true).'</p>';
|
||||
$mail_content .= '<p>ip:'.request()->ip().'</p>';
|
||||
$mail_content .= '<p>详情请登录宝塔查看日志</p>';
|
||||
|
||||
$emails = SundryConfig::val('admin_error_log_email');
|
||||
if(config('sys_env') == 'PROD'){//线上环境才发错误邮件
|
||||
EmailTool::email_to_person($title,$mail_content,$emails);
|
||||
}
|
||||
|
||||
if(request()->LogObj){
|
||||
request()->LogObj->flush();
|
||||
}
|
||||
if(request()->ServeLogObj){
|
||||
request()->ServeLogObj->flush();
|
||||
}
|
||||
|
||||
//可以在此交由系统处理
|
||||
return parent::render($e);
|
||||
}
|
||||
}
|
||||
21
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/api/ApiException.php
vendored
Normal file
21
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/api/ApiException.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/14} {10:04}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception\api;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\exception\BaseException;
|
||||
|
||||
class ApiException extends BaseException
|
||||
{
|
||||
const API_RESPONSE_FORMAT_ERROR='The api response result is incorrectly formatted: code is not exist.';
|
||||
|
||||
|
||||
const EMPTY_PARAM_ERROR ='param is empty.';
|
||||
const EMPTY_URL_ERROR ='url of param is empty.';
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/14} {10:13}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception\request;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\exception\BaseException;
|
||||
|
||||
class RequestException extends BaseException
|
||||
{
|
||||
const EMPTY_PARAM_ERROR ='param is empty.';
|
||||
const EMPTY_URL_ERROR ='url of param is empty.';
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/14} {10:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception\response;
|
||||
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\exception\BaseException;
|
||||
|
||||
class ResponseException extends BaseException
|
||||
{
|
||||
const RESPONSE_FORMAT_ERROR='The response result is incorrectly formatted.';
|
||||
|
||||
}
|
||||
53
digital_doctor/vendor/wanghua/general-utility-tools-php/src/fastadmin/FastadminTools.php
vendored
Normal file
53
digital_doctor/vendor/wanghua/general-utility-tools-php/src/fastadmin/FastadminTools.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/1/16} {17:15}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\fastadmin;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* 为fastadmin框架定制的功能
|
||||
*
|
||||
* Class FastadminTools
|
||||
* @package wanghua\general_utility_tools_php\fastadmin
|
||||
*/
|
||||
class FastadminTools
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:线上需要自动隐藏的菜单
|
||||
*
|
||||
* 当你有这种需求:
|
||||
* 我的菜单只需要本地显示,线上或非本地环境不需要显示时,就可以使用此方法。
|
||||
* 为什么需要此方法?
|
||||
* 因为,我每次在本地增加功能并新增菜单之后,都需要把本地的菜单同步到线上,但是命令管理菜单,或者有些只需要开发者才能
|
||||
* 动的菜单,需要在线上隐藏。我又不想每次同步之后去改菜单表。
|
||||
* 手动去菜单表改也是可以,但是次数多了就很麻烦,有时候会忘记。
|
||||
*
|
||||
* 如:命令管理菜单、开发者相关配置
|
||||
*
|
||||
* author:wh
|
||||
* @param array $menu_arr 需要隐藏的菜单数组
|
||||
* @param string $sys_env
|
||||
* @return bool
|
||||
*/
|
||||
static function auto_hidden_menu_online(array $menu_arr, string $sys_env){
|
||||
|
||||
foreach ($menu_arr as $menu_name){
|
||||
if($sys_env == 'LOCAL'){
|
||||
//本地显示
|
||||
Db::table('fa_auth_rule')->where('name',$menu_name)->data(['status'=>'normal'])->update();
|
||||
}else{
|
||||
Db::table('fa_auth_rule')->where('name',$menu_name)->data(['status'=>'hidden'])->update();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
236
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/File.php
vendored
Normal file
236
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/File.php
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/2/4} {16:59}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\file;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 文件、文件夹操作类
|
||||
*
|
||||
* eg:读取文件夹、复制文件等
|
||||
*
|
||||
* Class FileOperate
|
||||
* @package wanghua\general_utility_tools_php\file
|
||||
*/
|
||||
class File
|
||||
{
|
||||
|
||||
public $file_ext = '*.*';//扩展名
|
||||
public $unzip_path = '';//解压路径
|
||||
|
||||
/**
|
||||
* desc:读取文件和文件夹
|
||||
*
|
||||
* author:wh
|
||||
* @param $folderPath 读取目标路径下的文件夹和文件
|
||||
*
|
||||
* @param $dirs 存储文件路径 eg:D:\wanghua\old_files
|
||||
*
|
||||
//array(3) {
|
||||
// [0] => array(1) {
|
||||
// ["path"] => string(25) "D:\wanghua\test_files/111"
|
||||
// }
|
||||
// [1] => array(1) {
|
||||
// ["path"] => string(25) "D:\wanghua\test_files/222"
|
||||
// }
|
||||
//}
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param $file_name_arr 存储文件路径、文件名称
|
||||
*
|
||||
//array(64) {
|
||||
// [0] => array(3) {
|
||||
// ["path"] => string(25) "D:\wanghua\test_files/111"
|
||||
// ["path_file"] => string(33) "D:\wanghua\test_files/111/111.txt"
|
||||
// ["filename"] => string(7) "111.txt"
|
||||
// }
|
||||
// [1] => array(3) {
|
||||
// ["path"] => string(25) "D:\wanghua\test_files/111"
|
||||
// ["path_file"] => string(37) "D:\wanghua\test_files/111/1111111.txt"
|
||||
// ["filename"] => string(11) "1111111.txt"
|
||||
// }
|
||||
//}
|
||||
*/
|
||||
function read_folder($folderPath,&$dirs,&$file_name_arr) {
|
||||
// 获取指定目录下所有文件和文件夹
|
||||
$files = scandir($folderPath);
|
||||
foreach ($files as $file) {
|
||||
// 如果当前项为文件夹且不是"."或者".."
|
||||
if (is_dir("$folderPath/$file") && !in_array($file, array('.', '..'))) {
|
||||
$dirs[] = ['path'=>$folderPath.'/'.$file];//此时的$file是文件夹名称
|
||||
// 调用自身进行递归操作
|
||||
$this->read_folder("$folderPath/$file",$dirs,$file_name_arr);
|
||||
} elseif (!in_array($file, array('.', '..'))){ // 如果当前项为文件而非"."或者".."
|
||||
$file_name_arr[] = ['path'=>$folderPath,'path_file'=>"$folderPath/$file",'filename'=>$file];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:复制文件
|
||||
*
|
||||
* author:wh
|
||||
* @param array $sourceFileArr 源文件路径数组 path,path_file,filename
|
||||
*
|
||||
* @param string $destination_path 目标存放路径 D:\wanghua\test_files\new_files
|
||||
*
|
||||
* @param array $cp_type_arr 允许复制的文件后缀 eg:['jpg','png,'spine']
|
||||
*
|
||||
* @param bool $is_cover 是否覆盖 默认false,不覆盖会以源文件名+微秒时间戳格式作为新的文件名
|
||||
*
|
||||
* @param bool $is_continue 相同文件是否跳过复制 默认 true
|
||||
*
|
||||
* 实战案例:
|
||||
*
|
||||
function testcopy(){
|
||||
$source_dir = 'D:\wanghua\test_files';//源文件路径
|
||||
$destination_path = 'D:\wanghua\test_files\new_files';//目标文件路径
|
||||
|
||||
$dirs = [];//存储文件路径
|
||||
$file_name_arr = [];//含文件路径、名称
|
||||
$file_obj = new File();
|
||||
$file_obj->read_folder($source_dir,$dirs,$file_name_arr);
|
||||
//dump($dirs);
|
||||
//dump($file_name_arr);die;
|
||||
$file_obj->copy($file_name_arr,$destination_path,['jpg','png,'spine']);
|
||||
}
|
||||
*
|
||||
*/
|
||||
function copy(array $sourceFileArr, string $destination_path, $cp_type_arr=['jpg','png'], $is_cover=false, $is_continue=false){
|
||||
//设置不超时
|
||||
set_time_limit(0);
|
||||
//源文件路径 => 目标文件路径
|
||||
foreach ($sourceFileArr as $key=>$file_arr){
|
||||
if(!file_exists($file_arr['path_file'])){
|
||||
continue;
|
||||
}
|
||||
//验证目标文件夹路径
|
||||
if(!file_exists($destination_path)){
|
||||
mkdir($destination_path,0777,true);
|
||||
}
|
||||
$name_arr = explode('.',$file_arr['filename']);
|
||||
//验证符合条件的文件类型
|
||||
if(!in_array($name_arr[1],$cp_type_arr)){
|
||||
continue;
|
||||
}
|
||||
if(file_exists($destination_path.'/'.$file_arr['filename'])){
|
||||
if($is_continue){
|
||||
continue;//相同文件跳过复制
|
||||
}
|
||||
//覆盖
|
||||
if($is_cover){
|
||||
copy($file_arr['path_file'], $destination_path.'/'.$file_arr['filename']);
|
||||
}else{
|
||||
//不覆盖,名称区分
|
||||
$microsecond = Tools::getMicrosecond();
|
||||
copy($file_arr['path_file'], $destination_path.'/'.$name_arr[0].'('.$microsecond.').'.$name_arr[1]);
|
||||
}
|
||||
}else{
|
||||
copy($file_arr['path_file'], $destination_path.'/'.$file_arr['filename']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:递归删除目录
|
||||
*
|
||||
* $dir 物理路径
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function recursive_delete($dir) {
|
||||
if (!is_dir($dir)) {
|
||||
return unlink($dir);
|
||||
}
|
||||
|
||||
$handle = opendir($dir);
|
||||
while (($file = readdir($handle)) !== false) {
|
||||
if ($file === '.' || $file === '..') {
|
||||
continue;
|
||||
}
|
||||
$path = $dir . DIRECTORY_SEPARATOR . $file;
|
||||
if (is_dir($path)) {
|
||||
$this->recursive_delete($path);
|
||||
} else {
|
||||
unlink($path);
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
rmdir($dir);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:解压ZIP文件并存储在本地
|
||||
* author:wh
|
||||
* @param resource $file_stream 文件流
|
||||
* 例如:$response = $client->request('POST', $url, [
|
||||
'headers' => $headers,
|
||||
'body' => $body,
|
||||
]);
|
||||
// 处理响应
|
||||
//$file_stream = $response->getBody();
|
||||
* @param string $save_path 存储路径
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
function unzip($file_stream,$save_path){
|
||||
$zpi_file_name = 'zip_tmp_file_'.Tools::rand_str(20).'.zip';
|
||||
//这个目录将会在结束时删除
|
||||
$zipTempPath = $save_path.'/tmp_zip_files/'; // 临时存放ZIP文件的路径
|
||||
//压缩文件保存目录
|
||||
if(!file_exists($zipTempPath)){
|
||||
mkdir($zipTempPath,0777,true);
|
||||
}
|
||||
$zpi_file = $zipTempPath.$zpi_file_name;
|
||||
// 保存ZIP文件到临时路径
|
||||
file_put_contents($zpi_file, $file_stream);
|
||||
|
||||
$this->unzip_path = $zipTempPath.'unzip_files/';
|
||||
//解压目录
|
||||
if(!file_exists( $this->unzip_path)){
|
||||
mkdir( $this->unzip_path,0777,true);
|
||||
}
|
||||
// 解压ZIP文件
|
||||
$zip = new \ZipArchive();
|
||||
if ($zip->open($zpi_file) === TRUE) {
|
||||
$zip->extractTo( $this->unzip_path);//移动到临时解压目录
|
||||
$zip->close();
|
||||
//遍历所有文件(file_ext后缀自行指定),遍历部分文件,如:*.json,*.zip,*.mp4,*.mp3等
|
||||
$wavFiles = $this->glob_by_ext( $this->unzip_path.$this->file_ext);
|
||||
|
||||
//$urls = [];
|
||||
//// 遍历解压后的文件,生成URL
|
||||
//foreach ($wavFiles as $wavFilePath) {
|
||||
// // 生成外部访问的URL
|
||||
// $downloadUrl = request()->domain() . explode('public',$wavFilePath)[1];
|
||||
// $urls[] = $downloadUrl;
|
||||
//}
|
||||
//// 返回所有WAV文件的URL
|
||||
//return ['wav_urls' => $urls];
|
||||
return $wavFiles;
|
||||
} else {
|
||||
throw new \Exception('Failed to open ZIP file.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取指定扩展类型的文件列表
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_ext 如: wav,pm4,mp3,json,zip
|
||||
* @return array|false
|
||||
*/
|
||||
function glob_by_ext($file_ext='*'){
|
||||
return glob( $this->unzip_path.'*.'.$file_ext);
|
||||
}
|
||||
}
|
||||
5
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/README.MD
vendored
Normal file
5
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/README.MD
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
## 文件处理
|
||||
|
||||
#### 文件夹读取,文件复制
|
||||
|
||||
#### 文件上传
|
||||
764
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/upload/FileUpload.php
vendored
Normal file
764
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/upload/FileUpload.php
vendored
Normal file
@@ -0,0 +1,764 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/4/3} {9:23}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\file\upload;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\oss\alicloud\Objects;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\MultipartStream;
|
||||
use GuzzleHttp\Psr7\Utils;
|
||||
use wanghua\general_utility_tools_php\huawei\obs\InitObs;
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\oss\huawei\obs\Config;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 上传组件
|
||||
* 支持单图,多图,单文件,多文件
|
||||
* Class FileUpload
|
||||
* @package libraries
|
||||
*/
|
||||
class FileUpload
|
||||
{
|
||||
//文件扩展
|
||||
protected $file_ext = 'ico,jpg,jpeg,png,gif,pdf,zip,rar,xls,xlsx,doc,docx';
|
||||
//图片扩展
|
||||
protected $img_ext = 'ico,jpg,jpeg,png,gif';
|
||||
|
||||
public $unique_key = '';//唯一key,临时文件会存储至该目录,推荐使用用户id
|
||||
|
||||
public $file_lists_urls = [];//要读取的文件地址列表
|
||||
/**
|
||||
* 文件存放目录
|
||||
*
|
||||
* 注意:后面不要“/”
|
||||
* 注意:后面不要“/”
|
||||
* 注意:后面不要“/”
|
||||
* @var string
|
||||
*/
|
||||
private $file_dir = '/uploads';
|
||||
|
||||
/**
|
||||
* desc:默认目录/uploads
|
||||
*
|
||||
* eg:/uploads/user/head_image 或 /files_manage/goods/images
|
||||
*
|
||||
* 注意:后面不要“/”
|
||||
* 注意:后面不要“/”
|
||||
* 注意:后面不要“/”
|
||||
*
|
||||
* author:wh
|
||||
* @param $file_dir
|
||||
*/
|
||||
function setFileDir($file_dir){
|
||||
$this->file_dir = $file_dir;
|
||||
}
|
||||
/**
|
||||
* desc:单图
|
||||
*
|
||||
* 【!!!必须确认php.ini中upload_max_filesize的配置足够大,否则上传失败但不会报错!!!】
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_upload_name 表单文件元素name值
|
||||
* @param int $size 大小,默认2M
|
||||
* @param string $ext 允许的扩展
|
||||
* @return array
|
||||
*/
|
||||
function image($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
if(!$this->uploadMaxFilesizeCheck($size)){
|
||||
return Tools::set_res(1, '上传文件受限');
|
||||
}
|
||||
// 获取表单上传文件 例如上传了001.jpg
|
||||
$file = request()->file($file_upload_name);
|
||||
if(empty($file)){
|
||||
return Tools::set_fail('请上传文件');
|
||||
}
|
||||
// 移动到框架应用根目录/uploads/ 目录下
|
||||
$outer_req_url = $this->file_dir.'/image';
|
||||
$physics_path = 'public'.$outer_req_url;
|
||||
$root_path = explode('vendor',__DIR__)[0];
|
||||
$upload_dir = $root_path.$physics_path;
|
||||
if(!is_dir($upload_dir)){
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
if(empty($file)){
|
||||
return Tools::set_res(1, '上传文件不存在');
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->img_ext;
|
||||
|
||||
$info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
|
||||
if($info){
|
||||
//原文件名
|
||||
$source_file_name = $info->getInfo('name');
|
||||
|
||||
//文件类型
|
||||
$file_type = $info->getInfo('type');
|
||||
|
||||
// 输出扩展名 jpg
|
||||
$extension = $info->getExtension();
|
||||
|
||||
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
|
||||
$save_name = $info->getSaveName();
|
||||
|
||||
// 输出 42a79759f284b767dfcb2a0197904287.jpg
|
||||
$new_filename = $info->getFilename();
|
||||
|
||||
$relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
|
||||
$result = [
|
||||
'prefix'=>request()->domain().$outer_req_url,//访问前缀
|
||||
'source_file_name'=>$source_file_name,
|
||||
'file_type'=>$file_type,
|
||||
'extension'=>$extension,
|
||||
'save_name'=>str_replace('\\', '/', $save_name),
|
||||
'new_filename'=>$new_filename,
|
||||
'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
|
||||
'outer_req_url'=>request()->domain().$relative_url,
|
||||
'outer_req_relative_url'=>$relative_url,
|
||||
'size'=>$info->getSize(),
|
||||
];
|
||||
return Tools::set_res(0, '上传成功', $result);
|
||||
}else{
|
||||
// 上传失败获取错误信息
|
||||
return Tools::set_res(1, $file->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:多图
|
||||
*
|
||||
* 【!!!必须确认php.ini中upload_max_filesize的配置足够大,否则上传失败但不会报错!!!】
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_upload_name 表单文件元素name值
|
||||
* @param int $size 大小,默认2M
|
||||
* @param string $ext 允许的扩展
|
||||
* @return array
|
||||
*/
|
||||
function images($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
if(!$this->uploadMaxFilesizeCheck($size)){
|
||||
return Tools::set_res(1, '上传文件受限');
|
||||
}
|
||||
// 获取表单上传文件
|
||||
$files = request()->file($file_upload_name);
|
||||
if(empty($files)){
|
||||
return Tools::set_fail('请上传文件');
|
||||
}
|
||||
$outer_req_url = $this->file_dir.'/image';
|
||||
$physics_path = 'public'.$outer_req_url;
|
||||
$root_path = explode('vendor',__DIR__)[0];
|
||||
$upload_dir = $root_path.$physics_path;
|
||||
if(!is_dir($upload_dir)){
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->img_ext;
|
||||
|
||||
$result = [];
|
||||
$error = [];
|
||||
foreach($files as $file){
|
||||
// 移动到框架应用根目录/uploads/ 目录下
|
||||
$info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
|
||||
if($info){
|
||||
//原文件名
|
||||
$source_file_name = $info->getInfo('name');
|
||||
|
||||
//文件类型
|
||||
$file_type = $info->getInfo('type');
|
||||
|
||||
// 输出扩展名 jpg
|
||||
$extension = $info->getExtension();
|
||||
|
||||
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
|
||||
$save_name = $info->getSaveName();
|
||||
|
||||
// 输出 42a79759f284b767dfcb2a0197904287.jpg
|
||||
$new_filename = $info->getFilename();
|
||||
|
||||
$relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
|
||||
$result[] = [
|
||||
'prefix'=>request()->domain().$outer_req_url,//访问前缀
|
||||
'source_file_name'=>$source_file_name,
|
||||
'file_type'=>$file_type,
|
||||
'extension'=>$extension,
|
||||
'save_name'=>str_replace('\\', '/', $save_name),
|
||||
'new_filename'=>$new_filename,
|
||||
'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
|
||||
'outer_req_url'=>request()->domain().$relative_url,
|
||||
'outer_req_relative_url'=>$relative_url,
|
||||
'size'=>$info->getSize(),
|
||||
];
|
||||
}else{
|
||||
//忽略错误
|
||||
// 上传失败获取错误信息
|
||||
$error[] = $file->getError();
|
||||
}
|
||||
}
|
||||
|
||||
$msg = '上传成功';
|
||||
$code = 0;
|
||||
if(count($error) > 0){
|
||||
$msg = '上传失败;提示:'.implode(',', $error);//顺带返回错误信息
|
||||
$code = 1;
|
||||
}
|
||||
return Tools::set_res($code, $msg, $result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:单文件
|
||||
*
|
||||
* 【!!!必须确认php.ini中upload_max_filesize的配置足够大,否则上传失败但不会报错!!!】
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_upload_name 表单文件元素name值
|
||||
* @param int $size 大小,默认10M
|
||||
* @param string $ext 允许的扩展
|
||||
* @return array
|
||||
*/
|
||||
function file($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
if(!$this->uploadMaxFilesizeCheck($size)){
|
||||
return Tools::set_res(1, '上传文件受限');
|
||||
}
|
||||
// 获取表单上传文件 例如上传了001.jpg
|
||||
$file = request()->file($file_upload_name);
|
||||
if(empty($file)){
|
||||
return Tools::set_fail('请上传文件');
|
||||
}
|
||||
// 移动到框架应用根目录/uploads/ 目录下
|
||||
$outer_req_url = $this->file_dir.'/file';
|
||||
$physics_path = 'public'.$outer_req_url;
|
||||
|
||||
$root_path = explode('vendor',__DIR__)[0];
|
||||
|
||||
$upload_dir = $root_path.$physics_path;
|
||||
if(!is_dir($upload_dir)){
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
if(empty($file)){
|
||||
return Tools::set_res(1, '上传文件不存在');
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
|
||||
$info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
|
||||
if($info){
|
||||
//原文件名
|
||||
$source_file_name = $info->getInfo('name');
|
||||
|
||||
//文件类型
|
||||
$file_type = $info->getInfo('type');
|
||||
|
||||
// 输出扩展名 jpg
|
||||
$extension = $info->getExtension();
|
||||
|
||||
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
|
||||
$save_name = $info->getSaveName();
|
||||
|
||||
// 输出 42a79759f284b767dfcb2a0197904287.jpg
|
||||
$new_filename = $info->getFilename();
|
||||
|
||||
$relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
|
||||
$result = [
|
||||
'prefix'=>request()->domain().$outer_req_url,//访问前缀
|
||||
'source_file_name'=>$source_file_name,
|
||||
'file_type'=>$file_type,
|
||||
'extension'=>$extension,
|
||||
'save_name'=>str_replace('\\', '/', $save_name),
|
||||
'new_filename'=>$new_filename,
|
||||
'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
|
||||
'outer_req_url'=>request()->domain().$relative_url,
|
||||
'outer_req_relative_url'=>$relative_url,
|
||||
'size'=>$info->getSize(),
|
||||
];
|
||||
return Tools::set_res(0, '上传成功', $result);
|
||||
}else{
|
||||
// 上传失败获取错误信息
|
||||
return Tools::set_res(1, $file->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:多文件
|
||||
*
|
||||
* 【!!!必须确认php.ini中upload_max_filesize的配置足够大,否则上传失败但不会报错!!!】
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_upload_name 表单文件元素name值
|
||||
* @param int $size 单文件大小,默认10M
|
||||
* @param string $ext 允许的扩展
|
||||
* @return array
|
||||
*/
|
||||
function files($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
if(!$this->uploadMaxFilesizeCheck($size)){
|
||||
return Tools::set_res(1, '上传文件受限');
|
||||
}
|
||||
|
||||
$root_path = explode('vendor',__DIR__)[0];
|
||||
// 获取表单上传文件
|
||||
$files = request()->file($file_upload_name);
|
||||
if(empty($files)){
|
||||
return Tools::set_fail('请上传文件');
|
||||
}
|
||||
$outer_req_url = $this->file_dir.'/file';
|
||||
$physics_path = 'public'.$outer_req_url;
|
||||
$upload_dir = $root_path.$physics_path;
|
||||
if(!is_dir($upload_dir)){
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
|
||||
$result = [];
|
||||
$error = [];
|
||||
foreach($files as $file){
|
||||
// 移动到框架应用根目录/uploads/ 目录下
|
||||
$info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
|
||||
if($info){
|
||||
//原文件名
|
||||
$source_file_name = $info->getInfo('name');
|
||||
|
||||
//文件类型
|
||||
$file_type = $info->getInfo('type');
|
||||
|
||||
// 输出扩展名 jpg
|
||||
$extension = $info->getExtension();
|
||||
|
||||
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
|
||||
$save_name = $info->getSaveName();
|
||||
|
||||
// 输出 42a79759f284b767dfcb2a0197904287.jpg
|
||||
$new_filename = $info->getFilename();
|
||||
|
||||
$relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
|
||||
$result[] = [
|
||||
'prefix'=>request()->domain().$outer_req_url,//访问前缀
|
||||
'source_file_name'=>$source_file_name,
|
||||
'file_type'=>$file_type,
|
||||
'extension'=>$extension,
|
||||
'save_name'=>str_replace('\\', '/', $save_name),
|
||||
'new_filename'=>$new_filename,
|
||||
'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
|
||||
'outer_req_url'=>request()->domain().$relative_url,
|
||||
'outer_req_relative_url'=>$relative_url,
|
||||
'size'=>$info->getSize(),
|
||||
];
|
||||
}else{
|
||||
//忽略错误
|
||||
// 上传失败获取错误信息
|
||||
$error[] = $file->getError();
|
||||
}
|
||||
}
|
||||
$msg = '上传成功';
|
||||
$code = 0;
|
||||
if(count($error) > 0){
|
||||
$msg = '上传失败;提示:'.implode(',', $error);//顺带返回错误信息
|
||||
$code = 1;
|
||||
}
|
||||
return Tools::set_res($code, $msg, $result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:单文件或多文件上传至阿里云OSS服务
|
||||
*
|
||||
* author:wh
|
||||
* @param array $config 配置
|
||||
* //阿里云oss配置
|
||||
'aliyun_oss_config' => [
|
||||
//项目应用名称
|
||||
'bucket'=>'wanlliuyinli-adm',//每创建一个bucket必须标明前缀,代表这个bucket属于哪个项目
|
||||
'UserPrincipalName'=>'wanghua@1113242774600735.onaliyun.com',
|
||||
'Password'=>'0osE4cGo%tllnP1|uOQADPhM}Y?obR4U',
|
||||
'AccessKeyId'=>'LTAI5tPqn1n7jugviVoGqFfa',
|
||||
'AccessKeySecret'=>'BRoB5TdcUAFEuIR11BbN3R47Cm4Yep',
|
||||
//https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.41ae2effA6oZar
|
||||
'region_id'=>'cn-chengdu',//这里配置不能包含oss-前缀,否则提示:Invalid signing region in Authorization header
|
||||
//西南1(成都)
|
||||
//oss-cn-chengdu
|
||||
//oss-cn-chengdu.aliyuncs.com
|
||||
//oss-cn-chengdu-internal.aliyuncs.com
|
||||
'endpoint'=>'oss-cn-chengdu.aliyuncs.com',//成都节点
|
||||
'sts_endpoint'=>'sts.cn-chengdu.aliyuncs.com',//sts服务节点
|
||||
]
|
||||
* @param string $unique_id 唯一id,可以是用户id,可以是其它用于区分的标识,默认存放在(项目名称/控制器/方法/(唯一标识,可为空)/年月日/*.jpg)
|
||||
* @param string $file_upload_name 文件上传控件的name值,必须带[],例如:file_upload[]
|
||||
* @param string $oss_type oss类型,可选值:ali_cloud 阿里云,hua_wei 华为云(待扩展)
|
||||
* @param int $size 单文件大小,默认10M
|
||||
* @param string $ext 允许的文件扩展名
|
||||
* @return array
|
||||
*/
|
||||
function filesUploadToAliCloudOss($config,$unique_id='',$file_upload_name = 'file_upload',$size=10, $ext=''){
|
||||
return Mmodel::catch(function ()use ($config,$unique_id,$file_upload_name,$size,$ext){
|
||||
$ini_upload_max_filesize = str_replace('M','',ini_get('upload_max_filesize'));
|
||||
if(($size > $ini_upload_max_filesize)){
|
||||
return Tools::set_res(1, '上传文件size受限,不能超过upload_max_filesize='.ini_get('upload_max_filesize').'M');
|
||||
}
|
||||
// 获取表单上传文件
|
||||
$files = request()->file($file_upload_name);
|
||||
if(empty($files)){
|
||||
return Tools::set_fail('请上传文件');
|
||||
}
|
||||
//扩展
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
//初始化阿里云OSS客户端
|
||||
$oss_obj= new Objects($config);
|
||||
//默认存储地址
|
||||
$file_save_dir = $this->setFileSaveDir($unique_id);
|
||||
$urls = [];
|
||||
foreach($files as $file){
|
||||
if(!$file->isValid()){
|
||||
return Tools::set_fail('文件不合法');
|
||||
}
|
||||
$check_size = $file->checkSize($size*1024*1024);
|
||||
if(!$check_size){
|
||||
return Tools::set_fail('文件大小超限');
|
||||
}
|
||||
$check_res = $file->checkExt($ext);
|
||||
if(!$check_res){
|
||||
return Tools::set_fail('请上传合法文件');
|
||||
}
|
||||
$extension = explode('.',$file->getInfo('name'))[1];
|
||||
$new_filename = 'file_'.Tools::rand_str(18).'.'.explode('.',$file->getInfo('name'))[1];
|
||||
//必须加后缀
|
||||
$filename = $file_save_dir.$new_filename;
|
||||
|
||||
// 从文件流上传
|
||||
$res = $oss_obj->fileUpload($filename, $file->getInfo('tmp_name'));//上传之前的临时文件物理地址
|
||||
$urls[] = [
|
||||
'prefix'=>explode('.com',$res['info']['url'])[0].'.com',//访问前缀
|
||||
'source_file_name'=>$file->getInfo('name'),//源文件名
|
||||
'size'=>$file->getInfo('size'),//大小(b)
|
||||
'extension'=>$extension,//扩展名
|
||||
'file_type'=>$file->getInfo('type'),//文件后缀
|
||||
'save_name'=>$filename,//保存文件名
|
||||
'new_filename'=>$new_filename,//新文件名
|
||||
'real_path'=>$res['info']['url'],//实际路径
|
||||
'outer_req_url'=>$res['info']['url'],//外部访问地址
|
||||
'outer_req_relative_url'=>$res['info']['url'],//外部访问相对地址
|
||||
];
|
||||
}
|
||||
return Tools::set_ok('ok', $urls);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:单文件上传至阿里云OSS
|
||||
*
|
||||
* author:wh
|
||||
* @param array $config 配置
|
||||
* //阿里云oss配置
|
||||
'aliyun_oss_config' => [
|
||||
//项目应用名称
|
||||
'bucket'=>'wanlliuyinli-adm',//每创建一个bucket必须标明前缀,代表这个bucket属于哪个项目
|
||||
'UserPrincipalName'=>'wanghua@1113242774600735.onaliyun.com',
|
||||
'Password'=>'0osE4cGo%tllnP1|uOQADPhM}Y?obR4U',
|
||||
'AccessKeyId'=>'LTAI5tPqn1n7jugviVoGqFfa',
|
||||
'AccessKeySecret'=>'BRoB5TdcUAFEuIR11BbN3R47Cm4Yep',
|
||||
//https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.41ae2effA6oZar
|
||||
'region_id'=>'cn-chengdu',//这里配置不能包含oss-前缀,否则提示:Invalid signing region in Authorization header
|
||||
//西南1(成都)
|
||||
//oss-cn-chengdu
|
||||
//oss-cn-chengdu.aliyuncs.com
|
||||
//oss-cn-chengdu-internal.aliyuncs.com
|
||||
'endpoint'=>'oss-cn-chengdu.aliyuncs.com',//成都节点
|
||||
'sts_endpoint'=>'sts.cn-chengdu.aliyuncs.com',//sts服务节点
|
||||
]
|
||||
* @param string $unique_id 唯一id,可以是用户id,可以是其它用于区分的标识,默认存放在(项目名称/控制器/方法/(唯一标识,可为空)/年月日/*.jpg)
|
||||
* @param string $file_upload_name 文件上传控件的name值,例如:file_upload
|
||||
* @param string $oss_type oss类型,可选值:ali_cloud 阿里云,hua_wei 华为云(待扩展)
|
||||
* @param int $size 单文件大小,默认10M
|
||||
* @param string $ext 允许的文件扩展名
|
||||
* @return array
|
||||
*/
|
||||
function fileUploadToAliCloudOss($config,$unique_id='',$file_upload_name = 'file_upload',$size=10, $ext=''){
|
||||
return Mmodel::catch(function ()use ($config,$unique_id,$file_upload_name,$size,$ext){
|
||||
$ini_upload_max_filesize = str_replace('M','',ini_get('upload_max_filesize'));
|
||||
if(($size > $ini_upload_max_filesize)){
|
||||
return Tools::set_res(1, '上传文件size受限,不能超过upload_max_filesize='.ini_get('upload_max_filesize').'M');
|
||||
}
|
||||
// 获取表单上传文件
|
||||
$file = request()->file($file_upload_name);
|
||||
if(empty($file)){
|
||||
return Tools::set_fail('请上传文件');
|
||||
}
|
||||
//扩展
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
//初始化阿里云OSS客户端
|
||||
$oss_obj= new Objects($config);
|
||||
//默认存储地址
|
||||
$file_save_dir = $this->setFileSaveDir($unique_id);
|
||||
$urls = [];
|
||||
if(!$file->isValid()){
|
||||
return Tools::set_fail('文件不合法');
|
||||
}
|
||||
$check_size = $file->checkSize($size*1024*1024);
|
||||
if(!$check_size){
|
||||
return Tools::set_fail('文件大小超限');
|
||||
}
|
||||
$check_res = $file->checkExt($ext);
|
||||
if(!$check_res){
|
||||
return Tools::set_fail('请上传合法文件');
|
||||
}
|
||||
$extension = explode('.',$file->getInfo('name'))[1];
|
||||
$new_filename = 'file_'.Tools::rand_str(18).'.'.explode('.',$file->getInfo('name'))[1];
|
||||
//必须加后缀
|
||||
$filename = $file_save_dir.$new_filename;
|
||||
|
||||
// 从文件流上传
|
||||
$res = $oss_obj->fileUpload($filename, $file->getInfo('tmp_name'));//上传之前的临时文件物理地址
|
||||
$urls[] = [
|
||||
'prefix'=>explode('.com',$res['info']['url'])[0].'.com',//访问前缀
|
||||
'source_file_name'=>$file->getInfo('name'),//源文件名
|
||||
'size'=>$file->getInfo('size'),//大小(b)
|
||||
'extension'=>$extension,//扩展名
|
||||
'file_type'=>$file->getInfo('type'),//文件后缀
|
||||
'save_name'=>$filename,//保存文件名
|
||||
'new_filename'=>$new_filename,//新文件名
|
||||
'real_path'=>$res['info']['url'],//实际路径
|
||||
'outer_req_url'=>$res['info']['url'],//外部访问地址
|
||||
'outer_req_relative_url'=>$res['info']['url'],//外部访问相对地址
|
||||
];
|
||||
return Tools::set_ok('ok', $urls);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置文件保存目录
|
||||
* author:wh
|
||||
* @param string $unique_id 唯一id,可以是用户id,可以是其它用于区分的标识
|
||||
* @return string
|
||||
*/
|
||||
function setFileSaveDir($unique_id=''){
|
||||
if($unique_id){
|
||||
$unique_id = $unique_id.'/';
|
||||
}
|
||||
//项目名称
|
||||
$project_name = Tools::get_project_name();
|
||||
//控制器方法路径
|
||||
$ctl = strtolower(request()->controller().'/'.request()->action());
|
||||
return $project_name.'/'.$ctl.'/'.$unique_id.date('Ymd').'/';//日期
|
||||
}
|
||||
/**
|
||||
* desc:检测size是否在ini配置范围
|
||||
*
|
||||
* author:wh
|
||||
* @param $size
|
||||
* @return bool
|
||||
*/
|
||||
private function uploadMaxFilesizeCheck($size){
|
||||
$ini_upload_max_filesize = str_replace('M','',ini_get('upload_max_filesize'));
|
||||
return $size<=$ini_upload_max_filesize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:上传base64格式图片【文件不用base64传输】
|
||||
* author:wh
|
||||
* @param string $file_upload_name
|
||||
* @param int $size
|
||||
* @param array $ext
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
function uploadBase64Img($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
$source = input($file_upload_name, 'file_upload');
|
||||
$file_size = strlen($source);
|
||||
if($file_size > $size * 1024 * 1024){
|
||||
return Tools::set_res(1, '上传失败,大小限制');
|
||||
}
|
||||
if(preg_match('/^(data:\s*image\/(\w+);base64,)/', $source, $result) < 1){
|
||||
return Tools::set_res(1, '上传文件不合法');
|
||||
}
|
||||
$type = $result[2];
|
||||
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
|
||||
if(!in_array($type, explode($ext))){
|
||||
return Tools::set_res(1, '上传失败,类型限制');
|
||||
}
|
||||
$result = base64_image_content($source);
|
||||
if(false === $result){
|
||||
return Tools::set_res(1, '上传失败');
|
||||
}
|
||||
return Tools::set_res(0, '上传成功', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:批量上传base64格式图片【文件不用base64传输】
|
||||
* author:wh
|
||||
* @param string $file_upload_name
|
||||
* @param int $size
|
||||
* @param array $ext
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
function uploadBase64Imgs($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
$source_list = input($file_upload_name, 'file_upload');
|
||||
if(!is_array($source_list)){
|
||||
return Tools::set_res(1, '参数错误');
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
|
||||
$result = [];
|
||||
$error = [];
|
||||
foreach ($source_list as $source){
|
||||
$file_size = strlen($source);
|
||||
if($file_size > $size * 1024 * 1024){
|
||||
$error[] = '上传失败,大小限制';
|
||||
continue;
|
||||
}
|
||||
if(preg_match('/^(data:\s*image\/(\w+);base64,)/', $source, $temp) < 1){
|
||||
$error[] = '上传文件不合法';
|
||||
continue;
|
||||
}
|
||||
$type = $temp[2];
|
||||
if(!in_array($type, explode(',', $ext))){
|
||||
$error[] = '类型限制';
|
||||
continue;
|
||||
}
|
||||
$up_result = base64_image_content($source);
|
||||
if(false === $up_result){
|
||||
$error[] = '上传失败';
|
||||
continue;
|
||||
}
|
||||
$result[] = $up_result;
|
||||
}
|
||||
|
||||
$msg = '上传成功';
|
||||
$code = 0;
|
||||
if(count($error) > 0){
|
||||
$msg = '上传失败;提示:'.implode(',', $error);//顺带返回错误信息
|
||||
$code = 1;
|
||||
}
|
||||
return Tools::set_res($code, $msg, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:优化路径格式
|
||||
* author:wh
|
||||
*/
|
||||
private function dealPath(string $path){
|
||||
$str = str_replace('\\','/',$path);
|
||||
|
||||
return str_replace('//','/',$str);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:curl上传文件,php上传文件到远程服务器地址
|
||||
*
|
||||
* [php curl模拟文件上传]
|
||||
*
|
||||
* 依赖库:"guzzlehttp/guzzle": "^7.8",
|
||||
*
|
||||
* author:wh
|
||||
* @param $url
|
||||
* @param $params
|
||||
* @param false[] $config
|
||||
*/
|
||||
function uploadCurlFiles($url,$params, $config=['verify' => false]){
|
||||
if(empty($this->unique_key)){
|
||||
throw new \Exception('UNIQUE_KEY 不能为空');
|
||||
}
|
||||
if(empty($this->file_lists_urls)){
|
||||
throw new \Exception('文件地址列表不能为空');
|
||||
}
|
||||
// 创建 Guzzle HTTP 客户端实例
|
||||
$client = new Client($config);
|
||||
|
||||
// 定义要上传的文件列表
|
||||
$files = [
|
||||
//[
|
||||
// 'name' => 'file1', // 服务器接收的文件字段名
|
||||
// 'contents' => Utils::tryFopen('D:\wanghua\projects\big_world_projects\universal_gravitation\public\uploads\20240506\dc1c441d81d48565ac6817b89d0f8bef.mp4', 'r'), // 文件路径
|
||||
// 'filename' => 'dc1c441d81d48565ac6817b89d0f8bef.mp4', // 文件名,可自定义
|
||||
//],
|
||||
//[
|
||||
// 'name' => 'files',
|
||||
// 'contents' => Utils::tryFopen('D:\wanghua\projects\big_world_projects\universal_gravitation\public\uploads\20240506\f80179b23b60619fba8033bfd64f8817.mp4', 'r'),
|
||||
// 'filename' => 'f80179b23b60619fba8033bfd64f8817.mp4',
|
||||
//],
|
||||
//['name'=>'prompt','contents'=>$prompt],
|
||||
//['name'=>'tts_url','contents'=>$tts_url]
|
||||
// 可以继续添加更多文件...
|
||||
];
|
||||
//print_r($params);
|
||||
foreach ($params as $key=>$val){
|
||||
$files[] = ['name'=>$key,'contents'=>$val];
|
||||
}
|
||||
$controller = strtolower(request()->controller());
|
||||
$action = strtolower(request()->action());
|
||||
$save_path = Tools::get_root_path() . "public/uploads/{$controller}/{$action}/".$this->unique_key;
|
||||
if(!file_exists($save_path)){
|
||||
mkdir($save_path,0777,true);
|
||||
}
|
||||
|
||||
//文件远程可访问地址列表
|
||||
foreach ($this->file_lists_urls as $name=>$video_url) {
|
||||
//处理可用地址(可能存储在本地或oss)
|
||||
$video_url = $this->get_usable_url($video_url);
|
||||
$files[] = [
|
||||
'name'=>"files",//服务器接收的文件字段名
|
||||
//读取地址文件流(本地地址或远程地址均可,本地真实物理地址也行)
|
||||
'contents'=>Utils::tryFopen($video_url, 'r'),
|
||||
'filename'=>$name,//可自定义 文件名
|
||||
];
|
||||
}
|
||||
|
||||
// 构建多部分表单数据
|
||||
$multipartStream = new MultipartStream($files);
|
||||
$boundary = $multipartStream->getBoundary();
|
||||
$headers = [
|
||||
'Content-Type' => "multipart/form-data; boundary={$boundary}",
|
||||
];
|
||||
|
||||
// 准备请求体
|
||||
$body = $multipartStream->getContents();
|
||||
|
||||
// 发起 POST 请求
|
||||
try {
|
||||
$postinfo = [
|
||||
'headers' => $headers,
|
||||
'body' => $body,
|
||||
];
|
||||
//上传
|
||||
$response = $client->request('POST', $url, $postinfo);
|
||||
// 处理响应
|
||||
//$responseBody = (string) $response->getBody();
|
||||
// 检查状态码
|
||||
//if ($response->getStatusCode() !== 200) {
|
||||
// return false;
|
||||
//}
|
||||
return $response;//返回上传结果
|
||||
} catch (\GuzzleHttp\Exception\RequestException $e) {
|
||||
// 错误处理
|
||||
//echo "Error: " . $e->getMessage();
|
||||
Tools::error_txt_log($e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取视频可用地址(兼容远程地址或本地地址)
|
||||
* author:wh
|
||||
* @param $video_url
|
||||
* @return string|string[]
|
||||
*/
|
||||
private function get_usable_url($video_url){
|
||||
if(strpos($video_url,'http')!==false){
|
||||
return $video_url;//远程地址
|
||||
}
|
||||
return Tools::get_root_path().$video_url;//本地地址
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
1
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/upload/README.MD
vendored
Normal file
1
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/upload/README.MD
vendored
Normal file
@@ -0,0 +1 @@
|
||||
## 文件上传类库
|
||||
210
digital_doctor/vendor/wanghua/general-utility-tools-php/src/framework/BaseController.php
vendored
Normal file
210
digital_doctor/vendor/wanghua/general-utility-tools-php/src/framework/BaseController.php
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/08/25} {15:45}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\framework;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Cache;
|
||||
use think\Controller;
|
||||
use think\Db;
|
||||
use think\Exception;
|
||||
use think\Request;
|
||||
use wanghua\general_utility_tools_php\api\ApiDocument;
|
||||
use wanghua\general_utility_tools_php\tool\MySqlTools;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 基础架构
|
||||
*
|
||||
* Class BaseController
|
||||
* @package app\index\controller
|
||||
*/
|
||||
class BaseController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
//校验系统维护状态 start
|
||||
$chm = $this->checkMaintain();
|
||||
if ($chm['is_maintain']) {
|
||||
if ($chm['users_ids']) {
|
||||
//解析openid
|
||||
if (!in_array(api_user_info('id'), explode(',', $chm['users_ids']))) {
|
||||
//白名单之外维护中
|
||||
//Tools::log_to_write_txt([
|
||||
// '维护测试'=>$chm['users_ids'],
|
||||
// 'my'=>index_user_openid()
|
||||
//]);
|
||||
return $this->error($chm['msg']);
|
||||
}
|
||||
} else {
|
||||
//不存在,直接维护中
|
||||
return $this->error($chm['msg'] . '!');
|
||||
}
|
||||
}
|
||||
//校验系统维护状态 end
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:检查路径维护状态
|
||||
*
|
||||
* “===”完全匹配,不能使用like
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
protected function checkMaintain(){
|
||||
$configs = Db::table(TabConf::$fa_sys_maintain_config)
|
||||
->where('status','1')
|
||||
->cache()
|
||||
->select();
|
||||
|
||||
//模块
|
||||
$strmodule = request()->module();
|
||||
foreach ($configs as $config){
|
||||
if($strmodule == $config['url']){
|
||||
//模块维护中
|
||||
return ['is_maintain'=>true,'msg'=>$config['msg'],'users_ids'=>$config['users_ids']];
|
||||
}
|
||||
}
|
||||
|
||||
//模块/控制器
|
||||
$strcontroller = strtolower(request()->module().'/'.request()->controller());
|
||||
foreach ($configs as $config){
|
||||
if($strcontroller == $config['url']){
|
||||
//模块维护中
|
||||
return ['is_maintain'=>true,'msg'=>$config['msg'],'users_ids'=>$config['users_ids']];
|
||||
}
|
||||
}
|
||||
|
||||
//模块/控制器/方法
|
||||
$straction = strtolower(request()->module().'/'.request()->controller().'/'.request()->action());
|
||||
foreach ($configs as $config){
|
||||
if($straction == $config['url']){
|
||||
//模块维护中
|
||||
return ['is_maintain'=>true,'msg'=>$config['msg'],'users_ids'=>$config['users_ids']];
|
||||
}
|
||||
}
|
||||
|
||||
//未维护
|
||||
return ['is_maintain'=>false,'msg'=>'服务运行中'];
|
||||
}
|
||||
/**
|
||||
* desc:清空系统缓存
|
||||
*
|
||||
/index/Test/clearCache
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function clearCache(){
|
||||
|
||||
Cache::clear();
|
||||
}
|
||||
/**
|
||||
* eg:/index/test/buildTablesConf
|
||||
*
|
||||
* desc:构建统一的表名配置
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function buildTablesConf(){
|
||||
|
||||
(new MySqlTools())->buildTablesConf();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:创建&更新接口文档
|
||||
*
|
||||
* 默认存放在/public/api_docs/api_list.md
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function buildApiDoc()
|
||||
{
|
||||
$obj = new ApiDocument();
|
||||
//根据自己的实际情况设置直接继承类(仅供参考)
|
||||
$obj->extends_base_class = 'app\\api\\controller\\BaseHttpApi,wanghua\\general_utility_tools_php\\framework\\base\\BaseWechatAuthController';
|
||||
//设置过滤的类(仅供参考)
|
||||
$obj->setFilterClass([
|
||||
'BaseCommonController',
|
||||
'BaseHttpApi',
|
||||
'BaseWssApi',
|
||||
'Wsspush',
|
||||
'BaseController',
|
||||
'BaseAuthController',
|
||||
//'BaseWechatAuthController',
|
||||
'BasePublicController'
|
||||
]);
|
||||
$obj->setFilterFunction([
|
||||
'buildApiDoc',
|
||||
'buildTablesConf',
|
||||
'checkfailed',
|
||||
'clearCache',
|
||||
'defaultAuth',
|
||||
'operateLog',
|
||||
'checkMaintain'
|
||||
]);
|
||||
//构建接口文档
|
||||
$obj->buildDoc();
|
||||
//生成html
|
||||
$html = $obj->buildApiDocHtml();
|
||||
$path = Tools::get_root_path().'/public/api_docs/';
|
||||
if(!file_exists($path)){
|
||||
mkdir($path,0777,true);
|
||||
}
|
||||
file_put_contents($path.'api_list.html',$html);
|
||||
echo "<a href='/api_docs/api_list.html' target='_blank'>api_list.html</a>";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:用户操作日志
|
||||
* author:wh
|
||||
*/
|
||||
protected function operateLog($msg,$users_id=0,$username='',$name=''){
|
||||
$tbname = 'fa_users_operate_log';
|
||||
$sql = "
|
||||
CREATE TABLE `{$tbname}` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`users_id` int(10) unsigned DEFAULT '0' COMMENT '用户ID',
|
||||
`username` varchar(15) DEFAULT '' COMMENT '用户名',
|
||||
`name` varchar(20) DEFAULT '' COMMENT '名称',
|
||||
`url` varchar(60) DEFAULT '' COMMENT 'URL',
|
||||
`msg` varchar(90) DEFAULT '' COMMENT '做了什么',
|
||||
`ip` varchar(30) DEFAULT '' COMMENT '登录ip',
|
||||
`input` text COMMENT '提交参数',
|
||||
`create_time` timestamp NULL DEFAULT NULL COMMENT '登陆时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='用户操作日志';";
|
||||
|
||||
if(cache('cache_db_tables_now_project')){
|
||||
$table_arr = cache('cache_db_tables_now_project');
|
||||
}else{
|
||||
$table_arr = Tools::get_tables();
|
||||
}
|
||||
//表是否存在
|
||||
if(!in_array($tbname,$table_arr)){
|
||||
cache('cache_db_tables_now_project',$table_arr);
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'users_id'=>$users_id,
|
||||
'username'=>$username,
|
||||
'name'=>$name,
|
||||
'url'=>request()->url(),
|
||||
'msg'=>$msg,
|
||||
'ip'=>request()->ip(),
|
||||
'input'=>json_encode(input(),JSON_UNESCAPED_UNICODE),
|
||||
];
|
||||
Db::table($tbname)->data($data)->insert();
|
||||
|
||||
}
|
||||
}
|
||||
1
digital_doctor/vendor/wanghua/general-utility-tools-php/src/framework/README.MD
vendored
Normal file
1
digital_doctor/vendor/wanghua/general-utility-tools-php/src/framework/README.MD
vendored
Normal file
@@ -0,0 +1 @@
|
||||
### this classes only to thinkphp5+
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/08/27} {10:35}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\framework\base;
|
||||
|
||||
use wanghua\general_utility_tools_php\framework\BaseController;
|
||||
use think\Exception;
|
||||
use think\Request;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 基础权限架构
|
||||
* Class BaseAuthController
|
||||
* @package library\framework\base
|
||||
*/
|
||||
class BaseAuthController extends BaseController
|
||||
{
|
||||
|
||||
public $debug = false;
|
||||
//权限错误重定向URL
|
||||
protected $auth_err_redirect_url = '/index/err/fail';
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
|
||||
$err_redirect_url = config('service_framework_config.auth_err_redirect_url');
|
||||
if($err_redirect_url){
|
||||
$this->auth_err_redirect_url = $err_redirect_url;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:默认鉴权
|
||||
* author:wh
|
||||
* @return bool
|
||||
*/
|
||||
function defaultAuth(){
|
||||
$params = input();
|
||||
if(empty($params['nonce'])){
|
||||
Tools::log_to_write_txt(['服务被拒绝,鉴权参数缺失:nonce。params'=>input()]);
|
||||
//跳转至错误中转控制器
|
||||
return $this->response($this->auth_err_redirect_url,['title'=>'服务被拒绝. permission denied']);
|
||||
}
|
||||
if(empty($params['timestamp'])){
|
||||
Tools::log_to_write_txt(['服务被拒绝,鉴权参数缺失:timestamp。params'=>input()]);
|
||||
//跳转至错误中转控制器
|
||||
return $this->response($this->auth_err_redirect_url,['title'=>'服务被拒绝. permission denied.']);
|
||||
}
|
||||
if(empty($params['sign'])){
|
||||
Tools::log_to_write_txt(['服务被拒绝,鉴权参数缺失:sign。params'=>input()]);
|
||||
//跳转至错误中转控制器
|
||||
return $this->response($this->auth_err_redirect_url,['title'=>'服务被拒绝. permission denied。']);
|
||||
}
|
||||
$sign = $params['sign'];
|
||||
unset($params['sign']);
|
||||
if(Tools::signature($params) != $sign){
|
||||
|
||||
Tools::log_to_write_txt(['签名失败,服务被拒绝.'=>input()]);
|
||||
|
||||
//跳转至错误中转控制器
|
||||
return $this->response($this->auth_err_redirect_url,['title'=>'服务被拒绝. permission denied!']);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
protected function response($url,$params){
|
||||
|
||||
if(Request::instance()->isAjax() || Request::instance()->isPost()){
|
||||
return json(Tools::set_res(500,$params['title'],['url'=>$url]));
|
||||
}
|
||||
//跳转至错误中转控制器
|
||||
return $this->redirect(url($url,$params));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/08/25} {15:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\framework\base;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\framework\BaseController;
|
||||
use think\Request;
|
||||
|
||||
/**
|
||||
* common controller have no permission
|
||||
*
|
||||
* 外部公用架构
|
||||
*
|
||||
* 无权限校验的公用架构
|
||||
*
|
||||
* Class PublicController
|
||||
* @package app\index\controller
|
||||
*/
|
||||
class BasePublicController extends BaseController
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/23} {0:12}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\framework\base;
|
||||
|
||||
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Db;
|
||||
use think\Request;
|
||||
use wanghua\general_utility_tools_php\framework\BaseController;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 微信专用权限架构
|
||||
*
|
||||
* Class BaseWechatAuthController
|
||||
* @package wanghua\general_utility_tools_php\framework\base
|
||||
*/
|
||||
class BaseWechatAuthController extends BaseController
|
||||
{
|
||||
protected $wechat_user_table_name = 'fa_users';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
|
||||
//首页提示语
|
||||
$this->assign('index_msg', cache('index_msg_alert_cache_time'));
|
||||
|
||||
//线上环境加载微信授权
|
||||
if (config('sys_env') == 'PROD') {
|
||||
$wx_user_info = session('wx_user_info');
|
||||
if (empty($wx_user_info['openid'])) {
|
||||
//重定向之前,保存当前url, 在获取授权信息之后,回跳到授权之前的网页地址
|
||||
session('redirect_before_url_session', request()->url(true));
|
||||
$ver = Tools::get_thinkphp_version();
|
||||
if($ver == '5.0'){
|
||||
$url = url('index/Wexinauth/usrAuth','',false,true);
|
||||
}else{
|
||||
$url = request()->domain().url('index/Wexinauth/usrAuth');
|
||||
}
|
||||
//没有则重定向去授权
|
||||
return $this->redirect($url);
|
||||
}
|
||||
|
||||
$this->saveWechatUser($wx_user_info);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:周期更新当前用户信息
|
||||
* author:wh
|
||||
* @param $wx_user_info
|
||||
*/
|
||||
private function saveWechatUser($wx_user_info)
|
||||
{
|
||||
try {
|
||||
$wechat_user = $this->getWxUserByOpenid($wx_user_info['openid']);
|
||||
if (empty($wechat_user)) {
|
||||
return $this->insertInfo($wx_user_info);
|
||||
}
|
||||
//扩展,按周期更新,而不是不更新
|
||||
if (empty($wechat_user['update_time']) || time() - strtotime($wechat_user['update_time']) > 5 * 3600) {
|
||||
|
||||
return $this->updateUser($wx_user_info);
|
||||
}
|
||||
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Tools::log_to_write_txt([
|
||||
'error' => '存储异常.' . $e->getMessage(),
|
||||
'wx_user_info' => $wx_user_info,
|
||||
'error_info' => $e->getTraceAsString()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:新增微信用户信息
|
||||
* author:wh
|
||||
* @param $wx_user_info \app\index\model\微信用户
|
||||
*
|
||||
* {
|
||||
* "openid":"or9D2vs863Ky5Py2ovkAiu9XFLO4",
|
||||
* "nickname":"起源果蔬副食大华",
|
||||
* "sex":0,
|
||||
* "language":"",
|
||||
* "city":"",
|
||||
* "province":"",
|
||||
* "country":"",
|
||||
* "headimgurl":"https://thirdwx.qlogo.cn/mmopen/vi_32/joiaA475nx3fJiaqx0ibdnWo4A7Q3uCgu2hsribI0ATLItORjuUgCSP8mCaBkqL61ibGojib4pQYX1djUhZpF5zoqpSg/132",
|
||||
* "privilege":[]
|
||||
* }
|
||||
*/
|
||||
private function insertInfo(array $wx_user_info)
|
||||
{
|
||||
|
||||
if (isset($wx_user_info['privilege'])) {
|
||||
$wx_user_info['privilege'] = json_encode($wx_user_info['privilege']);
|
||||
}
|
||||
$data = [
|
||||
'nickname' => $wx_user_info['nickname'],
|
||||
'country' => $wx_user_info['country'],
|
||||
'province' => $wx_user_info['province'],
|
||||
'city' => $wx_user_info['city'],
|
||||
'headimage' => $wx_user_info['headimgurl'],
|
||||
'language' => $wx_user_info['language'],
|
||||
'openid' => $wx_user_info['openid'],
|
||||
'unionid' => isset($wx_user_info['unionid']) ? $wx_user_info['unionid'] : '',
|
||||
'privilege' => $wx_user_info['privilege'],
|
||||
'sex' => $wx_user_info['sex'],
|
||||
'arm_group' => '',
|
||||
'score' => 0,//积分
|
||||
'group_buy_earnings' => 0,//拼团收益
|
||||
'water_drop_balance' => 0,//水滴
|
||||
];
|
||||
Db::table($this->wechat_user_table_name)
|
||||
->data($data)
|
||||
->insert();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:更新当前用户信息
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
private function updateUser($wx_user_info)
|
||||
{
|
||||
$data = [
|
||||
'nickname' => $wx_user_info['nickname'],
|
||||
'headimage' => $wx_user_info['headimgurl'],
|
||||
'unionid' => isset($wx_user_info['unionid']) ? $wx_user_info['unionid'] : '',
|
||||
];
|
||||
Db::table($this->wechat_user_table_name)
|
||||
->data($data)
|
||||
->where('openid', index_user_openid())
|
||||
->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:根据unionid获取用户信息
|
||||
* author:wh
|
||||
* @param string $unionid
|
||||
*/
|
||||
private function getWxUserByUnionid(string $unionid)
|
||||
{
|
||||
return Db::table($this->wechat_user_table_name)
|
||||
->field('id')
|
||||
->where('unionid', $unionid)
|
||||
->find();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取微信用户信息
|
||||
* author:wh
|
||||
* @param string $openid
|
||||
*/
|
||||
private function getWxUserByOpenid(string $openid)
|
||||
{
|
||||
return Db::table($this->wechat_user_table_name)
|
||||
//->field('id')
|
||||
->where('openid', $openid)
|
||||
->find();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:根据openid获取昵称
|
||||
* author:wh
|
||||
* @param string $openid
|
||||
*/
|
||||
private function getNicknameByOpenid(string $openid)
|
||||
{
|
||||
return Db::table($this->wechat_user_table_name)
|
||||
->where('openid', $openid)
|
||||
->value('nickname');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
213
digital_doctor/vendor/wanghua/general-utility-tools-php/src/ftp/Ftp.php
vendored
Normal file
213
digital_doctor/vendor/wanghua/general-utility-tools-php/src/ftp/Ftp.php
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/3/22} {9:42}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\ftp;
|
||||
|
||||
|
||||
/**
|
||||
* 利用ftp操作服务器文件(增删改查下载)
|
||||
* Class Ftp
|
||||
* @package wanghua\general_utility_tools_php\ftp
|
||||
*/
|
||||
class Ftp
|
||||
{
|
||||
public $off; // 返回操作状态(成功/失败)
|
||||
public $conn_id; // FTP连接
|
||||
|
||||
/**
|
||||
* FTP连接
|
||||
* $host -- FTP主机
|
||||
* $port -- 端口
|
||||
* $user -- 用户名
|
||||
* $password -- 密码
|
||||
*/
|
||||
function __construct(string $host,string $port='21',string $user,string $password)
|
||||
{
|
||||
set_time_limit(10);//防止连接超时
|
||||
|
||||
$this->conn_id = ftp_connect($host, $port);
|
||||
if(!$this->conn_id) throw new \Exception("FTP服务器连接失败");
|
||||
$login_res = ftp_login($this->conn_id, $user, $password);
|
||||
if(!$login_res) throw new \Exception("FTP服务器登陆失败");
|
||||
ftp_pasv($this->conn_id, false); // true打开被动模拟,默认关闭,如果总是失败,可试试true
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:打开被动模拟,登录后使用
|
||||
* author:wh
|
||||
*/
|
||||
function set_ftp_pasv(){
|
||||
ftp_pasv($this->conn_id, true); // true打开被动模拟
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
* param $path 本地文件路径[包含文件名]
|
||||
* param $newPath 目标目录[包含文件名][默认存放在ftp用户被授权的根路径]
|
||||
* param bool $type 若目标目录不存在则新建
|
||||
*/
|
||||
function up_file($path, $newPath, $type = true)
|
||||
{
|
||||
if ($type) $this->dir_mkdirs($newPath);
|
||||
$this->off = ftp_put($this->conn_id, $newPath, $path, FTP_BINARY);
|
||||
if (!$this->off)
|
||||
return ['code'=>500, 'msg'=>'文件上传失败,请检查权限及路径是否正确!'];
|
||||
return ['code'=>200, 'msg'=>'文件移动成功'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动文件
|
||||
* 特别注意:
|
||||
* $path 如果是当前目录,则必须以 “/”开始
|
||||
* 正确:/test2.zip
|
||||
* 错误:test2.zip
|
||||
* param $path 原路径(含文件名)
|
||||
* param $newPath 新路径(含文件名)
|
||||
* param bool $type 若目标目录不存在则新建
|
||||
*/
|
||||
function move_file($path, $newPath, $ftpbasedir, $type = true)
|
||||
{
|
||||
if ($type) $this->ftp_mksubdirs($ftpbasedir,$newPath);
|
||||
$this->off = ftp_rename($this->conn_id, $path, $newPath);
|
||||
if (!$this->off)
|
||||
return ['code'=>500, 'msg'=>'文件移动失败,请检查权限及原路径是否正确!'];
|
||||
return ['code'=>200, 'msg'=>'文件移动成功'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件改名
|
||||
* param $path 原路径
|
||||
* param $newPath 新路径
|
||||
*/
|
||||
function rename_file($path, $newPath)
|
||||
{
|
||||
$this->off = ftp_rename($this->conn_id, $path, $newPath);
|
||||
if (!$this->off)
|
||||
return ['code'=>500, 'msg'=>'文件改名失败,请检查权限及原路径是否正确!'];
|
||||
return ['code'=>200, 'msg'=>'文件改名成功'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制文件
|
||||
* 说明:由于FTP无复制命令,本方法变通操作为:下载后再上传到新的路径
|
||||
* param $path 原路径
|
||||
* param $newPath 新路径
|
||||
* param bool $type 若目标目录不存在则新建
|
||||
*/
|
||||
function copy_file($path, $newPath, $type = true)
|
||||
{
|
||||
$downPath = "c:/tmp.dat";
|
||||
$this->off = ftp_get($this->conn_id, $downPath, $path, FTP_BINARY);// 下载
|
||||
if (!$this->off)
|
||||
return ['code'=>500, 'msg'=>'文件复制失败,请检查权限及原路径是否正确!'];
|
||||
|
||||
$this->up_file($downPath, $newPath, $type);
|
||||
return ['code'=>200, 'msg'=>'文件复制成功'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* param $path 路径
|
||||
*/
|
||||
function del_file($path)
|
||||
{
|
||||
$this->off = ftp_delete($this->conn_id, $path);
|
||||
if (!$this->off)
|
||||
return ['code'=>500, 'msg'=>'文件删除失败,请检查权限及路径是否正确!'];
|
||||
|
||||
return ['code'=>200, 'msg'=>'文件删除成功'];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除给定目录
|
||||
* 注:
|
||||
* 删除多个目录需重复调用
|
||||
* author:wh
|
||||
* param $dir
|
||||
* return bool
|
||||
*/
|
||||
function del_dir($dir){
|
||||
|
||||
|
||||
$children = ftp_nlist ($this->conn_id, $dir);
|
||||
if(!$children) {
|
||||
ftp_rmdir($this->conn_id, $dir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new \Exception('请确保目录中无内容');
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:生成目录
|
||||
* author:wh
|
||||
* param $ftpcon
|
||||
* param $ftpbasedir
|
||||
* param $ftpath
|
||||
*/
|
||||
function ftp_mksubdirs($ftpbasedir,$ftpath){
|
||||
ftp_chdir($this->conn_id, $ftpbasedir); // /var/www/uploads
|
||||
$parts = explode('/',$ftpath); // 2013/06/11/username
|
||||
|
||||
if(strpos($parts[count($parts)-1], '.')){
|
||||
unset($parts[count($parts)-1]);
|
||||
}
|
||||
|
||||
foreach($parts as $part){
|
||||
if(!ftp_chdir($this->conn_id, $part)){
|
||||
ftp_mkdir($this->conn_id, $part);
|
||||
ftp_chdir($this->conn_id, $part);
|
||||
//ftp_chmod($this->conn_id, 0777, $part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:使用ftp连接方式下载文件
|
||||
* author:wh
|
||||
* param string $local_file 文件本地的路径(如果文件已经存在,则会被覆盖)。
|
||||
* param string $remote_file 文件的远程路径。[默认查找ftp用户被授权的根路径]
|
||||
* return array
|
||||
*/
|
||||
function download(string $local_file, string $remote_file){
|
||||
// 进行ftp下载[默认保存在本地根目录]
|
||||
if (!ftp_get($this->conn_id, $local_file, $remote_file, FTP_BINARY)) {
|
||||
return ['code'=>500, 'msg'=>'ftp download fail'];
|
||||
}
|
||||
return ['code'=>200, 'msg'=>'ftp download success'];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:判断ftp文件大小, 如果>-1, 说明文件存在;否则不存在.
|
||||
* author:wh
|
||||
* param $remote_file
|
||||
* return int
|
||||
*/
|
||||
function ftp_size($remote_file){
|
||||
return ftp_size($this->conn_id, $remote_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:返回当前目录
|
||||
* author:wh
|
||||
* return false|string
|
||||
*/
|
||||
function ftp_pwd(){
|
||||
return ftp_pwd($this->conn_id);
|
||||
}
|
||||
/**
|
||||
* 关闭FTP连接
|
||||
*/
|
||||
function close()
|
||||
{
|
||||
ftp_close($this->conn_id);
|
||||
}
|
||||
}
|
||||
21
digital_doctor/vendor/wanghua/general-utility-tools-php/src/ftp/README.md
vendored
Normal file
21
digital_doctor/vendor/wanghua/general-utility-tools-php/src/ftp/README.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# PHP ftp类库
|
||||
#### 实现用ftp方式上传、复制、移动、重命名、删除、下载文件
|
||||
|
||||
##### 案例代码:
|
||||
```
|
||||
$ftp = new Ftp();//初始化
|
||||
//$ftp->up_file('D:\whua\test.zip','test.zip'); // 上传文件
|
||||
//$ftp->rename_file('test.zip','test-rename.zip'); // 移动文件
|
||||
//$ftp->move_file('/test2.zip','/testdir2/test2.zip', '/www/wwwroot/testftp/'); // 移动文件2
|
||||
//$ftp->copy_file('test.zip','test-copy.zip'); // 复制文件
|
||||
//$ftp->del_file('/www/aaa.txt'); // 删除具体文件
|
||||
$ftp->del_dir('/www'); // 删除目录(错误示范),必须精确到具体文件夹删除
|
||||
$ftp->del_dir('/ftp/test/copy-test/a-dir'); // 删除目录(正确示范),必须精确到具体文件夹删除,批量删除请多次调用
|
||||
|
||||
//下载文件
|
||||
//$ftp->download('D:\whua\projects\zc_game_admin3.0\data\local.zip', 'test.zip');
|
||||
//$ftp->close(); // 关闭FTP连接
|
||||
|
||||
//dump($ftp->ftp_pwd());die;
|
||||
//dump($ftp->ftp_size('test2.zip'));die;
|
||||
```
|
||||
35
digital_doctor/vendor/wanghua/general-utility-tools-php/src/gpt/chat/BaseChat.php
vendored
Normal file
35
digital_doctor/vendor/wanghua/general-utility-tools-php/src/gpt/chat/BaseChat.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/3/26} {16:06}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\gpt\chat;
|
||||
|
||||
|
||||
class BaseChat
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:将字符串里含有json_encode后的一维数组提取出来
|
||||
* @param $str
|
||||
* @return string
|
||||
*/
|
||||
function dealstr($str){
|
||||
$rep_str = str_replace("\n",'',$str);
|
||||
$rep_str = str_replace("\r",'',$rep_str);
|
||||
$rep_str = str_replace(" ",'',$rep_str);
|
||||
|
||||
$start_sit = strpos($rep_str,"[{");
|
||||
$end_sit = strpos($rep_str,"}]");
|
||||
|
||||
$last_json_str = substr($rep_str,$start_sit,$end_sit-$start_sit);
|
||||
|
||||
$last_json_str.="}]";
|
||||
|
||||
return $last_json_str;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
175
digital_doctor/vendor/wanghua/general-utility-tools-php/src/gpt/chat/ChatGPT.php
vendored
Normal file
175
digital_doctor/vendor/wanghua/general-utility-tools-php/src/gpt/chat/ChatGPT.php
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
<?php namespace wanghua\general_utility_tools_php\gpt\chat;
|
||||
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
|
||||
class ChatGPT extends BaseChat
|
||||
{
|
||||
public $url = '';
|
||||
public $apiKey = '';
|
||||
public $model = '';
|
||||
private $messages = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:定制个性
|
||||
* author:wh
|
||||
* @param array $customize
|
||||
*/
|
||||
function setCustomize($customize = [])
|
||||
{
|
||||
if ($customize) {
|
||||
foreach ($customize as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setBefore($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setAfter($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function check()
|
||||
{
|
||||
if (empty($this->url) || empty($this->apiKey) || empty($this->model)) {
|
||||
throw new Exception('PARAMS ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
function chat($question = '', $config = [], &$answer_json_arr)
|
||||
{
|
||||
$answer = '';
|
||||
$this->curlPostChat($question, $config, function ($ch, $data) use ($question, &$answer, &$answer_json_arr) {
|
||||
$answer_json_arr[] = $data;
|
||||
$answer .= $data;
|
||||
echo $data;
|
||||
ob_flush();
|
||||
flush();
|
||||
return strlen($data);
|
||||
});
|
||||
return $answer;
|
||||
}
|
||||
|
||||
function returnAnswer($question = '', $config = [], &$answer_json_arr)
|
||||
{
|
||||
$answer = '';
|
||||
$this->curlPostChat($question, $config, function ($ch, $data) use ($question, &$answer, &$answer_json_arr) {
|
||||
$answer_json_arr[] = $data;
|
||||
$answer .= $data;
|
||||
return strlen($data);
|
||||
});
|
||||
return $answer;
|
||||
}
|
||||
|
||||
private function curlPostChat($question = '', $config = [], $callback)
|
||||
{
|
||||
$url = $this->url;
|
||||
$apiKey = $this->apiKey;
|
||||
$model = $this->model;
|
||||
$headers = ["Authorization: Bearer $apiKey", 'Accept: application/json', 'Content-Type: application/json',];
|
||||
$post_msg_body = ["model" => $model, 'stream' => true,];
|
||||
if ($config) {
|
||||
foreach ($config as $key => $val) {
|
||||
$post_msg_body[$key] = $val;
|
||||
}
|
||||
}
|
||||
if ($question) {
|
||||
$this->messages[] = ["role" => "user", "content" => $question];
|
||||
}
|
||||
$post_msg_body['messages'] = $this->messages;
|
||||
$postData = json_encode($post_msg_body);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
|
||||
curl_exec($ch);
|
||||
}
|
||||
|
||||
function getchatgptresponse($question = '', $config = [])
|
||||
{
|
||||
$url = $this->url;
|
||||
$apiKey = $this->apiKey;
|
||||
$model = $this->model;
|
||||
$headers = ["Authorization: Bearer $apiKey", "Content-Type: application/json"];
|
||||
$post_msg_body = ["model" => $model, 'stream' => false];
|
||||
if ($config) {
|
||||
foreach ($config as $key => $val) {
|
||||
$post_msg_body[$key] = $val;
|
||||
}
|
||||
}
|
||||
if ($question) {
|
||||
$this->messages[] = ["role" => "user", "content" => $question];
|
||||
}
|
||||
$post_msg_body['messages'] = $this->messages;
|
||||
$post_msg_body = json_encode($post_msg_body);
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_msg_body);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$response = curl_exec($ch);
|
||||
if (curl_error($ch)) {
|
||||
return ['code' => curl_errno($ch), 'msg' => curl_error($ch)];
|
||||
} else {
|
||||
curl_close($ch);
|
||||
return ['code' => 200, 'msg' => 'cURL ok', 'data' => $response];
|
||||
}
|
||||
}
|
||||
|
||||
private function parseData($data)
|
||||
{
|
||||
if (@json_decode($data)->choices[0]->message->content) {
|
||||
return json_decode($data)->choices[0]->message->content;
|
||||
}
|
||||
$data = str_replace('data: {', '{', $data);
|
||||
$data = rtrim($data, "\n\n");
|
||||
if (strpos($data, 'data: [DONE]') !== false) {
|
||||
return 'data: [DONE]';
|
||||
} else {
|
||||
if (false !== strpos($data, "\n\n")) {
|
||||
$exp_arr = explode("\n\n", $data);
|
||||
$str = '';
|
||||
try {
|
||||
for ($i = 0; $i < count($exp_arr) - 1; $i++) {
|
||||
$jsondecode_arr = json_decode($exp_arr[$i], true);
|
||||
$str .= $jsondecode_arr['choices'][0]['delta']['content'];
|
||||
}
|
||||
return $str;
|
||||
} catch (\Exception $e) {
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
$data = @json_decode($data, true);
|
||||
if (!is_array($data)) {
|
||||
return '';
|
||||
}
|
||||
if ($data['choices'][0]['finish_reason'] == 'stop') {
|
||||
return 'data: [DONE]';
|
||||
} elseif ($data['choices'][0]['finish_reason'] == 'length') {
|
||||
return 'data: [CONTINUE]';
|
||||
}
|
||||
return $data['choices'][0]['delta']['content'] ?? '';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php namespace wanghua\general_utility_tools_php\gpt\chat;
|
||||
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class F37A49CDED4199801B05D5FFFAF78E010 extends BaseChat
|
||||
{
|
||||
public $url = '';
|
||||
public $apiKey = '';
|
||||
public $model = '';
|
||||
public $chatId = '';
|
||||
public $detail = false;
|
||||
private $messages = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
function s8EB5A47634F626B142D2A93E9BAF009F($customize = [])
|
||||
{
|
||||
if ($customize) {
|
||||
foreach ($customize as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function s3ASCD163240094B8C736D3A1A5CSD($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function s326723D163240094B8C736D3A1A5CAD3($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function c2111E682402A3955B616FA5795DEDE4F()
|
||||
{
|
||||
if (empty($this->url) || empty($this->apiKey)) {
|
||||
throw new Exception('PARAMS ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
function cAA8AF3EBE14831A7CD1B6D1383A03755($question = '', $config = [], &$answer_json_arr)
|
||||
{
|
||||
$answer = '';
|
||||
$this->c8ECA4C82960B4611B076D51EF8ADF979($question, $config, function ($ch, $data) use ($question, &$answer, &$answer_json_arr) {
|
||||
$answer_json_arr[] = $data;
|
||||
echo $data;
|
||||
ob_flush();
|
||||
flush();
|
||||
return strlen($data);
|
||||
});
|
||||
}
|
||||
|
||||
private function c8ECA4C82960B4611B076D51EF8ADF979($question = '', $config = [], $callback)
|
||||
{
|
||||
$this->c2111E682402A3955B616FA5795DEDE4F();
|
||||
$url = $this->url;;
|
||||
$apiKey = $this->apiKey;
|
||||
$model = $this->model;
|
||||
$chatId = $this->chatId;
|
||||
$detail = $this->detail;
|
||||
$headers = ["Authorization: Bearer $apiKey", 'Accept: application/json', 'Content-Type: application/json',];
|
||||
$post_msg_body = ['detail' => $detail, 'stream' => true,];
|
||||
if ($detail) {
|
||||
$post_msg_body['detail'] = $detail;
|
||||
}
|
||||
if ($chatId) {
|
||||
$post_msg_body['chatId'] = $chatId;
|
||||
}
|
||||
if ($model) {
|
||||
$post_msg_body['model'] = $model;
|
||||
}
|
||||
if ($config) {
|
||||
foreach ($config as $key => $val) {
|
||||
$post_msg_body[$key] = $val;
|
||||
}
|
||||
}
|
||||
if ($question) {
|
||||
$this->messages[] = ["role" => "user", "content" => $question];
|
||||
}
|
||||
$post_msg_body['messages'] = $this->messages;
|
||||
$postData = json_encode($post_msg_body);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
|
||||
curl_exec($ch);
|
||||
}
|
||||
|
||||
private function pCD736318A127E12426EED8700FF2BF28($data)
|
||||
{
|
||||
if (@json_decode($data)->choices[0]->message->content) {
|
||||
return json_decode($data)->choices[0]->message->content;
|
||||
}
|
||||
$data = str_replace('data: {', '{', $data);
|
||||
$data = rtrim($data, "\n\n");
|
||||
if (strpos($data, 'data: [DONE]') !== false) {
|
||||
return 'data: [DONE]';
|
||||
} else {
|
||||
if (false !== strpos($data, "\n\n")) {
|
||||
$exp_arr = explode("\n\n", $data);
|
||||
$str = '';
|
||||
try {
|
||||
for ($i = 0; $i < count($exp_arr) - 1; $i++) {
|
||||
$jsondecode_arr = json_decode($exp_arr[$i], true);
|
||||
$str .= $jsondecode_arr['choices'][0]['delta']['content'];
|
||||
}
|
||||
return $str;
|
||||
} catch (\Exception $e) {
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
$data = @json_decode($data, true);
|
||||
if (!is_array($data)) {
|
||||
return '';
|
||||
}
|
||||
if ($data['choices'][0]['finish_reason'] == 'stop') {
|
||||
return 'data: [DONE]';
|
||||
} elseif ($data['choices'][0]['finish_reason'] == 'length') {
|
||||
return 'data: [CONTINUE]';
|
||||
}
|
||||
return $data['choices'][0]['delta']['content'] ?? '';
|
||||
}
|
||||
}
|
||||
}
|
||||
146
digital_doctor/vendor/wanghua/general-utility-tools-php/src/gpt/chat/FastGPT.php
vendored
Normal file
146
digital_doctor/vendor/wanghua/general-utility-tools-php/src/gpt/chat/FastGPT.php
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php namespace wanghua\general_utility_tools_php\gpt\chat;
|
||||
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class FastGPT extends BaseChat
|
||||
{
|
||||
public $url = '';
|
||||
public $apiKey = '';
|
||||
public $model = '';
|
||||
public $chatId = '';
|
||||
public $detail = false;
|
||||
private $messages = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:定制个性
|
||||
* author:wh
|
||||
* @param array $customize
|
||||
*/
|
||||
function setCustomize($customize = [])
|
||||
{
|
||||
if ($customize) {
|
||||
foreach ($customize as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setBefore($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setAfter($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function check()
|
||||
{
|
||||
if (empty($this->url) || empty($this->apiKey)) {
|
||||
throw new Exception('PARAMS ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
function chat($question = '', $config = [], &$answer_json_arr)
|
||||
{
|
||||
$answer = '';
|
||||
$this->curlPostChat($question, $config, function ($ch, $data) use ($question, &$answer, &$answer_json_arr) {
|
||||
$answer_json_arr[] = $data;
|
||||
echo $data;
|
||||
ob_flush();
|
||||
flush();
|
||||
return strlen($data);
|
||||
});
|
||||
}
|
||||
|
||||
private function curlPostChat($question = '', $config = [], $callback)
|
||||
{
|
||||
$this->check();
|
||||
$url = $this->url;;
|
||||
$apiKey = $this->apiKey;
|
||||
$model = $this->model;
|
||||
$chatId = $this->chatId;
|
||||
$detail = $this->detail;
|
||||
$headers = ["Authorization: Bearer $apiKey", 'Accept: application/json', 'Content-Type: application/json',];
|
||||
$post_msg_body = ['detail' => $detail, 'stream' => true,];
|
||||
if ($detail) {
|
||||
$post_msg_body['detail'] = $detail;
|
||||
}
|
||||
if ($chatId) {
|
||||
$post_msg_body['chatId'] = $chatId;
|
||||
}
|
||||
if ($model) {
|
||||
$post_msg_body['model'] = $model;
|
||||
}
|
||||
if ($config) {
|
||||
foreach ($config as $key => $val) {
|
||||
$post_msg_body[$key] = $val;
|
||||
}
|
||||
}
|
||||
if ($question) {
|
||||
$this->messages[] = ["role" => "user", "content" => $question];
|
||||
}
|
||||
$post_msg_body['messages'] = $this->messages;
|
||||
$postData = json_encode($post_msg_body);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
|
||||
curl_exec($ch);
|
||||
}
|
||||
|
||||
private function parseData($data)
|
||||
{
|
||||
if (@json_decode($data)->choices[0]->message->content) {
|
||||
return json_decode($data)->choices[0]->message->content;
|
||||
}
|
||||
$data = str_replace('data: {', '{', $data);
|
||||
$data = rtrim($data, "\n\n");
|
||||
if (strpos($data, 'data: [DONE]') !== false) {
|
||||
return 'data: [DONE]';
|
||||
} else {
|
||||
if (false !== strpos($data, "\n\n")) {
|
||||
$exp_arr = explode("\n\n", $data);
|
||||
$str = '';
|
||||
try {
|
||||
for ($i = 0; $i < count($exp_arr) - 1; $i++) {
|
||||
$jsondecode_arr = json_decode($exp_arr[$i], true);
|
||||
$str .= $jsondecode_arr['choices'][0]['delta']['content'];
|
||||
}
|
||||
return $str;
|
||||
} catch (\Exception $e) {
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
$data = @json_decode($data, true);
|
||||
if (!is_array($data)) {
|
||||
return '';
|
||||
}
|
||||
if ($data['choices'][0]['finish_reason'] == 'stop') {
|
||||
return 'data: [DONE]';
|
||||
} elseif ($data['choices'][0]['finish_reason'] == 'length') {
|
||||
return 'data: [CONTINUE]';
|
||||
}
|
||||
return $data['choices'][0]['delta']['content'] ?? '';
|
||||
}
|
||||
}
|
||||
}
|
||||
224
digital_doctor/vendor/wanghua/general-utility-tools-php/src/html/Html.php
vendored
Normal file
224
digital_doctor/vendor/wanghua/general-utility-tools-php/src/html/Html.php
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/4/19} {11:14}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\html;
|
||||
|
||||
|
||||
/**
|
||||
* PHP操作html元素【不包含修改】
|
||||
* Class Html
|
||||
* @package wanghua\general_utility_tools_php\html
|
||||
*/
|
||||
class Html
|
||||
{
|
||||
/**
|
||||
* desc:提取a标签
|
||||
* 返回标签和标签包含的内容
|
||||
* author:wh
|
||||
* @param $html
|
||||
* @return null
|
||||
*/
|
||||
function getAElement(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<a .*?>.*?<\/a>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:提取div标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getDiv(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<div .*?>.*?<\/div>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取img标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getImg(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<img .*?>.*?<\/img>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取span标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getSpan(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<span .*?>.*?<\/span>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取ul标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getUl(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<ul .*?>.*?<\/ul>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取li标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getLi(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<li .*?>.*?<\/li>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取table标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getTable(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<table .*?>.*?<\/table>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取table tr标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getTableTr(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<tr .*?>.*?<\/tr>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取table td标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getTableTd(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<td .*?>.*?<\/td>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:提取a标签属性
|
||||
* author:wh
|
||||
* @param $html
|
||||
* @return array
|
||||
*/
|
||||
function getAAttribute($html){
|
||||
$aarray = null;
|
||||
$reg1="/<a .*?>.*?<\/a>/";
|
||||
preg_match_all($reg1,$html,$aarray);
|
||||
|
||||
$hrefarray=null;//这个存放的是匹配出来的href的链接地址
|
||||
$acontent=null;//存放匹配出来的a标签的内容
|
||||
$reg2="/href=\"([^\"]+)/";
|
||||
$a_arr = [];
|
||||
for($i=0;$i<count($aarray[0]);$i++){
|
||||
preg_match_all($reg2,$aarray[0][$i],$hrefarray);
|
||||
//这里输出的就是遍历出来的所有a标签的链接
|
||||
$a_arr['url'] = $hrefarray[1][0];
|
||||
|
||||
//拿出《a》标签的内容
|
||||
$reg3="/>(.*)<\/a>/";
|
||||
preg_match_all($reg3,$aarray[0][$i],$acontent);
|
||||
//这里输出的就是a标签的文字了
|
||||
$a_arr['text'] = $acontent[1][0];
|
||||
}
|
||||
return $a_arr;
|
||||
}
|
||||
/**
|
||||
* desc:提取img标签src(提取图片链接)
|
||||
* author:wh
|
||||
* @param $html
|
||||
* @return array
|
||||
*/
|
||||
function getImgAttribute($html){
|
||||
$aarray = null;
|
||||
$reg1="/<img .*?>.*?<\/img>/";
|
||||
preg_match_all($reg1,$html,$aarray);
|
||||
|
||||
$hrefarray=null;//这个存放的是匹配出来的href的链接地址
|
||||
$acontent=null;//存放匹配出来的a标签的内容
|
||||
$reg2="/src=\"([^\"]+)/";
|
||||
$a_arr = [];
|
||||
for($i=0;$i<count($aarray[0]);$i++){
|
||||
preg_match_all($reg2,$aarray[0][$i],$hrefarray);
|
||||
//这里输出的就是遍历出来的所有a标签的链接
|
||||
$a_arr['url'] = $hrefarray[1][0];
|
||||
|
||||
//拿出《a》标签的内容
|
||||
$reg3="/>(.*)<\/img>/";
|
||||
preg_match_all($reg3,$aarray[0][$i],$acontent);
|
||||
//这里输出的就是a标签的文字了
|
||||
$a_arr['text'] = $acontent[1][0];
|
||||
}
|
||||
return $a_arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除字符串
|
||||
* author:wh
|
||||
*/
|
||||
function clearHtml($html, $str){
|
||||
return str_replace($str,'',$html);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:正则提取html元素的内容
|
||||
*
|
||||
* 用法eg:
|
||||
* $temp = '
|
||||
<div class="num">1</div>
|
||||
<div class="num">2</div>
|
||||
<div class="num">3</div>
|
||||
<div class="num">4</div>
|
||||
<div class="num1">3</div>
|
||||
<div class="num2">4</div>
|
||||
<div class="num">5</div>';
|
||||
$result = $this->get_tag_data($html,"div","class","num");
|
||||
*
|
||||
* author:wh
|
||||
* @param $html
|
||||
* @param $tag
|
||||
* @param $class
|
||||
* @param $value
|
||||
* @return mixed
|
||||
*/
|
||||
function getTagData($html,$tag,$class,$value){
|
||||
//$value 为空,则获取class=$class的所有内容
|
||||
$regex = $value ? "/<$tag.*?$class=\"$value\".*?>(.*?)<\/$tag>/is" : "/<$tag.*?$class=\".*?$value.*?\".*?>(.*?)<\/$tag>/is";
|
||||
preg_match_all($regex,$html,$matches,PREG_PATTERN_ORDER);
|
||||
//返回数组 ,指定标签内容
|
||||
return $matches[1];
|
||||
}
|
||||
}
|
||||
126
digital_doctor/vendor/wanghua/general-utility-tools-php/src/html/Htmlcontent.php
vendored
Normal file
126
digital_doctor/vendor/wanghua/general-utility-tools-php/src/html/Htmlcontent.php
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/11/8} {15:05}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\html;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class Htmlcontent
|
||||
{
|
||||
|
||||
/**
|
||||
* [curlHtml 获取页面信息]
|
||||
* 使用curl获取html页面内容
|
||||
* @param [type] $url [网址]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
|
||||
function curlHtml($url)
|
||||
{
|
||||
$curl = curl_init();
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => "{$url}",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => "GET",
|
||||
CURLOPT_HTTPHEADER => array(
|
||||
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
|
||||
"Accept-Encoding: gzip, deflate, br",
|
||||
"Accept-Language: zh-CN,zh;q=0.9",
|
||||
"Cache-Control: no-cache",
|
||||
"Connection: keep-alive",
|
||||
"Pragma: no-cache",
|
||||
"Upgrade-Insecure-Requests: 1",
|
||||
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36",
|
||||
"cache-control: no-cache"
|
||||
),
|
||||
));
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
|
||||
$response = curl_exec($curl);
|
||||
$err = curl_error($curl);
|
||||
curl_close($curl);
|
||||
if ($err) return false;
|
||||
else return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* [get_tag_data 使用正则获取html内容中指定的内容]
|
||||
* @param [type] $html [爬取的页面内容]
|
||||
* @param [type] $tag [要查找的标签]
|
||||
* @param [type] $attr [要查找的属性名]
|
||||
* @param [type] $value [属性名对应的值]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
function get_tag_data($html, $tag, $attr, $value)
|
||||
{
|
||||
|
||||
// var_dump($tag, $attr, $value);
|
||||
$regex = "/<$tag.*?$attr=\".*?$value.*?\".*?>(.*?)<\/$tag>/is";
|
||||
// var_dump($regex);
|
||||
preg_match_all($regex, $html, $matches, PREG_PATTERN_ORDER);
|
||||
//var_dump($matches);die;
|
||||
$data = isset($matches[1]) ? $matches[1] : '';
|
||||
// var_dump($data);die;
|
||||
return $data;
|
||||
}
|
||||
/**
|
||||
* [get_html_data 使用xpath对获取到的html内容进行处理]
|
||||
* @param [type] $html [爬取的页面内容]
|
||||
* @param [type] $path [Xpath语句]
|
||||
* @param integer $tag [类型 0内容 1标签内容 自定义标签]
|
||||
* @param boolean $type [单个 还是多个(默认单个时输出单个)]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
|
||||
function get_html_data($html, $path, $tag = 1, $type = true)
|
||||
{
|
||||
$dom = new \DOMDocument();
|
||||
@$dom->loadHTML("<?xml encoding='UTF-8'>" . $html); // 从一个字符串加载HTML并设置UTF8编码
|
||||
$dom->normalize(); // 使该HTML规范化
|
||||
$xpath = new \DOMXPath($dom); //用DOMXpath加载DOM,用于查询
|
||||
$contents = $xpath->query($path); // 获取所有内容
|
||||
$data = [];
|
||||
foreach ($contents as $value) {
|
||||
if ($tag == 1) {
|
||||
$data[] = $value->nodeValue; // 获取不带标签内容
|
||||
} elseif ($tag == 2) {
|
||||
$data[] = $dom->saveHtml($value); // 获取带标签内容
|
||||
} else {
|
||||
$data[] = $value->attributes->getNamedItem($tag)->nodeValue; // 获取attr内容
|
||||
}
|
||||
}
|
||||
if (count($data) == 1) {
|
||||
$data = $data[0];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
//调用
|
||||
public function get_content($url,$tag,$attr='',$value='')
|
||||
{
|
||||
//$url = input('url') ?? '';
|
||||
//$tag = g('tag') ?? '';
|
||||
//$attr = g('attr') ?? '';
|
||||
//$value = g('value') ?? '';
|
||||
if (empty($url) || empty($tag)) {
|
||||
return Tools::set_res(4, '缺少关键参数!');
|
||||
}
|
||||
|
||||
$html = $this->curlHtml($url);
|
||||
//使用正则获取
|
||||
$data = $this->get_tag_data($html, $tag, $attr, $value);
|
||||
//Xpath方法,暂未搞明白
|
||||
// $data = $this->get_html_data($html, $path, $tag = 1, $type = true);
|
||||
return Tools::set_res(1, 'ok!', $data);
|
||||
}
|
||||
}
|
||||
575
digital_doctor/vendor/wanghua/general-utility-tools-php/src/http/Curl.php
vendored
Normal file
575
digital_doctor/vendor/wanghua/general-utility-tools-php/src/http/Curl.php
vendored
Normal file
@@ -0,0 +1,575 @@
|
||||
<?php
|
||||
/*
|
||||
* desc:
|
||||
*
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/03/30} {09:59}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\http;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\MultipartStream;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Psr7\Utils;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* desc:cUrl网络库【推荐】
|
||||
*
|
||||
* author:wh
|
||||
* Class Curl
|
||||
* @package wanghua\general_utility_tools_php\http
|
||||
*/
|
||||
class Curl
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:[推荐] curl请求
|
||||
*
|
||||
* 如果是文件流,则需要用getContents()方法获取
|
||||
* eg: $res->getBody()->getContents();
|
||||
*
|
||||
* author:wh
|
||||
* @param $url
|
||||
* @param string $method
|
||||
* @param false[] $config
|
||||
* @param array $headers
|
||||
* @return mixed
|
||||
*/
|
||||
static function request($url,$method='POST',$config=['verify' => false],$headers=[]){
|
||||
$client = new Client($config);
|
||||
//$headers = [
|
||||
// //'User-Agent' => 'Apifox/1.0.0 (https://apifox.com)',
|
||||
// //'Accept' => '*/*',
|
||||
// //'Host' => 'vits_simple.excn.top',
|
||||
// //'Connection' => 'keep-alive'
|
||||
//];
|
||||
$request = new Request($method, $url, $headers);
|
||||
$res = $client->sendAsync($request)->wait();
|
||||
//$res->getBody()->getContents();//如果是文件流,则需要用getContents()方法获取
|
||||
return $res->getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:php curl远程上传文件,提交到远程服务器,适用于上传多个文件(文件类型不限)
|
||||
*
|
||||
* 应用场景:
|
||||
* 前端->后端A->后端B
|
||||
* 说明:前端发起文件上传,后端A接收到文件后,将文件使用guzzlehttp/guzzle上传到后端B,后端B将文件处理
|
||||
*
|
||||
* 当前版本依赖:"guzzlehttp/guzzle": "^7.8"
|
||||
*
|
||||
* author:wh
|
||||
* @param $url 远程地址
|
||||
* @param $params 提交参数
|
||||
* @param array $config 配置项
|
||||
*/
|
||||
function curlRemoteUploadFiles($url,$params, $config=['verify' => false]){
|
||||
// 创建 Guzzle HTTP 客户端实例
|
||||
$client = new Client($config);
|
||||
|
||||
// 定义要上传的文件列表
|
||||
$files = [
|
||||
//[
|
||||
// 'name' => 'file1', // 服务器接收的文件字段名
|
||||
// 'contents' => Utils::tryFopen('D:\wanghua\projects\big_world_projects\universal_gravitation\public\uploads\20240506\dc1c441d81d48565ac6817b89d0f8bef.mp4', 'r'), // 文件路径
|
||||
// 'filename' => 'dc1c441d81d48565ac6817b89d0f8bef.mp4', // 文件名,可自定义
|
||||
//],
|
||||
//[
|
||||
// 'name' => 'files',
|
||||
// 'contents' => Utils::tryFopen('D:\wanghua\projects\big_world_projects\universal_gravitation\public\uploads\20240506\f80179b23b60619fba8033bfd64f8817.mp4', 'r'),
|
||||
// 'filename' => 'f80179b23b60619fba8033bfd64f8817.mp4',
|
||||
//],
|
||||
//['name'=>'prompt','contents'=>$prompt],
|
||||
//['name'=>'tts_url','contents'=>$tts_url]
|
||||
// 可以继续添加更多文件...
|
||||
];
|
||||
foreach ($params as $key=>$val){
|
||||
$files[] = ['name'=>$key,'contents'=>$val];
|
||||
}
|
||||
$controller = \request()->controller();
|
||||
$action = \request()->action();
|
||||
$save_path = Tools::get_root_path() . "public/uploads/{$controller}/{$action}/";
|
||||
$files_obj = \request()->file('files');
|
||||
foreach ($files_obj as $k=>$file) {
|
||||
if ($file->check()) {
|
||||
$save_res = $file->move($save_path);
|
||||
$fileinfo = $file->getInfo();
|
||||
// 使用CURLFile包装文件路径以供上传
|
||||
$filename = $save_path.date('Ymd').'/'.$save_res->getFilename();
|
||||
$files[] = [
|
||||
'name'=>"files",//服务器接收的文件字段名
|
||||
'contents'=>Utils::tryFopen($filename, 'r'),
|
||||
'filename'=>$fileinfo['name'],//可自定义
|
||||
];
|
||||
}
|
||||
//else {
|
||||
// return json(['code' => -1, 'msg' => '文件上传失败: ' . $file->getError()]);
|
||||
//}
|
||||
}
|
||||
|
||||
// 构建多部分表单数据
|
||||
$multipartStream = new MultipartStream($files);
|
||||
$boundary = $multipartStream->getBoundary();
|
||||
$headers = [
|
||||
'Content-Type' => "multipart/form-data; boundary={$boundary}",
|
||||
];
|
||||
|
||||
// 准备请求体
|
||||
$body = $multipartStream->getContents();
|
||||
|
||||
// 发起 POST 请求
|
||||
try {
|
||||
$response = $client->request('POST', $url, [
|
||||
'headers' => $headers,
|
||||
'body' => $body,
|
||||
]);
|
||||
|
||||
// 处理响应
|
||||
$responseBody = (string) $response->getBody();
|
||||
//echo "Server response: " . $responseBody;
|
||||
return Tools::set_ok('ok',$responseBody);
|
||||
} catch (\GuzzleHttp\Exception\RequestException $e) {
|
||||
// 错误处理
|
||||
//echo "Error: " . $e->getMessage();
|
||||
return Tools::set_fail("Error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* GET
|
||||
*
|
||||
* author:wh
|
||||
* @param string $url
|
||||
* @param int $timeout
|
||||
* @return bool|int|string
|
||||
*/
|
||||
static function curl_get(string $url, int $timeout = 10, $header=[])
|
||||
{
|
||||
|
||||
$header = $header?:array(
|
||||
'Accept: application/json',
|
||||
);
|
||||
$curl = curl_init();
|
||||
//curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
//curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
//curl_setopt($curl, CURLOPT_SSLVERSION, 3);
|
||||
//设置抓取的url
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
//设置头文件的信息作为数据流输出
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
// 超时设置,以秒为单位
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||||
|
||||
// 超时设置,以毫秒为单位
|
||||
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
|
||||
|
||||
// 设置请求头
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
||||
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
|
||||
//执行命令
|
||||
$data = curl_exec($curl);
|
||||
|
||||
// 显示错误信息
|
||||
if (curl_error($curl)) {
|
||||
//print "Error: ".curl_errno($curl).'-' . curl_error($curl);
|
||||
//返回错误码
|
||||
return ['code' => curl_errno($curl), 'msg' => curl_error($curl)];
|
||||
} else {
|
||||
//关闭句柄
|
||||
curl_close($curl);
|
||||
// 返回的内容
|
||||
return ['code' => 200, 'msg' => 'cURL ok', 'data' => $data];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* POST 表单
|
||||
*
|
||||
* author:wh
|
||||
* @param string $url 是请求的链接
|
||||
* @param array $postdata 传输的数据,数组格式
|
||||
* @return bool|int|string
|
||||
*/
|
||||
static function curl_post(string $url, array $postdata, $header=[]) {
|
||||
$timeout = 4;
|
||||
$connect_timeout = 1;
|
||||
$set_time_limit = 5;
|
||||
if($timeout + $connect_timeout < $set_time_limit) throw new \Exception('脚本超时值必须大于等于连接超时与请求处理超时之和');
|
||||
set_time_limit($set_time_limit);
|
||||
$header = $header?:array(
|
||||
'Accept: application/json',
|
||||
);
|
||||
|
||||
//初始化
|
||||
$curl = curl_init();
|
||||
//设置抓取的url
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
//设置头文件的信息作为数据流输出
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
// 超时设置
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||||
//发起连接前等待的时间,如果设置为0,则无限等待。
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
|
||||
|
||||
// 超时设置,以毫秒为单位
|
||||
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
|
||||
|
||||
// 设置请求头
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE );
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE );
|
||||
|
||||
//设置post方式提交
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata);
|
||||
//执行命令
|
||||
$data = curl_exec($curl);
|
||||
|
||||
// 显示错误信息
|
||||
if (curl_error($curl)) {
|
||||
//返回错误码
|
||||
return ['code'=>curl_errno($curl), 'msg'=>curl_error($curl)];
|
||||
} else {
|
||||
//关闭句柄
|
||||
curl_close($curl);
|
||||
// 返回的内容
|
||||
return ['code'=>200, 'msg'=>'cURL ok', 'data'=>$data];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* POST 查询参数
|
||||
*
|
||||
* author:wh
|
||||
* @param string $url 是请求的链接
|
||||
* @param array $postdata 传输的数据,http_build_query查询参数格式
|
||||
* @return bool|int|string
|
||||
*/
|
||||
static function curl_post_build_query(string $url, array $postdata, $header=[]) {
|
||||
$timeout = 4;
|
||||
$connect_timeout = 1;
|
||||
$set_time_limit = 5;
|
||||
if($timeout + $connect_timeout < $set_time_limit) throw new \Exception('脚本超时值必须大于等于连接超时与请求处理超时之和');
|
||||
set_time_limit($set_time_limit);
|
||||
$header = $header?:array(
|
||||
'Accept: application/json',
|
||||
);
|
||||
|
||||
//初始化
|
||||
$curl = curl_init();
|
||||
//设置抓取的url
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
//设置头文件的信息作为数据流输出
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
// 超时设置
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||||
//发起连接前等待的时间,如果设置为0,则无限等待。
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
|
||||
|
||||
// 超时设置,以毫秒为单位
|
||||
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
|
||||
|
||||
// 设置请求头
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE );
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE );
|
||||
|
||||
//设置post方式提交
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($postdata));
|
||||
//执行命令
|
||||
$data = curl_exec($curl);
|
||||
|
||||
// 显示错误信息
|
||||
if (curl_error($curl)) {
|
||||
//返回错误码
|
||||
return ['code'=>curl_errno($curl), 'msg'=>curl_error($curl)];
|
||||
} else {
|
||||
//关闭句柄
|
||||
curl_close($curl);
|
||||
// 返回的内容
|
||||
return ['code'=>200, 'msg'=>'ok', 'data'=>$data];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* POST json
|
||||
*
|
||||
* author:wh
|
||||
* @param string $url 是请求的链接
|
||||
* @param array $postdata 传输的数据,json格式
|
||||
* @return 返回数组格式
|
||||
*/
|
||||
static function curl_post_json(string $url, array $postdata, $header=[]) {
|
||||
$timeout = 4;
|
||||
$connect_timeout = 1;
|
||||
$set_time_limit = 5;
|
||||
if($timeout + $connect_timeout < $set_time_limit) throw new \Exception('脚本超时值必须大于等于连接超时与请求处理超时之和');
|
||||
set_time_limit($set_time_limit);
|
||||
$header = $header?:array(
|
||||
'Accept: application/json',
|
||||
);
|
||||
|
||||
//初始化
|
||||
$curl = curl_init();
|
||||
//设置抓取的url
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
//设置头文件的信息作为数据流输出
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
// 超时设置
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||||
//发起连接前等待的时间,如果设置为0,则无限等待。
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
|
||||
|
||||
// 超时设置,以毫秒为单位
|
||||
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
|
||||
|
||||
// 设置请求头
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE );
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE );
|
||||
|
||||
//设置post方式提交
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($postdata,JSON_UNESCAPED_UNICODE));
|
||||
//执行命令
|
||||
$data = curl_exec($curl);
|
||||
|
||||
// 显示错误信息
|
||||
if (curl_error($curl)) {
|
||||
//返回错误码
|
||||
return ['code'=>curl_errno($curl), 'msg'=>curl_error($curl)];
|
||||
} else {
|
||||
//关闭句柄
|
||||
curl_close($curl);
|
||||
// 返回的内容
|
||||
return ['code'=>200, 'msg'=>'cURL ok', 'data'=>$data];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* POST json ,成功直接返回请求结果,错误返回数组
|
||||
*
|
||||
* 注:此方法不是表单提交
|
||||
*
|
||||
* author:wh
|
||||
* @param string $url 是请求的链接
|
||||
* @param array $postdata 传输的数据,最终会转换为json格式请求
|
||||
* @return 直接返回请求数据,适合请求第三方返回BUFFER数据流的接口
|
||||
*/
|
||||
static function curl_post_json_return_buffer(string $url, array $postdata, $header=[]) {
|
||||
$timeout = 4;
|
||||
$connect_timeout = 1;
|
||||
$set_time_limit = 5;
|
||||
if($timeout + $connect_timeout < $set_time_limit) throw new \Exception('脚本超时值必须大于等于连接超时与请求处理超时之和');
|
||||
set_time_limit($set_time_limit);
|
||||
$header = $header?:array(
|
||||
'Accept: application/json',
|
||||
);
|
||||
|
||||
//初始化
|
||||
$curl = curl_init();
|
||||
//设置抓取的url
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
//设置头文件的信息作为数据流输出
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
// 超时设置
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||||
//发起连接前等待的时间,如果设置为0,则无限等待。
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
|
||||
|
||||
// 超时设置,以毫秒为单位
|
||||
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
|
||||
|
||||
// 设置请求头
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE );
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE );
|
||||
|
||||
//设置post方式提交
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($postdata,JSON_UNESCAPED_UNICODE));
|
||||
//执行命令
|
||||
$data = curl_exec($curl);
|
||||
|
||||
// 显示错误信息
|
||||
if (curl_error($curl)) {
|
||||
//返回错误码
|
||||
return ['code'=>curl_errno($curl), 'msg'=>curl_error($curl)];
|
||||
} else {
|
||||
//关闭句柄
|
||||
curl_close($curl);
|
||||
// 返回的内容
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* POST [流]
|
||||
*
|
||||
* [请求Java接口]
|
||||
*
|
||||
* 思考:1、Java端如果用文件流的方式去获取数据,调用此方法
|
||||
*
|
||||
* @param $url
|
||||
* @param $postdata
|
||||
* @param int $timeout
|
||||
* @return array
|
||||
* @link
|
||||
* @example
|
||||
* @see
|
||||
*/
|
||||
static function java_curl_post_file_request($url, $postdata, $timeout = 10, $header=[])
|
||||
{
|
||||
|
||||
$header = $header?:array(
|
||||
'Accept: application/json',
|
||||
);
|
||||
|
||||
//初始化
|
||||
$curl = curl_init();
|
||||
//设置抓取的url
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
//设置头文件的信息作为数据流输出
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
// 超时设置
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||||
|
||||
// 超时设置,以毫秒为单位
|
||||
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
|
||||
|
||||
// 设置请求头
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
|
||||
//设置post方式提交
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata);
|
||||
//执行命令
|
||||
$data = curl_exec($curl);
|
||||
|
||||
// 显示错误信息
|
||||
if (curl_error($curl)) {
|
||||
//返回错误码
|
||||
return ['code' => curl_errno($curl), 'msg' => curl_error($curl)];
|
||||
} else {
|
||||
//关闭句柄
|
||||
curl_close($curl);
|
||||
// 返回的内容
|
||||
return ['code' => 200, 'msg' => 'ok', 'data' => $data];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* 统一请求 GET/POST请求
|
||||
*
|
||||
* 注:此设置允许header重定向,适合部分请求头中携带参数的接口,如请求头携带token
|
||||
*
|
||||
* @param String $url 接口地址
|
||||
*/
|
||||
static function curl_request($url, $method = 'GET',$data=null,$header=array(),$call_back=null)
|
||||
{
|
||||
set_time_limit(30);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
if($header){
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
}
|
||||
if($method == 'POST'){
|
||||
if($data) curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
if($call_back){
|
||||
//使用此特性前除非你清楚理解回调函数,否则不推荐
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $call_back);
|
||||
}
|
||||
$result = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
return [
|
||||
'status' => 'error',
|
||||
'message' => 'curl 错误信息: ' . curl_error($ch)
|
||||
];
|
||||
}
|
||||
curl_close($ch);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* desc:php curl模拟文件上传
|
||||
* post
|
||||
* author:wh
|
||||
* @param $url 提交地址
|
||||
* @param $params 表单参数
|
||||
* @param $files 上传文件
|
||||
* @param $header 请求头
|
||||
* @return array
|
||||
*/
|
||||
static function curlFileUpload($url,$params,$files,$header)
|
||||
{
|
||||
// 初始化cURL会话
|
||||
$ch = curl_init();
|
||||
$header = $header ?: array(
|
||||
'Accept: application/json',
|
||||
'Content-Type: multipart/form-data'
|
||||
);
|
||||
// 合并文件和其他字段数据
|
||||
$data = array_merge($params, $files);
|
||||
|
||||
// 设置cURL选项
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
// 设置请求头
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
|
||||
// 执行cURL请求
|
||||
$result = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
return ['code' => curl_errno($ch), 'msg' => curl_error($ch)];
|
||||
}
|
||||
//关闭句柄
|
||||
curl_close($ch);
|
||||
// 返回的内容
|
||||
return ['code' => 200, 'msg' => 'cURL ok', 'data' => $result];
|
||||
}
|
||||
|
||||
}
|
||||
47
digital_doctor/vendor/wanghua/general-utility-tools-php/src/image/Image.php
vendored
Normal file
47
digital_doctor/vendor/wanghua/general-utility-tools-php/src/image/Image.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/1/17} {13:07}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\image;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class Image
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:将二进制字符串转为PNG图片
|
||||
*
|
||||
* 应用场景:当你的图片来源是buffer二进制时
|
||||
*
|
||||
* 实战场景:微信小程序获取小程序码,调用获取微信小程序码接口时,微信接口返回的是图片Buffer二进制,
|
||||
* 这时候需要前端转换为图片,有时候与你和做的前端技术需要你转换为图片,再把图片路径传给他直接使用
|
||||
*
|
||||
* author:wh
|
||||
* @param $binary 图片的Buffer二进制数据
|
||||
* @param $img_save_path 系统保存路径(传public网站根目录下面的路径)
|
||||
* @param $filename 要保存的文件名称,必须带后缀名
|
||||
*/
|
||||
function binaryToImage($binary,$img_save_path,$filename){
|
||||
// 获取二进制数据(这里假设从文件或其他地方获得)
|
||||
//$binaryData = file_get_contents($binary); // 替换成真正的路径
|
||||
|
||||
// 创建图像资源
|
||||
$imageResource = imagecreatefromstring($binary);
|
||||
|
||||
$img_save_path = Tools::get_root_path().'public/'.$img_save_path;
|
||||
if(!file_exists($img_save_path)){
|
||||
mkdir($img_save_path,0777,true);
|
||||
}
|
||||
// 保存图像到指定位置
|
||||
imagepng($imageResource, $img_save_path.$filename); // 替换成想要保存的路径及名称
|
||||
|
||||
// 释放内存并关闭图像资源
|
||||
imagedestroy($imageResource);
|
||||
}
|
||||
}
|
||||
82
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/BaseLog.php
vendored
Normal file
82
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/BaseLog.php
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/10} {18:00}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\log;
|
||||
|
||||
/**
|
||||
* @deprecated 预计2025年01月01日移除
|
||||
*
|
||||
* 使用本类之前,将fa_zc_log.sql导入数据库,配置可根据实际需求修改
|
||||
* Class BaseLog
|
||||
* @package wanghua\general_utility_tools_php\log
|
||||
*/
|
||||
class BaseLog
|
||||
{
|
||||
/**
|
||||
* 日志存储类型:文件、数据库(mysql)
|
||||
* 如果是文件类型,则在runtime目录中tool_log目录按日期生成文件
|
||||
* eg:/runtime/tool_log/2020-01-01.log
|
||||
* @var string
|
||||
*/
|
||||
protected static $log_type = 'file';//file or db
|
||||
|
||||
/**
|
||||
* desc:入参
|
||||
* author:wh
|
||||
* @param string $title
|
||||
* @param string $content
|
||||
*/
|
||||
static function in($content='', $title=''){
|
||||
$content = $content?$content:input();
|
||||
$title = is_string($title)?$title:json_encode($title, JSON_UNESCAPED_UNICODE);
|
||||
$content = is_string($content)?$content:json_encode($content);
|
||||
|
||||
$title = date('Ymd H:i:s').' ___IN | '.$title;
|
||||
self::ready($title, $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:出参
|
||||
* author:wh
|
||||
* @param string $title
|
||||
* @param string $content
|
||||
*/
|
||||
static function out($content='', $title=''){
|
||||
$title = is_string($title)?$title:json_encode($title, JSON_UNESCAPED_UNICODE);
|
||||
$content = is_string($content)?$content:json_encode($content);
|
||||
|
||||
$title = date('Ymd H:i:s').' __OUT | '.$title;
|
||||
self::ready($title, $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:错误信息
|
||||
* author:wh
|
||||
* @param string $title
|
||||
* @param string $content
|
||||
*/
|
||||
static function err($content='', $title=''){
|
||||
$content = $content?$content:input();
|
||||
$title = is_string($title)?$title:json_encode($title, JSON_UNESCAPED_UNICODE);
|
||||
$content = is_string($content)?$content:json_encode($content);
|
||||
|
||||
$title = date('Ymd H:i:s').' ERROR | '.$title;
|
||||
self::ready($title, $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $title
|
||||
* @param $content
|
||||
*/
|
||||
protected static function ready($title, $content){
|
||||
self::$log_type != 'file'?:(new File())->write($title, $content);
|
||||
self::$log_type != 'db'?:(new Mysql())->write($title, $content);
|
||||
}
|
||||
}
|
||||
134
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/Driver.php
vendored
Normal file
134
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/Driver.php
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/14} {11:51}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\log;
|
||||
|
||||
/**
|
||||
* 日志驱动
|
||||
*
|
||||
* only for thinkphp!
|
||||
*
|
||||
* eg:
|
||||
*
|
||||
$dr = new Driver();
|
||||
//$dr->setDriver('file');
|
||||
$dr->write(['start'=>11]);
|
||||
|
||||
$dr->write(['end'=>222]);
|
||||
|
||||
$dr->write(['result'=>333]);
|
||||
$dr->flush();//must
|
||||
*
|
||||
* Class Driver
|
||||
* @package wanghua\general_utility_tools_php\log
|
||||
*/
|
||||
class Driver
|
||||
{
|
||||
private $driver;
|
||||
|
||||
private $lib_path = '';//驱动路径
|
||||
|
||||
protected $static = null;
|
||||
|
||||
public function __construct(string $driver='')
|
||||
{
|
||||
//driver
|
||||
$sys_log_type = $driver?$driver:\think\Config::get('sys_log_type');
|
||||
//default driver
|
||||
$this->driver = isset($sys_log_type)&&$sys_log_type!=''?$sys_log_type:'file';
|
||||
//init driver
|
||||
$this->initDriver();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:choose driver
|
||||
*
|
||||
* author:wh
|
||||
* @param string $driver
|
||||
*/
|
||||
function setDriver(string $driver){
|
||||
//重新设置驱动
|
||||
$this->driver = $driver;
|
||||
//init driver
|
||||
$this->initDriver();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:get driver name
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function getDriverName(){
|
||||
return $this->driver;
|
||||
}
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
*/
|
||||
private function initDriver(){
|
||||
$this->driver = $this->driverPath().ucfirst($this->driver);
|
||||
$this->static = new $this->driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置日志路径
|
||||
* author:wh
|
||||
* @param string $logDir
|
||||
*/
|
||||
function setLogDir(string $logDir){
|
||||
$this->static->setLogDir($logDir);
|
||||
}
|
||||
|
||||
function getLogDir(){
|
||||
return $this->static->getLogDir();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:set driver lib path
|
||||
*
|
||||
* author:wh
|
||||
* @param $lib_path
|
||||
*/
|
||||
function setLibPath($lib_path){
|
||||
$this->lib_path = $lib_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:init
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
private function driverPath(){
|
||||
if($this->lib_path) return $this->lib_path;
|
||||
return 'wanghua\general_utility_tools_php\log\driver\\';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:group data
|
||||
*
|
||||
* author:wh
|
||||
* @param $data
|
||||
*/
|
||||
function write($data){
|
||||
|
||||
$this->static->write($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:output data
|
||||
*
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
function flush(){
|
||||
|
||||
return $this->static->flush();
|
||||
}
|
||||
}
|
||||
41
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/File.php
vendored
Normal file
41
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/File.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/11} {10:08}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\log;
|
||||
|
||||
/**
|
||||
* @deprecated 预计2025年01月01日移除
|
||||
* Class File
|
||||
* @package wanghua\general_utility_tools_php\log
|
||||
*/
|
||||
class File
|
||||
{
|
||||
//目录
|
||||
protected $log_dir = '';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$vendor_dir = __DIR__;
|
||||
$index = strpos($vendor_dir, 'vendor')?:0;
|
||||
|
||||
$this->log_dir = (substr($vendor_dir,0,$index)).'runtime/toollog/'.date('Ymd');
|
||||
file_exists($this->log_dir)?:mkdir($this->log_dir, 0777, true);
|
||||
$this->log_dir = $this->log_dir.'/'.date('Y-m-d-H').'.log';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $title
|
||||
* @param string $content
|
||||
*/
|
||||
function write(string $title, string $content=''){
|
||||
$string = "\r\n".$title.' '. $content;
|
||||
file_put_contents($this->log_dir, $string, FILE_APPEND);
|
||||
}
|
||||
}
|
||||
21
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/Log.php
vendored
Normal file
21
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/Log.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/10} {18:00}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\log;
|
||||
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* @deprecated 预计2025年01月01日移除
|
||||
* Class Log
|
||||
* @package wanghua\general_utility_tools_php\log
|
||||
*/
|
||||
class Log extends BaseLog
|
||||
{
|
||||
|
||||
}
|
||||
158
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/Logger.php
vendored
Normal file
158
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/Logger.php
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/12/07} {10:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\log;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\phpmailer\Mail;
|
||||
use wanghua\general_utility_tools_php\phpmailer\SMTP;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* @deprecated 预计2025年01月01日移除
|
||||
*
|
||||
* 文件日志专用
|
||||
*
|
||||
* 邮件配置必须
|
||||
*
|
||||
* Class Logger
|
||||
* @package app\common\tools
|
||||
*/
|
||||
class Logger
|
||||
{
|
||||
protected static $debug = 0;//调试模式
|
||||
//发件服务器 start
|
||||
//qq邮件服务器配置参考:https://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=331
|
||||
protected static $send_server_nickname = '系统异常';//发送方邮件服务器昵称 必须
|
||||
protected static $send_server_username = '';//发送方邮件服务器账号 必须 //'1003076966@qq.com';
|
||||
protected static $send_server_pwd = '';//发送方邮件服务器密码 必须 //'pdosdyjuurowbcfc';
|
||||
protected static $send_server_host = 'smtp.qq.com';//发送方邮件服务器 qq服务器:smtp.qq.com 必须
|
||||
//发件服务器 end
|
||||
|
||||
//收件邮箱 start
|
||||
protected static $receiver_email = '';//收件人邮箱 必须 eg: 1003076966@qq.com
|
||||
protected static $receiver_nickname = '收件人昵称';//收件人昵称 必须
|
||||
//收件邮箱 end
|
||||
|
||||
protected static $filter = [];//过滤指定日志,不发送至email
|
||||
|
||||
/**
|
||||
* desc:开启调试模式
|
||||
* author:wh
|
||||
*/
|
||||
static function open_debug(){
|
||||
self::$debug = SMTP::DEBUG_SERVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:关闭调试模式
|
||||
* author:wh
|
||||
*/
|
||||
static function close_debug(){
|
||||
self::$debug = SMTP::DEBUG_OFF;
|
||||
}
|
||||
/**
|
||||
* 【必须】
|
||||
* desc:设置邮件服务器配置
|
||||
* author:wh
|
||||
* @param $send_server_nickname
|
||||
* @param $send_server_username
|
||||
* @param $send_server_pwd
|
||||
* @param $send_server_host
|
||||
*/
|
||||
static function set_email_config(string $send_server_nickname,string $send_server_username,string $send_server_pwd,string $send_server_host){
|
||||
self::$send_server_nickname = $send_server_nickname;
|
||||
self::$send_server_username = $send_server_username;
|
||||
self::$send_server_pwd = $send_server_pwd;
|
||||
self::$send_server_host = $send_server_host;
|
||||
}
|
||||
|
||||
/**
|
||||
* 【必须】
|
||||
* desc:设置收件人配置
|
||||
* author:wh
|
||||
* @param $receiver_email
|
||||
* @param $receiver_nickname
|
||||
*/
|
||||
static function set_receiver_config(string $receiver_email,string $receiver_nickname){
|
||||
self::$receiver_email = $receiver_email;
|
||||
self::$receiver_nickname = $receiver_nickname;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:过滤指定日志,不发送至email
|
||||
* author:wh
|
||||
*/
|
||||
static function set_filter(array $filter=[]){
|
||||
self::$filter = $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:写入普通日志
|
||||
* author:wh
|
||||
* @param array $data
|
||||
* @param string $log_file_name
|
||||
* @return array
|
||||
*/
|
||||
static function write_text(array $data,string $log_file_name){
|
||||
try {
|
||||
$result = ['code'=>200,'msg'=>'ok'];
|
||||
Tools::log_to_write_txt($data,$log_file_name);
|
||||
return $result;//含 code、msg、data结构
|
||||
}catch (\Exception $e){
|
||||
//一般不会出错
|
||||
return ['code'=>500,'msg'=>'写入普通日志,日志记录失败.','data'=>['error'=>$e->getMessage(),'error_info'=>$e->getTraceAsString()]];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* desc:记录普通日志同时记录邮件日志
|
||||
*
|
||||
* author:wh
|
||||
* @param array $data 如果data里面的一维数组的key包含了被过滤的配置,则当次不发送邮件
|
||||
* @param string $log_file_name
|
||||
* @return array
|
||||
*/
|
||||
static function write_text_email(array $data,string $log_file_name){
|
||||
$keys = array_keys($data);
|
||||
try {
|
||||
Tools::log_to_write_txt($data,$log_file_name);
|
||||
if(self::$filter){
|
||||
$is_send = true;//发送
|
||||
foreach ($keys as $key){
|
||||
//过滤不发送邮件的key,可以是任意字符串
|
||||
if(in_array($key, self::$filter)){
|
||||
$is_send = false;
|
||||
}
|
||||
}
|
||||
if($is_send){
|
||||
return self::send($data);
|
||||
}
|
||||
}
|
||||
return self::send($data);
|
||||
}catch (\Exception $e){
|
||||
//一般不会出错
|
||||
return ['code'=>500,'msg'=>'普通日志邮件日志记录失败.','data'=>['error'=>$e->getMessage(),'error_info'=>$e->getTraceAsString()]];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param array $data
|
||||
* @param string $log_file_name
|
||||
* @return array
|
||||
*/
|
||||
protected static function send(array $data = []){
|
||||
$body = json_encode($data,JSON_UNESCAPED_UNICODE);
|
||||
$body = str_replace('\\"','"',$body);
|
||||
$body = str_replace('\\n"','',$body);
|
||||
$mail = new Mail(self::$send_server_nickname,self::$send_server_host,self::$send_server_username,self::$send_server_pwd);
|
||||
$mail->debug = self::$debug;
|
||||
return $mail->send(self::$receiver_email,self::$receiver_nickname,'EMAIL TITLE',$body);
|
||||
}
|
||||
}
|
||||
41
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/Mysql.php
vendored
Normal file
41
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/Mysql.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/11} {10:23}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\log;
|
||||
|
||||
/**
|
||||
* @deprecated 预计2025年01月01日移除
|
||||
*
|
||||
* 仅支持ThinkPHP框架
|
||||
* Class Mysql
|
||||
* @package wanghua\general_utility_tools_php\log
|
||||
*/
|
||||
class Mysql
|
||||
{
|
||||
//日志数据表前缀,如果没有前缀,可能和已有表名称冲突
|
||||
protected static $prefix = 'fa_sys_';
|
||||
//日志表名
|
||||
protected static $table = 'log';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $title
|
||||
* @param string $content
|
||||
*/
|
||||
function write($title, $content=''){
|
||||
Db::table(self::$prefix.self::$table)->insert([
|
||||
'title'=>$title, 'content'=>$content,
|
||||
]);
|
||||
}
|
||||
}
|
||||
90
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/driver/Base.php
vendored
Normal file
90
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/driver/Base.php
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/14} {16:04}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\log\driver;
|
||||
|
||||
/**
|
||||
* desc:日志驱动基类
|
||||
*
|
||||
* 用法参考:general_utility_tools_php\src\log\Driver.php类
|
||||
*
|
||||
* author:wh
|
||||
* Class Base
|
||||
* @package wanghua\general_utility_tools_php\log\driver
|
||||
*/
|
||||
class Base
|
||||
{
|
||||
|
||||
protected $reqid = '';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->reqid = $this->initReqID();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取日志目录
|
||||
*
|
||||
* 子类根据情况实现(Email,MySQL这种不需要目录则不实现)
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function getLogDir(){
|
||||
return '';
|
||||
}
|
||||
/**
|
||||
* 获取当前系统时间(精确到毫秒)
|
||||
* @return float
|
||||
*/
|
||||
protected function getMillisecond()
|
||||
{
|
||||
list($t1, $t2) = explode(' ', microtime());
|
||||
return sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000);
|
||||
}
|
||||
/**
|
||||
* 获取当前系统时间(精确到微秒)
|
||||
* @return float
|
||||
*/
|
||||
protected function getMicrosecond()
|
||||
{
|
||||
list($t1, $t2) = explode(' ', microtime());
|
||||
return sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000000);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:初始化请求id
|
||||
*
|
||||
* author:wh
|
||||
* @return float
|
||||
*/
|
||||
function initReqID(){
|
||||
return $this->getMicrosecond();
|
||||
}
|
||||
/**
|
||||
* desc:获取请求id
|
||||
*
|
||||
* author:wh
|
||||
* @return float
|
||||
*/
|
||||
function getReqID(){
|
||||
return $this->reqid;
|
||||
}
|
||||
|
||||
function write($content){
|
||||
|
||||
}
|
||||
|
||||
function flush(){
|
||||
|
||||
}
|
||||
|
||||
function getLogData(){
|
||||
|
||||
}
|
||||
}
|
||||
206
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/driver/Email.php
vendored
Normal file
206
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/driver/Email.php
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/12/07} {10:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\log\driver;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\phpmailer\Mail;
|
||||
use wanghua\general_utility_tools_php\phpmailer\SMTP;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 邮件日志驱动
|
||||
*
|
||||
* 说明:邮件发送到指定邮箱,使用之前请配置邮件账号、密码、服务器等必要参数
|
||||
*
|
||||
* 用法参考:general_utility_tools_php\src\log\Driver.php类
|
||||
*
|
||||
* 1. 邮件配置必须;
|
||||
* 2. 支持普通文本和html文本;
|
||||
*
|
||||
*
|
||||
* Class Logger
|
||||
* @package app\common\tools
|
||||
*/
|
||||
class Email extends Base
|
||||
{
|
||||
//file:文本(写文本文件), mysql:数据库, esdb:es数据库(直接存es数据库),esapi:es接口(调用接口向es存储数据)
|
||||
private $driver = 'file';
|
||||
protected $debug = 0;//调试模式
|
||||
//发件服务器 start
|
||||
//qq邮件服务器配置参考:https://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=331
|
||||
protected $send_server_nickname = '系统异常';//发送方邮件服务器昵称 必须
|
||||
protected $send_server_username = '';//发送方邮件服务器账号 必须 //'1003076966@qq.com';
|
||||
protected $send_server_pwd = '';//发送方邮件服务器密码 必须 //'pdosdyjuurowbcfc';
|
||||
protected $send_server_host = 'smtp.qq.com';//发送方邮件服务器 qq服务器:smtp.qq.com 必须
|
||||
//发件服务器 end
|
||||
|
||||
//收件邮箱 start
|
||||
protected $receiver_email = '';//收件人邮箱 必须 eg: 1003076966@qq.com
|
||||
protected $receiver_nickname = '收件人昵称';//收件人昵称 必须
|
||||
//收件邮箱 end
|
||||
|
||||
protected $filter = [];//过滤指定日志,不发送至email
|
||||
|
||||
public $port = 465;//国内qq服务器,亚马逊 25、587 或 2587
|
||||
public $protocol = 'ssl';//国内QQ是ssl,亚马逊TLS
|
||||
public $sender_email = '';//发送方邮箱
|
||||
|
||||
/**
|
||||
* desc:开启调试模式
|
||||
* author:wh
|
||||
*/
|
||||
function open_debug(){
|
||||
$this->debug = SMTP::DEBUG_SERVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:关闭调试模式
|
||||
* author:wh
|
||||
*/
|
||||
function close_debug(){
|
||||
$this->debug = SMTP::DEBUG_OFF;
|
||||
}
|
||||
/**
|
||||
* 【必须】
|
||||
* desc:设置邮件服务器配置
|
||||
* author:wh
|
||||
* @param $send_server_nickname
|
||||
* @param $send_server_username
|
||||
* @param $send_server_pwd
|
||||
* @param $send_server_host
|
||||
*/
|
||||
function set_email_config(string $send_server_nickname,string $send_server_username,string $send_server_pwd,string $send_server_host){
|
||||
$this->send_server_nickname = $send_server_nickname;
|
||||
$this->send_server_username = $send_server_username;
|
||||
$this->send_server_pwd = $send_server_pwd;
|
||||
$this->send_server_host = $send_server_host;
|
||||
}
|
||||
|
||||
/**
|
||||
* 【必须】
|
||||
* desc:设置收件人配置
|
||||
* author:wh
|
||||
* @param $receiver_email
|
||||
* @param $receiver_nickname
|
||||
*/
|
||||
function set_receiver_config($receiver_email,string $receiver_nickname){
|
||||
$this->receiver_email = $receiver_email;
|
||||
$this->receiver_nickname = $receiver_nickname;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:过滤指定日志,不发送至email
|
||||
* author:wh
|
||||
*/
|
||||
function set_filter(array $filter=[]){
|
||||
$this->filter = $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:记录普通日志同时记录邮件日志
|
||||
*
|
||||
* author:wh
|
||||
* @param array $data 如果data里面的一维数组的key包含了被过滤的配置,则当次不发送邮件
|
||||
* @param string $log_file_name
|
||||
* @return array
|
||||
*/
|
||||
function write_text_email(array $data,string $log_file_name){
|
||||
$keys = array_keys($data);
|
||||
try {
|
||||
Tools::log_to_write_txt($data,$log_file_name);
|
||||
if($this->filter){
|
||||
$is_send = true;//发送
|
||||
foreach ($keys as $key){
|
||||
//过滤不发送邮件的key,可以是任意字符串
|
||||
if(in_array($key, $this->filter)){
|
||||
$is_send = false;
|
||||
}
|
||||
}
|
||||
if($is_send){
|
||||
return $this->send($data);
|
||||
}
|
||||
}
|
||||
return $this->send($data);
|
||||
}catch (\Exception $e){
|
||||
//一般不会出错
|
||||
return ['code'=>500,'msg'=>'普通日志邮件日志记录失败.','data'=>['error'=>$e->getMessage(),'error_info'=>$e->getTraceAsString()]];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* desc:记录普通日志同时记录邮件日志
|
||||
*
|
||||
* author:wh
|
||||
* @param array $data 如果data里面的一维数组的key包含了被过滤的配置,则当次不发送邮件
|
||||
* @param string $log_file_name
|
||||
* @return array
|
||||
*/
|
||||
function write_text(string $title,string $body){
|
||||
return $this->sendText($title, $body);
|
||||
}
|
||||
/**
|
||||
* desc:记录普通日志同时记录邮件日志
|
||||
*
|
||||
* author:wh
|
||||
* @param array $data 如果data里面的一维数组的key包含了被过滤的配置,则当次不发送邮件
|
||||
* @param string $log_file_name
|
||||
* @return array
|
||||
*/
|
||||
function write_text_aws(string $title,string $body){
|
||||
return $this->sendTextAWS($title, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @return array|void
|
||||
*/
|
||||
function write($content){
|
||||
return $this->sendText($content['title'], $content['body']);
|
||||
}
|
||||
/**
|
||||
* desc:数组格式
|
||||
* author:wh
|
||||
* @param array $data
|
||||
* @param string $log_file_name
|
||||
* @return array
|
||||
*/
|
||||
protected function send(array $data = []){
|
||||
$body = json_encode($data,JSON_UNESCAPED_UNICODE);
|
||||
$body = str_replace('\\"','"',$body);
|
||||
$body = str_replace('\\n"','',$body);
|
||||
$mail = new Mail($this->send_server_nickname,$this->send_server_host,$this->send_server_username,$this->send_server_pwd,$this->send_server_username,$this->port,$this->protocol);
|
||||
$mail->debug = $this->debug;
|
||||
return $mail->send($this->receiver_email,$this->receiver_nickname,'EMAIL TITLE',$body);
|
||||
}
|
||||
/**
|
||||
* desc:文本格式
|
||||
* author:wh
|
||||
* @param array $data
|
||||
* @param string $log_file_name
|
||||
* @return array
|
||||
*/
|
||||
protected function sendText(string $title='邮件标题',string $body='邮件正文'){
|
||||
$mail = new Mail($this->send_server_nickname,$this->send_server_host,$this->send_server_username,$this->send_server_pwd,$this->send_server_username,$this->port,$this->protocol);
|
||||
$mail->debug = $this->debug;
|
||||
return $mail->send($this->receiver_email,$this->receiver_nickname,$title,$body);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:文本格式
|
||||
* author:wh
|
||||
* @param array $data
|
||||
* @param string $log_file_name
|
||||
* @return array
|
||||
*/
|
||||
protected function sendTextAWS(string $title='邮件标题',string $body='邮件正文'){
|
||||
$mail = new Mail($this->send_server_nickname,$this->send_server_host,$this->send_server_username,$this->send_server_pwd,$this->sender_email,$this->port,$this->protocol);
|
||||
$mail->debug = $this->debug;
|
||||
return $mail->sendAWS($this->receiver_email,$this->receiver_nickname,$title,$body);
|
||||
}
|
||||
}
|
||||
157
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/driver/File.php
vendored
Normal file
157
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/driver/File.php
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/11} {10:08}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\log\driver;
|
||||
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 文件日志驱动
|
||||
*
|
||||
* 说明:日志记录在文件中,默认目录 runtime/log,你可以自定义目录,参考setLogDir方法,都将记录在默认目录中。
|
||||
*
|
||||
* 用法参考:general_utility_tools_php\src\log\Driver.php类
|
||||
*
|
||||
* Class File
|
||||
* @package wanghua\general_utility_tools_php\log\lib
|
||||
*
|
||||
* 普通使用方法:
|
||||
* $LogObj = new Driver();
|
||||
* $LogObj->write('333333');
|
||||
* $LogObj->write('444444');
|
||||
* $LogObj->write('55555');
|
||||
* $LogObj->flush();
|
||||
*
|
||||
* tp框架使用方法:
|
||||
* 1、注册全局LogObj对象属性(参考example/tags.php)
|
||||
* 2、使用全局LogObj对象功能
|
||||
* eg:
|
||||
* //写入数据到内存
|
||||
* request()->LogObj->write('333333');
|
||||
* request()->LogObj->write('测试');
|
||||
* request()->LogObj->write('444444');
|
||||
* //持久化存储
|
||||
* request()->LogObj->flush();
|
||||
*
|
||||
*
|
||||
* tp框架行为使用方法:
|
||||
* 1、在应用目录中添加行为定义文件LoggerBehavior.php(参考example/LoggerBehavior.php)
|
||||
* 2、注册全局LogObj对象属性
|
||||
* 3、注册行为(侦听标签位)
|
||||
*
|
||||
*/
|
||||
class File extends Base
|
||||
{
|
||||
//目录
|
||||
private $log_dir = 'runtime/log/sys_log';//默认日志目录
|
||||
|
||||
private $log_data = [];
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置日志目录
|
||||
*
|
||||
* write之前调用
|
||||
*
|
||||
* author:wh
|
||||
* @param $log_dir
|
||||
*/
|
||||
function setLogDir($log_dir){
|
||||
$this->log_dir = 'runtime/log/'.$log_dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取日志目录
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function getLogDir(){
|
||||
return $this->log_dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:写日志
|
||||
*
|
||||
* 先压到内存中,调用flush方法写入磁盘,建议一次不要压太多
|
||||
*
|
||||
* author:wh
|
||||
* @param $content
|
||||
*/
|
||||
function write($content){
|
||||
$ip = request()->ip();
|
||||
$write_time = $this->getMicrosecond();
|
||||
$date = date('Y-m-d H:i:s');
|
||||
$tmp = [];
|
||||
$tmp['all'] = 0;
|
||||
$tmp['date'] = $date;
|
||||
$tmp['ip'] = $ip;
|
||||
$tmp['url'] = request()->baseUrl();
|
||||
$tmp['reqid'] = $this->reqid;
|
||||
|
||||
$tmp_data = [];
|
||||
if($this->log_data){
|
||||
$use_time = $write_time-$this->log_data['content'][count($this->log_data['content'])-1]['time'];
|
||||
$tmp_data['total'] = (array_sum(array_column($this->log_data['content'], 'use')) + $use_time);
|
||||
$tmp_data['use'] = ($write_time-$this->log_data['content'][count($this->log_data['content'])-1]['time']);
|
||||
$tmp_data['time'] = $write_time;
|
||||
$tmp_data['log_info'] = $content;
|
||||
}else{
|
||||
$tmp_data['total'] = 0;
|
||||
$tmp_data['use'] = 0;
|
||||
$tmp_data['time'] = $write_time;
|
||||
$tmp_data['log_info'] = $content;
|
||||
}
|
||||
$tmp['input'] = $_POST;
|
||||
$this->log_data['base'] = $tmp;
|
||||
$this->log_data['content'][] = $tmp_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:刷新日志数据到文件
|
||||
*
|
||||
* 仅调用一次
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function flush(){
|
||||
//计算单次request消耗
|
||||
$this->log_data['base']['all'] = array_sum(array_column($this->log_data['content'], 'use'));
|
||||
|
||||
//dir
|
||||
$this->log_dir = Tools::get_root_path().$this->log_dir.'/'.date('Ymd');
|
||||
|
||||
is_dir($this->log_dir)?:mkdir($this->log_dir, 0777, true);
|
||||
|
||||
$log_file = $this->log_dir.'/log'.date('YmdH').'.txt';
|
||||
|
||||
$base = json_encode($this->log_data['base'], JSON_UNESCAPED_UNICODE);
|
||||
$content = json_encode($this->log_data['content'], JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$content_str = str_replace('{"total"',"\n{'total'",$content);
|
||||
$content_str = str_replace('"log_info":',"'log_info':\n",$content_str);
|
||||
$strdata = "\n".$base ."\n".$content_str;
|
||||
|
||||
file_put_contents($log_file, "\n".$strdata, FILE_APPEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取当次请求日志数据
|
||||
*
|
||||
* 注:需在write方法之后调用,否则可能不准确
|
||||
*
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getLogData(){
|
||||
return $this->log_data;
|
||||
}
|
||||
}
|
||||
158
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/driver/Mysql.php
vendored
Normal file
158
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/driver/Mysql.php
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/11} {10:23}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\log\driver;
|
||||
|
||||
/**
|
||||
* MySQL日志驱动
|
||||
*
|
||||
* 说明:日志记录在mysql数据库,把日志记录在数据库中;不建议记录大量日志。
|
||||
* 推荐记录诸如系统生命周期日志、临时调试日志等少量日志,因为日志将占用大量空间,存在数据库中可能降低MySQL效率
|
||||
*
|
||||
* 用法参考:general_utility_tools_php\src\log\Driver.php类
|
||||
*
|
||||
* 仅支持ThinkPHP框架
|
||||
*
|
||||
* DDL:
|
||||
Create Table If Not Exists `t_sys_period_log` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`url` varchar(150) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'URL(不含查询参数)',
|
||||
`time` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '当前时间(微秒)',
|
||||
`use` int(10) unsigned DEFAULT '0' COMMENT '消耗(微秒)',
|
||||
`all` int(10) unsigned DEFAULT '0' COMMENT '总消耗(微秒)',
|
||||
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '当前时间',
|
||||
`ip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'IP',
|
||||
`reqid` varchar(16) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请求ID',
|
||||
`user_agent` varchar(3000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '代理',
|
||||
`input` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '输入',
|
||||
`log_info` text COLLATE utf8mb4_general_ci COMMENT '日志内容',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `index_create_time` (`create_time`) USING BTREE,
|
||||
KEY `index_time` (`time`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统周期日志';
|
||||
*
|
||||
* Class Mysql
|
||||
* @package wanghua\general_utility_tools_php\log
|
||||
*/
|
||||
class Mysql extends Base
|
||||
{
|
||||
//日志数据
|
||||
private $log_data = [];
|
||||
//日志数据表前缀:
|
||||
//如果没有前缀,可能和已有表名称冲突
|
||||
private $table = 't_sys_period_log';//默认表
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
//初始化日志
|
||||
$this->initLogTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:初始化日志表
|
||||
*
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
private function initLogTable(){
|
||||
$ddl = "Create Table If Not Exists `t_sys_period_log` (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`url` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'URL(不含查询参数)',
|
||||
`time` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '当前时间(微秒)',
|
||||
`use` int unsigned DEFAULT '0' COMMENT '消耗(微秒)',
|
||||
`all` int unsigned DEFAULT '0' COMMENT '总消耗(微秒)',
|
||||
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '当前时间',
|
||||
`ip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'IP',
|
||||
`reqid` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请求ID',
|
||||
`user_agent` varchar(3000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '代理',
|
||||
`input` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '输入',
|
||||
`log_info` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '日志内容',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `index_create_time` (`create_time`) USING BTREE,
|
||||
KEY `index_time` (`time`) USING BTREE,
|
||||
KEY `index_all` (`all`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统周期日志';";
|
||||
|
||||
if(!\think\Cache::get('mysql_init_log_table_cache')){
|
||||
\think\Db::execute($ddl);
|
||||
\think\Cache::set('mysql_init_log_table_cache',1);//1存在
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置日志表名
|
||||
*
|
||||
* author:wh
|
||||
* @param $tab
|
||||
*/
|
||||
function setTable($tab){
|
||||
$this->table = $tab;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* desc:获取日志表名
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function getTable(){
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:写日志
|
||||
*
|
||||
* 写进内存
|
||||
*
|
||||
* author:wh
|
||||
* @param $content
|
||||
*/
|
||||
function write($content){
|
||||
parent::write($content);
|
||||
$log_len = count($this->log_data);
|
||||
$time = $this->getMicrosecond();
|
||||
$use = $log_len>0?$time-$this->log_data[$log_len-1]['time']:0;
|
||||
//data
|
||||
$this->log_data[] = [
|
||||
'url'=>request()->domain().request()->baseUrl(),
|
||||
'time'=>$this->getMicrosecond(),
|
||||
'ip'=>request()->ip(),
|
||||
'reqid'=>$this->getReqID(),
|
||||
'use'=>$use,//单次消耗
|
||||
'all'=>array_sum(array_column($this->log_data, 'use'))+$use,
|
||||
'user_agent'=>json_encode(request()->header(),JSON_UNESCAPED_UNICODE),
|
||||
'input'=>json_encode(input(), JSON_UNESCAPED_UNICODE),
|
||||
'log_info'=>json_encode($content, JSON_UNESCAPED_UNICODE),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:持久化
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function flush()
|
||||
{
|
||||
parent::flush();
|
||||
return \think\Db::table($this->getTable())->insertAll($this->log_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取日志数据
|
||||
* author:wh
|
||||
* @return array|void
|
||||
*/
|
||||
function getLogData()
|
||||
{
|
||||
parent::getLogData();
|
||||
return $this->log_data;
|
||||
}
|
||||
}
|
||||
168
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/example/Logger.php
vendored
Normal file
168
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/example/Logger.php
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/12/07} {13:44}
|
||||
*/
|
||||
|
||||
namespace app\common\tools;
|
||||
|
||||
|
||||
use app\common\model\SundryConfigModel;
|
||||
use wanghua\general_utility_tools_php\log\Logger as LoggerObj;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* @deprecated 预计2025年01月01日移除
|
||||
*
|
||||
* 通用日志工具类
|
||||
*
|
||||
* 请将此类放入项目目录app\common\tools中再调用
|
||||
* 请将SundryConfigModel类放入项目目录app\common\model中再调用
|
||||
*
|
||||
* 使用案例:
|
||||
*
|
||||
$rspArray = ['asfdasd'=>['1111'=>['222'=>['测试'=>'测试内容']]]];
|
||||
$res = Logger::log_email(['aaaaaaaa'=>['1111'=>['222']]],'test_log');
|
||||
dump($res);
|
||||
$res = Logger::log_email(['bbbbbbbbbbbbbbb',$rspArray],'test_log');
|
||||
dump($res);
|
||||
*
|
||||
* Class Logger
|
||||
* @package app\common\tools
|
||||
*/
|
||||
class Logger
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:开启调试模式
|
||||
* author:wh
|
||||
*/
|
||||
static function open_debug(){
|
||||
LoggerObj::open_debug();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:关闭调试模式
|
||||
* author:wh
|
||||
*/
|
||||
static function close_debug(){
|
||||
LoggerObj::close_debug();
|
||||
}
|
||||
/**
|
||||
* desc:系统未来通用统一日志记录
|
||||
*
|
||||
* eg:Logger::log(['测试测试测试测试.',$rspArray],$this->wechat_pay_log);//普通日志写入
|
||||
*
|
||||
* author:wh
|
||||
* @param array $data
|
||||
* @param string $file_log_name
|
||||
*/
|
||||
static function log(array $data=[], string $file_log_name){
|
||||
try {
|
||||
//服务器配置 start
|
||||
$send_server_nickname = SundryConfigModel::getConfigVal('send_server_username');
|
||||
$send_server_username = SundryConfigModel::getConfigVal('send_server_username');
|
||||
$send_server_pwd = SundryConfigModel::getConfigVal('send_server_pwd');
|
||||
$send_server_host = SundryConfigModel::getConfigVal('send_server_host');
|
||||
//服务器配置 end
|
||||
|
||||
//收件人信息 start
|
||||
$receiver = SundryConfigModel::getConfigVal('admin_error_log_email');
|
||||
$receiver_nickname = '日志管理员';//默认收件人昵称
|
||||
//收件人信息 end
|
||||
|
||||
//写入日志
|
||||
LoggerObj::set_email_config($send_server_nickname,$send_server_username,$send_server_pwd,$send_server_host);
|
||||
LoggerObj::set_receiver_config($receiver,$receiver_nickname);
|
||||
return LoggerObj::write_text($data,$file_log_name);
|
||||
}catch (\Exception $e){
|
||||
Tools::log_to_write_txt(['error'=>'系统未来通用统一日志记录,出错.'.$e->getMessage(),'日志入参:'=>$data,'error_info'=>$e->getTraceAsString()],$file_log_name);
|
||||
return ['code'=>500,'msg'=>'日志写入异常.'.$e->getMessage()];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:记录错误信息并发送邮件
|
||||
*
|
||||
* eg:Logger::log_email(['收银宝统一支付-支付失败.',$rspArray],$this->wechat_pay_log);
|
||||
*
|
||||
* 小贴士:即将写入的数据将被添加一个error键名,再调用底层日志写入
|
||||
*
|
||||
* 使用案例:
|
||||
*
|
||||
$rspArray = ['asfdasd'=>['1111'=>['222'=>['测试'=>'测试内容']]]];
|
||||
$res = Logger::log_email(['aaaaaaaa'=>['1111'=>['222']]],'test_log');
|
||||
dump($res);
|
||||
$res = Logger::log_email(['bbbbbbbbbbbbbbb',$rspArray],'test_log');
|
||||
dump($res);
|
||||
*
|
||||
*
|
||||
* 【注】
|
||||
* 必须的邮件配置包含:
|
||||
*
|
||||
send_server_nickname 邮件发送服务器昵称
|
||||
send_server_username 邮件发送服务器账号
|
||||
send_server_pwd 邮件发送服务器密码
|
||||
send_server_host 邮件发送服务器
|
||||
admin_error_log_email 接收异常日志的管理员邮箱
|
||||
*
|
||||
* sql,复制可用:
|
||||
INSERT INTO `fa_zc_sundry_config` ( `name`, `key`, `val`, `msg`, `group`, `ext_one`, `ext_two`, `ext_three`, `create_time`, `update_time`) VALUES ( '邮件发送服务器昵称', 'send_server_nickname', '掌电竞技', '', 'email', '', '', '', '2021-12-07 11:37:11', NULL);
|
||||
INSERT INTO `fa_zc_sundry_config` ( `name`, `key`, `val`, `msg`, `group`, `ext_one`, `ext_two`, `ext_three`, `create_time`, `update_time`) VALUES ( '邮件发送服务器账号', 'send_server_username', '1003076950@qq.com', '', 'email', '', '', '', '2021-12-07 11:37:11', NULL);
|
||||
INSERT INTO `fa_zc_sundry_config` ( `name`, `key`, `val`, `msg`, `group`, `ext_one`, `ext_two`, `ext_three`, `create_time`, `update_time`) VALUES ( '邮件发送服务器密码', 'send_server_pwd', 'pdosdyjuurowbcfc', '', 'email', '', '', '', '2021-12-07 11:37:11', NULL);
|
||||
INSERT INTO `fa_zc_sundry_config` ( `name`, `key`, `val`, `msg`, `group`, `ext_one`, `ext_two`, `ext_three`, `create_time`, `update_time`) VALUES ( '邮件发送服务器', 'send_server_host', 'smtp.qq.com', '', 'email', '', '', '', '2021-12-07 11:37:11', NULL);
|
||||
INSERT INTO `fa_zc_sundry_config` ( `name`, `key`, `val`, `msg`, `group`, `ext_one`, `ext_two`, `ext_three`, `create_time`, `update_time`) VALUES ( '接收异常日志的管理员邮箱', 'admin_error_log_email', '1003076950@qq.com', '', 'email', '', '', '', '2021-12-07 13:48:18', '2021-12-07 13:48:27');
|
||||
|
||||
*
|
||||
*
|
||||
* author:wh
|
||||
* @param array $data
|
||||
* @param string $file_log_name
|
||||
*/
|
||||
static function log_email(array $data=[], string $file_log_name){
|
||||
try {
|
||||
//服务器配置 start
|
||||
$send_server_nickname = SundryConfigModel::getConfigVal('send_server_username');
|
||||
$send_server_username = SundryConfigModel::getConfigVal('send_server_username');
|
||||
$send_server_pwd = SundryConfigModel::getConfigVal('send_server_pwd');
|
||||
$send_server_host = SundryConfigModel::getConfigVal('send_server_host');
|
||||
//服务器配置 end
|
||||
if(empty($send_server_nickname)){
|
||||
Tools::log_to_write_txt(['服务器配置错误.发件服务器昵称为空.'],$file_log_name);
|
||||
return Tools::set_res(500,'服务器配置错误.发件服务器昵称为空');
|
||||
}
|
||||
if(empty($send_server_username)){
|
||||
Tools::log_to_write_txt(['服务器配置错误.发件服务器邮箱为空.'],$file_log_name);
|
||||
return Tools::set_res(500,'服务器配置错误.发件服务器邮箱为空');
|
||||
}
|
||||
if(empty($send_server_pwd)){
|
||||
Tools::log_to_write_txt(['服务器配置错误.发件服务器密码为空.'],$file_log_name);
|
||||
return Tools::set_res(500,'服务器配置错误.发件服务器密码为空.');
|
||||
}
|
||||
if(empty($send_server_host)){
|
||||
Tools::log_to_write_txt(['服务器配置错误.发件服务器HOST为空.'],$file_log_name);
|
||||
return Tools::set_res(500,'服务器配置错误.发件服务器HOST为空..');
|
||||
}
|
||||
|
||||
//收件人信息 start
|
||||
$receiver = SundryConfigModel::getConfigVal('admin_error_log_email');
|
||||
$receiver_nickname = '日志管理员';//默认收件人昵称
|
||||
//收件人信息 end
|
||||
if(empty($send_server_host)){
|
||||
Tools::log_to_write_txt(['服务器配置错误.发件服务器HOST为空.'],$file_log_name);
|
||||
return Tools::set_res(500,'服务器配置错误.发件服务器HOST为空..');
|
||||
}
|
||||
|
||||
LoggerObj::set_email_config($send_server_nickname,$send_server_username,$send_server_pwd,$send_server_host);
|
||||
LoggerObj::set_receiver_config($receiver,$receiver_nickname);
|
||||
|
||||
//写入日志
|
||||
return LoggerObj::write_text_email($data,$file_log_name);
|
||||
}catch (\Exception $e){
|
||||
Tools::log_to_write_txt(['error'=>'系统未来通用统一日志记录,出错.'.$e->getMessage(),'日志入参:'=>$data,'error_info'=>$e->getTraceAsString()],$file_log_name);
|
||||
return ['code'=>500,'msg'=>'日志写入异常.'.$e->getMessage()];
|
||||
}
|
||||
}
|
||||
}
|
||||
54
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/example/LoggerBehavior.php
vendored
Normal file
54
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/example/LoggerBehavior.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/14} {16:50}
|
||||
*/
|
||||
namespace wanghua\general_utility_tools_php\log\example;
|
||||
|
||||
use wanghua\general_utility_tools_php\log\Driver;
|
||||
|
||||
/**
|
||||
* 行为定义
|
||||
*
|
||||
* 使用方法,请阅读example/README.MD,第“使用驱动记录日志”项。
|
||||
*
|
||||
*
|
||||
* Class LoggerBehavior
|
||||
* @package app\behavior
|
||||
*/
|
||||
class LoggerBehavior
|
||||
{
|
||||
//function run(){
|
||||
//
|
||||
//}
|
||||
|
||||
|
||||
function appInit(){
|
||||
if(!request()->LogObj) {
|
||||
request()->LogObj = new Driver();
|
||||
}
|
||||
request()->LogObj->write(['app start']);
|
||||
|
||||
|
||||
|
||||
//业务日志对象
|
||||
if(!request()->ServeLogObj) {
|
||||
request()->ServeLogObj = new Driver();
|
||||
request()->ServeLogObj->setDriver('file');
|
||||
}
|
||||
request()->ServeLogObj->write(['app serve start']);
|
||||
}
|
||||
function appEnd(){
|
||||
//框架生命周期日志对象
|
||||
request()->LogObj->write(['app end']);
|
||||
request()->LogObj->flush();
|
||||
|
||||
|
||||
|
||||
//业务日志对象
|
||||
request()->ServeLogObj->write(['app serve end']);
|
||||
request()->ServeLogObj->flush();
|
||||
}
|
||||
}
|
||||
70
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/example/README.MD
vendored
Normal file
70
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/example/README.MD
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
## 可直接使用的案例
|
||||
|
||||
### 使用驱动记录日志
|
||||
如需记录系统生命周期日志、临时调试日志(不推荐记录巨量日志数据),参考如下方案(简单修改即可):
|
||||
|
||||
* 在tags.php文件中初始化日志对象并监听应用行为, 复制代码即可使用
|
||||
|
||||
````
|
||||
|
||||
//框架生命周期日志(bind的变量名可以自定义,不一定是LogObj)
|
||||
\think\Request::instance()->bind('LogObj',new \wanghua\general_utility_tools_php\log\Driver('mysql'));
|
||||
//业务日志对象
|
||||
\think\Request::instance()->bind('ServeLogObj',new \wanghua\general_utility_tools_php\log\Driver('file'));
|
||||
|
||||
````
|
||||
|
||||
* (完成上一步即可使用)需要注意的是,LogObj对象的日志记录在变量中(内存中),
|
||||
一旦程序异常终止,则日志也将丢失。有一个好办法,那就是捕获系统异常并刷新已经
|
||||
记录的日志到介质(磁盘、数据库)。在框架config.php配置文件中配置异常接管类,
|
||||
参考以下案例:
|
||||
|
||||
````
|
||||
|
||||
// 异常处理handle类 留空使用 \think\exception\Handle
|
||||
// 如果想扩展异常类的功能,可以创建一个类来继承此类,然后把新建的类配置在这里
|
||||
'exception_handle' => '\\wanghua\\general_utility_tools_php\\src\\exception\\SystemException',
|
||||
|
||||
````
|
||||
|
||||
* 在系统中,你可以随时记录日志,参考代码:
|
||||
|
||||
``````
|
||||
|
||||
request()->LogObj->write(['你的文本,这里是数据哦!']);//记录一条简单的日志
|
||||
|
||||
``````
|
||||
|
||||
当然,如果你觉得此代码不好记忆和使用的话,你可以自由封装此代码,方便在应用中调用。
|
||||
|
||||
### 灵活的日志记录方式(可以在系统任意地方使用)
|
||||
eg1:
|
||||
```
|
||||
|
||||
//一维数组
|
||||
//记录一条简单的日志
|
||||
Tools::log_to_write_txt(['测试日志标题'=>'测试日志内容'],'test_log_dir');
|
||||
//记录错误日志
|
||||
Tools::log_to_write_txt([
|
||||
'error'=>'系统错误.'.$e->getMessage(),
|
||||
'input'=>input(),
|
||||
'error_info'=>$e->getTraceAsString()
|
||||
],'test_log_dir');
|
||||
|
||||
```
|
||||
|
||||
eg2:
|
||||
```
|
||||
|
||||
//多维数组
|
||||
Tools::log_to_write_txt([
|
||||
'数组类型的日志'=>'随便记录点什么',
|
||||
[
|
||||
'可以是多维数组'=>
|
||||
[
|
||||
'a'=>'test'
|
||||
]
|
||||
]
|
||||
],'test_log_dir');//test_log_dir是你的日志文件路径
|
||||
|
||||
```
|
||||
30
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/example/SundryConfigModel.php
vendored
Normal file
30
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/example/SundryConfigModel.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/08/25} {17:37}
|
||||
*/
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* @deprecated 预计2025年01月01日移除
|
||||
*
|
||||
* Class SundryConfigModel
|
||||
* @package app\common\model
|
||||
*/
|
||||
class SundryConfigModel
|
||||
{
|
||||
protected static $self_table = 'fa_zc_sundry_config';
|
||||
|
||||
|
||||
static function getConfigVal(string $key){
|
||||
|
||||
return Db::table(self::$self_table)->where('key',$key)->value('val');
|
||||
}
|
||||
|
||||
}
|
||||
56
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/example/tags.php
vendored
Normal file
56
digital_doctor/vendor/wanghua/general-utility-tools-php/src/log/example/tags.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
// 应用行为扩展定义文件
|
||||
|
||||
|
||||
// 动态绑定Request对象属性
|
||||
//框架生命周期日志(用mysql驱动)
|
||||
\think\Request::instance()->bind('LogObj',new \wanghua\general_utility_tools_php\log\Driver('mysql'));
|
||||
//业务日志对象(用文件驱动)
|
||||
\think\Request::instance()->bind('ServeLogObj',new \wanghua\general_utility_tools_php\log\Driver('file'));
|
||||
|
||||
|
||||
// 注册 app\index\behavior\CheckLang行为类到app_init标签位
|
||||
\think\Hook::add('app_init', '\\wanghua\\general_utility_tools_php\\log\\example\\LoggerBehavior');
|
||||
//注册 app\admin\behavior\CronRun行为类到app_init标签位
|
||||
\think\Hook::add('app_end', '\\wanghua\\general_utility_tools_php\\log\\example\\LoggerBehavior');
|
||||
|
||||
|
||||
|
||||
|
||||
return [
|
||||
// 应用初始化
|
||||
'app_init' => [],
|
||||
// 应用开始
|
||||
'app_begin' => [],
|
||||
// 应用调度
|
||||
'app_dispatch' => [
|
||||
'app\\common\\behavior\\Common',
|
||||
],
|
||||
// 模块初始化
|
||||
'module_init' => [
|
||||
'app\\common\\behavior\\Common',
|
||||
],
|
||||
// 插件开始
|
||||
'addon_begin' => [
|
||||
'app\\common\\behavior\\Common',
|
||||
],
|
||||
// 操作开始执行
|
||||
'action_begin' => [],
|
||||
// 视图内容过滤
|
||||
'view_filter' => [],
|
||||
// 日志写入
|
||||
'log_write' => [],
|
||||
// 应用结束
|
||||
'app_end' => [],
|
||||
];
|
||||
119
digital_doctor/vendor/wanghua/general-utility-tools-php/src/md5rsa/Md5RSA.php
vendored
Normal file
119
digital_doctor/vendor/wanghua/general-utility-tools-php/src/md5rsa/Md5RSA.php
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/11/02} {20:17}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\md5rsa;
|
||||
|
||||
|
||||
/**
|
||||
* md5rsa对称加密
|
||||
*
|
||||
* Class Md5RSA
|
||||
* @package app\index\pay
|
||||
*/
|
||||
class Md5RSA{
|
||||
|
||||
/**
|
||||
* 利用约定数据和私钥生成数字签名
|
||||
* @param string $data 待签数据
|
||||
* @return String 返回签名
|
||||
*
|
||||
* 使用示例:
|
||||
*
|
||||
* $crypted = (new Md5RSA())->sign($signMsg='待加密字符串',$mo_bao_cust_privite_key='私钥');
|
||||
if(empty($crypted)){
|
||||
return Tools::set_res(500, '加密失败');
|
||||
}
|
||||
|
||||
$eb64_cry = base64_encode($crypted);
|
||||
|
||||
|
||||
*
|
||||
* 私钥格式参考:
|
||||
* -----BEGIN PRIVATE KEY-----
|
||||
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKaQA2YLzj0g6e1h
|
||||
BB1KAu8wwabxX+7zfwBMdqhnC/B6hjJ37/tbH5vHlt2S0lvjphupLW/PdVF1ezIk
|
||||
haGk1ya0qFiKfByXzdou3Ml4qzOemmozIAix5ooh4Cbq1Py6202SvbM7KYv89syk
|
||||
HJNB4QWXLLWmgsHCuiXQXhRJz6jDAgMBAAECgYAIF5cSriAm+CJlVgFNKvtZg5Tk
|
||||
93UhttLEwPJC3D7IQCuk6A7Qt2yhtOCvgyKVNEotrdp3RCz++CY0GXIkmE2bj7i0
|
||||
fv5vT3kWvO9nImGhTBH6QlFDxc9+p3ukwsonnCshkSV9gmH5NB/yFoH1m8tck2Gm
|
||||
BXDj+bBGUoKGWtQ7gQJBANR/jd5ZKf6unLsgpFUS/kNBgUa+EhVg2tfr9OMioWDv
|
||||
MSqzG/sARQ2AbO00ytpkbAKxxKkObPYsn47MWsf5970CQQDIqRiGmCY5QDAaejW4
|
||||
HbOcsSovoxTqu1scGc3Qd6GYvLHujKDoubZdXCVOYQUMEnCD5j7kdNxPbVzdzXll
|
||||
9+p/AkEAu/34iXwCbgEWQWp4V5dNAD0kXGxs3SLpmNpztLn/YR1bNvZry5wKew5h
|
||||
z1zEFX+AGsYgQJu1g/goVJGvwnj/VQJAOe6f9xPsTTEb8jkAU2S323BG1rQFsPNg
|
||||
jY9hnWM8k2U/FbkiJ66eWPvmhWd7Vo3oUBxkYf7fMEtJuXu+JdNarwJAAwJK0YmO
|
||||
LxP4U+gTrj7y/j/feArDqBukSngcDFnAKu1hsc68FJ/vT5iOC6S7YpRJkp8egj5o
|
||||
pCcWaTO3GgC5Kg==
|
||||
-----END PRIVATE KEY-----
|
||||
*/
|
||||
public function sign(string $data, string $private_key)
|
||||
{
|
||||
if (empty($data) || empty($private_key))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//$private_key = file_get_contents(dirname(__FILE__).'/rsa_private_key.pem');
|
||||
//if (empty($private_key))
|
||||
//{
|
||||
// echo "Private Key error!";
|
||||
// return False;
|
||||
//}
|
||||
|
||||
$pkeyid = openssl_get_privatekey($private_key);
|
||||
if (empty($pkeyid))
|
||||
{
|
||||
// "private key resource identifier False!";
|
||||
return false;
|
||||
}
|
||||
|
||||
$verify = openssl_sign($data, $signature, $pkeyid, OPENSSL_ALGO_MD5);
|
||||
openssl_free_key($pkeyid);
|
||||
return $signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* 利用公钥和数字签名以及约定数据验证合法性
|
||||
* @param string $data 待验证数据
|
||||
* @param string $signature 数字签名
|
||||
* @return -1:error验证错误 1:correct验证成功 0:incorrect验证失败
|
||||
*/
|
||||
public function isValid(string $data, string $signature, string $public_key)
|
||||
{
|
||||
if (empty($data) || empty($signature) || empty($public_key))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//$public_key = file_get_contents(dirname(__FILE__).'/rsa_public_key.pem');
|
||||
//if (empty($public_key))
|
||||
//{
|
||||
// echo "Public Key error!";
|
||||
// return False;
|
||||
//}
|
||||
|
||||
$pkeyid = openssl_get_publickey($public_key);
|
||||
if (empty($pkeyid))
|
||||
{
|
||||
// "public key resource identifier False!";
|
||||
return false;
|
||||
}
|
||||
|
||||
$ret = openssl_verify($data, $signature, $pkeyid, OPENSSL_ALGO_MD5);
|
||||
//switch ($ret)
|
||||
//{
|
||||
// case -1:
|
||||
// echo "error";
|
||||
// break;
|
||||
// default:
|
||||
// echo $ret==1 ? "correct" : "incorrect";//0:incorrect
|
||||
// break;
|
||||
//}
|
||||
return $ret==1;
|
||||
}
|
||||
|
||||
}
|
||||
6
digital_doctor/vendor/wanghua/general-utility-tools-php/src/mysql/README.MD
vendored
Normal file
6
digital_doctor/vendor/wanghua/general-utility-tools-php/src/mysql/README.MD
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
## 仅适用于tp5+, php7+
|
||||
|
||||
|
||||
## 表管理
|
||||
|
||||
## 字段管理
|
||||
314
digital_doctor/vendor/wanghua/general-utility-tools-php/src/mysql/lib/Field.php
vendored
Normal file
314
digital_doctor/vendor/wanghua/general-utility-tools-php/src/mysql/lib/Field.php
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {10:57}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\mysql\lib;
|
||||
|
||||
|
||||
use think\Db;
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated 废弃,未来将会删除
|
||||
*
|
||||
* desc:
|
||||
*
|
||||
* author:wh
|
||||
* Class Field
|
||||
* @package wanghua\general_utility_tools_php\mysql\lib
|
||||
*/
|
||||
class Field
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* desc:创建字段,存在则修改字段
|
||||
* author:wh
|
||||
* @param array $table
|
||||
*/
|
||||
function createfield(array $table){
|
||||
$table_name = $table['tablename'];
|
||||
//新增字段
|
||||
$dec_num = '';
|
||||
|
||||
if(in_array(strtoupper($table['type']), ['TINYINT','SMALLINT','MEDIUMINT','INT','BIGINT','FLOAT','DOUBLE','DECIMAL'])){
|
||||
$table['default'] = '0';//整型默认值 浮点类型自动转为0.00
|
||||
if(in_array(strtoupper($table['type']), ['FLOAT','DOUBLE','DECIMAL'])){
|
||||
$dec_num = ','.$table['decimals_size'];//浮点类型小数位位数
|
||||
}
|
||||
}elseif ($table['type'] == 'enum'){
|
||||
//枚举值不转换
|
||||
}else{
|
||||
$table['default'] = '""';
|
||||
}
|
||||
|
||||
if(in_array(strtolower($table['type']), ['timestamp','datetime','date','time','text','mediumtext','longtext'])){
|
||||
$table['size'] = 0;//重写 默认0
|
||||
$table['default'] = 'null';//重写
|
||||
}
|
||||
//是否可以负数
|
||||
if(in_array(strtolower($table['type']), ['int','tinyint','bigint','smallint', 'double', 'float', 'decimal']) && !empty($post['is_unsigned'])){//不是
|
||||
$is_unsigned = 'unsigned';
|
||||
}else{//是 表单可选值
|
||||
$is_unsigned = '';
|
||||
}
|
||||
|
||||
if (in_array($table['fields_name'], ['create_time', 'update_time'])){
|
||||
if($table['fields_name'] == 'create_time'){
|
||||
$table['default'] = 'CURRENT_TIMESTAMP';
|
||||
}
|
||||
if($table['fields_name'] == 'update_time'){
|
||||
$table['default'] = 'NULL ON UPDATE CURRENT_TIMESTAMP';
|
||||
}
|
||||
}
|
||||
//验证字段是否存在
|
||||
$f = DB::table($table_name)->getTableFields();
|
||||
if(in_array($table['fields_name'], $f)){
|
||||
//枚举类型
|
||||
if ($table['type'] == 'enum'){
|
||||
$enum_str = '';
|
||||
$enum_default = '';
|
||||
//组合枚举值
|
||||
if($table['default']){
|
||||
$enum_str.='ENUM('.$table['default'].')';
|
||||
$enum_default = explode(',', $table['default'])[0];
|
||||
}
|
||||
$sql2 = "ALTER TABLE {$table_name} MODIFY {$table['fields_name']} {$enum_str} NOT NULL DEFAULT {$enum_default} COMMENT '{$table['title']}';";
|
||||
}else{
|
||||
$sql2 = "ALTER TABLE {$table_name} MODIFY COLUMN {$table['fields_name']} {$table['type']}(".$table['size'].$dec_num.") {$is_unsigned} DEFAULT {$table['default']} COMMENT '{$table['title']}';";
|
||||
}
|
||||
}else{
|
||||
|
||||
if(in_array($table['type'], ['text','longtext'])){
|
||||
$sql2 = "ALTER TABLE {$table_name} ADD COLUMN {$table['fields_name']} {$table['type']} COMMENT '{$table['title']}' AFTER id;";
|
||||
}elseif ($table['type'] == 'enum'){//枚举类型
|
||||
$enum_str = '';
|
||||
$enum_default = '';
|
||||
//组合枚举值
|
||||
if($table['default']){
|
||||
$enum_str.='ENUM('.$table['default'].')';
|
||||
$enum_default = explode(',', $table['default'])[0];
|
||||
}
|
||||
$sql2 = "ALTER TABLE {$table_name} ADD {$table['fields_name']} {$enum_str} NOT NULL DEFAULT {$enum_default} COMMENT '{$table['title']}' AFTER id;";
|
||||
}else{
|
||||
$sql2 = "ALTER TABLE {$table_name} ADD COLUMN {$table['fields_name']} {$table['type']}(".$table['size'].$dec_num.") {$is_unsigned} DEFAULT {$table['default']} COMMENT '{$table['title']}' AFTER id;";
|
||||
}
|
||||
}
|
||||
|
||||
DB::execute($sql2);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除字段
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $fieldname
|
||||
*/
|
||||
function dropFieldName($tablename, $fieldname){
|
||||
$sql = "ALTER TABLE {$tablename} DROP COLUMN {$fieldname};";
|
||||
DB::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:改注释
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $comment
|
||||
* @return bool
|
||||
*/
|
||||
function updateComment($tablename,$field, $comment){
|
||||
|
||||
$sql = "ALTER TABLE {$tablename} MODIFY COLUMN {$field} INT COMMENT '{$comment}';";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取数据表中所有字段的数据类型(含其它属性)
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldsDataType(string $dbname,string $tablename){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'";
|
||||
return Db::query($sql);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:获取数据表中某个字段的数据类型(含这个字段的其它属性)
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldDataType(string $dbname,string $tablename,string $fieldname){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'
|
||||
AND COLUMN_NAME='$fieldname'
|
||||
";
|
||||
$ar = Db::query($sql);
|
||||
return $ar[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:获取数据表中某个字段的数据类型
|
||||
*
|
||||
* 不含这个字段的其它属性
|
||||
*
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldDataTypeVal(string $dbname,string $tablename,string $fieldname){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'
|
||||
AND COLUMN_NAME='$fieldname'
|
||||
";
|
||||
$ar = Db::query($sql);
|
||||
return $ar[0]['F_DATATYPE'];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取数据表中某个字段的属性
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldAttrVal(string $dbname,string $tablename,string $fieldname,string $attr){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'
|
||||
AND COLUMN_NAME='$fieldname'
|
||||
";
|
||||
$ar = Db::query($sql);
|
||||
return $ar[0][$attr];
|
||||
}
|
||||
}
|
||||
181
digital_doctor/vendor/wanghua/general-utility-tools-php/src/mysql/lib/Table.php
vendored
Normal file
181
digital_doctor/vendor/wanghua/general-utility-tools-php/src/mysql/lib/Table.php
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {10:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\mysql\lib;
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* @deprecated 废弃,未来将会删除
|
||||
*
|
||||
* desc:
|
||||
*
|
||||
* author:wh
|
||||
* Class Table
|
||||
* @package wanghua\general_utility_tools_php\mysql\lib
|
||||
*/
|
||||
class Table
|
||||
{
|
||||
/**
|
||||
* desc:创建表,初始化默认字段
|
||||
* author:wh
|
||||
* @param $data
|
||||
* @return bool
|
||||
*/
|
||||
function createTable($data){
|
||||
$tablename = $data['tablename'];
|
||||
$title = $data['title'];
|
||||
//创建表
|
||||
$sql = "CREATE TABLE IF NOT EXISTS {$tablename}(
|
||||
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
create_time timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
update_time timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY key(id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='{$title}' ;";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:改注释
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $comment
|
||||
* @return bool
|
||||
*/
|
||||
function updateComment($tablename, $comment){
|
||||
$sql = "ALTER TABLE {$tablename} COMMENT '{$comment}';";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:改表名
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $new_table_name
|
||||
* @return bool
|
||||
*/
|
||||
function updateTableName($tablename, $new_table_name){
|
||||
$sql = "ALTER TABLE {$tablename} RENAME TO {$new_table_name}";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:查询当前数据库所有的表名
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
function getTables(){
|
||||
$dbname = $this->getNowDbName();
|
||||
return array_column(Db::query('SHOW TABLES;'), 'Tables_in_'.$dbname);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取数据表字所有段名
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @return array
|
||||
*/
|
||||
function getTableFields($tablename){
|
||||
$dbname = $this->getNowDbName();
|
||||
$sql = "SELECT COLUMN_NAME column_name,COLUMN_COMMENT column_comment,DATA_TYPE data_type
|
||||
FROM information_schema.columns WHERE TABLE_NAME='{$tablename}' AND table_schema='{$dbname}'";
|
||||
return array_column(Db::query($sql), 'column_name');
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:查询当前数据库名
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
function getNowDbName(){
|
||||
$sql = "SELECT DATABASE() AS dbname;";
|
||||
return Db::query($sql)['dbname'];
|
||||
}
|
||||
/**
|
||||
* desc:获取表的属性
|
||||
* Name:
|
||||
表名称
|
||||
Engine:
|
||||
表的存储引擎
|
||||
Version:
|
||||
版本
|
||||
Row_format:
|
||||
行格式。对于MyISAM引擎,这可能是Dynamic,Fixed或Compressed。动态行的行长度可变,例如Varchar或Blob类型字段。固定行是指行长度不变,例如Char和Integer类型字段
|
||||
Rows:
|
||||
表中的行数。对于MyISAM和其他存储引擎,这个值是精确的,对于innoDB存储引擎,这个值通常是估算的
|
||||
Avg_row_length:
|
||||
平均每行包括的字节数
|
||||
Data_length:
|
||||
整个表的数据量(以字节为单位)
|
||||
Max_data_length:
|
||||
表可以容纳的最大数据量,该值和存储引擎相关
|
||||
Index_length:
|
||||
索引占用磁盘的空间大小(以字节为单位)
|
||||
Data_free:
|
||||
对于MyISAM引擎,表示已经分配,但目前没有使用的空间。这部分空间包含之前被删除的行,以及后续可以被insert利用到的空间
|
||||
Auto_increment:
|
||||
下一个Auto_increment的值
|
||||
Create_time:
|
||||
表的创建时间
|
||||
Update_time:
|
||||
表的最近更新时间
|
||||
Check_time:
|
||||
使用 check table 或myisamchk工具最后一次检查表的时间
|
||||
Collation:
|
||||
表的默认字符集和字符排序规则
|
||||
Checksum:
|
||||
如果启用,保存的是整个表的实时校验和
|
||||
Create_options:
|
||||
创建表时指定的其他选项
|
||||
Comment:
|
||||
包含了其他额外信息,对于MyISAM引擎,保存的是表在创建时带的注释。如果表使用的是innodb引擎 ,保存的是InnoDB表空间的剩余空间。如果是一个视图,注释里面包含了VIEW字样。
|
||||
*
|
||||
* @param $tablename 表名(无表名则查询所有表)
|
||||
*
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
function getTableInfo(string $tablename=''){
|
||||
if($tablename){
|
||||
$sql = "SHOW TABLE STATUS WHERE Name = 'fa_agent';";
|
||||
return Db::query($sql);
|
||||
}
|
||||
$sql = 'show table status;';
|
||||
return Db::query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:检查某个表是否存在
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @return bool
|
||||
*/
|
||||
function isExistTable(string $dbname,string $tablename){
|
||||
$sql = "SELECT TABLE_SCHEMA,TABLE_NAME
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA ='$dbname'
|
||||
AND TABLE_NAME = '$tablename';";
|
||||
return empty(Db::query($sql));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取表注释
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function getTableComment($table){
|
||||
$prefix = config('database.prefix');
|
||||
$table = $prefix.$table;
|
||||
$sql = 'show table status;';
|
||||
$arr = Db::query($sql);
|
||||
$tmp = Tools::key_val_arr($arr,'Name','Comment');
|
||||
return empty($tmp[$table])?'':$tmp[$table];
|
||||
}
|
||||
}
|
||||
140
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/alicloud/AliyunOSS.php
vendored
Normal file
140
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/alicloud/AliyunOSS.php
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/5/16} {14:22}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\oss\alicloud;
|
||||
|
||||
|
||||
use AlibabaCloud\SDK\Sts\V20150401\Models\AssumeRoleRequest;
|
||||
use AlibabaCloud\SDK\Sts\V20150401\Sts;
|
||||
use AlibabaCloud\Tea\Utils\Utils\RuntimeOptions;
|
||||
use Darabonba\OpenApi\Models\Config;
|
||||
use OSS\Core\OssException;
|
||||
use OSS\Credentials\StaticCredentialsProvider;
|
||||
use OSS\OssClient;
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 阿里云OSS存储服务工具库
|
||||
*
|
||||
* 封装了快捷方法,支持快速使用
|
||||
*
|
||||
* 功能:
|
||||
* 创建桶、查询桶(bucket),删除(必须先删除桶下面的所有文件)
|
||||
* sts临时凭证获取,用于前端Browser.js直接操作oss,上传、下载等操作
|
||||
* 上传文件、下载文件、查询文件列表
|
||||
*
|
||||
* 依赖:
|
||||
* composer require aliyuncs/oss-sdk-php
|
||||
*
|
||||
* 如果要使用临时凭证,您需要使用composer require alibabacloud/sts-20150401命令安装STS依赖,使用composer require alibabacloud/sdk命令安装PHP SDK依赖。
|
||||
*
|
||||
* Class AliyunOSS
|
||||
* @package wanghua\general_utility_tools_php\oss\alicloud
|
||||
*/
|
||||
class AliyunOSS
|
||||
{
|
||||
public $bucket = '';//必须,且后续操作都存放在这个bucket中
|
||||
protected $provider = null;
|
||||
protected $aliyun_config = [];
|
||||
protected $ossClient = [];
|
||||
protected $file_save_path = '';//文件存储路径
|
||||
public function __construct($aliyun_config)
|
||||
{
|
||||
$this->aliyun_config = $aliyun_config;
|
||||
if(empty($aliyun_config['AccessKeyId'])||empty($aliyun_config['AccessKeySecret'])||empty($aliyun_config['bucket'])){
|
||||
throw new \Exception('OSS 配置错误');
|
||||
}
|
||||
if(empty($this->bucket)){
|
||||
$this->bucket = $aliyun_config['bucket'];
|
||||
}
|
||||
//默认存储路径
|
||||
$this->setSavePath();
|
||||
// 从环境变量中获取RAM用户的访问密钥(AccessKey ID和AccessKey Secret)。
|
||||
$accessKeyId = $aliyun_config['AccessKeyId'];//config('aliyun_config.AccessKeyId');
|
||||
$accessKeySecret = $aliyun_config['AccessKeySecret'];//config('aliyun_config.AccessKeySecret');
|
||||
// 使用代码嵌入的RAM用户的访问密钥配置访问凭证。
|
||||
$this->provider = new StaticCredentialsProvider($accessKeyId, $accessKeySecret);
|
||||
// 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
|
||||
$endpoint = $aliyun_config['endpoint'];
|
||||
$config = array(
|
||||
"provider" => $this->provider,
|
||||
"signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
|
||||
// 填写Endpoint对应的Region信息,例如cn-hangzhou。
|
||||
"region" => $this->aliyun_config['region_id'],
|
||||
"endpoint" => $endpoint,
|
||||
);
|
||||
$this->ossClient = new OssClient($config);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:生成临时访问凭证。
|
||||
*
|
||||
* doc:https://help.aliyun.com/zh/oss/developer-reference/authorize-access-2?spm=a2c4g.11186623.0.i6#section-8rj-9sk-q7r
|
||||
* author:wh
|
||||
*/
|
||||
function getAccessToken(){
|
||||
return Mmodel::catch(function (){
|
||||
// 运行本代码示例之前,请确保已使用步骤1创建的RAM用户的访问密钥设置环境变量YOUR_ACCESS_KEY_ID和YOUR_ACCESS_KEY_SECRET。
|
||||
$config = new Config([
|
||||
'accessKeyId' => $this->aliyun_config['AccessKeyId'],//getenv('YOUR_ACCESS_KEY_ID'),
|
||||
'accessKeySecret' => $this->aliyun_config['AccessKeySecret'],//getenv('YOUR_ACCESS_KEY_SECRET'),
|
||||
]);
|
||||
//
|
||||
$config->endpoint = $this->aliyun_config['sts_endpoint'];
|
||||
$client = new Sts($config);
|
||||
|
||||
$assumeRoleRequest = new AssumeRoleRequest([
|
||||
// roleArn填写步骤2获取的角色ARN,例如acs:ram::175708322470****:role/ramtest。
|
||||
"roleArn" => "acs:ram::1113242774600735:role/ramoss",
|
||||
// roleSessionName用于自定义角色会话名称,用来区分不同的令牌,例如填写为sessiontest。
|
||||
"roleSessionName" => "sessiontest",
|
||||
// durationSeconds用于设置临时访问凭证有效时间单位为秒,最小值为900,最大值以当前角色设定的最大会话时间为准。本示例指定有效时间为3000秒。
|
||||
"durationSeconds" => 3000,
|
||||
// policy填写自定义权限策略,用于进一步限制STS临时访问凭证的权限。如果不指定Policy,则返回的STS临时访问凭证默认拥有指定角色的所有权限。
|
||||
// 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集。
|
||||
//"policy" => ""
|
||||
]);
|
||||
$runtime = new RuntimeOptions([
|
||||
//'http' => [
|
||||
// 'verify' => false, // 禁用SSL验证,仅限于调试
|
||||
//],
|
||||
]);
|
||||
$result = $client->assumeRoleWithOptions($assumeRoleRequest, $runtime);
|
||||
//printf("AccessKeyId:" . $result->body->credentials->accessKeyId. PHP_EOL);
|
||||
//printf("AccessKeySecret:".$result->body->credentials->accessKeySecret.PHP_EOL);
|
||||
//printf("Expiration:".$result->body->credentials->expiration.PHP_EOL);
|
||||
//printf("SecurityToken:".$result->body->credentials->securityToken.PHP_EOL);
|
||||
return Tools::set_ok('ok',[
|
||||
'accessKeyId'=>$result->body->credentials->accessKeyId,
|
||||
'accessKeySecret'=>$result->body->credentials->accessKeySecret,
|
||||
'expiration'=>$result->body->credentials->expiration,
|
||||
'securityToken'=>$result->body->credentials->securityToken,
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置文件保存目录
|
||||
* author:wh
|
||||
* @param string $unique_id 唯一id,可以是用户id,可以是其它用于区分的标识
|
||||
* @return string
|
||||
*/
|
||||
function setSavePath($unique_id=''){
|
||||
if($unique_id){
|
||||
$unique_id = $unique_id.'/';
|
||||
}
|
||||
//项目名称
|
||||
$project_name = Tools::get_project_name();
|
||||
//控制器方法路径
|
||||
$ctl = strtolower(request()->controller().'/'.request()->action());
|
||||
$this->file_save_path = $project_name.'/'.$ctl.'/'.$unique_id.date('Ymd').'/';//日期
|
||||
return $this->file_save_path;
|
||||
}
|
||||
}
|
||||
101
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/alicloud/Bucket.php
vendored
Normal file
101
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/alicloud/Bucket.php
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/5/16} {17:42}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\oss\alicloud;
|
||||
|
||||
|
||||
use OSS\Core\OssException;
|
||||
use OSS\OssClient;
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
|
||||
class Bucket extends AliyunOSS
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:创建Bucket
|
||||
* author:wh
|
||||
* @param string $bucket_name bucket名称 为空则使用bucket,否则以bucket+$bucket_name组成
|
||||
*/
|
||||
function createBucket($bucket_name='',$opts=[],$oss_acl_type = OssClient::OSS_ACL_TYPE_PRIVATE){
|
||||
if(empty($this->aliyun_config['bucket'])){
|
||||
throw new \Exception('OSS bucket必须');
|
||||
}
|
||||
$bucket_name = !$bucket_name?$this->aliyun_config['bucket']:$this->aliyun_config['bucket'].'-'.$bucket_name;
|
||||
return Mmodel::catch(function () use ($bucket_name,$opts,$oss_acl_type){
|
||||
// 填写Bucket名称,例如examplebucket。
|
||||
//$bucket_name = "examplebucket";
|
||||
// 设置Bucket的存储类型为标准类型。
|
||||
$options = $opts?:array(
|
||||
OssClient::OSS_STORAGE => OssClient::OSS_STORAGE_STANDARD
|
||||
);
|
||||
return $this->ossClient->createBucket($bucket_name, $oss_acl_type, $options);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:列出所有bucket
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getAllBucket(){
|
||||
return Mmodel::catch(function (){
|
||||
// 列举当前账号所有地域下的存储空间。
|
||||
$bucketListInfo = $this->ossClient->listBuckets();
|
||||
|
||||
$bucketList = $bucketListInfo->getBucketList();
|
||||
$arr = [];
|
||||
foreach($bucketList as $bucket) {
|
||||
$arr['name'] = $bucket->getName();
|
||||
$arr['location'] = $bucket->getLocation();
|
||||
$arr['create_time'] = $bucket->getCreatedate();
|
||||
}
|
||||
return $arr;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:查询指定前缀bucket
|
||||
* author:wh
|
||||
* @param $prefix 指定前缀
|
||||
* @throws OssException
|
||||
* @throws \OSS\Http\RequestCore_Exception
|
||||
*/
|
||||
function getBucketPrefix($prefix){
|
||||
|
||||
return Mmodel::catch(function () use ($prefix){
|
||||
|
||||
$options = array(OssClient::OSS_QUERY_STRING => array(OssClient::OSS_PREFIX => $prefix));
|
||||
// 列举当前账号所有地域下指定前缀的存储空间。
|
||||
$bucketListInfo = $this->ossClient->listBuckets($options);
|
||||
|
||||
$bucketList = $bucketListInfo->getBucketList();
|
||||
$arr = [];
|
||||
foreach($bucketList as $bucket) {
|
||||
$arr['name'] = $bucket->getName();
|
||||
$arr['location'] = $bucket->getLocation();
|
||||
$arr['create_time'] = $bucket->getCreatedate();
|
||||
}
|
||||
return $arr;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除bucket
|
||||
* author:wh
|
||||
* @param $bucket_name
|
||||
* doc:https://help.aliyun.com/zh/oss/developer-reference/delete-buckets-3?spm=a2c4g.11186623.0.0.61556dd5SHNYgV
|
||||
* @return array
|
||||
*/
|
||||
function deleteBucket($bucket_name){
|
||||
return Mmodel::catch(function () use ($bucket_name){
|
||||
// 填写Bucket名称,例如examplebucket。
|
||||
return $this->ossClient->deleteBucket($bucket_name);
|
||||
});
|
||||
}
|
||||
}
|
||||
318
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/alicloud/Objects.php
vendored
Normal file
318
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/alicloud/Objects.php
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/5/16} {18:02}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\oss\alicloud;
|
||||
|
||||
|
||||
use OSS\Core\OssException;
|
||||
use OSS\Core\OssUtil;
|
||||
use OSS\OssClient;
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 文件对象操作类
|
||||
*
|
||||
* 包含上传、下载(可以上传字符串文本和文件)
|
||||
*
|
||||
* Class Objects
|
||||
* @package app\api\logic
|
||||
*/
|
||||
class Objects extends AliyunOSS
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:文本上传
|
||||
* author:wh
|
||||
* @param string $object 保存文件名(包含完整路径)eg:exampledir/exampleobject.txt,Object完整路径中不能包含Bucket名称
|
||||
* @param string $content 上传文本内容
|
||||
* @param string $opts 上传时可以设置相关的headers,例如设置访问权限为private、自定义元数据等。
|
||||
*
|
||||
* 访问权限:
|
||||
* 文件的访问权限(ACL)有以下四种:default,private,public-read,public-read-write
|
||||
* 权限doc: https://help.aliyun.com/zh/oss/developer-reference/manage-object-acls-6?spm=a2c4g.11186623.0.0.63286dd53fYcTB
|
||||
* @return array
|
||||
*/
|
||||
function txtUpload($object,$content='',$opts=[]){
|
||||
return Mmodel::catch(function () use ($object,$content,$opts){
|
||||
$options = [
|
||||
OssClient::OSS_HEADERS => $opts?:[
|
||||
'x-oss-object-acl' => 'public-read',//$permissions='public-read-write'
|
||||
'x-oss-meta-info' => $content
|
||||
],
|
||||
];
|
||||
return $this->ossClient->putObject($this->bucket, $this->file_save_path.$object, $content, $options);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:文件上传
|
||||
*
|
||||
* author:wh
|
||||
* @param string $object 上传后的文件名,完整路径中不能包含Bucket名称 如:"exampledir/exampleobject.txt";
|
||||
* @param string $filePath 本地文件的完整路径,例如:D:\\localpath\\examplefile.txt, $file->getInfo('tmp_name')可获取临时文件路径
|
||||
* @param $opts 权限等其它header参数配置
|
||||
* 访问权限:
|
||||
* 文件的访问权限(ACL)有以下四种:default,private,public-read,public-read-write
|
||||
* 权限doc: https://help.aliyun.com/zh/oss/developer-reference/manage-object-acls-6?spm=a2c4g.11186623.0.0.63286dd53fYcTB
|
||||
* @return array
|
||||
*/
|
||||
function fileUpload($object, $filePath, $opts=[]){
|
||||
return Mmodel::catch(function () use ($object, $filePath,$opts){
|
||||
$options = [
|
||||
OssClient::OSS_HEADERS => $opts?:[
|
||||
'x-oss-object-acl' => 'public-read',//'public-read-write'
|
||||
],
|
||||
];
|
||||
return $this->ossClient->uploadFile($this->bucket, $this->file_save_path.$object, $filePath,$options);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:文件流上传
|
||||
*
|
||||
* author:wh
|
||||
* @param $object
|
||||
* @param $stream
|
||||
* @param array $opts
|
||||
* @return array
|
||||
*/
|
||||
function uploadFileStream($object, $stream, $opts=[]){
|
||||
return Mmodel::catch(function () use ($object, $stream,$opts){
|
||||
$options = [
|
||||
OssClient::OSS_HEADERS => $opts?:[
|
||||
'x-oss-object-acl' => 'public-read',//'public-read-write'
|
||||
],
|
||||
];
|
||||
// 从文件流上传
|
||||
$res = $this->ossClient->putObject($this->bucket, $this->file_save_path.$object, $stream, $options);
|
||||
return $res;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* desc:分片上传文件
|
||||
* author:wh
|
||||
* @param $object 上传后的文件名,完整路径中不能包含Bucket名称 如:"exampledir/exampleobject.txt";
|
||||
* @param $uploadFile 填写本地文件的完整路径 如:'D:\\localpath\\examplefile.txt'
|
||||
*/
|
||||
function multipartUpload($object,$uploadFile){
|
||||
$object = $this->file_save_path.$object;
|
||||
//填写不包含Bucket名称在内的Object完整路径,例如exampledir/exampleobject.txt。
|
||||
//$object = 'exampledir/exampleobject.txt';
|
||||
// 填写本地文件的完整路径。
|
||||
//$uploadFile = 'D:\\localpath\\examplefile.txt';
|
||||
$uploadId = '';
|
||||
$initOptions = array(
|
||||
OssClient::OSS_HEADERS => array(
|
||||
// 指定该Object被下载时的网页缓存行为。
|
||||
// 'Cache-Control' => 'no-cache',
|
||||
// 指定该Object被下载时的名称。
|
||||
// 'Content-Disposition' => 'attachment;filename=oss_download.jpg',
|
||||
// 指定该Object被下载时的内容编码格式。
|
||||
// 'Content-Encoding' => 'utf-8',
|
||||
// 指定过期时间,单位为毫秒。
|
||||
'Expires' => 150,
|
||||
// 指定初始化分片上传时是否覆盖同名Object。此处设置为true,表示禁止覆盖同名Object。
|
||||
'x-oss-forbid-overwrite' => 'false',
|
||||
// 指定上传该Object的每个part时使用的服务器端加密方式。
|
||||
// 'x-oss-server-side-encryption'=> 'KMS',
|
||||
// 指定Object的加密算法。
|
||||
// 'x-oss-server-side-data-encryption'=>'SM4',
|
||||
// 指定KMS托管的用户主密钥。
|
||||
//'x-oss-server-side-encryption-key-id' => '9468da86-3509-4f8d-a61e-6eab1eac****',
|
||||
// 指定Object的存储类型。
|
||||
'x-oss-storage-class' => 'Standard',
|
||||
// 指定Object的对象标签,可同时设置多个标签。
|
||||
// 'x-oss-tagging' => 'TagA=A&TagB=B',
|
||||
),
|
||||
OssClient::OSS_ACL => OssClient::OSS_ACL_TYPE_PUBLIC_READ,
|
||||
);
|
||||
|
||||
/**
|
||||
* 步骤1:初始化一个分片上传事件,并获取uploadId。
|
||||
*/
|
||||
try{
|
||||
|
||||
//返回uploadId。uploadId是分片上传事件的唯一标识,您可以根据uploadId发起相关的操作,如取消分片上传、查询分片上传等。
|
||||
$uploadId = $this->ossClient->initiateMultipartUpload($this->bucket, $object, $initOptions);
|
||||
//print("initiateMultipartUpload OK" . "\n");
|
||||
// 根据uploadId执行取消分片上传事件或者列举已上传分片的操作。
|
||||
// 如果您需要根据您需要uploadId执行取消分片上传事件的操作,您需要在调用InitiateMultipartUpload完成初始化分片之后获取uploadId。
|
||||
// 如果您需要根据您需要uploadId执行列举已上传分片的操作,您需要在调用InitiateMultipartUpload完成初始化分片之后,且在调用CompleteMultipartUpload完成分片上传之前获取uploadId。
|
||||
//print("UploadId: " . $uploadId . "\n");
|
||||
} catch(OssException $e) {
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail('初始化一个分片上传事件,并获取uploadId ERROR.'.$e->getMessage());
|
||||
}
|
||||
//dump('$uploadId:'.$uploadId);
|
||||
|
||||
/*
|
||||
* 步骤2:上传分片。
|
||||
*/
|
||||
$partSize = 10 * 1024 * 1024;
|
||||
$uploadFileSize = sprintf('%u',filesize($uploadFile));
|
||||
$pieces = $this->ossClient->generateMultiuploadParts($uploadFileSize, $partSize);
|
||||
$responseUploadPart = array();
|
||||
$uploadPosition = 0;
|
||||
$isCheckMd5 = true;
|
||||
foreach ($pieces as $i => $piece) {
|
||||
$fromPos = $uploadPosition + (integer)$piece[$this->ossClient::OSS_SEEK_TO];
|
||||
$toPos = (integer)$piece[$this->ossClient::OSS_LENGTH] + $fromPos - 1;
|
||||
$upOptions = array(
|
||||
// 上传文件。
|
||||
$this->ossClient::OSS_FILE_UPLOAD => $uploadFile,
|
||||
// 设置分片号。
|
||||
$this->ossClient::OSS_PART_NUM => ($i + 1),
|
||||
// 指定分片上传起始位置。
|
||||
$this->ossClient::OSS_SEEK_TO => $fromPos,
|
||||
// 指定文件长度。
|
||||
$this->ossClient::OSS_LENGTH => $toPos - $fromPos + 1,
|
||||
// 是否开启MD5校验,true为开启。
|
||||
$this->ossClient::OSS_CHECK_MD5 => $isCheckMd5,
|
||||
);
|
||||
// 开启MD5校验。
|
||||
if ($isCheckMd5) {
|
||||
$contentMd5 = OssUtil::getMd5SumForFile($uploadFile, $fromPos, $toPos);
|
||||
$upOptions[$this->ossClient::OSS_CONTENT_MD5] = $contentMd5;
|
||||
}
|
||||
try {
|
||||
// 上传分片。
|
||||
$responseUploadPart[] = $this->ossClient->uploadPart($this->bucket, $object, $uploadId, $upOptions);
|
||||
//printf("initiateMultipartUpload, uploadPart - part#{$i} OK\n");
|
||||
} catch(OssException $e) {
|
||||
Tools::error_txt_log($e);
|
||||
//printf("initiateMultipartUpload, uploadPart - part#{$i} FAILED\n");
|
||||
//printf($e->getMessage() . "\n");
|
||||
return Tools::set_fail('上传分片ERROR.'.$e->getMessage());
|
||||
}
|
||||
}
|
||||
// $uploadParts是由每个分片的ETag和分片号(PartNumber)组成的数组。
|
||||
$uploadParts = array();
|
||||
foreach ($responseUploadPart as $i => $eTag) {
|
||||
$uploadParts[] = array(
|
||||
'PartNumber' => ($i + 1),
|
||||
'ETag' => $eTag,
|
||||
);
|
||||
}
|
||||
//dump($uploadParts);
|
||||
//die;
|
||||
/**
|
||||
* 步骤3:完成上传。
|
||||
*/
|
||||
$comOptions['headers'] = array(
|
||||
// 指定完成分片上传时是否覆盖同名Object。此处设置为true,表示禁止覆盖同名Object。
|
||||
'x-oss-forbid-overwrite' => 'false',
|
||||
// 如果指定了x-oss-complete-all:yes,则OSS会列举当前uploadId已上传的所有Part,然后按照PartNumber的序号排序并执行CompleteMultipartUpload操作。
|
||||
// 'x-oss-complete-all'=> 'yes'
|
||||
);
|
||||
|
||||
try {
|
||||
// 执行completeMultipartUpload操作时,需要提供所有有效的$uploadParts。OSS收到提交的$uploadParts后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,OSS将把这些分片组合成一个完整的文件。
|
||||
$res = $this->ossClient->completeMultipartUpload($this->bucket, $object, $uploadId, $uploadParts,$comOptions);
|
||||
//dump($res);
|
||||
//printf( "Complete Multipart Upload OK\n");
|
||||
$this->ossClient->putObjectAcl($this->bucket, $object, OssClient::OSS_ACL_TYPE_PUBLIC_READ);
|
||||
return Tools::xml_to_array(($res['body']));
|
||||
} catch(OssException $e) {
|
||||
Tools::error_txt_log($e);
|
||||
//printf("Complete Multipart Upload FAILED\n");
|
||||
//printf($e->getMessage() . "\n");
|
||||
return Tools::set_fail('ERROR:Complete Multipart Upload FAILED.'.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:查询文件列表
|
||||
* author:wh
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
function getLists($options=[]){
|
||||
return Mmodel::catch(function () use ($options){
|
||||
$options = $options?:[
|
||||
'max-keys'=>200,//设置最大个数为200。
|
||||
'delimiter' => '',//分隔符,表示将Object名称按该分隔符进行截断,并返回结果。
|
||||
];
|
||||
$listObjectInfo = $this->ossClient->listObjects($this->bucket,$options);
|
||||
//文件列表
|
||||
$objectList = $listObjectInfo->getObjectList();
|
||||
//前缀列表
|
||||
//$prefixList = $listObjectInfo->getPrefixList();
|
||||
$arr = [];
|
||||
foreach ($objectList as $objectInfo) {
|
||||
$arr[] = $objectInfo->getKey();
|
||||
}
|
||||
return $arr;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:文件下载到本地
|
||||
*
|
||||
* author:wh
|
||||
* @param string $object 存储空间内的文件名 eg: testfolder/exampleobject.txt
|
||||
*
|
||||
* @param string $save_local_path 本地保存路径 eg: D:\\localpath\\examplefile.txt
|
||||
* 如果指定的本地文件存在会覆盖,不存在则新建。如果未指定本地路径,则下载后的文件默认保存到示例程序所属项目对应本地路径中。
|
||||
*
|
||||
* @param array $options 可选参数
|
||||
*/
|
||||
function downloadLocal($object,$save_local_path='',$options=[]){
|
||||
// 填写不包含Bucket名称在内的Object完整路径,例如testfolder/exampleobject.txt。
|
||||
//$object = "testfolder/exampleobject.txt";
|
||||
// 下载Object到本地文件examplefile.txt,并保存到指定的本地路径中(D:\\localpath)。如果指定的本地文件存在会覆盖,不存在则新建。
|
||||
// 如果未指定本地路径,则下载后的文件默认保存到示例程序所属项目对应本地路径中。
|
||||
//$save_local_path = "D:\\localpath\\examplefile.txt";
|
||||
$opts = [];
|
||||
if($save_local_path){
|
||||
$opts = array(
|
||||
OssClient::OSS_FILE_DOWNLOAD => $save_local_path
|
||||
);
|
||||
}
|
||||
|
||||
if($options){
|
||||
$opts = array_merge($opts, $options);
|
||||
}
|
||||
// 使用try catch捕获异常。如果捕获到异常,则说明下载失败;如果没有捕获到异常,则说明下载成功。
|
||||
try{
|
||||
$res = $this->ossClient->getObject($this->bucket, $object, $opts);
|
||||
if($res){
|
||||
return $res;
|
||||
}
|
||||
//下载成功
|
||||
//print(__FUNCTION__ . ": OK, please check localfile: 'examplefile.txt'" . "\n");
|
||||
return Tools::set_ok('ok',['save_path'=>$save_local_path]);
|
||||
} catch(OssException $e) {
|
||||
Tools::error_txt_log($e);
|
||||
//printf(__FUNCTION__ . ": FAILED\n");
|
||||
//printf($e->getMessage() . "\n");
|
||||
return Tools::set_fail('ERROR:'.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:下载文件到内存
|
||||
*
|
||||
* author:wh
|
||||
* @param $object
|
||||
* @throws \OSS\Http\RequestCore_Exception
|
||||
*/
|
||||
function downloadMemory($object){
|
||||
try{
|
||||
$this->ossClient->getObject($this->bucket, $object);
|
||||
//dump($content);
|
||||
return Tools::set_ok('下载文件到内存ok');
|
||||
} catch(OssException $e) {
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail('ERROR:'.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
29
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/Config.php
vendored
Normal file
29
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/Config.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/6/17} {18:22}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\oss\huawei\obs;
|
||||
|
||||
|
||||
/**
|
||||
* obs配置
|
||||
*
|
||||
* Class Config
|
||||
* @package wanghua\general_utility_tools_php\huawei\obs
|
||||
*/
|
||||
class Config
|
||||
{
|
||||
//'*** Provide your Access Key ***'
|
||||
static $key = '6XA5YIMA3MTDCHTGNXBQ';
|
||||
//*** Provide your Secret Key ***'
|
||||
static $secret = 'y1hptl5f820aayVfHAqkEFYnZGZ8xC8UTIAzygJm';
|
||||
//桶名称
|
||||
static $bucket_name = 'white-hand-bucket';
|
||||
//'https://your-endpoint'
|
||||
static $endpoint = 'obs.cn-east-3.myhuaweicloud.com';
|
||||
|
||||
}
|
||||
52
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/InitObs.php
vendored
Normal file
52
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/InitObs.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/6/17} {18:22}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\huawei\obs;
|
||||
|
||||
|
||||
use Obs\ObsClient;
|
||||
|
||||
/**
|
||||
* 初始化OBS
|
||||
*
|
||||
* Composer依赖:obs/esdk-obs-php
|
||||
*
|
||||
* Class InitObs
|
||||
* @package wanghua\general_utility_tools_php\huawei\obs
|
||||
*/
|
||||
class InitObs
|
||||
{
|
||||
protected static $obsClient = null;
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @return ObsClient|null
|
||||
*/
|
||||
static function getObsClient(int $socket_timeout=30, int $connect_timeout=10){
|
||||
if(null === self::$obsClient){
|
||||
self::$obsClient = ObsClient::factory ( [
|
||||
'key' => Config::$key,
|
||||
'secret' => Config::$secret,
|
||||
'endpoint' => Config::$endpoint,
|
||||
'socket_timeout' => $socket_timeout,
|
||||
'connect_timeout' => $connect_timeout
|
||||
] );
|
||||
}
|
||||
return self::$obsClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:关闭obsClient
|
||||
* author:wh
|
||||
*/
|
||||
static function close(){
|
||||
// 关闭obsClient
|
||||
return self::$obsClient->close();
|
||||
}
|
||||
}
|
||||
4
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/README.md
vendored
Normal file
4
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/README.md
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
## 华为OBS-对象存储服务
|
||||
###支持常规功能,例如文件上传下载。
|
||||
####温馨提示:你可能会遇到权限拒绝问题,请确认在华为云控制台已给用户授权
|
||||
资料参考地址:https://support.huaweicloud.com/productdesc-obs/zh-cn_topic_0045829060.html
|
||||
40
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/service/BaseObs.php
vendored
Normal file
40
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/service/BaseObs.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/6/19} {18:09}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\huawei\obs\service;
|
||||
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\huawei\obs\InitObs;
|
||||
|
||||
/**
|
||||
* obs基类负责初始化客户端
|
||||
* 注意:所有操作必须具有权限,否则会报权限错误
|
||||
* Class BaseObs
|
||||
* @package libraries\huawei\obs\service
|
||||
*/
|
||||
class BaseObs
|
||||
{
|
||||
|
||||
//桶名
|
||||
protected $bucketName = 'bs-obs1';
|
||||
//文件夹
|
||||
public $dir = '';
|
||||
|
||||
//protected $origin = '';
|
||||
//客户端
|
||||
protected $obsClient = null;
|
||||
|
||||
public function __construct($dir='bs')
|
||||
{
|
||||
$this->obsClient = InitObs::getObsClient();
|
||||
if($dir) {
|
||||
$this->dir = (false !== strpos($dir, '/'))?$dir:$dir.'/';
|
||||
}
|
||||
}
|
||||
}
|
||||
288
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/service/BucketManage.php
vendored
Normal file
288
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/service/BucketManage.php
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/6/19} {17:25}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\huawei\obs\service;
|
||||
|
||||
|
||||
use Obs\ObsClient;
|
||||
|
||||
/**
|
||||
* 华为云obs桶管理
|
||||
* 包括创建桶、删除、修改属性、修改权限等
|
||||
* 资料参考地址:https://support.huaweicloud.com/sdk-php-devg-obs/obs_28_0301.html
|
||||
* Class BucketManage
|
||||
* @package libraries\huawei\obs\service
|
||||
*/
|
||||
class BucketManage extends BaseObs
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:列举桶
|
||||
* 包含名称、创建时间、区域位置
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getBuckList(){
|
||||
$resp = $this->obsClient->listBuckets([
|
||||
'QueryLocation' => true
|
||||
]);
|
||||
$data = [];
|
||||
$data['RequestId'] = $resp['RequestId'];
|
||||
$data['OwnerID'] = $resp['Owner']['ID'];
|
||||
$data['OwnerName'] = $resp ['Owner']['DisplayName'];
|
||||
|
||||
$tmp = [];
|
||||
foreach ($resp['Buckets'] as $index => $bucket){
|
||||
array_push($tmp, [
|
||||
'Name'=> $bucket['Name'],
|
||||
'CreationDate'=> $bucket['CreationDate'],
|
||||
'Location'=> $bucket['Location'],
|
||||
]);
|
||||
}
|
||||
$data['Buckets'] = $tmp;
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:创建桶
|
||||
* 桶的名字是全局唯一的,所以您需要确保不与已有的桶名称重复。
|
||||
* 同一用户在同一区域多次创建同名桶不会报错,创建的桶属性以第一次请求为准。
|
||||
* 本示例创建的桶的访问权限默认是私有读写,存储类型默认是标准类型,区域位置是默认区域华北-北京一(cn-north-1)。
|
||||
* 须知:
|
||||
* 创建桶时,如果使用的终端节点归属于默认区域华北-北京一(cn-north-1),则可以不指定区域;如果使用的终端节点归属于其他区域,
|
||||
* 则必须指定区域,且指定的区域必须与终端节点归属的区域一致。当前有效的区域名称可从这里查询。
|
||||
* 您可以使用带参数创建方式,在创建桶时,指定桶的区域位置。
|
||||
* 资料参考地址:https://support.huaweicloud.com/sdk-php-devg-obs/obs_28_0301.html
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function createBucket(){
|
||||
// 创建桶
|
||||
$resp = $this->obsClient->createBucket([
|
||||
'Bucket' => $this->bucketName
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:带参数创建桶
|
||||
* 说明:
|
||||
* 使用ACL参数指定桶的访问权限;使用StorageClass参数指定桶的存储类型;使用LocationConstraint参数指定桶的区域位置。
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function createBucketByParam(){
|
||||
// 创建桶
|
||||
$resp = $this->obsClient->createBucket([
|
||||
'Bucket' => $this->bucketName,
|
||||
// 设置桶访问权限为公共读写,默认是私有读写
|
||||
'ACL' => ObsClient::AclPublicReadWrite,
|
||||
// 设置桶的存储类型为归档存储类型
|
||||
'StorageClass' => ObsClient::StorageClassCold,
|
||||
// 设置桶区域位置
|
||||
'LocationConstraint' => 'bucketlocation'
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除桶
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function deleteBucket(){
|
||||
// 删除桶
|
||||
$resp = $this->obsClient->deleteBucket([
|
||||
'Bucket' => $this->bucketName
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取桶存量信息
|
||||
* 桶存量信息包括桶已使用的空间大小以及桶包含的对象个数。
|
||||
* 您可以通过ObsClient->getBucketStorageInfo获取桶的存量信息。
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getBucketStorageInfo(){
|
||||
$resp = $this->obsClient->getBucketStorageInfo([
|
||||
'Bucket' => $this->bucketName
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
'Size'=>$resp['Size'],
|
||||
'ObjectNumber'=>$resp['ObjectNumber'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取桶配额
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getBucketQuota(){
|
||||
$resp = $this->obsClient->getBucketQuota([
|
||||
'Bucket' => $this->bucketName
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
'StorageQuota'=>$resp['StorageQuota'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置桶配额
|
||||
* 使用StorageQuota参数指定桶的配额大小。
|
||||
* 桶配额值必须为非负整数,单位为字节,支持的最大值为2^63 - 1。
|
||||
* author:wh
|
||||
* @param float|int $StorageQuota
|
||||
* @return array
|
||||
*/
|
||||
function setBucketQuota($StorageQuota = 1024 * 1024 * 100){
|
||||
$resp = $this->obsClient->setBucketQuota([
|
||||
'Bucket' => $this->bucketName,
|
||||
'StorageQuota' => $StorageQuota
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取桶存储类型
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getBucketStoragePolicy(){
|
||||
$resp = $this->obsClient->getBucketStoragePolicy([
|
||||
'Bucket' => $this->bucketName
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
'StorageClass'=>$resp['StorageClass'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置桶存储类型
|
||||
* OBS允许您对桶配置不同的存储类型,桶中对象的存储类型默认将与桶的存储类型保持一致。
|
||||
* 不同的存储类型可以满足客户业务对存储性能、成本的不同诉求。桶的存储类型分为三类
|
||||
* 标准存储
|
||||
标准存储拥有低访问时延和较高的吞吐量,适用于有大量热点对象(平均一个月多次)或小对象(<1MB),且需要频繁访问数据的业务场景。
|
||||
ObsClient::StorageClassStandard
|
||||
低频访问存储
|
||||
低频访问存储适用于不频繁访问(平均一年少于12次)但在需要时也要求能够快速访问数据的业务场景。
|
||||
ObsClient::StorageClassWarm
|
||||
归档存储
|
||||
归档存储适用于很少访问(平均一年访问一次)数据的业务场景。
|
||||
ObsClient::StorageClassCold
|
||||
* 资料参考地址:https://support.huaweicloud.com/sdk-php-devg-obs/obs_28_0311.html
|
||||
* author:wh
|
||||
* @param $StorageClass
|
||||
* @return array
|
||||
*/
|
||||
function setBucketStoragePolicy($StorageClass){
|
||||
$resp = $this->obsClient->setBucketStoragePolicy([
|
||||
'Bucket' => $this->bucketName,
|
||||
'StorageClass' => $StorageClass
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取桶区域位置
|
||||
* 说明:
|
||||
* 创建桶时可以指定桶的区域位置,请参见创建桶。
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getBucketLocation(){
|
||||
$resp = $this->obsClient->getBucketLocation([
|
||||
'Bucket' => $this->bucketName
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
'Location'=>$resp['Location'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取桶策略
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getBucketPolicy(){
|
||||
$resp = $this->obsClient->getBucketPolicy([
|
||||
'Bucket' => $this->bucketName
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
'Policy'=>$resp['Policy'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 未完成
|
||||
* desc:设置桶策略[此方法待扩展]
|
||||
* 除了桶访问权限外,桶的拥有者还可以通过桶策略,提供对桶和桶内对象的集中访问控制。
|
||||
* 更多关于桶策略的内容请参考桶策略 https://support.huaweicloud.com/usermanual-obs/zh-cn_topic_0045829071.html
|
||||
* 说明:
|
||||
* 桶策略内容的具体格式(JSON格式字符串)请参考《对象存储服务API参考》。
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function setBucketPolicy(){
|
||||
$resp = $this->obsClient->setBucketPolicy([
|
||||
'Bucket' => $this->bucketName,
|
||||
'Policy' => 'your policy'
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除桶策略
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function deleteBucketPolicy(){
|
||||
$resp = $this->obsClient->deleteBucketPolicy([
|
||||
'Bucket' => $this->bucketName
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
];
|
||||
}
|
||||
}
|
||||
87
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/service/Cors.php
vendored
Normal file
87
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/service/Cors.php
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/6/22} {14:09}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\huawei\obs\service;
|
||||
|
||||
|
||||
/**
|
||||
* 跨域资源共享
|
||||
* 跨域资源共享(CORS)允许Web端的应用程序访问不属于本域的资源。OBS提供接口方便开发者控制跨域访问的权限。
|
||||
* Class Cors
|
||||
* @package libraries\huawei\obs\service
|
||||
*/
|
||||
class Cors extends BaseObs
|
||||
{
|
||||
public $AllowedMethod = [];// 指定允许的跨域请求方法(GET/PUT/DELETE/POST/HEAD)
|
||||
|
||||
public $domains = [];//// 指定允许跨域请求的来源 ['http://www.a.com', 'http://www.b.com']
|
||||
|
||||
/**
|
||||
* desc:设置跨域规则
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function setBucketCors(){
|
||||
$resp = $this->obsClient->setBucketCors ( [
|
||||
'Bucket' => $this->bucketName,
|
||||
'CorsRules' => [
|
||||
[
|
||||
'ID' => 'rule1',
|
||||
// 指定允许的跨域请求方法(GET/PUT/DELETE/POST/HEAD)
|
||||
'AllowedMethod' => $this->AllowedMethod,
|
||||
// 指定允许跨域请求的来源
|
||||
'AllowedOrigin' => $this->domains,
|
||||
// 控制在OPTIONS预取指令中Access-Control-Request-Headers头中指定的header是否被允许使用
|
||||
'AllowedHeader' => [ 'x-obs-header'],
|
||||
// 指定允许用户从应用程序中访问的header
|
||||
'ExposeHeader' => ['x-obs-expose-header'],
|
||||
// 指定浏览器对特定资源的预取(OPTIONS)请求返回结果的缓存时间,单位为秒
|
||||
'MaxAgeSeconds' => 60
|
||||
]
|
||||
]
|
||||
] );
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:查看跨域规则
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getBucketCors(){
|
||||
$resp = $this->obsClient->getBucketCors ( [
|
||||
'Bucket' => $this->bucketName,
|
||||
] );
|
||||
$data = [];
|
||||
foreach ( $resp ['CorsRules'] as $index => $rule ) {
|
||||
$data[]['ID'] = $rule ['ID'];
|
||||
$data[]['MaxAgeSeconds'] = $rule ['MaxAgeSeconds'];
|
||||
$data[]['AllowedMethod'] = $rule ['AllowedMethod'];
|
||||
$data[]['AllowedOrigin'] = $rule ['AllowedOrigin'];
|
||||
$data[]['AllowedHeader'] = $rule ['AllowedHeader'];
|
||||
$data[]['ExposeHeader'] = $rule ['ExposeHeader'];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除跨域规则
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function deleteBucketCors(){
|
||||
$resp = $this->obsClient->deleteBucketCors ( [
|
||||
'Bucket' => $this->bucketName,
|
||||
] );
|
||||
return [
|
||||
'RequestId'=>$resp['RequestId'],
|
||||
];
|
||||
}
|
||||
}
|
||||
79
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/service/Download.php
vendored
Normal file
79
digital_doctor/vendor/wanghua/general-utility-tools-php/src/oss/huawei/obs/service/Download.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/6/22} {15:26}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\huawei\obs\service;
|
||||
|
||||
|
||||
class Download extends BaseObs
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:文本下载
|
||||
* 文本下载方式下返回结果中的Body是包含文本内容的GuzzleHttp\Psr7\StreamInterface对象。
|
||||
* author:wh
|
||||
* @param string $objectname
|
||||
* @return array
|
||||
*/
|
||||
function text(string $objectname){
|
||||
$resp = $this->obsClient -> getObject([
|
||||
'Bucket' => $this->bucketName,
|
||||
'Key' => $objectname
|
||||
]);
|
||||
$str = '';
|
||||
// 获取对象内容
|
||||
while(!$resp['Body'] -> eof()){
|
||||
$str .= $resp['Body'] -> read(65536);
|
||||
}
|
||||
return [
|
||||
'RequestId'=>$resp ['RequestId'],
|
||||
'text'=>$str
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:流式下载(向浏览器输出流直接下载文件)
|
||||
*
|
||||
* 使用SaveAsStream参数指定使用流式下载。
|
||||
* 返回结果中的Body是一个可读的GuzzleHttp\Psr7\StreamInterface对象,可将对象的内容读取到本地文件或者内存中。
|
||||
* author:wh
|
||||
* @param string $objectname
|
||||
* @param string $filename
|
||||
*/
|
||||
function stream(string $objectname, string $filename){
|
||||
$resp = $this->obsClient -> getObject([
|
||||
'Bucket' => $this->bucketName,
|
||||
'Key' => $objectname,
|
||||
'SaveAsStream' => true
|
||||
]);
|
||||
header("Content-Disposition:attachment; filename={$filename}");
|
||||
while(!$resp['Body'] -> eof()){
|
||||
echo $resp['Body'] -> read(65536);//开始下载
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:文件下载(将文件从obs下载到当前应用所在服务器)
|
||||
* 说明:
|
||||
* 使用SaveAsFile参数指定文件下载的路径。
|
||||
* author:wh
|
||||
* @param string $objectname
|
||||
* @param $localfile "将文件从obs下载到当前应用所在服务器"
|
||||
* @return array
|
||||
*/
|
||||
function file(string $objectname,string $localfile){
|
||||
$resp = $this->obsClient -> getObject([
|
||||
'Bucket' => $this->bucketName,
|
||||
'Key' => $objectname,
|
||||
'SaveAsFile' => $localfile,
|
||||
]);
|
||||
|
||||
return [
|
||||
'RequestId'=>$resp ['RequestId'],
|
||||
];
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user