Initial commit

This commit is contained in:
php 2024-09-16 17:17:26 +08:00
commit 3606cb7584
190 changed files with 26765 additions and 0 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
/.idea
/.vscode
/vendor
/public/uploads/**
*.log
.env
*.http
runtime/*
app/admin/controller/Gen/Gen.php

42
.travis.yml Normal file
View File

@ -0,0 +1,42 @@
sudo: false
language: php
branches:
only:
- stable
cache:
directories:
- $HOME/.composer/cache
before_install:
- composer self-update
install:
- composer install --no-dev --no-interaction --ignore-platform-reqs
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip .
- composer require --update-no-dev --no-interaction "topthink/think-image:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0"
- composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0"
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip .
script:
- php think unit
deploy:
provider: releases
api_key:
secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw=
file:
- ThinkPHP_Core.zip
- ThinkPHP_Full.zip
skip_cleanup: true
on:
tags: true

32
LICENSE.txt Normal file
View File

@ -0,0 +1,32 @@
ThinkPHP遵循Apache2开源协议发布并提供免费使用。
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
Apache Licence是著名的非盈利开源组织Apache采用的协议。
该协议和BSD类似鼓励代码共享和尊重原作者的著作权
允许代码修改,再作为开源或商业软件发布。需要满足
的条件:
1 需要给代码的用户一份Apache Licence
2 如果你修改了代码,需要在被修改的文件中说明;
3 在延伸的代码中(修改和有源代码衍生的代码中)需要
带有原来代码中的协议,商标,专利声明和其他原来作者规
定需要包含的说明;
4 如果再发布的产品中包含一个Notice文件则在Notice文
件中需要带有本协议内容。你可以在Notice中增加自己的
许可但不可以表现为对Apache Licence构成更改。
具体的协议参考http://www.apache.org/licenses/LICENSE-2.0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

56
README.md Normal file
View File

@ -0,0 +1,56 @@
ThinkPHP 6.0
===============
> 运行环境要求PHP7.1+兼容PHP8.0。
[官方应用服务市场](https://market.topthink.com) | [`ThinkAPI`——官方统一API服务](https://docs.topthink.com/think-api)
ThinkPHPV6.0版本由[亿速云](https://www.yisu.com/)独家赞助发布。
## 主要新特性
* 采用`PHP7`强类型(严格模式)
* 支持更多的`PSR`规范
* 原生多应用支持
* 更强大和易用的查询
* 全新的事件系统
* 模型事件和数据库事件统一纳入事件系统
* 模板引擎分离出核心
* 内部功能中间件化
* SESSION/Cookie机制改进
* 对Swoole以及协程支持改进
* 对IDE更加友好
* 统一和精简大量用法
## 安装
~~~
composer create-project topthink/think tp 6.0.*
~~~
如果需要更新框架使用
~~~
composer update topthink/framework
~~~
## 文档
[完全开发手册](https://www.kancloud.cn/manual/thinkphp6_0/content)
## 参与开发
请参阅 [ThinkPHP 核心框架包](https://github.com/top-think/framework)。
## 版权信息
ThinkPHP遵循Apache2开源协议发布并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2006-2020 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
更多细节参阅 [LICENSE.txt](LICENSE.txt)

1
app/.htaccess Normal file
View File

@ -0,0 +1 @@
deny from all

22
app/AppService.php Normal file
View File

@ -0,0 +1,22 @@
<?php
declare (strict_types = 1);
namespace app;
use think\Service;
/**
* 应用服务类
*/
class AppService extends Service
{
public function register()
{
// 服务注册
}
public function boot()
{
// 服务启动
}
}

138
app/BaseController.php Normal file
View File

@ -0,0 +1,138 @@
<?php
declare(strict_types=1);
namespace app;
use think\App;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\Request;
use think\Validate;
/**
* 控制器基础类
*/
abstract class BaseController
{
/**
* Request实例
* @var \think\Request
*/
protected $request;
/**
* 应用实例
* @var \think\App
*/
protected $app;
/**
* 是否批量验证
* @var bool
*/
protected $batchValidate = false;
/**
* 控制器中间件
* @var array
*/
protected $middleware = [];
/**
* 构造方法
* @access public
* @param App $app 应用对象
*/
public function __construct(App $app)
{
$this->app = $app;
$this->request = $this->app->request;
// 控制器初始化
$this->initialize();
}
// 初始化
protected function initialize()
{
}
/**
* 验证数据
* @access protected
* @param array $data 数据
* @param string|array $validate 验证器名或者验证规则数组
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @return array|string|true
* @throws ValidateException
*/
protected function validate(array $data, $validate, array $message = [], bool $batch = true)
{
if (is_array($validate)) {
$v = new Validate();
$v->rule($validate);
} else {
if (strpos($validate, '.')) {
// 支持场景
[$validate, $scene] = explode('.', $validate);
}
$class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
$v = new $class();
if (!empty($scene)) {
$v->scene($scene);
}
}
$v->message($message);
// 是否批量验证
if ($batch || $this->batchValidate) {
$v->batch(true);
}
return $v->failException(true)->check($data);
}
/**
* 开启事务
*
* @param callable $cb
* @param array $args
* @return mixed
* @date 2022-07-22
* @example
* @author admin
* @since 1.0.0
*/
protected static function transaction(callable $cb, array $args = [])
{
Db::startTrans();
try {
$result = invoke($cb, $args);
Db::commit();
return $result;
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
}
/**
* 分页包装器
*
* @param $query
* @date 2022-03-03
* @example
* @author admin
* @since 1.0.0
*/
protected static function pageWrapper($query)
{
return (clone $query)->page(
(int) Request::param('page', 1),
(int) Request::param('limit', 10)
);
}
}

16
app/BaseModel.php Normal file
View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace app;
use app\common\traits\Model as TraitsModel;
use think\Model;
/**
* 模型层基础类
*/
abstract class BaseModel extends Model
{
use TraitsModel;
}

16
app/BasePivot.php Normal file
View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace app;
use app\common\traits\Model as TraitsModel;
use think\model\Pivot;
/**
* 模型层基础类
*/
abstract class BasePivot extends Pivot
{
use TraitsModel;
}

133
app/ExceptionHandle.php Normal file
View File

@ -0,0 +1,133 @@
<?php
namespace app;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\Response;
use Throwable;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
use app\common\exception\LoginTimeOut;
use app\common\exception\NotAuthApi;
use think\facade\Env;
use app\common\arw\adjfut\src\Exception\ErrorMsg as ExceptionErrorMsg;
/**
* 应用异常处理类
*/
class ExceptionHandle extends Handle
{
/**
* 不需要记录信息(日志)的异常类列表
* @var array
*/
protected $ignoreReport = [
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
DataNotFoundException::class,
ValidateException::class,
LoginTimeOut::class,
NotAuthApi::class,
ErrorMsg::class,
ExceptionErrorMsg::class
];
/**
* 记录异常信息(包括日志或者其它方式记录)
*
* @access public
* @param Throwable $exception
* @return void
*/
public function report(Throwable $exception): void
{
// 使用内置的方式记录异常日志
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @access public
* @param \app\Request $request
* @param Throwable $e
* @return Response
*/
public function render($request, Throwable $e): Response
{
// 添加自定义异常处理机制
// 未授权接口
if ($e instanceof NotAuthApi) {
return $this->respone([
'code' => 40050,
'msg' => $e->getMessage(),
]);
}
// 登录超时
if ($e instanceof LoginTimeOut) {
return $this->respone([
'code' => 40026,
'msg' => $request->isDev() ? $e->getMessage() : '登录超时',
]);
}
// 参数验证不通过
if ($e instanceof ValidateException) {
return $this->respone([
'code' => 40030,
'msg' => $e->getMessage()
]);
}
// 业务异常
if ($e instanceof ErrorMsg || $e instanceof ExceptionErrorMsg) {
$code = $e->getCode();
return $this->respone([
'code' => $code == 0 ? 40052 : $code,
'msg' => $e->getMessage(),
], $e);
}
// 服务器异常
// if ($e instanceof Exception) {
// return $this->respone([
// 'code' => 40051,
// 'msg' => '服务器异常',
// ], $e);
// }
// 其他错误交给系统处理
return parent::render($request, $e);
}
/**
* 返回
*
* @param array $data
* @param Throwable $e
* @return Response
* @date 2022-04-15
* @example
* @author admin
* @since 1.0.0
*/
private function respone(array $data, $e = null): Response
{
$request = $this->app->request;
if ($e && Env::get('app_show_error')) {
$data['__error'] = [
'File' => $e->getFile(),
'Line' => $e->getLine(),
'Message' => $e->getMessage(),
'Trace' => $e->getTrace()
];
$data['__param'] = $request->param();
}
if ($request->isAjax()) {
return Response::create($data, 'json');
} else {
return Response::create(json_encode($data), 'html');
}
}
}

80
app/Request.php Normal file
View File

@ -0,0 +1,80 @@
<?php
namespace app;
use app\common\model\Token;
use app\common\model\User\User;
use think\facade\Env;
// 应用请求对象类
class Request extends \think\Request
{
/**
* 获取当前用户
*
* @return User
* @date 2023-01-03
* @example
* @author admin
* @since 1.0.0
*/
public static function getCurrentUser(): User
{
return Token::getCurrentUser();
}
/**
* 获取当前token
*
* @return Token
* @date 2023-01-03
* @example
* @author admin
* @since 1.0.0
*/
public static function getCurrentToken(): Token
{
return Token::getCurrent();
}
/**
* 是否登陆
*
* @return boolean
* @date 2022-12-30
* @example
* @author admin
* @since 1.0.0
*/
public static function isLogin(): bool
{
return Token::isLogin();
}
/**
* 是否开发模式
*
* @date 2022-04-07
* @example
* @author admin
* @since 1.0.0
*/
public static function isDev(): bool
{
return !self::isProd();
}
/**
* 是否生产环境
*
* @date 2022-04-07
* @example
* @author admin
* @since 1.0.0
*/
public static function isProd(): bool
{
return Env::get('app_mode') === 'production';
}
}

View File

@ -0,0 +1,90 @@
<?php
namespace app\admin\controller\AboutUs;
use app\BaseController;
use app\common\model\AboutUs\AboutUs as ModelAboutUs;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\exception\Tool;
class AboutUs extends BaseController
{
/**
* 获取关于我们内容
*/
public function getAboutUs(Request $request): array
{
$params = $request->param();
$con = Tool::getOptionalQuery(['i18n_lang_type_guid', '=']);
$query = ModelAboutUs::where($con)
->field([
'i18n_lang_type_guid',
'about_us_id',
'about_us_guid',
'about_us_profile',
'about_us_profile_history',
'about_us_honor',
'about_us_honor_more',
'about_us_factory',
'about_us_exhibition',
])->find();
return [
'code' => 0,
'data' => $query,
'msg' => 'ok'
];
}
/**
* 编辑关于我们
*/
public function editAboutUs(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'i18n_lang_type_guid|语言类型' => 'require',
'about_us_profile|公司简介头图' => 'require',
'about_us_profile_history|公司简介历史' => 'require',
'about_us_honor|荣誉资质' => 'require',
'about_us_honor_more|荣誉资质-更多' => 'require',
'about_us_factory|工厂照片' => 'require',
'about_us_exhibition|展会信息' => 'require',
]);
$con = Tool::getOptionalQuery(['i18n_lang_type_guid', '=']);
$model = ModelAboutUs::where($con)->find();
// 如果没有数据则新增
if (!$model) {
ModelAboutUs::create($params, [
'i18n_lang_type_guid',
'about_us_profile',
'about_us_profile_history',
'about_us_honor',
'about_us_honor_more',
'about_us_factory',
'about_us_exhibition',
'about_us_update_user_guid'
]);
return msg('编辑成功!');
}
// 更新数据
$model->allowField([
'about_us_profile',
'about_us_profile_history',
'about_us_honor',
'about_us_honor_more',
'about_us_factory',
'about_us_exhibition',
'about_us_update_user_guid'
])->save($params);
return msg('编辑成功!');
}
}

View File

@ -0,0 +1,136 @@
<?php
namespace app\admin\controller\Banners;
use app\BaseController;
use app\common\model\Banners\Banner as ModelBanner;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class Banner extends BaseController
{
/**
* 获取轮播图列表
*/
public function getBannerList(Request $request): array
{
$con = Tool::getOptionalQuery(['a.i18n_lang_type_guid', '='],);
$query = ModelBanner::where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'a.banner_id',
'a.banner_img',
'a.banner_location',
'a.banner_link',
'a.banner_order',
'a.banner_guid',
'a.i18n_lang_type_guid',
'c.i18n_lang_type_name',
'c.i18n_lang_type_code',
])
->order('banner_order', 'asc');
return msg("获取轮播图列表成功!", $query);
}
/**
* 添加轮播图
*/
public function addBanner(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('banner');
try {
$params = $request->param();
$this->validate($params, [
'banner_img|轮播图图片' => 'require',
// 'banner_order
]);
ModelBanner::create($params, [
'i18n_lang_type_guid',
'banner_link',
'banner_guid',
'banner_create_user_guid',
'banner_update_user_guid',
'banner_img',
'banner_location',
'banner_order'
]);
Db::commit();
Tool::unlockTable();
return msg('添加成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 编辑轮播图
*/
public function editBanner(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('banner');
try {
$params = $request->param();
$this->validate($params, [
'banner_img|轮播图图片' => 'require',
]);
$model = ModelBanner::where('banner_guid', $params['banner_guid'])->find();
if (!$model) throwErrorMsg("该轮播图不存在", 1);
$model->allowField([
'banner_link',
'i18n_lang_type_guid',
'banner_update_user_guid',
'banner_img',
'banner_location',
'banner_order'
])->save($params);
Db::commit();
Tool::unlockTable();
return msg('编辑成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 删除轮播图
*/
public function deleteBanner(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('banner');
try {
$params = $request->param();
$this->validate($params, [
'banner_guid' => 'require',
]);
$banner = ModelBanner::where([
'banner_guid' => explode(',', $params['banner_guid'])
])->select();
$banner->delete();
Db::commit();
Tool::unlockTable();
return msg('删除成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
}

View File

@ -0,0 +1,141 @@
<?php
namespace app\admin\controller\Banners;
use app\BaseController;
use app\common\model\Banners\Poster as ModelPoster;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class Poster extends BaseController
{
/**
* 获取海报列表
*/
public function getPosterList(Request $request): array
{
$params = $request->param();
$con = Tool::getOptionalQuery(['poster_location', '='], ['a.i18n_lang_type_guid', '='],);
$query = ModelPoster::where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'a.poster_id',
'a.poster_guid',
'a.poster_location',
'a.poster_img',
'a.poster_title',
'a.poster_describe',
'a.poster_sort',
'a.i18n_lang_type_guid',
'c.i18n_lang_type_name',
'c.i18n_lang_type_code',
])
->order('poster_sort', 'asc');
return msg("获取海报列表成功!", $query);
}
/**
* 编辑海报
*/
public function editPoster(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('poster');
try {
$params = $request->param();
$this->validate($params, [
'poster_location|位置' => 'require',
'poster_img|图片' => 'require',
]);
$model = ModelPoster::where('poster_guid', $params['poster_guid'])->find();
if (!$model) throwErrorMsg("该海报不存在", 1);
$model->allowField([
'i18n_lang_type_guid',
'poster_update_user_guid',
'poster_location',
'poster_img',
'poster_title',
'poster_describe',
'poster_sort'
])->save($params);
Db::commit();
Tool::unlockTable();
return msg('编辑成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 添加海报
*/
public function addPoster(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('poster');
try {
$params = $request->param();
$this->validate($params, [
'poster_location|位置' => 'require',
'poster_img|图片' => 'require',
]);
$model = ModelPoster::create($params, [
'i18n_lang_type_guid',
'poster_guid',
'poster_create_user_guid',
'poster_update_user_guid',
'poster_location',
'poster_img',
'poster_title',
'poster_describe',
'poster_sort'
]);
Db::commit();
Tool::unlockTable();
return msg('添加成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 删除海报
*/
public function deletePoster(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('poster');
try {
$params = $request->param();
$this->validate($params, [
'poster_guid' => 'require',
]);
$poster = ModelPoster::where([
'poster_guid' => explode(',', $params['poster_guid'])
])->select();
$poster->delete();
Db::commit();
Tool::unlockTable();
return msg('删除成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
}

View File

@ -0,0 +1,82 @@
<?php
namespace app\admin\controller;
use app\model\Banner as ModelBanner;
use app\BaseController;
use app\Request;
use app\exception\ErrorMsg;
use think\facade\Validate;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use think\facade\Env;
class Common extends BaseController
{
/**
* 上传图片
*/
public function uploadImg(Request $request)
{
$dirName = $request->param('dirName');
$upload = new UploadFile('uploads', 'file');
$path = $upload->putFile($dirName . 'Img');
$url = "/uploads/" . $path;
//图片大小>500k压缩图片质量
$absolute_path = public_path() . $url;
if (ceil(filesize($absolute_path) / 1000) > 500) {
$image = \think\Image::open($absolute_path);
$image->save($absolute_path, null, 80);
}
return [
'code' => 0,
'data' => [
"name" => $path,
"url" => $url,
],
'msg' => '上传成功!'
];
}
/**
* 上传文件
*/
public function uploadFile(Request $request)
{
$dirName = $request->param('dirName');
$upload = new UploadFile('uploads', 'file');
$path = $upload->putFile($dirName . 'File');
return [
'code' => 0,
'data' => [
"name" => $path,
"url" => "/uploads/" . $path,
],
'msg' => '上传成功!'
];
}
/**
* 上传视频
*/
public function uploadVideo(Request $request)
{
$dirName = $request->param('dirName');
$upload = new UploadFile('uploads', 'file');
$path = $upload->putFile($dirName . 'File');
return [
'code' => 0,
'data' => [
"name" => $path,
"url" => "/uploads/" . $path,
],
'msg' => '上传成功!'
];
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace app\admin\controller\ContactUs;
use app\BaseController;
use app\common\model\ContactUs\ContactUs as ModelContactUs;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\exception\Tool;
class ContactUs extends BaseController
{
/**
* 获取联系我们内容
*/
public function getContactUs(Request $request): array
{
$params = $request->param();
$query = ModelContactUs::field([
'contact_us_id',
'contact_us_guid',
'contact_us_address',
'contact_us_phone',
'contact_us_mail',
'contact_us_mobile_phone'
])->where(1)->find();
return [
'code' => 0,
'data' => $query,
'msg' => 'ok'
];
}
/**
* 编辑联系我们
*/
public function editContactUs(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'contact_us_address|地址' => 'require',
'contact_us_phone|座机电话' => 'require',
'contact_us_mail|邮箱' => 'require',
'contact_us_mobile_phone|手机号码' => 'require'
]);
$model = ModelContactUs::where(1)->find();
$model->allowField([
'contact_us_address',
'contact_us_phone',
'contact_us_mail',
'contact_us_mobile_phone',
'contact_us_update_user_guid'
])->save($params);
return msg('编辑成功!');
}
}

View File

@ -0,0 +1,234 @@
<?php
namespace app\admin\controller\Dictionary;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\arw\adjfut\src\Traverse;
use app\BaseController;
use app\exception\ErrorMsg;
use app\common\model\Dictionary\Dictionary as ModelDictionary;
use app\Request;
class Dictionary extends BaseController
{
/**
* 获取字典列表
*
* @param Request $request
* @date 2022-03-14
* @example
* @author admin
* @since 1.0.0
*/
public function getDictionaryList(Request $request): array
{
$select = ModelDictionary::where('dictionary_parent_guid', 0)->order([
'dictionary_index',
'dictionary_order' => 'desc',
])->select();
return [
'code' => 0,
'msg' => 'ok',
'data' => $select
];
}
/**
* 获取菜单树
*
* @param Request $request
* @return array
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function getDictionaryTree(Request $request)
{
$dictionary = ModelDictionary::withoutGlobalScope(['status'])->order([
'dictionary_index',
'dictionary_order' => 'desc',
])->field([
'dictionary_parent_guid',
'dictionary_name',
'dictionary_index',
'dictionary_value',
'dictionary_order',
'dictionary_status',
'dictionary_allow_update',
'dictionary_list_class',
'dictionary_guid',
])->select()->toArray();
array_unshift($dictionary, [
'dictionary_guid' => '0',
'dictionary_parent_guid' => '-1',
'dictionary_name' => '系统字典',
'dictionary_index' => 0,
'dictionary_value' => '',
'dictionary_order' => 0,
'dictionary_status' => 0,
'dictionary_allow_update' => 2,
'dictionary_list_class' => '',
]);
$Traverse = new Traverse('dictionary_guid', 'dictionary_parent_guid');
$dictionaryTree = $Traverse->tree($dictionary, '-1', function ($v) {
return [
'label' => $v['dictionary_name'],
'id' => $v['dictionary_guid'],
'parent_id' => $v['dictionary_parent_guid'],
'index' => $v['dictionary_index'],
'order' => $v['dictionary_order'],
'status' => $v['dictionary_status'],
'allow' => $v['dictionary_allow_update'],
'value' => $v['dictionary_value'],
'list_class' => $v['dictionary_list_class']
];
});
return [
'code' => 0,
'msg' => 'ok',
'data' => $dictionaryTree
];
}
/**
* 添加字典
*
* @param Request $request
* @return array
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function addDictionary(Request $request)
{
$params = $request->param();
$this->validate($params, [
'dictionary_name' => 'require',
'dictionary_index' => 'require',
'dictionary_order' => 'require',
'dictionary_parent_guid' => 'require',
]);
if (isset($params['dictionary_guid'])) {
unset($params['dictionary_guid']);
}
ModelDictionary::create($params);
return [
'code' => 0,
'msg' => '添加成功'
];
}
/**
* 更新部门
*
* @param Request $request
* @return array
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function updateDictionary(Request $request)
{
$params = $request->param();
$this->validate($params, [
'dictionary_guid' => 'require'
]);
ModelDictionary::withoutGlobalScope(['status'])->update($params, [
'dictionary_guid' => $params['dictionary_guid']
]);
return [
'code' => 0,
'msg' => '更新成功'
];
}
/**
* 删除菜单
*
* @param Request $request
* @return array
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function deleteDictionary(Request $request)
{
$params = $request->param();
$this->validate($params, [
'dictionary_guid' => 'require'
]);
ModelDictionary::find($params['dictionary_guid'])->delete();
return [
'code' => 0,
'msg' => '删除成功'
];
}
// 获取字典
public function getDictionary(Request $request)
{
$dictionary_value = $request->param('dictionary_value');
$dictionary_guid = ModelDictionary::where('dictionary_value', $dictionary_value)->find()['dictionary_guid'];
$res = ModelDictionary::field([
'dictionary_guid',
'dictionary_parent_guid',
'dictionary_name',
'dictionary_value',
'dictionary_list_class',
])->where('dictionary_parent_guid', $dictionary_guid)
->where('dictionary_status', 1)->select();
if (!$res) throwErrorMsg("字典不存在");
else return $res;
}
/**
* 下载导入模板
*/
public function downloadTemplate(Request $request)
{
$params = $request->param();
$data = [
[
'上级字典',
'名称',
'值',
'层级',
'排序',
'回显',
]
];
$data[] = ['','状态','status','1','0','',];
$data[] = ['状态','启用','1','2','1','primary'];
$data[] = ['状态','禁用','2','2','2','danger',];
$excel = (new Excel())->exporTsheet($data);
$excel->save('字典导入模板.xlsx');
}
/**
* 导入excel
*/
public function importExcel(Request $request)
{
$file = new UploadFile('uploads', 'fileExt:xlsx');
$file->putFile('Dictionary');
$msg = ModelDictionary::importExcel($file);
return [
'code' => 0,
'msg' => $msg
];
}
}

View File

@ -0,0 +1,176 @@
<?php
namespace app\admin\controller\Faq;
use app\BaseController;
use app\common\model\Faq\Faq as ModelFaq;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class Faq extends BaseController
{
/**
* 获取常见问题列表
*/
public function getFaqList(Request $request, $isExport = false): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery(['faq_questions', 'LIKE'], ['c.i18n_lang_type_guid', '=']);
$query = ModelFaq::where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'faq_id',
'faq_guid',
'faq_questions',
'faq_answer',
'faq_sort',
'a.i18n_lang_type_guid',
'c.i18n_lang_type_name',
'c.i18n_lang_type_code',
])
->order('faq_sort', 'asc');
return $isExport ? $query->select()->toArray() : msg("获取常见问题列表成功!", $query);
}
/**
* 添加常见问题
*/
public function addFaq(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('faq');
try {
$params = $request->param();
$this->validate($params, [
'faq_questions|问题' => 'require',
'faq_answer|答案' => 'require',
]);
$model = ModelFaq::create($params, [
'i18n_lang_type_guid',
'tdk_create_user_guid',
'tdk_update_user_guid',
'faq_questions',
'faq_answer',
'faq_sort',
'faq_guid',
'faq_create_user_guid',
'faq_update_user_guid'
]);
Db::commit();
Tool::unlockTable();
return msg('添加成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 编辑常见问题
*/
public function editFaq(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('faq');
try {
$params = $request->param();
$this->validate($params, [
'faq_questions|问题' => 'require',
'faq_answer|答案' => 'require',
'faq_sort|顺序' => 'require'
]);
$model = ModelFaq::where('faq_guid', $params['faq_guid'])->find();
if (!$model) throwErrorMsg("该常见问题不存在", 1);
$model->allowField([
'i18n_lang_type_guid',
'faq_questions',
'faq_answer',
'faq_sort',
'faq_update_user_guid'
])->save($params);
Db::commit();
Tool::unlockTable();
return msg('编辑成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 删除常见问题
*/
public function deleteFaq(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('faq');
try {
$params = $request->param();
$this->validate($params, [
'faq_guid' => 'require',
]);
$faq = ModelFaq::where([
'faq_guid' => explode(',', $params['faq_guid'])
])->select();
$faq->delete();
Db::commit();
Tool::unlockTable();
return msg('删除成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 导出Excel
*/
public function exportExcel(Request $request): void
{
ModelFaq::exportExcel(self::getFaqList($request, true));
}
/**
* 下载导入模板
*/
public function downloadTemplate(Request $request): void
{
$params = $request->param();
$data = [
array_values(ModelFaq::EXCELFIELD),
['zh', '默认值1', '默认值2', '默认值3',]
];
$excel = (new Excel())->exporTsheet($data);
$excel->save('常见问题导入模板.xlsx');
}
/**
* 导入excel
*/
public function importExcel(Request $request): array
{
$file = new UploadFile('uploads', 'fileExt:xlsx');
$file->putFile('faq');
$msg = ModelFaq::importExcel($file);
return [
'code' => 0,
'msg' => $msg
];
}
}

View File

@ -0,0 +1,324 @@
<?php
namespace app\admin\controller\Flow;
use app\Request;
use app\common\model\Flow\Flow as ModelFlow;
use think\db\Where;
use think\facade\Validate;
use app\BaseController;
use app\exception\ErrorMsg;
use think\facade\Filesystem;
class Flow extends BaseController
{
// (new ModelFlow)->track();
/**
* 查询流量访问记录
* @throws \think\db\exception\DbException
*/
public function getFlowRecord(Request $request): array
{
$query = ModelFlow::where([]);
$select = self::pageWrapper($query)
->field([
'flow_id',
'flow_record_no',
'flow_visitor_ip',
'flow_location',
'flow_create_time',
'flow_source',
'flow_target',
'flow_os',
'flow_browser'
])
->order('flow_id', 'desc')
->select();
$count = $query->count();
return [
'msg' => '查询成功',
'code' => 0,
'data' => $select,
'count' => $count
];
}
/**
* 删除流量统计
*/
public function deleteFlowRecord(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'flow_id' => 'require',
]);
$leave_message = ModelFlow::where([
'flow_id' => explode(',', $params['flow_id'])
])->select();
$leave_message->delete();
return msg('删除成功!');
}
/**
* 查询流量来源统计
*/
public function getFlowSourceCount(): array
{
$query = ModelFlow::where([]);
$count = $query->count();
$select = $query->field([
'flow_id',
'flow_source',
'flow_target',
'flow_os',
])->select();
$GDP = $query->field([
'flow_source',
])->group('flow_source')->select();
foreach ($GDP as $k => &$i) {
$i['number'] = 0;
$i['percentage'] = 0;
}
foreach ($select as $key => &$item) {
foreach ($GDP as $k => &$i) {
if ($item['flow_source'] === $i['flow_source']) {
$i['number'] += 1;
}
}
}
foreach ($GDP as $k => $i) {
$i['percentage'] = round($i['number'] / $count * 100);
}
return [
'msg' => '查询完成',
'code' => 0,
'count' => $count,
'data' => [
'GDP' => $GDP,
'select' => $select
]
];
}
/**
* 查询流量浏览器统计
*/
public function getFlowBrowserCount(): array
{
$query = ModelFlow::where([]);
$count = $query->count();
$select = $query->field([
'flow_id',
'flow_browser',
])->select();
$GDP = $query->field([
'flow_browser',
])->group('flow_browser')->select();
foreach ($GDP as $k => &$i) {
$i['number'] = 0;
$i['percentage'] = 0;
}
foreach ($select as $key => &$item) {
foreach ($GDP as $k => &$i) {
if ($item['flow_browser'] === $i['flow_browser']) {
$i['number'] += 1;
}
}
}
foreach ($GDP as $k => $i) {
$i['percentage'] = round($i['number'] / $count * 100);
}
return [
'msg' => '查询完成',
'code' => 0,
'count' => $count,
'data' => [
'select' => $select,
'GDP' => $GDP
]
];
}
/**
* 查询流量月统计
*/
public function getFlowMonthCount(Request $request): array
{
$current_year = input('post.current_year') ?? 0;
$query = ModelFlow::where([]);
$current_year = date('Y', strtotime("$current_year year"));
$count = $query->whereYear('flow_create_time', $current_year)
->field([
'flow_create_time',
])
->select()->count();
$select = $query->whereYear('flow_create_time', $current_year)
->field([
'flow_id',
'flow_record_no',
'flow_visitor_ip',
'flow_location',
'flow_create_time',
'flow_source',
'flow_target',
'flow_os',
'flow_browser'
])
->order('flow_id', 'desc')
->select()->toArray();
$res_select = [];
for ($i = 1; $i <= 12; $i++) {
array_push($res_select, [
'flow_Date' => $current_year .
'-' .
date('m', strtotime($current_year . '-' . $i)),
'number' => 0,
'percentage' => 0
]);
}
foreach ($select as $key => &$item) {
$date_format = explode('-', explode(' ', $item['flow_create_time'])[0]);
$item['flow_Date'] = $date_format[0] . '-' . $date_format[1];
foreach ($res_select as $k => &$it) {
if ($item['flow_Date'] == $it['flow_Date']) {
$it['number'] += 1;
}
}
foreach ($res_select as $k => &$it) {
$it['percentage'] = round($it['number'] / $count * 100);
}
};
foreach ($res_select as $k => &$it) {
foreach ($select as $key => &$item) {
if ($it['flow_Date'] === $item['flow_Date']) {
$it = array_merge($it, $item);
}
}
}
return [
'code' => 0,
'msg' => '查询成功',
'count' => $count,
'data' => [
'current_date' => ['y' => $current_year],
'select' => $res_select
]
];
}
/**
* 查询流量日统计
*/
public function getFlowDayCount(Request $request)
{
$current_month = input('post.current_month') ?? 0;
// return ['a'=>$current_month];
$query = ModelFlow::where([]);
$current_month_date = date('Y-m', strtotime(date('Y-m-01') . "$current_month month"));
// return ['a'=>$current_month_date];
$count = $query->whereMonth('flow_create_time', $current_month_date)
->field([
'flow_create_time',
])
->select()->count();
// $select = $query->whereMonth('flow_create_time', $current_month_date)
// ->field([
// 'flow_create_time',
// ])
// ->order('flow_id', 'desc')
// ->select()->toArray();
$select = $query->whereMonth('flow_create_time', $current_month_date)
->field([
'flow_create_time',
])
->buildSql();
return $select;
$GDP = [];
$res_select = [];
for ($i = 1; $i <= date('t', strtotime(date('Y-m-01') . "$current_month month")); $i++) {
array_push($res_select, [
'week' => $this->getWeek(date('Y-m', strtotime(date('Y-m-01') . "$current_month month"))
. '-'
. date('d', strtotime(date('Y-m', strtotime(date('Y-m-01') . "$current_month month")) . "-$i"))),
'flow_Date' => date('Y-m', strtotime(date('Y-m-01') . "$current_month month"))
. '-'
. date('d', strtotime(date('Y-m', strtotime(date('Y-m-01') . "$current_month month")) . "-$i")),
'number' => 0, 'percentage' => 0
]);
}
foreach ($select as $key => &$item) {
$item['flow_Date'] = explode(' ', $item['flow_create_time'])[0];
foreach ($res_select as $k => &$it) {
if ($item['flow_Date'] == $it['flow_Date']) {
$it['number'] += 1;
}
}
foreach ($res_select as $k => &$it) {
$it['percentage'] = round($it['number'] / $count * 100);
}
};
foreach ($res_select as $k => &$it) {
foreach ($select as $key => &$item) {
if ($it['flow_Date'] === $item['flow_Date']) {
$it = array_merge($it, $item);
}
}
}
return [
'code' => 0,
'msg' => '查询成功',
'count' => $count,
'data' => [
'current_date' => ['y' => date('Y', strtotime(date('Y-m-01') . "$current_month month")), 'm' => date('m', strtotime(date('Y-m-01') . "$current_month month"))],
'select' => $res_select
]
];
}
/**
* @param $date
* @return string
* @descript 获取指定日期星期
*/
private function getWeek($date): string
{
//强制转换日期格式
$date_str = date('Y-m-d', strtotime($date));
//封装成数组
$arr = explode("-", $date_str);
//参数赋值
//年
$year = $arr[0];
//月输出2位整型不够2位右对齐
$month = sprintf('%02d', $arr[1]);
//日输出2位整型不够2位右对齐
$day = sprintf('%02d', $arr[2]);
//时分秒默认赋值为0
$hour = $minute = $second = 0;
//转换成时间戳
$strap = mktime($hour, $minute, $second, $month, $day, $year);
//获取数字型星期几
$number_wk = date("w", $strap);
//自定义星期数组
$weekArr = array("星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六");
//获取数字对应的星期
return $weekArr[$number_wk];
}
}

View File

@ -0,0 +1,517 @@
<?php
namespace app\admin\controller\Gen\GenApi;
use app\admin\controller\Gen\Gen;
/**
* 后端生成类
*/
class GenApi
{
/**
* 项目根目录路径
* @var string
*/
protected $root;
/**
* 字段信息
* @var array
*/
protected $fields = [];
/**
* 生成信息
* @var array
*/
protected $table = [];
/**
* 实体类名
* @var string User
*/
protected $class_name;
/**
* 模块名
* @var string User
*/
protected $module_name;
/**
* 业务名 user
* @var string
*/
protected $business_name;
/**
* 方法名
* @var string 例:用户
*/
protected $function_name;
/**
* 后端生成模板文件路径配置
* @var array
*/
protected const TEMP_PATH_CONFIG = [
'crud' => [ //单表(增删改查)
'api' => 'resources/view/api/controller.tpl',
'admin' => 'resources/view/admin/controller.tpl',
'model' => 'resources/view/admin/model.tpl',
],
'crud_sort' => [ //单表(增删改查+排序处理)
'api' => 'resources/view/api/controller.tpl',
'admin' => 'resources/view/business/sort/sortAdminController.tpl',
'model' => 'resources/view/business/sort/sortModel.tpl',
],
'web_static' => [ //门户静态
'api' => 'resources/view/business/webApiController.tpl',
'admin' => 'resources/view/business/webController.tpl',
'model' => 'resources/view/admin/model.tpl',
],
];
/**
* 模型层模板读取路径
* @var string
*/
protected $model_temp_path;
/**
* 模型层模块生成路径
* @var string
*/
protected $model_module_path;
/**
* 模型层生成路径
* @var string
*/
protected $model_path;
/**
* 后台控制器模板读取路径
* @var string
*/
protected $admin_con_temp_path;
/**
* 后台控制器模块生成路径
* @var string
*/
protected $admin_con_module_path;
/**
* 后台控制器生成路径
* @var string
*/
protected $admin_con_path;
/**
* 前台控制器模板读取路径
* @var string
*/
protected $api_con_temp_path;
/**
* 前台控制器生成路径
* @var string
*/
protected $api_con_path;
/**
* 前台控制器模块生成路径
* @var string
*/
protected $api_con_module_path;
/**
* 新增功能必要字段
* @var array
*/
protected $add_required_fields = ['guid', 'create_user_guid', 'update_user_guid'];
/**
* 新增允许字段模板字符串
* @var string :['user_name','user_id',...]
*/
protected $add_fields_temp;
/**
* 新增必填验证模板字符串
* @var string : ['user_name|用户名称' => 'require',...]
*/
protected $add_required_verify_temp;
/**
* 修改功能必要字段
* @var array
*/
protected $edit_required_fields = ['update_user_guid'];
/**
* 编辑允许字段模板字符串
* @var string :['user_name','user_id',...]
*/
protected $edit_fields_temp;
/**
* 编辑必填验证模板字符串
* @var string : ['user_name|用户名称' => 'require',...]
*/
protected $edit_required_verify_temp;
/**
* 业务字段
* @var array :[ 'user_name' => '用户名称',...]
*/
protected $business_fields = [];
/**
* 是否导入
* @var bool
*/
protected $is_import = false;
/**
* 是否导出
* @var bool
*/
protected $is_export = false;
/**
* 是否排序处理
* @var bool
*/
protected $is_sort = false;
/**
* 图片字段数组
* @var array
*/
protected $img_fields = [];
/**
* 生成后端模板类型
* @var string crud:: 单表(增删改查) | web_static: 门户静态模块(查询修改)
*/
protected $gen_api_type;
/**
* 查询列表显示字段
* @var array :['user_name','user_id',...]
*/
protected $query_list_fields = [];
/**
* 排序字段
* @var string
*/
protected $sort_field;
/**
* 排序类型
* @var string
*/
protected $sort_type;
/**
* 查询列表条件模板字符串
* @var string 例子:Tool::getOptionalQuery(['user_name', 'LIKE'])
*/
protected $query_list_where_temp;
/**
* 构造器
*
* @param array $fields 字段信息
* @param array $table 生成信息
*/
public function __construct(array $fields, array $table)
{
//基本参数初始化
$this->root = base_path();
$this->fields = $fields;
$this->table = $table;
$this->class_name = $this->table['className'];
$this->module_name = $this->table['moduleName'];
$this->business_name = $this->table['businessName'];
$this->function_name = $this->table['functionName'];
//后端生成通用数据初始化
$this->initBusinessFields();
$this->initRequiredFields('add_required_fields');
$this->initRequiredFields('edit_required_fields');
$this->initImportExportStatus();
$this->initImgFields();
$this->buildAddFieldsTemp();
$this->buildEditFieldsTemp();
$this->initGenApiType();
$this->initQueryListDisplayFields();
$this->initSortInfo();
$this->initRequiredVerifyFieldsTemp();
$this->buildQueryWhereContentTemp();
$this->initIsSortStatus();
//后端生成所需路径初始化
$this->initModelGenPath();
$this->initAdminControllerGenPath();
$this->initApiControllerGenPath();
}
/**
* 构建查询列表条件模板字符串
*/
public function buildQueryWhereContentTemp(): void
{
$where_content_arr = [];
foreach ($this->fields as $val) {
if ($val['isQuery']) {
$where_content_arr[] = [$val['columnName'], $val['queryType']];
}
};
$this->query_list_where_temp = self::toFormTempStr($where_content_arr, 3);
}
/**
* 初始化排序信息
*/
private function initSortInfo(): void
{
$this->sort_field = $this->table['options']->SortField ?? "{$this->business_name}_update_time";
$this->sort_type = $this->table['options']->SortType ?? 'desc';
}
/**
* 初始化查询列表可显字段
*/
private function initQueryListDisplayFields(): void
{
foreach ($this->fields as $val) {
if ($val['isList']) {
$this->query_list_fields[] = $val['columnName'];
}
};
}
/**
* 初始化后端模板类型
*/
private function initGenApiType(): void
{
$this->gen_api_type = $this->table['tplCategory'];
}
/**
* 初始化模型层生成所需路径
*/
private function initModelGenPath(): void
{
$this->model_temp_path = self::initFilePath($this->getTempPath('model'));
$this->model_module_path = self::initFilePath("{$this->root}common/model/{$this->module_name}");
$this->model_path = self::initFilePath("{$this->model_module_path}/{$this->class_name}.php");
}
/**
* 初始化后台控制器生成所需路径
*/
private function initAdminControllerGenPath(): void
{
$this->admin_con_temp_path = self::initFilePath($this->getTempPath('admin'));
$this->admin_con_module_path = self::initFilePath("{$this->root}admin/controller/{$this->module_name}");
$this->admin_con_path = self::initFilePath("{$this->admin_con_module_path}/{$this->class_name}.php");
}
/**
* 初始化前台控制器生成所需路径
*/
private function initApiControllerGenPath(): void
{
$this->api_con_temp_path = self::initFilePath($this->getTempPath('api'));
$this->api_con_module_path = self::initFilePath("{$this->root}api/controller/{$this->module_name}");
$this->api_con_path = self::initFilePath("{$this->api_con_module_path}/{$this->class_name}.php");
}
/**
* 获取生成模板文件路径
*
* @param string $type 生成模板文件类型 admin:后台控制器 | api:前台控制器 | model:模型层
*/
private function getTempPath(string $type): string
{
//模板类型
$temp_type = $this->gen_api_type;
//若排序处理开启并且模板类型为crud则使用crud_sort单表(增删改查+排序处理)
if ($this->is_sort) {
$temp_type = ($temp_type == 'crud') ? 'crud_sort' : $temp_type;
}
return $this->root . self::TEMP_PATH_CONFIG[$temp_type][$type];
}
/**
* 初始化图片字段变量
*/
private function initImgFields(): void
{
foreach ($this->fields as $val) {
if ($val['htmlType'] == 'imageUpload') {
$this->img_fields[] = $val['columnName'];
}
}
}
/**
* 初始化导入导出状态
*/
private function initImportExportStatus(): void
{
//其他选项 4导出 6导入
$checked_btn_arr = $this->table['options']->CheckedBtn;
$this->is_import = in_array('6', $checked_btn_arr);
$this->is_export = in_array('4', $checked_btn_arr);
}
/**
* 初始化是否排序处理状态
*/
private function initIsSortStatus(): void
{
$this->is_sort = ($this->table['isSort'] == 1);
}
/**
* 构建新增允许字段模板字符
*/
private function buildAddFieldsTemp(): void
{
$field_arr = array_merge(array_keys($this->business_fields), $this->add_required_fields);
$this->add_fields_temp = self::toFormTempStr($field_arr);
}
/**
* 构建编辑允许字段模板字符
*/
private function buildEditFieldsTemp(): void
{
$field_arr = array_merge(array_keys($this->business_fields), $this->edit_required_fields);
$this->edit_fields_temp = self::toFormTempStr($field_arr);
}
/**
* 初始化功能必填验证模板字符
*/
private function initRequiredVerifyFieldsTemp(): void
{
$edit_require_fields = [];
$add_require_fields = [];
foreach ($this->fields as $val) {
$column_name = $val['columnName'];
if ($val['isEdit']) {
if ($val['isRequired']) {
$edit_require_fields[] = $column_name;
}
}
if ($val['isInsert']) {
if ($val['isRequired']) {
$add_require_fields[] = $column_name;
}
}
};
$this->edit_required_verify_temp = self::toFormTempStr($edit_require_fields, 2);
$this->add_required_verify_temp = self::toFormTempStr($add_require_fields, 2);
}
/**
* 构建业务字段名
*/
private function initBusinessFields()
{
foreach ($this->fields as $val) {
if (!$val['isInit']) {
$this->business_fields[$val['columnName']] = $val['columnComment'];
}
}
}
/**
* 生成模块文件夹
*
* @param string $path 模块文件夹路径
*/
protected function createModuleMkdir(string $module_path): void
{
self::mkdir($module_path);
}
/**
* 初始化文件路径
*
* @param string $path 文件路径
* @return string 初始化后的文件路径
*/
protected static function initFilePath(string $path): string
{
//系统分隔符替换
return str_replace('/', DIRECTORY_SEPARATOR, $path);
}
/**
* 获取模板文件字符串
*
* @param string $temp_path 模板文件路径
*/
protected static function getTempStr(string $temp_path): string
{
//打开该文件资源(r只读方式打开),读取模板文件内容
return fread(fopen($temp_path, "r"), filesize($temp_path));
}
/**
* 写入文件
*
* @param string $path 文件路径
* @param string $content 写入内容
*/
protected static function writeFile(string $path, string $content): void
{
//打开文件资源(w写入方式打开),进行写入
fwrite(fopen($path, 'w'), $content);
}
/**
* 初始化必要字段
*
* @param string 必要字段变量名
*
*/
protected function initRequiredFields(string $op_name): void
{
$init_data = [];
foreach ($this->$op_name as $val) {
$init_data[] = "{$this->business_name}_{$val}";
}
$this->$op_name = $init_data;
}
/**
* 创建文件夹
*
* @param string $path 文件夹创建所属路径
*/
protected static function mkdir(string $path): void
{
if (!(new Gen(new \think\App()))->mkdir($path)) {
throwErrorMsg(__METHOD__ . "创建文件夹失败!");
}
}
/**
* 数组转换为模板字符串
* @param array $arr 数组
* @param int $type 模板字符类型 1:一维数组格式 2:验证器格式 3:列表条件查询 4:关联数组格式
*/
protected function toFormTempStr(array $arr, int $type = 1): string
{
return (new Gen(new \think\App()))->toFormTempStr($arr, $this->business_fields, $type);
}
}

View File

@ -0,0 +1,122 @@
<?php
namespace app\admin\controller\Gen\GenApi\GenController;
use app\admin\controller\Gen\GenApi\GenApi;
use app\common\exception\Tool;
/**
* 后端后台接口生成类
*/
class Admin extends GenApi
{
/**
* 生成后台控制器
*/
public function createAdminController(): void
{
//创建后台控制器层模块目录
self::createModuleMkdir($this->admin_con_module_path);
//模板文件字符串替换
$temp_str = Tool::strReplacePlus(
self::getTempStr($this->admin_con_temp_path),
[
//实体类名
'{$className}' => $this->class_name,
//模块名
'{$moduleName}' => $this->module_name,
//业务名
'{$businessName}' => $this->business_name,
//方法名
'{$functionName}' => $this->function_name,
//查询列表显示字段
'{$queryFields}' => self::toFormTempStr($this->query_list_fields),
//排序字段
'{$orderField}' => $this->sort_field,
//排序类型
'{$orderMode}' => $this->sort_type,
//新增允许字段
'{$addAllowFields}' => $this->add_fields_temp,
//编辑允许字段
'{$editAllowFields}' => $this->edit_fields_temp,
//列表查询条件
'{$whereContent}' => $this->query_list_where_temp,
//导出接口
'{$exportExcelContent}' => $this->buildExportExcelApiTemp(),
//导入接口
'{$importExcelContent}' => $this->buildImportExcelApiTemp(),
//下载模板接口
'{$downloadTempContent}' => $this->buildDownloadTemplateApiTemp(),
//编辑必填验证
'{$editRequireFields}' => $this->edit_required_verify_temp,
//新增必填验证
'{$addRequireFields}' => $this->add_required_verify_temp,
]
);
//文件写入
self::writeFile($this->admin_con_path, $temp_str);
}
/**
* 构建Excel导出接口模板字符串
*/
private function buildExportExcelApiTemp(): string
{
if (!$this->is_export) return '';
//模板字符串构建并返回
return "/**\n* 导出Excel\n*/
public function exportExcel(Request \$request):void
{
Model{$this->class_name}::exportExcel(self::get{$this->class_name}List(\$request, true));
}";
}
/**
* 构建Excel导入接口模板字符串
*/
private function buildImportExcelApiTemp(): string
{
if (!$this->is_import) return '';
//模板字符串构建并返回
return "/**\n* 导入excel\n*/
public function importExcel(Request \$request):array
{
\$file = new UploadFile('uploads', 'fileExt:xlsx');
\$file->putFile('{$this->business_name}');
\$msg = Model{$this->class_name}::importExcel(\$file);
return [
'code' => 0,
'msg' => \$msg
];
}";
}
/**
* 构建Excel下载模板接口模板字符串
*/
private function buildDownloadTemplateApiTemp(): string
{
if (!$this->is_import) return '';
$initial_value_temp = '';
for($i =0 ;$i<count($this->business_fields);$i++){
$index =$i+1;
$initial_value_temp .= "'默认值{$index}',";
}
//模板字符串构建并返回
return "/**\n* 下载导入模板\n*/
public function downloadTemplate(Request \$request):void
{
\$params = \$request->param();
\$data = [
array_values(Model{$this->class_name}::EXCELFIELD),
[{$initial_value_temp}]
];
\$excel = (new Excel())->exporTsheet(\$data);
\$excel->save('{$this->function_name}导入模板.xlsx');
}";
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace app\admin\controller\Gen\GenApi\GenController;
use app\admin\controller\Gen\GenApi\GenApi;
use app\common\exception\Tool;
/**
* 后端前台接口生成类
*/
class Api extends GenApi
{
/**
* 生成前台控制器
*/
public function createApiController(): void
{
//创建前台控制器层模块目录
self::createModuleMkdir($this->api_con_module_path);
//模板文件字符串替换
$temp_str = Tool::strReplacePlus(
self::getTempStr($this->api_con_temp_path),
[
//实体类名
'{$className}' => $this->class_name,
//模块名
'{$moduleName}' => $this->module_name,
//业务名
'{$businessName}' => $this->business_name,
//方法名
'{$functionName}' => $this->function_name,
//查询列表显示字段
'{$queryFields}' => self::toFormTempStr($this->query_list_fields),
//排序字段
'{$orderField}' => $this->sort_field,
//排序类型
'{$orderMode}' => $this->sort_type,
//新增允许字段
'{$addAllowFields}' => $this->add_fields_temp,
//编辑允许字段
'{$editAllowFields}' => $this->edit_fields_temp,
//列表查询条件
'{$whereContent}' => $this->query_list_where_temp,
]
);
//文件写入
self::writeFile($this->api_con_path, $temp_str);
}
}

View File

@ -0,0 +1,209 @@
<?php
namespace app\admin\controller\Gen\GenApi\GenModel;
use app\admin\controller\Gen\GenApi\GenApi;
use app\common\exception\Tool;
/**
* 后端模型层生成类
*/
class Model extends GenApi
{
/**
* 生成模型层
*/
public function createNewModel(): void
{
//创建模型层模块目录
self::createModuleMkdir($this->model_module_path);
//模板文件字符串替换
$temp_str = Tool::strReplacePlus(
self::getTempStr($this->model_temp_path),
[
//实体类名
'{$className}' => $this->class_name,
//模块名
'{$moduleName}' => $this->module_name,
//业务名
'{$businessName}' => $this->business_name,
//模型层字段信息
'{$fields}' => $this->buildFieldsInfoTemp(),
//模型层导出Excel方法
'{$exportExcelContent}' => $this->buildExportFun(),
//模型层导入/下载模板Excel表头
'{$importExcelField}' => $this->buildImportDownloadFieldsTemp(),
//模型层导入Excel方法
'{$importExcelContent}' => $this->buildImportFunTemp(),
//模型层导入Excel初始化方法
'{$importExcelInitContent}' => $this->buildImportInitFunTemp(),
//排序字段
'{$orderField}' => $this->sort_field,
]
);
//文件写入
self::writeFile($this->model_path, $temp_str);
}
/**
* 构建模型层字段信息模板字符串
*/
public function buildFieldsInfoTemp(): string
{
$str = "";
foreach ($this->fields as $value) {
$str .= " '{$value['columnName']}' => '{$value['columnType']}' , \n";
}
return $str;
}
/**
* 构建模型层导出方法模板字符串
*/
private function buildExportFun(): string
{
if (!$this->is_export) return '';
//excel表头字符串构建
$excel_header = [];
foreach ($this->business_fields as $name) {
$excel_header[] = $name;
};
$excel_header_temp = $this->toFormTempStr($excel_header);
//导出数据分配
$data_str = '';
foreach ($this->business_fields as $field => $name) {
//图片字段处理
if (in_array($field, $this->img_fields)) {
$data_str .= "Excel::ExportImgFiled(\$val['$field']),\n";
} else {
$data_str .= "\$val['{$field}'],\n";
}
}
$data_str = "[\n{$data_str}]";
//模板字符串构建并返回
return "
/**
* 导出Excel
*
* @param array \$select 导出的数据
*/
public static function exportExcel(array \$select): void
{
\$data = [{$excel_header_temp}];
foreach (\$select as \$key => \$val) {
\$data[] = {$data_str};
}
\$excel = (new Excel())->exporTsheet(\$data);
\$excel->save('{$this->function_name}.xlsx');
}";
}
/**
* 构建导入/下载模板表头模板字符串
*/
private function buildImportDownloadFieldsTemp(): string
{
if (!$this->is_import) return '';
$init_fields_str = $this->toFormTempStr($this->business_fields, 4);
$init_fields_str = substr($init_fields_str, 0, strlen($init_fields_str) - 1); //末尾的逗号去除
return " // excel导入/下载模板表头
public const EXCELFIELD = {$init_fields_str};";
}
/**
* 构建模型层导入方法模板字符串
*/
private function buildImportFunTemp(): string
{
if (!$this->is_import) return '';
//模板字符串构建并返回
return "
/**
* 导入excel
*
* @param \app\common\arw\adjfut\src\UploadFile \$file excel
*/
public static function importExcel(\app\common\arw\adjfut\src\UploadFile \$file): string
{
\$msg = [];
Db::startTrans();
try {
\$excel = new Excel(\$file);
\$data = \$excel->parseExcel(
Tool::getExcelRule(self::EXCELFIELD),
['titleLine' => [1]]);
if (!\$data) throwErrorMsg('excel无数据', 1);
\$msg = [];
foreach (\$data as \$line => \$value) {
try {
\$model = self::importExcelInit(\$value);
\$msg[] = \"{\$line} <span style='color:#27af49'>新增成功!</span><br>\";
} catch (\Throwable \$th) {
\$msg[] = \"{\$line} <span style='color:red'>{\$th->getMessage()}</span><br>\";
}
}
Db::commit();
return implode(', ', \$msg);
} catch (\Throwable \$th) {
Db::rollback();
throw \$th;
}
}";
}
/**
* 构建模型层导入初始化方法模板字符串
*/
private function buildImportInitFunTemp(): string
{
if (!$this->is_import) return '';
/**
* (匿名函数)获取excel每行导入数据变量分配-模板字符串
*/
$getImportAllocationTemp = function () {
$str = "";
foreach ($this->business_fields as $field => $name) {
$str .= "\${$field} = \$value['{$field}'];";
};
return $str;
};
$import_allocation_temp = $getImportAllocationTemp();
/**
* (匿名函数)获取新增的字段值们-模板字符串
*/
$getAddFieldsTemp = function () {
$str = "";
foreach ($this->business_fields as $field => $name) {
$str .= "'{$field}' => \${$field},\n";
};
return $str;
};
$add_allocation_temp = $getAddFieldsTemp();
//模板字符串构建并返回
return "
/**
* 导入excel初始化
*
* @param array \$value excel每行数据
*/
public static function importExcelInit(array \$value):void
{
{$import_allocation_temp}
self::create(
[{$add_allocation_temp}],
{$this->add_fields_temp}
);
}
";
}
}

View File

@ -0,0 +1,223 @@
<?php
namespace app\admin\controller\Gen\GenVue;
use app\admin\controller\Gen\Gen;
/**
* 前端生成类
*/
class GenDto
{
/**
* 项目根目录路径
* @var string
*/
protected $root;
/**
* 字段信息
* @var array
*/
protected $fields = [];
/**
* 生成信息
* @var array
*/
protected $table = [];
/**
* 实体类名
* @var string User
*/
protected $class_name;
/**
* 模块名
* @var string User
*/
protected $module_name;
/**
* 业务名 user
* @var string
*/
protected $business_name;
/**
* 方法名
* @var string 例:用户
*/
protected $function_name;
/**
* vue基础生成路径
* @var string
*/
protected $genPath;
/**
* 模型层模板读取路径
* @var string
*/
protected $vue_index_temp_path;
/**
* 模型层模块生成路径
* @var string
*/
protected $model_module_path;
/**
* 模型层生成路径
* @var string
*/
protected $model_path;
/**
* 业务字段
* @var array [ 'user_name' => '用户名称',...]
*/
protected $business_fields = [];
/**
* 新增允许字段模板字符
* @var string
*/
protected $add_fields_temp = "";
/**
* 是否导入
* @var bool
*/
protected $is_import = false;
/**
* 是否导出
* @var bool
*/
protected $is_export = false;
/**
* 图片字段数组
* @var array
*/
protected $img_fields = [];
/**
* 构造器
*
* @param array $fields 字段信息
* @param array $table 生成信息
*/
public function __construct(array $fields, array $table)
{
$this->root = base_path();
$this->fields = $fields;
$this->table = $table;
$this->class_name = $this->table['className'];
$this->module_name = $this->table['moduleName'];
$this->business_name = $this->table['businessName'];
$this->function_name = $this->table['functionName'];
$this->genPath = $this->table['genPath'];
$this->vue_index_temp_path = self::initFilePath("{$this->root}resources/view/admin/model.tpl");
$this->model_module_path = self::initFilePath("{$this->root}common/model/{$this->module_name}");
$this->model_path = self::initFilePath("{$this->model_module_path}/{$this->class_name}.php");
$this->mkdirModelModule();
$this->buildBusinessFields();
$this->buildAddFieldsTemp();
$this->initImportExportStatus();
$this->initImgFields();
}
/**
* 初始化图片字段变量
*/
private function initImgFields(): void
{
foreach ($this->fields as $val) {
if ($val['htmlType'] == 'imageUpload') {
$this->img_fields[] = $val['columnName'];
}
};
}
/**
* 初始化导入导出状态
*/
private function initImportExportStatus(): void
{
//其他选项 4导出 6导入
$checked_btn_arr = $this->table['options']->CheckedBtn;
$this->is_import = in_array('6', $checked_btn_arr);
$this->is_export = in_array('4', $checked_btn_arr);
}
/**
* 构建新增允许字段模板字符
*/
private function buildAddFieldsTemp(): void
{
$this->add_fields_temp .= '[';
foreach ($this->business_fields as $key => $val) {
$this->add_fields_temp .= "'{$key}',";
};
$this->add_fields_temp .= ']';
}
/**
* 构建业务字段名
*/
private function buildBusinessFields()
{
foreach ($this->fields as $val) {
if (!$val['isInit']) {
$this->business_fields[$val['columnName']] = $val['columnComment'];
}
};
}
/**
* 生成模型层模块文件夹
*/
private function mkdirModelModule()
{
self::mkdir($this->model_module_path);
}
/**
* 初始化文件路径
*
* @param string $path 文件路径
* @return string 初始化后的文件路径
*/
protected static function initFilePath(string $path): string
{
//系统分隔符替换
return str_replace('/', DIRECTORY_SEPARATOR, $path);
}
/**
* 创建文件夹
*
* @param string $path 文件夹创建所属路径
*/
protected static function mkdir(string $path): void
{
if (!(new Gen(new \think\App()))->mkdir($path)) {
throwErrorMsg(__METHOD__ . "创建文件夹失败!");
};
}
/**
* 数组转换为模板字符串
* @param array $arr 数组
* @param int $type 模板字符类型 1:一维数组格式 2:验证器格式 3:列表条件查询 4:关联数组格式
*/
protected function toFormTempStr(array $arr, int $type = 1): string
{
return (new Gen(new \think\App()))->toFormTempStr($arr, $this->business_fields, $type);
}
}

View File

@ -0,0 +1,212 @@
<?php
namespace app\admin\controller\Gen\GenApi\GenIndex;
use app\admin\controller\Gen\GenVue\GenDto;
use app\common\exception\Tool;
/**
* 前端列表页生成类
*/
class Index extends GenDto
{
/**
* 生成Index.vue
*/
public function createJsVue(): void
{
//打开Index.vue模板文件拿到该文件资源(r只读方式打开)
$tem_f = fopen($this->vue_index_temp_path, "r");
//读取Index.vue模板文件拿到模板文件的全部字符串
$temp_str = fread($tem_f, filesize($this->vue_index_temp_path));
//模板文件字符串替换
$temp_str = Tool::strReplacePlus($temp_str, [
//实体类名
'{$className}' => $this->class_name,
//模块名
'{$moduleName}' => $this->module_name,
//业务名
'{$businessName}' => $this->business_name,
//Index.vue字段信息
'{$fields}' => $this->buildFieldsInfoTemp(),
//Index.vue导出Excel方法
'{$exportExcelContent}' => $this->buildExportFun(),
//Index.vue导入/下载模板Excel表头
'{$importExcelField}' => $this->buildImportDownloadFieldsTemp(),
//Index.vue导入Excel方法
'{$importExcelContent}' => $this->buildImportFunTemp(),
//Index.vue导入Excel初始化方法
'{$importExcelInitContent}' => $this->buildImportInitFunTemp(),
]);
//打开Index.vue文件拿到该文件资源(w写入方式打开)
$gen_model = fopen($this->model_path, 'w');
//写入该Index.vue文件
fwrite($gen_model, $temp_str);
}
/**
* 构建Index.vue字段信息模板字符
*/
public function buildFieldsInfoTemp(): string
{
$str = "";
foreach ($this->fields as $value) {
$str .= " '{$value['columnName']}' => '{$value['columnType']}' , \n";
}
return $str;
}
/**
* 构建Index.vue导出方法模板字符
*/
private function buildExportFun(): string
{
if (!$this->is_export) return '';
//excel表头字符构建
$excel_header = [];
foreach ($this->business_fields as $name) {
$excel_header[] = $name;
};
$excel_header_temp = $this->toFormTempStr($excel_header);
//导出数据分配
$data_str = '';
foreach ($this->business_fields as $field => $name) {
if (in_array($name, $this->img_fields)) {
$data_str .= "Excel::ExportImgFiled(\$val['$field']),\n";
} else {
$data_str .= "\$val['{$field}'],\n";
}
}
$data_str = "[\n{$data_str}]";
//模板字符构建并返回
return "
/**
* 导出Excel
*
* @param array \$select 导出的数据
*/
public static function exportExcel(array \$select): void
{
\$data = [{$excel_header_temp}];
foreach (\$select as \$key => \$val) {
\$data[] = {$data_str};
}
\$excel = (new Excel())->exporTsheet(\$data);
\$excel->save('{$this->function_name}.xlsx');
}";
}
/**
* 构建导入/下载模板表头模板字符
*/
private function buildImportDownloadFieldsTemp(): string
{
if (!$this->is_import) return '';
$init_fields_str = $this->toFormTempStr($this->business_fields, 4);
$init_fields_str = substr($init_fields_str, 0, strlen($init_fields_str) - 1); //末尾的逗号去除
return "
// excel导入/下载模板表头
public const EXCELFIELD = {$init_fields_str};
";
}
/**
* 构建Index.vue导入方法模板字符
*/
private function buildImportFunTemp(): string
{
if (!$this->is_import) return '';
//模板字符构建并返回
return "
/**
* 导入excel
*
* @param \app\common\arw\adjfut\src\UploadFile \$file excel
*/
public static function importExcel(\app\common\arw\adjfut\src\UploadFile \$file): string
{
\$msg = [];
Db::startTrans();
try {
\$excel = new Excel(\$file);
\$data = \$excel->parseExcel(
Tool::getExcelRule(self::EXCELFIELD),
[
'titleLine' => [1]
]);
if (!\$data) throwErrorMsg('excel无数据', 1);
\$msg = [];
foreach (\$data as \$line => \$value) {
try {
\$model = self::importExcelInit(\$value);
\$msg[] = \"{\$line} <span style='color:#27af49'>新增成功!</span><br>\";
} catch (\Throwable \$th) {
\$msg[] = \"{\$line} <span style='color:red'>{\$th->getMessage()}</span><br>\";
}
}
Db::commit();
return implode(', ', \$msg);
} catch (\Throwable \$th) {
Db::rollback();
throw \$th;
}
}";
}
/**
* 构建Index.vue导入初始化方法模板字符
*/
private function buildImportInitFunTemp(): string
{
if (!$this->is_import) return '';
/**
* (匿名函数)获取excel每行导入数据变量分配-模板字符
*/
$getImportAllocationTemp = function () {
$str = "";
foreach ($this->business_fields as $field => $name) {
$str .= "\${$field} = \$value['{$field}'];";
};
return $str;
};
$import_allocation_temp = $getImportAllocationTemp();
/**
* (匿名函数)获取新增的字段值们-模板字符
*/
$getAddFieldsTemp = function () {
$str = "";
foreach ($this->business_fields as $field => $name) {
$str .= "'{$field}' => \${$field},\n";
};
return $str;
};
$add_allocation_temp = $getAddFieldsTemp();
//模板字符构建并返回
return "
/**
* 导入excel初始化
*
* @param array \$value excel每行数据
*/
public static function importExcelInit(array \$value):void
{
{$import_allocation_temp}
self::create(
[{$add_allocation_temp}],
{$this->add_fields_temp}
);
}
";
}
}

View File

@ -0,0 +1,132 @@
<?php
namespace app\admin\controller\Home\CrossBanner;
use app\BaseController;
use app\common\model\CrossBanner\CrossBanner as ModelCrossBanner;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class CrossBanner extends BaseController
{
/**
* 获取交叉轮播图列表
*/
public function getCrossBannerList(Request $request, $isExport = false): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery();
$query = ModelCrossBanner::where($con)
->field([
'cross_banner_id',
'cross_banner_guid',
'cross_banner_img',
'cross_banner_position',
'cross_banner_sort'
])
->order('cross_banner_update_time', 'desc');
return $isExport ? $query->select()->toArray() : msg("获取交叉轮播图列表成功!", $query);
}
/**
* 添加交叉轮播图
*/
public function addCrossBanner(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('cross_banner');
try {
$params = $request->param();
$this->validate($params, [
'cross_banner_img|图片' => 'require',
'cross_banner_position|位置' => 'require',
// 'cross_banner_sort|排序' => 'require'
]);
$model = ModelCrossBanner::create($params, [
'cross_banner_img',
'cross_banner_position',
'cross_banner_sort',
'cross_banner_guid',
'cross_banner_create_user_guid',
'cross_banner_update_user_guid'
]);
Db::commit();
Tool::unlockTable();
return msg('添加成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 编辑交叉轮播图
*/
public function editCrossBanner(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('cross_banner');
try {
$params = $request->param();
$this->validate($params, [
'cross_banner_img|图片' => 'require',
'cross_banner_position|位置' => 'require',
'cross_banner_sort|排序' => 'require'
]);
$model = ModelCrossBanner::where('cross_banner_guid', $params['cross_banner_guid'])->find();
if (!$model) throwErrorMsg("该交叉轮播图不存在", 1);
$model->allowField([
'cross_banner_img',
'cross_banner_position',
'cross_banner_sort',
'cross_banner_update_user_guid'
])->save($params);
Db::commit();
Tool::unlockTable();
return msg('编辑成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 删除交叉轮播图
*/
public function deleteCrossBanner(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('cross_banner');
try {
$params = $request->param();
$this->validate($params, [
'cross_banner_guid' => 'require',
]);
$cross_banner = ModelCrossBanner::where([
'cross_banner_guid' => explode(',', $params['cross_banner_guid'])
])->select();
$cross_banner->delete();
Db::commit();
Tool::unlockTable();
return msg('删除成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
}

View File

@ -0,0 +1,135 @@
<?php
namespace app\admin\controller\Home\Highlights;
use app\BaseController;
use app\common\model\Home\Highlights\Highlights as ModelHighlights;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class Highlights extends BaseController
{
/**
* 获取亮点列表
*/
public function getHighlightsList(Request $request, $isExport = false): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery(['a.i18n_lang_type_guid', '='], ['highlights_title', 'LIKE'],);
$query = ModelHighlights::where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'a.highlights_id',
'a.highlights_guid',
'c.i18n_lang_type_code',
'a.i18n_lang_type_guid',
'a.highlights_title',
'a.highlights_sort'
])
->order('highlights_sort', 'asc');
return $isExport ? $query->select()->toArray() : msg("获取亮点列表成功!", $query);
}
/**
* 添加亮点
*/
public function addHighlights(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('highlights');
try {
$params = $request->param();
$this->validate($params, [
'i18n_lang_type_guid|语言类型guid' => 'require',
'highlights_title|标题' => 'require',
// 'highlights_sort|排序' => 'require'
]);
$model = ModelHighlights::create($params, [
'i18n_lang_type_guid',
'highlights_title',
'highlights_sort',
'highlights_guid',
'highlights_create_user_guid',
'highlights_update_user_guid'
]);
Db::commit();
Tool::unlockTable();
return msg('添加成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 编辑亮点
*/
public function editHighlights(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('highlights');
try {
$params = $request->param();
$this->validate($params, [
'i18n_lang_type_guid|语言类型guid' => 'require',
'highlights_title|标题' => 'require',
'highlights_sort|排序' => 'require'
]);
$model = ModelHighlights::where('highlights_guid', $params['highlights_guid'])->find();
if (!$model) throwErrorMsg("该亮点不存在", 1);
$model->allowField([
'i18n_lang_type_guid',
'highlights_title',
'highlights_sort',
'highlights_update_user_guid'
])->save($params);
Db::commit();
Tool::unlockTable();
return msg('编辑成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 删除亮点
*/
public function deleteHighlights(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('highlights');
try {
$params = $request->param();
$this->validate($params, [
'highlights_guid' => 'require',
]);
$highlights = ModelHighlights::where([
'highlights_guid' => explode(',', $params['highlights_guid'])
])->select();
$highlights->delete();
Db::commit();
Tool::unlockTable();
return msg('删除成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace app\admin\controller\Home;
use app\BaseController;
use app\Request;
use app\common\model\Home\Home as ModelHome;
use app\common\model\TeachersStrength\Teacher as ModelTeacher;
class Home extends BaseController
{
/**
* 获取首页数据接口
*
* @param Request request
* @return array
* @date 2023-05-10
* @author xjh
* @since 1.0.0
*/
public function getHomeData(Request $request): array
{
return msg('获取首页数据成功!', ModelHome::getData());
}
}

View File

@ -0,0 +1,107 @@
<?php
namespace app\admin\controller\Home\HomeVideo;
use app\BaseController;
use app\common\model\Home\HomeVideo\HomeVideo as ModelHomeVideo;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class HomeVideo extends BaseController
{
/**
* 获取首页视频列表
*/
public function getHomeVideoList(Request $request, $isExport = false): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery(['i18n_lang_type_guid', '='],);
$query = ModelHomeVideo::where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'a.home_video_id',
'a.home_video_guid',
'c.i18n_lang_type_code',
'a.i18n_lang_type_guid',
'a.home_video_cover',
'a.home_video_url'
])
->order('home_video_create_time', 'desc');
return $isExport ? $query->select()->toArray() : msg("获取首页视频列表成功!", $query);
}
/**
* 添加首页视频
*/
public function addHomeVideo(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'i18n_lang_type_guid|语言类型guid' => 'require',
'home_video_url|视频' => 'require'
]);
$model = ModelHomeVideo::where('i18n_lang_type_guid', $params['i18n_lang_type_guid'])->find();
if ($model) throwErrorMsg("视频同语言只能添加一条", 1);
$model = ModelHomeVideo::create($params, [
'i18n_lang_type_guid',
'home_video_url',
'home_video_cover',
'home_video_guid',
'home_video_create_user_guid',
'home_video_update_user_guid'
]);
return msg('添加成功!');
}
/**
* 编辑首页视频
*/
public function editHomeVideo(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'i18n_lang_type_guid|语言类型guid' => 'require',
'home_video_url|视频' => 'require'
]);
$model = ModelHomeVideo::where('home_video_guid', $params['home_video_guid'])->find();
if (!$model) throwErrorMsg("该首页视频不存在", 1);
$model->allowField([
'i18n_lang_type_guid',
'home_video_cover',
'home_video_url',
'home_video_update_user_guid'
])->save($params);
return msg('编辑成功!');
}
/**
* 删除首页视频
*/
public function deleteHomeVideo(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'home_video_guid' => 'require',
]);
$home_video = ModelHomeVideo::where([
'home_video_guid' => explode(',', $params['home_video_guid'])
])->select();
$home_video->delete();
return msg('删除成功!');
}
}

View File

@ -0,0 +1,132 @@
<?php
namespace app\admin\controller\Home\Partners;
use app\BaseController;
use app\common\model\Home\Partners\Partners as ModelPartners;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class Partners extends BaseController
{
/**
* 获取合作伙伴列表
*/
public function getPartnersList(Request $request, $isExport = false): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery();
$query = ModelPartners::where($con)
->field([
'partners_id',
'partners_guid',
'partners_img',
'partners_des',
'partners_sort'
])
->order('partners_sort', 'asc');
return $isExport ? $query->select()->toArray() : msg("获取合作伙伴列表成功!", $query);
}
/**
* 添加合作伙伴
*/
public function addPartners(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('partners');
try {
$params = $request->param();
$this->validate($params, [
'partners_img|图片' => 'require',
// 'partners_des|描述' => 'require',
// 'partners_sort|排序' => 'require'
]);
$model = ModelPartners::create($params, [
'partners_img',
'partners_des',
'partners_sort',
'partners_guid',
'partners_create_user_guid',
'partners_update_user_guid'
]);
Db::commit();
Tool::unlockTable();
return msg('添加成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 编辑合作伙伴
*/
public function editPartners(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('partners');
try {
$params = $request->param();
$this->validate($params, [
'partners_img|图片' => 'require',
// 'partners_des|描述' => 'require',
'partners_sort|排序' => 'require'
]);
$model = ModelPartners::where('partners_guid', $params['partners_guid'])->find();
if (!$model) throwErrorMsg("该合作伙伴不存在", 1);
$model->allowField([
'partners_img',
'partners_des',
'partners_sort',
'partners_update_user_guid'
])->save($params);
Db::commit();
Tool::unlockTable();
return msg('编辑成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 删除合作伙伴
*/
public function deletePartners(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('partners');
try {
$params = $request->param();
$this->validate($params, [
'partners_guid' => 'require',
]);
$partners = ModelPartners::where([
'partners_guid' => explode(',', $params['partners_guid'])
])->select();
$partners->delete();
Db::commit();
Tool::unlockTable();
return msg('删除成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
}

View File

@ -0,0 +1,151 @@
<?php
namespace app\admin\controller\Home\ProfessionalService;
use app\BaseController;
use app\common\model\Home\ProfessionalService\ProfessionalService as ModelProfessionalService;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class ProfessionalService extends BaseController
{
/**
* 获取专业优质服务列表
*/
public function getProfessionalServiceList(Request $request, $isExport = false): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery(['a.i18n_lang_type_guid', '='], ['professional_service_title', 'LIKE'],);
$query = ModelProfessionalService::where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'a.professional_service_id',
'a.professional_service_guid',
'a.professional_service_link',
'a.professional_service_icon_name',
'a.professional_service_icon',
'a.professional_service_title',
'a.professional_service_describe',
'a.i18n_lang_type_guid',
'c.i18n_lang_type_code',
'a.professional_service_sort'
])
->order('professional_service_sort', 'asc');
return $isExport ? $query->select()->toArray() : msg("获取专业优质服务列表成功!", $query);
}
/**
* 添加专业优质服务
*/
public function addProfessionalService(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('professional_service');
try {
$params = $request->param();
$this->validate($params, [
'professional_service_icon|图标' => 'require',
'professional_service_title|标题' => 'require',
'professional_service_describe|描述' => 'require',
'professional_service_link|链接' => 'require',
// 'professional_service_sort|排序' => 'require'
]);
$model = ModelProfessionalService::create($params, [
'professional_service_icon',
'professional_service_title',
'professional_service_link',
'professional_service_describe',
'professional_service_icon_name',
'i18n_lang_type_guid',
'professional_service_sort',
'professional_service_guid',
'professional_service_create_user_guid',
'professional_service_update_user_guid'
]);
Db::commit();
Tool::unlockTable();
return msg('添加成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 编辑专业优质服务
*/
public function editProfessionalService(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('professional_service');
try {
$params = $request->param();
$this->validate($params, [
'professional_service_icon|图标' => 'require',
'professional_service_title|标题' => 'require',
'professional_service_describe|描述' => 'require',
'professional_service_sort|排序' => 'require',
'professional_service_link|链接' => 'require'
]);
$model = ModelProfessionalService::where('professional_service_guid', $params['professional_service_guid'])->find();
if (!$model) throwErrorMsg("该专业优质服务不存在", 1);
$model->allowField([
'professional_service_icon',
'professional_service_icon_name',
'professional_service_link',
'i18n_lang_type_guid',
'professional_service_title',
'professional_service_describe',
'professional_service_sort',
'professional_service_update_user_guid'
])->save($params);
Db::commit();
Tool::unlockTable();
return msg('编辑成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 删除专业优质服务
*/
public function deleteProfessionalService(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('professional_service');
try {
$params = $request->param();
$this->validate($params, [
'professional_service_guid' => 'require',
]);
$professional_service = ModelProfessionalService::where([
'professional_service_guid' => explode(',', $params['professional_service_guid'])
])->select();
$professional_service->delete();
Db::commit();
Tool::unlockTable();
return msg('删除成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
}

View File

@ -0,0 +1,142 @@
<?php
namespace app\admin\controller\I18n\I18nLang;
use app\BaseController;
use app\common\model\I18n\I18nLang\I18nLang as ModelI18nLang;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class I18nLang extends BaseController
{
/**
* 获取多语言设置列表
*/
public function getI18nLangList(Request $request, $isExport = false): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery(['a.i18n_lang_type_guid', '='], ['a.i18n_lang_key', 'LIKE'], ['a.i18n_lang_name', 'LIKE'],);
$query = ModelI18nLang::where($con)
->alias('a')
->leftjoin('i18n_lang_type b', 'a.i18n_lang_type_guid = b.i18n_lang_type_guid')
->field([
'a.i18n_lang_id',
'a.i18n_lang_guid',
'a.i18n_lang_type_guid',
'b.i18n_lang_type_name',
'a.i18n_lang_key',
'a.i18n_lang_name'
])
->order('i18n_lang_create_time', 'asc');
return $isExport ? $query->select()->toArray() : msg("获取多语言设置列表成功!", $query);
}
/**
* 添加多语言设置
*/
public function addI18nLang(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'i18n_lang_type_guid|语言类型guid' => 'require',
'i18n_lang_key|语言key' => 'require',
'i18n_lang_name|语言name' => 'require'
]);
$model = ModelI18nLang::create($params, [
'i18n_lang_type_guid',
'i18n_lang_key',
'i18n_lang_name',
'i18n_lang_guid',
'i18n_lang_create_user_guid',
'i18n_lang_update_user_guid'
]);
return msg('添加成功!');
}
/**
* 编辑多语言设置
*/
public function editI18nLang(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'i18n_lang_type_guid|语言类型guid' => 'require',
'i18n_lang_key|语言key' => 'require',
'i18n_lang_name|语言name' => 'require'
]);
$model = ModelI18nLang::where('i18n_lang_guid', $params['i18n_lang_guid'])->find();
if (!$model) throwErrorMsg("该多语言设置不存在", 1);
$model->allowField([
'i18n_lang_type_guid',
'i18n_lang_key',
'i18n_lang_name',
'i18n_lang_update_user_guid'
])->save($params);
return msg('编辑成功!');
}
/**
* 删除多语言设置
*/
public function deleteI18nLang(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'i18n_lang_guid' => 'require',
]);
$i18n_lang = ModelI18nLang::where([
'i18n_lang_guid' => explode(',', $params['i18n_lang_guid'])
])->select();
$i18n_lang->delete();
return msg('删除成功!');
}
/**
* 导出Excel
*/
public function exportExcel(Request $request): void
{
ModelI18nLang::exportExcel(self::getI18nLangList($request, true));
}
/**
* 下载导入模板
*/
public function downloadTemplate(Request $request): void
{
$params = $request->param();
$data = [
array_values(ModelI18nLang::EXCELFIELD),
['zh', 'home', '首页',],
['en', 'home', 'Home',]
];
$excel = (new Excel())->exporTsheet($data);
$excel->save('多语言设置导入模板.xlsx');
}
/**
* 导入excel
*/
public function importExcel(Request $request): array
{
$file = new UploadFile('uploads', 'fileExt:xlsx');
$file->putFile('i18n_lang');
$msg = ModelI18nLang::importExcel($file);
return [
'code' => 0,
'msg' => $msg
];
}
}

View File

@ -0,0 +1,102 @@
<?php
namespace app\admin\controller\I18n\I18nLangType;
use app\BaseController;
use app\common\model\I18n\I18nLangType\I18nLangType as ModelI18nLangType;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class I18nLangType extends BaseController
{
/**
* 获取多语言类型列表
*/
public function getI18nLangTypeList(Request $request, $isExport = false): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery(['i18n_lang_type_name', 'LIKE'],['i18n_lang_type_code', 'LIKE']);
$query = ModelI18nLangType::where($con)
->field([
'i18n_lang_type_id',
'i18n_lang_type_guid',
'i18n_lang_type_name',
'i18n_lang_type_code',
'i18n_lang_type_sort'
])
->order('i18n_lang_type_sort', 'asc');
return $isExport ? $query->select()->toArray() : msg("获取多语言类型列表成功!", $query);
}
/**
* 添加多语言类型
*/
public function addI18nLangType(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'i18n_lang_type_name|名称' => 'require',
'i18n_lang_type_code|code码' => 'require',
// 'i18n_lang_type_sort|排序' => 'require'
]);
$model = ModelI18nLangType::create($params, [
'i18n_lang_type_name',
'i18n_lang_type_code',
'i18n_lang_type_sort',
'i18n_lang_type_guid',
'i18n_lang_type_create_user_guid',
'i18n_lang_type_update_user_guid'
]);
return msg('添加成功!');
}
/**
* 编辑多语言类型
*/
public function editI18nLangType(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'i18n_lang_type_name|名称' => 'require',
'i18n_lang_type_code|code码' => 'require',
// 'i18n_lang_type_sort|排序' => 'require'
]);
$model = ModelI18nLangType::where('i18n_lang_type_guid', $params['i18n_lang_type_guid'])->find();
if (!$model) throwErrorMsg("该多语言类型不存在", 1);
$model->allowField([
'i18n_lang_type_name',
'i18n_lang_type_code',
'i18n_lang_type_sort',
'i18n_lang_type_update_user_guid'
])->save($params);
return msg('编辑成功!');
}
/**
* 删除多语言类型
*/
public function deleteI18nLangType(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'i18n_lang_type_guid' => 'require',
]);
$i18n_lang_type = ModelI18nLangType::where([
'i18n_lang_type_guid' => explode(',', $params['i18n_lang_type_guid'])
])->select();
$i18n_lang_type->delete();
return msg('删除成功!');
}
}

View File

@ -0,0 +1,115 @@
<?php
namespace app\admin\controller\LeaveMessage;
use app\BaseController;
use app\common\model\LeaveMessage\LeaveMessage as ModelLeaveMessage;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class LeaveMessage extends BaseController
{
/**
* 获取留言列表
*/
public function getLeaveMessageList(Request $request, $isExport = false): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery(['leave_message_name', 'LIKE'], ['leave_message_phone', 'LIKE'], ['leave_message_email', 'LIKE'],);
$query = ModelLeaveMessage::where($con)
->field([
'leave_message_id',
'leave_message_guid',
'leave_message_name',
'leave_message_phone',
'leave_message_email',
'leave_message_info'
])
->order('leave_message_create_time', 'desc');
return $isExport ? $query->select()->toArray() : msg("获取留言列表成功!", $query);
}
/**
* 添加留言
*/
public function addLeaveMessage(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'leave_message_name|姓名' => 'require',
'leave_message_phone|电话' => 'require',
'leave_message_email|邮箱' => 'require',
'leave_message_info|信息' => 'require'
]);
$model = ModelLeaveMessage::create($params, [
'leave_message_name',
'leave_message_phone',
'leave_message_email',
'leave_message_info',
'leave_message_guid',
'leave_message_create_user_guid',
'leave_message_update_user_guid'
]);
return msg('添加成功!');
}
/**
* 编辑留言
*/
public function editLeaveMessage(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'leave_message_name|姓名' => 'require',
'leave_message_phone|电话' => 'require',
'leave_message_email|邮箱' => 'require',
'leave_message_info|信息' => 'require'
]);
$model = ModelLeaveMessage::where('leave_message_guid', $params['leave_message_guid'])->find();
if (!$model) throwErrorMsg("该留言不存在", 1);
$model->allowField([
'leave_message_name',
'leave_message_phone',
'leave_message_email',
'leave_message_info',
'leave_message_update_user_guid'
])->save($params);
return msg('编辑成功!');
}
/**
* 删除留言
*/
public function deleteLeaveMessage(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'leave_message_id' => 'require',
]);
$leave_message = ModelLeaveMessage::where([
'leave_message_id' => explode(',', $params['leave_message_id'])
])->select();
$leave_message->delete();
return msg('删除成功!');
}
/**
* 导出Excel
*/
public function exportExcel(Request $request): void
{
ModelLeaveMessage::exportExcel(self::getLeaveMessageList($request, true));
}
}

View File

@ -0,0 +1,145 @@
<?php
namespace app\admin\controller;
use app\common\arw\adjfut\src\Validate;
use app\BaseController;
use app\common\logic\Login as LogicLogin;
use app\Request;
use think\captcha\facade\Captcha;
use think\middleware\SessionInit;
use think\Response;
class Login extends BaseController
{
/**
* 初始化
*
* @date 2022-03-15
* @example
* @author admin
* @since 1.0.0
*/
protected function initialize(): void
{
$this->middleware[SessionInit::class] = [
'only' => ['accountLogin', 'getCaptcha']
];
}
/**
* 验证token
*
* @param Request $request
* @return void
*/
public function validateToken(Request $request)
{
$token = $request->getCurrentToken();
return [
'code' => 0,
'data' => [
'exp_time' => $token->token_exp_time,
],
'msg' => 'ok'
];
}
/**
* 西北政法大学单点登陆
*
* @param Request $request
* @return Response
* @date 2023-01-04
* @example
* @author admin
* @since 1.0.0
*/
public function casOauthLogin(Request $request): Response
{
$url = $request->param('url');
return LogicLogin::casOauthLogin(
LogicLogin::casOauthLoginHandle($url)
);
}
/**
* 西北政法大学单点登出
*
* @param Request $request
* @return Response
* @date 2023-01-04
* @example
* @author admin
* @since 1.0.0
*/
public function casOauthLogout(Request $request): Response
{
$url = $request->param('url');
return LogicLogin::casOauthLogout($url);
}
/**
* 用户账号登录
*
* @param Request $request
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function accountLogin(Request $request): array
{
$param = Validate::param([
'account|账号' => 'require',
'password|密码' => 'require',
// 'captcha|验证码' => $request->isProd() ? 'require|captcha' : false
]);
$token = LogicLogin::accountLogin(
$param['account'],
$param['password']
);
return [
'code' => 0,
'data' => [
'token' => $token->token_content,
'exp_time' => $token->token_exp_time,
],
'msg' => 'ok'
];
}
/**
* 生成验证码
*
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function getCaptcha()
{
return Captcha::create();
}
/**
* 用户登出
*
* @param Request $request
* @date 2022-03-09
* @example
* @author admin
* @since 1.0.0
*/
public function userLogout(Request $request): array
{
$token = $request->getCurrentToken();
$token->logout();
return [
'code' => 0,
'msg' => '登出成功'
];
}
}

View File

@ -0,0 +1,368 @@
<?php
namespace app\admin\controller\Menu;
use app\common\arw\adjfut\src\Traverse;
use app\BaseController;
use app\common\model\Menu\Menu as ModelMenu;
use app\common\model\Menu\MenuApi;
use app\common\model\Role\Role;
use app\common\model\Role\RoleMenu;
use app\Request;
use think\facade\Db;
class Menu extends BaseController
{
/**
* 获取菜单接口树
*
* @param Request $request
* @return array
* @date 2022-03-07
* @example
* @author admin
* @since 1.0.0
*/
public function getMenuApiTree(Request $request)
{
$menu = ModelMenu::order([
'menu_index',
'menu_order' => 'desc',
])->field([
'menu_guid',
'menu_parent_guid',
'menu_name',
'menu_url',
])->select()->toArray();
$menuApi = [];
foreach (MenuApi::select() as $value) {
if (!isset($menuApi[$value->menu_guid])) {
$menuApi[$value->menu_guid] = [];
}
$menuApi[$value->menu_guid][] = $value->menu_api_url;
}
$Traverse = new Traverse('menu_guid', 'menu_parent_guid');
$menuTree = $Traverse->tree($menu, '0', function ($v) use ($menuApi) {
return [
'menu_api_url' => isset($menuApi[$v['menu_guid']]) ? $menuApi[$v['menu_guid']] : [],
'menu_name' => $v['menu_name'],
'menu_guid' => $v['menu_guid'],
'menu_parent_guid' => $v['menu_parent_guid'],
'menu_url' => $v['menu_url'],
];
}, function ($v) {
$v['hasChildren'] = isset($value['children']) && count($value['children']);
return $v;
});
return [
'code' => 0,
'msg' => 'ok',
'data' => $menuTree,
];
}
/**
* 添加菜单接口
*
* @param Request $request
* @return array
* @date 2022-03-08
* @example
* @author admin
* @since 1.0.0
*/
public function addMenuApi(Request $request)
{
Db::startTrans();
try {
$params = $request->param();
$this->validate($params, [
'menu_guid' => 'require',
'menu_api_url' => 'require'
]);
foreach (explode(',', $params['menu_api_url']) as $menu_api_url) {
MenuApi::create([
'menu_guid' => $params['menu_guid'],
'menu_api_url' => $menu_api_url,
]);
}
Db::commit();
return [
'code' => 0,
'msg' => '添加成功',
];
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
}
/**
* 删除菜单接口
*
* @param Request $request
* @return array
* @date 2022-03-08
* @example
* @author admin
* @since 1.0.0
*/
public function deleteMenuApi(Request $request)
{
$params = $request->param();
$this->validate($params, [
'menu_api_guid' => 'require'
]);
MenuApi::where([
'menu_api_guid' => explode(',', $params['menu_api_guid'])
])->select()->delete();
return [
'code' => 0,
'msg' => "删除成功"
];
}
/**
* 获取菜单接口列表
*
* @param Request $request
* @return array
* @date 2022-03-07
* @example
* @author admin
* @since 1.0.0
*/
public function getMenuApiList(Request $request)
{
$params = $request->param();
$this->validate($params, [
'menu_guid' => 'require'
]);
$query = ModelMenu::find($params['menu_guid'])->apis()->append([
'menu_api_status_text'
]);
$data = self::pageWrapper($query)->select();
$count = $query->count();
return [
'code' => 0,
'msg' => 'ok',
'data' => $data,
'count' => $count
];
}
/**
* 获取菜单树
*
* @param Request $request
* @return array
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function getMenuTree(Request $request)
{
$menu = ModelMenu::order([
'menu_index',
'menu_order' => 'desc',
])->field([
'menu_parent_guid',
'menu_name',
'menu_url',
'menu_index',
'menu_order',
'menu_status',
'menu_show',
'menu_guid',
])->select()->toArray();
array_unshift($menu, [
'menu_guid' => '0',
'menu_parent_guid' => '-1',
'menu_name' => '系统菜单',
'menu_index' => 0,
'menu_order' => 0,
'menu_status' => 0,
'menu_show' => 0,
'menu_url' => '',
]);
$Traverse = new Traverse('menu_guid', 'menu_parent_guid');
$menuTree = $Traverse->tree($menu, '-1', function ($v) {
return [
'label' => $v['menu_name'],
'id' => $v['menu_guid'],
'parent_id' => $v['menu_parent_guid'],
'index' => $v['menu_index'],
'order' => $v['menu_order'],
'status' => $v['menu_status'],
'show' => $v['menu_show'],
'url' => $v['menu_url'],
];
});
return [
'code' => 0,
'msg' => 'ok',
'data' => $menuTree
];
}
/**
* 获取角色菜单
*
* @param Request $request
* @return array
* @date 2022-03-09
* @example
* @author admin
* @since 1.0.0
*/
public function getRoleMenu(Request $request)
{
$params = $request->param();
$this->validate($params, [
'role_guid' => 'require'
]);
$menus = Role::getByRoleGuid($params['role_guid'])->menus;
$menu_guids = [];
$menu_parent_guids = [];
foreach ($menus as $menu) {
if (!in_array($menu->menu_guid, $menu_guids)) {
$menu_guids[] = $menu->menu_guid;
}
if (!in_array($menu->menu_parent_guid, $menu_parent_guids)) {
$menu_parent_guids[] = $menu->menu_parent_guid;
}
}
// 去除父id 存在父id会全选子节点
$temp = [];
foreach ($menu_guids as $menu_guid) {
if (!in_array($menu_guid, $menu_parent_guids)) {
$temp[] = $menu_guid;
}
}
return [
'code' => 0,
'data' => $temp,
'msg' => 'ok'
];
}
/**
* 绑定角色菜单
*
* @param Request $request
* @return array
* @date 2022-03-09
* @example
* @author admin
* @since 1.0.0
*/
public function bindRoleMenu(Request $request)
{
$params = $request->param();
$this->validate($params, [
'role_guid' => 'require',
'menu_guid' => 'require'
]);
$menus = array_map(function ($v) {
return ModelMenu::find($v);
}, explode(',', $params['menu_guid']));
RoleMenu::rebindRoleMenu(
[
Role::getByRoleGuid($params['role_guid']),
],
array_filter($menus)
);
return [
'code' => 0,
'msg' => '绑定成功'
];
}
/**
* 添加菜单
*
* @param Request $request
* @return array
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function addMenu(Request $request)
{
$params = $request->param();
$this->validate($params, [
'menu_name' => 'require',
'menu_index' => 'require',
'menu_order' => 'require',
'menu_show' => 'require',
'menu_parent_guid' => 'require',
]);
if (isset($params['menu_guid'])) {
unset($params['menu_guid']);
}
ModelMenu::create($params);
return [
'code' => 0,
'msg' => '添加成功'
];
}
/**
* 更新菜单
*
* @param Request $request
* @return array
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function updateMenu(Request $request)
{
$params = $request->param();
$this->validate($params, [
'menu_guid' => 'require'
]);
ModelMenu::withoutGlobalScope(['status'])->update($params, [
'menu_guid' => $params['menu_guid']
]);
return [
'code' => 0,
'msg' => '更新成功'
];
}
/**
* 删除菜单
*
* @param Request $request
* @return array
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function deleteMenu(Request $request)
{
$params = $request->param();
$this->validate($params, [
'menu_guid' => 'require'
]);
ModelMenu::where([
'menu_guid' => explode(',', $params['menu_guid'])
])->select()->delete();
return [
'code' => 0,
'msg' => '删除成功'
];
}
}

View File

@ -0,0 +1,210 @@
<?php
namespace app\admin\controller\News;
use app\BaseController;
use app\common\model\News\News as ModelNews;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class News extends BaseController
{
/**
* 获取新闻列表
*/
public function getNewsList(Request $request, $isExport = false): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery(['news_type', '='], ['news_title', 'LIKE'], ['c.i18n_lang_type_guid', '=']);
$query = ModelNews::where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'news_id',
'news_guid',
'news_type',
'news_cover',
'news_title',
'news_intro',
'news_source',
'news_link',
'news_issue_date',
'news_views_num',
'news_sort',
'news_content',
'a.i18n_lang_type_guid',
'c.i18n_lang_type_name',
'c.i18n_lang_type_code',
])
->order('news_sort', 'asc');
return $isExport ? $query->select()->toArray() : msg("获取新闻列表成功!", $query);
}
/**
* 添加新闻
*/
public function addNews(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('news');
try {
$params = $request->param();
$this->validate($params, [
'news_type|新闻类型' => 'require',
'news_title|新闻标题' => 'require',
'news_cover|新闻封面' => 'require',
'news_sort|新闻排序' => 'require'
]);
$model = ModelNews::create($params, [
'i18n_lang_type_guid',
'news_type',
'news_title',
'news_cover',
'news_intro',
'news_source',
'news_link',
'news_issue_date',
'news_views_num',
'news_sort',
'news_content',
'news_guid',
'news_create_user_guid',
'news_update_user_guid'
]);
Db::commit();
Tool::unlockTable();
return msg('添加成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 编辑新闻
*/
public function editNews(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('news');
try {
$params = $request->param();
$this->validate($params, [
'news_type|新闻类型' => 'require',
'news_title|新闻标题' => 'require',
'news_cover|新闻封面' => 'require',
'news_sort|新闻排序' => 'require'
]);
$model = ModelNews::where('news_guid', $params['news_guid'])->find();
if (!$model) throwErrorMsg("该新闻不存在", 1);
$model->allowField([
'i18n_lang_type_guid',
'news_type',
'news_title',
'news_cover',
'news_intro',
'news_source',
'news_link',
'news_issue_date',
'news_views_num',
'news_sort',
'news_content',
'news_update_user_guid'
])->save($params);
Db::commit();
Tool::unlockTable();
return msg('编辑成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 删除新闻
*/
public function deleteNews(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('news');
try {
$params = $request->param();
$this->validate($params, [
'news_guid' => 'require',
]);
$news = ModelNews::where([
'news_guid' => explode(',', $params['news_guid'])
])->select();
$news->delete();
Db::commit();
Tool::unlockTable();
return msg('删除成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
* 导出Excel
*/
public function exportExcel(Request $request): void
{
ModelNews::exportExcel(self::getNewsList($request, true));
}
/**
* 下载导入模板
*/
public function downloadTemplate(Request $request): void
{
$params = $request->param();
$data = [
array_values(ModelNews::EXCELFIELD),
[
'zh',
'公司新闻',
'机床的先进数控:领先的软件',
'/uploads/NewsImg/20240401\fcb291d25ebd321a4dcb864cdc308454.jpg',
'我们的先进数控机床技术为提升生产效率提供了独特优势。我们提供的领先软件确保了机床的可靠和精确控制,这有助于减少设置时间并确保加工零件的高精度。',
'广东隆邦智能装备实业有限公司',
'',
'2023.6.9',
'0',
'1',
'<p>我们的先进数控机床技术为提升生产效率提供了独特优势。我们提供的领先软件确保了机床的可靠和精确控制,这有助于减少设置时间并确保加工零件的高精度。</p><p>先进数控机床的优势</p><p>我们的先进数控机床技术提供了高速加工和最小化错误概率。这显著提高了生产效率和经济效益。可靠的控制系统确保了机床即使在长时间运行下也能稳定工作。</p><p>灵活的加工参数设置功能使机床能够适应各种任务和生产要求。这有助于提高生产质量,并在更换任务时节省机床重新设置的时间。我们的先进数控机床技术在零件加工中提供了速度和精度的最佳组合。</p><p>我们的先进数控机床技术使用起来简单方便。直观的界面使操作员能够快速掌握软件并有效地使用其所有功能。这有助于减少人员培训时间并提高劳动生产率。</p><p>领先的软件,实现高效工作</p><p>我们的领先软件提供了对加工过程的全面控制,并能够快速响应生产环境的变化。监控和控制系统允许远程控制机床并实时跟踪其工作状态。</p><p>与其他生产自动化系统的集成优化了机床和其他设备之间的交互。这降低了错误风险并提高了整个生产过程的有效性。我们的领先软件不仅确保了机床的最佳运行,还改善了整个生产线的互动。</p><p>由于我们先进数控机床技术的定期更新和支持,您将始终领先于竞争对手一步。我们不断努力改进我们的软件,为您提供最先进的技术和工具来管理机床。</p><p>选择我们的先进数控机床技术和领先软件,您将获得优化生产过程和提高企业效率的可靠伙伴。我们专业的团队随时准备支持您并帮助解决任何问题。不要落后于竞争对手 - 选择我们产品的质量和可靠性!</p><p><br></p>',
]
];
$excel = (new Excel())->exporTsheet($data);
$excel->save('新闻导入模板.xlsx');
}
/**
* 导入excel
*/
public function importExcel(Request $request): array
{
$file = new UploadFile('uploads', 'fileExt:xlsx');
$file->putFile('news');
$msg = ModelNews::importExcel($file);
return [
'code' => 0,
'msg' => $msg
];
}
}

View File

@ -0,0 +1,171 @@
<?php
namespace app\admin\controller\Products;
use app\BaseController;
use app\common\model\Products\Product as ModelProduct;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class Product extends BaseController
{
/**
* 获取产品列表
*/
public function getProductList(Request $request, $isExport = false): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery(['a.product_type_guid', '='], ['c.i18n_lang_type_guid', '='], ['product_name', 'LIKE'],);
$query = ModelProduct::alias('a')
->leftjoin('product_type b', 'a.product_type_guid = b.product_type_guid')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->where($con)
->field([
'a.product_id',
'a.product_guid',
'a.product_type_guid',
'a.i18n_lang_type_guid',
'c.i18n_lang_type_name',
'c.i18n_lang_type_code',
'b.product_type_name',
'a.product_name',
'a.product_img',
'a.product_description',
'a.product_link',
'a.product_details',
'a.product_is_hot',
'a.product_sort'
])
->order('product_sort', 'asc');
return $isExport ? $query->select()->toArray() : msg("获取产品列表成功!", $query);
}
/**
* 添加产品
*/
public function addProduct(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'product_type_guid|产品类目' => 'require',
'product_name|产品名称' => 'require',
'product_img|产品图片' => 'require',
]);
$model = ModelProduct::create($params, [
'product_type_guid',
'i18n_lang_type_guid',
'product_name',
'product_img',
'product_description',
'product_link',
'product_details',
'product_sort',
'product_is_hot',
'product_guid',
'product_create_user_guid',
'product_update_user_guid'
]);
return msg('添加成功!');
}
/**
* 编辑产品
*/
public function editProduct(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'product_type_guid|产品类目' => 'require',
'product_name|产品名称' => 'require',
'product_img|产品图片' => 'require',
]);
$model = ModelProduct::where('product_guid', $params['product_guid'])->find();
if (!$model) throwErrorMsg("该产品不存在", 1);
$model->allowField([
'product_type_guid',
'i18n_lang_type_guid',
'product_name',
'product_img',
'product_description',
'product_link',
'product_is_hot',
'product_details',
'product_sort',
'product_update_user_guid'
])->save($params);
return msg('编辑成功!');
}
/**
* 删除产品
*/
public function deleteProduct(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'product_guid' => 'require',
]);
$product = ModelProduct::where([
'product_guid' => explode(',', $params['product_guid'])
])->select();
$product->delete();
return msg('删除成功!');
}
/**
* 导出Excel
*/
public function exportExcel(Request $request): void
{
ModelProduct::exportExcel(self::getProductList($request, true));
}
/**
* 下载导入模板
*/
public function downloadTemplate(Request $request): void
{
$params = $request->param();
$data = [
array_values(ModelProduct::EXCELFIELD),
[
'zh',
'TS 系列',
'Arm Development StudioArm',
'https://www.lbie-group.ru/wp-content/uploads/1-16.jpg',
'Arm全面端到端的嵌入式开发工具',
'',
'',
'',
]
];
$excel = (new Excel())->exporTsheet($data);
$excel->save('产品导入模板.xlsx');
}
/**
* 导入excel
*/
public function importExcel(Request $request): array
{
$file = new UploadFile('uploads', 'fileExt:xlsx');
$file->putFile('product');
$msg = ModelProduct::importExcel($file);
return [
'code' => 0,
'msg' => $msg
];
}
}

View File

@ -0,0 +1,257 @@
<?php
namespace app\admin\controller\Products;
use app\BaseController;
use app\common\model\Products\ProductType as ModelProductType;
use app\common\arw\adjfut\src\Traverse;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class ProductType extends BaseController
{
/**
* 获取产品类目树形列表接口
*
* @param Request request
* @date 2023-03-25
* @example
* @author xjh
* @since 1.0.0
*/
public function getProductTypeTree(Request $request, $isExport = false): array
{
$con = Tool::getOptionalQuery(
['b.product_delete_time', 'NULL'],
['a.product_type_name', 'LIKE'],
['c.i18n_lang_type_guid', '=']
);
$product_type = ModelProductType::field([
'a.i18n_lang_type_guid',
'a.product_type_parent_guid',
'a.product_type_guid',
'a.product_type_name',
'b.product_type_name' => "product_type_parent_name",
'c.i18n_lang_type_name',
'c.i18n_lang_type_code',
'a.product_type_title',
'a.product_type_link',
'a.product_type_icon',
'a.product_type_order',
])
->alias('a')
->leftjoin('product_type b', 'a.product_type_parent_guid = b.product_type_guid')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->where($con)
->order(['product_type_order' => 'asc'])
->select()->toArray();
$Traverse = new Traverse('product_type_guid', 'product_type_parent_guid');
$product_type_tree = $Traverse->tree($product_type, '0', function ($v) {
return [
'i18n_lang_type_guid' => $v['i18n_lang_type_guid'],
'i18n_lang_type_code' => $v['i18n_lang_type_code'],
'product_type_guid' => $v['product_type_guid'],
'product_type_parent_guid' => $v['product_type_parent_guid'],
'product_type_name' => $v['product_type_name'],
'product_type_parent_name' => $v['product_type_parent_name'],
'product_type_title' => $v['product_type_title'],
'product_type_link' => $v['product_type_link'],
'product_type_icon' => $v['product_type_icon'],
'product_type_order' => $v['product_type_order'],
];
});
return $isExport ? $product_type : msg("获取产品类目列表成功!", $product_type_tree);
}
/**
* 添加产品类目接口
*
* @param Request request
* @date 2023-03-25
* @example
* @author xjh
* @since 1.0.0
*/
public function addProductType(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'product_type_name|产品类型名称' => 'require',
'product_type_order|产品类目排序' => 'require'
]);
// ModelProductType::isDuplicateName($params['product_type_name'], $params['product_type_parent_guid']);
$product_type_parent_where = [];
if (!empty($params['product_type_parent_guid'])) {
$params['product_type_ancestors_guid'] = ModelProductType::buildAncestorsGuid($params['product_type_parent_guid']);
$product_type_parent_where['product_type_parent_guid'] = $params['product_type_parent_guid'];
}
ModelProductType::create($params, [
'i18n_lang_type_guid',
'product_type_guid',
'product_type_create_user_guid',
'product_type_update_user_guid',
'product_type_parent_guid',
'product_type_ancestors_guid',
'product_type_name',
'product_type_title',
'product_type_link',
'product_type_icon',
'product_type_order'
]);
return msg('添加成功!');
}
/**
* 编辑产品类目接口
*
* @param Request request
* @date 2023-03-25
* @example
* @author xjh
* @since 1.0.0
*/
public function editProductType(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'product_type_guid|产品类目guid' => 'require',
'product_type_name|产品类目名称' => 'require',
'product_type_order|产品类目排序' => 'require',
]);
$model = ModelProductType::where('product_type_guid', $params['product_type_guid'])->find();
if (!$model) throwErrorMsg("该产品类目不存在", 1);
if ($model->product_type_parent_guid == $model->product_type_guid) {
throwErrorMsg("上级菜单不能选择与当前菜单一样的", 1);
}
// ModelProductType::isDuplicateName($params['product_type_name'], $params['product_type_guid']);
$params['product_type_ancestors_guid'] = ModelProductType::buildAncestorsGuid($params['product_type_parent_guid']);
$model->allowField([
'i18n_lang_type_guid',
'product_type_update_user_guid',
'product_type_name',
'product_type_title',
'product_type_link',
'product_type_icon',
'product_type_ancestors_guid',
'product_type_parent_guid',
'product_type_order',
])->save($params);
return msg('编辑成功!');
}
/**
* 删除产品类目接口
*
* @param Request request
* @date 2023-03-25
* @example
* @author xjh
* @since 1.0.0
*/
public function deleteProductType(Request $request): array
{
Db::startTrans();
try {
$params = $request->param();
$this->validate($params, [
'product_type_guid|产品类目guid' => 'require',
]);
$guids = explode(',', $params['product_type_guid']);
ModelProductType::where(['product_type_guid' => $guids])->select()->delete();
Db::commit();
return msg('删除成功!');
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
}
/**
* 导出Excel接口
*
* @param Request request
* @date 2023-03-25
* @example
* @author xjh
* @since 1.0.0
*/
public function exportExcel(Request $request)
{
ModelProductType::exportExcel(self::getProductTypeTree($request, true));
}
/**
* 下载导入模板接口
*
* @param Request request
* @date 2023-03-25
* @example
* @author xjh
* @since 1.0.0
*/
public function downloadTemplate(Request $request)
{
$params = $request->param();
// $data = array_values(ModelProductType::EXCELFIELD);
$data = [
array_values(ModelProductType::EXCELFIELD),
[
// 'zh',
'中文产品分类',
'TS 系列',
'1',
],
[
// 'zh',
'中文产品分类',
'L 系列',
'2',
],
];
$excel = (new Excel())->exporTsheet($data);
$excel->save('产品类目导入模板.xlsx');
}
/**
* 导入excel接口
*
* @param Request request
* @date 2023-03-25
* @example
* @author xjh
* @since 1.0.0
*/
public function importExcel(Request $request)
{
$file = new UploadFile('uploads', 'fileExt:xlsx');
$file->putFile('product_type');
$msg = ModelProductType::importExcel($file);
return [
'code' => 0,
'msg' => $msg
];
}
}

View File

@ -0,0 +1,143 @@
<?php
namespace app\admin\controller\Products;
use app\BaseController;
use app\common\model\Products\ProductTypeLang as ModelProductTypeLang;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class ProductTypeLang extends BaseController
{
/**
* 获取产品类型多语言列表
*/
public function getProductTypeLangList(Request $request, $isExport = false): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery(['a.product_type_guid', '='], ['a.i18n_lang_type_guid', '='], ['product_type_lang_name', 'LIKE'],);
$query = ModelProductTypeLang::where($con)
->alias('a')
->leftjoin('product_type b', 'a.product_type_guid = b.product_type_guid')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'a.product_type_lang_id',
'b.product_type_name',
'c.i18n_lang_type_code',
'a.product_type_lang_guid',
'a.product_type_guid',
'a.i18n_lang_type_guid',
'a.product_type_lang_name'
])
->order('product_type_lang_create_time', 'desc');
return $isExport ? $query->select()->toArray() : msg("获取产品类型多语言列表成功!", $query);
}
/**
* 添加产品类型多语言
*/
public function addProductTypeLang(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'product_type_guid|产品类型guid' => 'require',
'i18n_lang_type_guid|语言类型guid' => 'require',
'product_type_lang_name|产品类型多语言名称' => 'require'
]);
$model = ModelProductTypeLang::create($params, [
'product_type_guid',
'i18n_lang_type_guid',
'product_type_lang_name',
'product_type_lang_guid',
'product_type_lang_create_user_guid',
'product_type_lang_update_user_guid'
]);
return msg('添加成功!');
}
/**
* 编辑产品类型多语言
*/
public function editProductTypeLang(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'product_type_guid|产品类型guid' => 'require',
'i18n_lang_type_guid|语言类型guid' => 'require',
'product_type_lang_name|产品类型多语言名称' => 'require'
]);
$model = ModelProductTypeLang::where('product_type_lang_guid', $params['product_type_lang_guid'])->find();
if (!$model) throwErrorMsg("该产品类型多语言不存在", 1);
$model->allowField([
'product_type_guid',
'i18n_lang_type_guid',
'product_type_lang_name',
'product_type_lang_update_user_guid'
])->save($params);
return msg('编辑成功!');
}
/**
* 删除产品类型多语言
*/
public function deleteProductTypeLang(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'product_type_lang_guid' => 'require',
]);
$product_type_lang = ModelProductTypeLang::where([
'product_type_lang_guid' => explode(',', $params['product_type_lang_guid'])
])->select();
$product_type_lang->delete();
return msg('删除成功!');
}
/**
* 导出Excel
*/
public function exportExcel(Request $request): void
{
ModelProductTypeLang::exportExcel(self::getProductTypeLangList($request, true));
}
/**
* 下载导入模板
*/
public function downloadTemplate(Request $request): void
{
$params = $request->param();
$data = [
array_values(ModelProductTypeLang::EXCELFIELD),
['en', 'DSL & FD 系列', 'DSL & FD Service',]
];
$excel = (new Excel())->exporTsheet($data);
$excel->save('产品类型多语言导入模板.xlsx');
}
/**
* 导入excel
*/
public function importExcel(Request $request): array
{
$file = new UploadFile('uploads', 'fileExt:xlsx');
$file->putFile('product_type_lang');
$msg = ModelProductTypeLang::importExcel($file);
return [
'code' => 0,
'msg' => $msg
];
}
}

View File

@ -0,0 +1,198 @@
<?php
namespace app\admin\controller\Role;
use app\BaseController;
use app\common\model\Role\Role as ModelRole;
use app\Request;
class Role extends BaseController
{
/**
* 获取用户角色列表
*
* @param Request $request
* @return array
* @date 2022-03-02
* @example
* @author admin
* @since 1.0.0
*/
public function getUserRoleList(Request $request)
{
}
/**
* 获取角色列表
*
* @param Request $request
* @date 2022-02-25
* @example
* @author admin
* @since 1.0.0
*/
public function getRoleList(Request $request): array
{
$role_status = $request->param('role_status');
$role = $request->param('role');
$scope = explode(',', $request->param('scope', ''));
$con = [
// 'role_status' => 1
];
if ($role) {
$con['role_name'] = $role;
}
if ($role_status) {
$con['role_status'] = $role_status;
}
$query = ModelRole::scope($scope)->withSearch(['role_name'], $con)->where($con);
$select = self::pageWrapper($query)->field([
'role_name',
'role_status',
'role_guid',
])->append([
'role_status_text'
])->order([
'role_id' => 'desc'
])->select();
$count = $query->count();
return [
'code' => 0,
'data' => $select,
'count' => $count,
'msg' => 'ok'
];
}
/**
* 获取角色菜单
*
* @param Request $request
* @date 2022-03-08
* @example
* @author admin
* @since 1.0.0
*/
public function getRoleMenu(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'role_guid' => 'require'
]);
dump(ModelRole::getByRoleGuid($params['role_guid'])->menus);
return [
'code' => 0,
'msg' => 'ok',
// 'data' => $data
];
}
/**
* 编辑角色
*
* @param Request $request
* @date 2022-02-28
* @example
* @author admin
* @since 1.0.0
*/
public function editRole(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'role_guid' => 'require',
'role_name' => 'require',
]);
$role = ModelRole::where([
'role_guid' => $params['role_guid']
])->find();
if (!$role) {
throwErrorMsg("角色不存在", 1);
}
$role->save([
'role_name' => $params['role_name'],
]);
return [
'code' => 0,
'msg' => '编辑成功'
];
}
/**
* 添加角色
*
* @param Request $request
* @date 2022-02-28
* @example
* @author admin
* @since 1.0.0
*/
public function addRole(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'role_name' => 'require',
]);
ModelRole::create([
'role_name' => $params['role_name'],
]);
return [
'code' => 0,
'msg' => '添加成功'
];
}
/**
* 删除角色
*
* @param Request $request
* @date 2022-02-28
* @example
* @author admin
* @since 1.0.0
*/
public function deleteRole(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'role_guid' => 'require',
]);
$roles = ModelRole::where([
'role_guid' => ['in', $params['role_guid']]
])->select();
$roles->delete();
return [
'code' => 0,
'msg' => "删除成功"
];
}
/**
* 更新角色状态
*
* @param Request $request
* @date 2022-02-28
* @example
* @author admin
* @since 1.0.0
*/
public function updateRoleStatus(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'role_guid' => 'require',
'role_status' => 'require|in:1,2',
]);
$role_status = $params['role_status'];
$roles = ModelRole::where([
'role_guid' => explode(',', $params['role_guid'])
])->select();
$roles->update([
'role_status' => $role_status
]);
return [
'code' => 0,
'msg' => "更新成功"
];
}
}

View File

@ -0,0 +1,158 @@
<?php
namespace app\admin\controller\Tdk;
use app\BaseController;
use app\common\model\Tdk\Tdk as ModelTdk;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class Tdk extends BaseController
{
/**
* 获取网站tdk列表
*/
public function getTdkList(Request $request): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery(['tdk_type', '='], ['c.i18n_lang_type_guid', '='], ['tdk_title', 'LIKE'],);
$query = ModelTdk::where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'a.tdk_id',
'a.tdk_guid',
'a.tdk_type',
'a.tdk_title',
'a.tdk_description',
'a.tdk_keyword',
'a.i18n_lang_type_guid',
'c.i18n_lang_type_name',
'c.i18n_lang_type_code',
])
->order('tdk_update_time', 'desc');
return msg("获取网站tdk列表成功!", $query);
}
/**
* 编辑网站tdk
*/
public function editTdk(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'tdk_type|tdk所属模块' => 'require',
'tdk_title|网页标题' => 'require',
'tdk_description|网页简介' => 'require',
'tdk_keyword|网页关键词' => 'require'
]);
$model = ModelTdk::where('tdk_guid', $params['tdk_guid'])->find();
if (!$model) throwErrorMsg("该网站tdk不存在", 1);
$model->allowField([
'i18n_lang_type_guid',
'tdk_update_user_guid',
'tdk_type',
'tdk_title',
'tdk_description',
'tdk_keyword'
])->save($params);
return msg('编辑成功!');
}
/**
* 添加网站tdk
*/
public function addTdk(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'tdk_type|tdk所属模块' => 'require',
'tdk_title|网页标题' => 'require',
'tdk_description|网页简介' => 'require',
'tdk_keyword|网页关键词' => 'require'
]);
$model = ModelTdk::create($params, [
'tdk_guid',
'i18n_lang_type_guid',
'tdk_create_user_guid',
'tdk_update_user_guid',
'tdk_type',
'tdk_title',
'tdk_description',
'tdk_keyword'
]);
return msg('添加成功!');
}
/**
* 删除网站tdk
*/
public function deleteTdk(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'tdk_guid' => 'require',
]);
$tdk = ModelTdk::where([
'tdk_guid' => explode(',', $params['tdk_guid'])
])->select();
$tdk->delete();
return msg('删除成功!');
}
/**
* 导出Excel
*/
public function exportExcel(Request $request)
{
$params = $request->param();
$select = ModelTdk::field([
'i18n_lang_type_guid',
'tdk_type',
'tdk_title',
'tdk_description',
'tdk_keyword'
])
->order('tdk_update_time', 'desc')
->select();
return ModelTdk::exportExcel($select);
}
/**
* 下载导入模板
*/
public function downloadTemplate(Request $request)
{
$params = $request->param();
$data = array_values(ModelTdk::EXCELFIELD);
$excel = (new Excel())->exporTsheet($data);
$excel->save('网站tdk导入模板.xlsx');
}
/**
* 导入excel
*/
public function importExcel(Request $request)
{
$file = new UploadFile('uploads', 'fileExt:xlsx');
$file->putFile('tdk');
$msg = ModelTdk::importExcel($file);
return [
'code' => 0,
'msg' => $msg
];
}
}

View File

@ -0,0 +1,371 @@
<?php
namespace app\admin\controller\User;
use app\common\arw\adjfut\src\Traverse;
use app\BaseController;
use app\exception\ErrorMsg;
use app\model\Role;
use app\common\model\Token;
use app\common\model\User\User as ModelUser;
use app\common\model\Role\Role as ModelRole;
use app\common\model\User\UserRole as ModelUserRole;
use app\model\UserRole;
use app\Request;
use think\db\Query;
use think\Exception;
use think\facade\Db;
use app\common\arw\adjfut\src\Validate;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
class User extends BaseController
{
/**
* 获取用户信息
*
* @param Request $request
* @date 2022-03-09
* @example
* @author admin
* @since 1.0.0
*/
public function getUserInfo(Request $request): array
{
$user = $request->getCurrentUser();
return [
'code' => 0,
'data' => [
'user_name' => $user['user_name']
],
'msg' => 'ok'
];
}
/**
* 获取用户菜单
*
* @param Request $request
* @return array
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function getUserMenu(Request $request)
{
// $user = $request->getCurrentUser();
// $menus = [];
// foreach ($user->roles as $role) {
// $menus = array_merge($menus, $role->menus->toArray());
// }
// array_multisort(array_column($menus, 'menu_order'), SORT_DESC, $menus);
// var_dump($menus);
$token = Token::getCurrent();
$menus = $token->token_menu;
$Traverse = new Traverse('menu_guid', 'menu_parent_guid');
$tree = $Traverse->tree($menus, '0', function ($v) {
return [
'key' => $v['menu_guid'],
'name' => $v['menu_name'],
'url' => $v['menu_url'],
'show' => $v['menu_show'],
'icon' => $v['menu_icon'],
];
});
return [
'code' => 0,
'msg' => 'ok',
'data' => $tree
];
}
/**
* 获取用户列表
*
* @param Request $request
* @date 2022-02-25
* @example
* @author admin
* @since 1.0.0
*/
public function getUserList(Request $request): array
{
$user = $request->param('user');
$con = [
// 'user_status' => 1
];
$search = [];
if ($user) {
$search['user_name'] = $user;
}
$query = ModelUser::scope(['admin'])
->withSearch(array_keys($search), $search)->where($con)
->leftjoin('user_role', 'user_role.user_guid = user.user_guid')
->join('role', join(' AND ', [
'role.role_guid = user_role.role_guid',
'role.role_status = 1',
'role.role_delete_time IS NULL',
]), 'left')->where($con);
$select = self::pageWrapper($query)->field([
'user.user_guid',
'user.user_name',
'user.user_phone',
'user.user_position',
'user.user_department',
'user.user_img',
'user.user_status',
'role.role_name',
])
->append([
'roles',
])
->group('user.user_guid')->order([
'user.user_update_time' => 'desc'
])->select();
$count = $query->count();
return [
'code' => 0,
'data' => $select,
'count' => $count,
'msg' => 'ok'
];
}
/**
* 编辑用户
*
* @param Request $request
* @date 2022-02-28
* @example
* @author admin
* @since 1.0.0
*/
public function editUser(Request $request): array
{
$params = Validate::param([
'user_guid' => 'require',
'user_name' => 'require',
'roles|角色' => 'require',
]);
$model = ModelUser::where([
'user_guid' => $params['user_guid']
])->find();
if (!$model) {
throwErrorMsg("用户不存在", 1);
}
$model->save($params);
ModelUser::editUserRole($params);
return [
'code' => 0,
'msg' => '编辑成功'
];
}
/**
* 添加用户
*
* @param Request $request
* @date 2022-02-28
* @example
* @author admin
* @since 1.0.0
*/
public function addUser(Request $request): array
{
$params = Validate::param([
'user_name' => 'require',
'user_password' => 'require',
'roles|角色' => 'require',
]);
$params['user_status'] = 1;
$model = ModelUser::create($params);
$user_guid = $model->user_guid;
ModelUser::addUserRole($user_guid, $params);
return [
'code' => 0,
'msg' => '添加成功'
];
}
/**
* 删除用户
*
* @param Request $request
* @date 2022-02-28
* @example
* @author admin
* @since 1.0.0
*/
public function deleteUser(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'user_guid' => 'require',
]);
$users = ModelUser::where([
'user_guid' => explode(',', $params['user_guid'])
])->select();
$users->delete();
return [
'code' => 0,
'msg' => "删除成功"
];
}
/**
* 更新用户状态
*
* @param Request $request
* @date 2022-02-28
* @example
* @author admin
* @since 1.0.0
*/
public function updateUserStatus(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'user_guid' => 'require',
'user_status' => 'require|in:1,2',
]);
$user_status = $params['user_status'];
$users = ModelUser::where([
'user_guid' => explode(',', $params['user_guid'])
])->select();
$users->update([
'user_status' => $user_status
]);
return [
'code' => 0,
'msg' => "更新成功"
];
}
/**
* 重置用户密码
*
* @param Request $request
* @date 2022-02-25
* @example
* @author admin
* @since 1.0.0
*/
public function resetUserPassword(Request $request): array
{
$params = Validate::param([
'user_guid' => 'require',
'password' => 'require',
]);
$password = $params['password'];
$users = ModelUser::select(explode(',', $params['user_guid']));
// $users = ModelUser::where([
// 'user_guid' => ['in', $params['user_guid']]
// ])->select();
$users->update([
'user_password' => $password
]);
return [
'code' => 0,
'msg' => "密码已重置为:$password ,请及时修改密码"
];
}
/**
* 导出Excel
*/
public function exportExcel(Request $request)
{
$user = $request->param('user');
$con = [
// 'user_status' => 1
];
$search = [];
if ($user) {
$search['user_name'] = $user;
}
$select = ModelUser::scope(['admin'])
->where($con)->field([
'user.user_guid',
'user.user_name',
'user.user_phone',
'user.user_position',
'user.user_department',
'user.user_img',
'role.role_name',
])
->append([
'roles',
])
->withSearch(array_keys($search), $search)->where($con)
->leftjoin('user_role', 'user_role.user_guid = user.user_guid')
->join('role', join(' AND ', [
'role.role_guid = user_role.role_guid',
'role.role_status = 1',
'role.role_delete_time IS NULL',
]), 'left')
->group('user.user_guid')->order([
'user.user_update_time' => 'desc'
])->select();
return ModelUser::exportExcel($select);
}
/**
* 下载导入模板
*/
public function downloadTemplate(Request $request)
{
$params = $request->param();
$data = [
[
'用户名',
'头像',
'角色',
'手机号',
'密码',
]
];
$data[] = [
'负责人',
'https://img13.360buyimg.com/n5/jfs/t1/195344/2/24691/95759/6295e145E6fae20b9/1172b44c351eeaab.jpg.avif',
'管理员,部门负责人',
'10086',
'123456@aerwen',
];
$excel = (new Excel())->exporTsheet($data);
$excel->save('用户导入模板.xlsx');
}
/**
* 导入excel
*/
public function importExcel(Request $request)
{
$file = new UploadFile('uploads', 'fileExt:xlsx');
$file->putFile('User');
$msg = ModelUser::importExcel($file);
return [
'code' => 0,
'msg' => $msg
];
}
}

View File

@ -0,0 +1,153 @@
<?php
namespace app\admin\controller\User;
use app\BaseController;
use app\common\model\Role\Role as ModelRole;
use app\common\model\User\User as ModelUser;
use app\common\model\User\UserRole as ModelUserRole;
use app\Request;
class UserRole extends BaseController
{
/**
* 获取未绑定角色用户列表
*
* @param Request $request
* @return void
* @date 2022-03-02
* @example
* @author admin
* @since 1.0.0
*/
public function getUnbindUserList(Request $request): array
{
$role_guid = $request->param('role_guid');
$user = $request->param('user');
$this->validate($request->param(), [
'role_guid' => 'require'
]);
$user_guids = [];
$con = [];
$users = ModelRole::getByRoleGuid($role_guid)->users;
if ($users) {
$user_guids = $users->column('user_guid');
}
if ($user) {
$con['user_name'] = $user;
}
$query = ModelUser::withSearch(['user_name'], $con)->where($con)->where('user_guid', 'not in', $user_guids);
$select = self::pageWrapper($query)->field([
'user_name',
'user_guid',
])->order([
'user_id' => 'desc'
])->select();
$count = $query->count();
return [
'code' => 0,
'data' => $select,
'count' => $count,
'msg' => 'ok'
];
}
/**
* 获取绑定角色用户列表
*
* @param Request $request
* @return void
* @date 2022-03-02
* @example
* @author admin
* @since 1.0.0
*/
public function getBindUserList(Request $request): array
{
$role_guid = $request->param('role_guid');
$user = $request->param('user');
$this->validate($request->param(), [
'role_guid' => 'require'
]);
$user_ids = [];
$con = [];
$users = ModelRole::getByRoleGuid($role_guid)->users;
if ($users) {
$user_ids = $users->column('user_id');
}
if ($user) {
$con['user_name'] = $user;
}
$query = ModelUser::withSearch(['user_name'], $con)->where($con)->where('user_id', 'in', $user_ids);
$select = self::pageWrapper($query)->field([
'user_name',
'user_guid',
])->order([
'user_id' => 'desc'
])->select();
$count = $query->count();
return [
'code' => 0,
'data' => $select,
'count' => $count,
'msg' => 'ok'
];
}
/**
* 绑定用户角色
*
* @param Request $request
* @date 2022-03-02
* @example
* @author admin
* @since 1.0.0
*/
public function bindUserRole(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'user_guid' => 'require',
'role_guid' => 'require',
]);
$users = array_map(function ($v) {
return ModelUser::getByUserGuid($v);
}, explode(',', $params['user_guid']));
$roles = array_map(function ($v) {
return ModelRole::getByRoleGuid($v);
}, explode(',', $params['role_guid']));
ModelUserRole::bindUserRole($users, $roles);
return [
'code' => 0,
'msg' => '绑定成功'
];
}
/**
* 绑定用户角色
*
* @param Request $request
* @date 2022-03-02
* @example
* @author admin
* @since 1.0.0
*/
public function unBindUserRole(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'user_guid' => 'require',
'role_guid' => 'require',
]);
$users = array_map(function ($v) {
return ModelUser::getByUserGuid($v);
}, explode(',', $params['user_guid']));
$roles = array_map(function ($v) {
return ModelRole::getByRoleGuid($v);
}, explode(',', $params['role_guid']));
ModelUserRole::unbindUserRole($users, $roles);
return [
'code' => 0,
'msg' => '解绑成功'
];
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace app\admin\controller\WechatHistory;
use app\BaseController;
use app\common\model\WechatHistory\WechatHistory as ModelWechatHistory;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class WechatHistory extends BaseController
{
/**
* 获取列表
*/
public function getWechatHistoryList(Request $request, $isExport = false): array
{
$con = Tool::getOptionalQuery(['wechat_history_nickname', 'LIKE']);
$query = ModelWechatHistory::where($con)
->field([
'wechat_history_id',
'wechat_history_ip',
'wechat_history_openid',
'wechat_history_useragent',
'wechat_history_nickname',
'wechat_history_avatar',
'wechat_history_refer',
'create_time',
'delete_time',
])
->order('wechat_history_id', 'desc');
return $isExport ? $query->select()->toArray() : msg("获取列表成功!", $query);
}
/**
* 删除
*/
public function deleteWechatHistory(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'wechat_history_id' => 'require',
]);
$wechat_history = ModelWechatHistory::where([
'wechat_history_id' => explode(',', $params['wechat_history_id'])
])->select();
$wechat_history->delete();
return msg('删除成功!');
}
}

View File

@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
namespace app\admin\middleware;
use app\common\exception\NotAuthApi;
use app\common\model\Token;
use app\common\traits\Auth as TraitsAuth;
use app\Request;
use think\Response;
class Auth
{
use TraitsAuth;
/**
* 忽略登录
*
* @var array
* @date 2023-01-07
* @example
* @author admin
* @since 1.0.0
*/
// private $ignoreLogin = [
// 'Login' => ['*'],
// 'admin' => ['*'],
// ];
/**
* 处理请求
*
* @param \app\Request $request
* @param \Closure $next
* @return Response
*/
public function handle(Request $request, \Closure $next): Response
{
$this->request = $request;
if ($this->isIgnoreLogin()) {
return $next($request);
}
if ($request->isLogin()) {
$user = $request->getCurrentUser();
if ($user->user_admin) {
return $next($request);
}
}
$api = join('/', [
$request->controller(),
$request->action()
]);
$token = Token::getCurrent();
/**
* 缓存接口权限验证
*/
$validate = $this->validateApi($token->token_api);
/**
* 缓存权限验证不通过
*/
if ($validate === false) {
/**
* 自定义验证权限
* 如果验证通过刷新缓存接口
*/
$validate = $this->validateUser();
if ($validate) {
Token::getCurrentUser()->login();
}
}
/**
* 权限验证通过
*/
if ($validate) {
return $next($request);
}
throw new NotAuthApi("未授权接口 [ $api ]", 1);
}
}

11
app/admin/route/route.php Normal file
View File

@ -0,0 +1,11 @@
<?php
use think\facade\Route;
use app\admin\middleware\Auth;
// 注册中间件到admin应用的路由组
Route::middleware(Auth::class)->group(function () {
// 这里是admin应用的路由定义
// Route::get('index', 'Index/index');
// ... 其他admin应用的路由定义
});

View File

@ -0,0 +1,50 @@
<?php
namespace app\api\controller\AboutUs;
use app\BaseController;
use app\common\model\AboutUs\AboutUs as ModelAboutUs;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\exception\Tool;
class AboutUs extends BaseController
{
/**
* 获取关于我们内容
*/
public function getAboutUs(Request $request): array
{
$params = $request->param();
$this->validate($params, ['locale' => 'require']);
$con = Tool::getOptionalQuery(['c.i18n_lang_type_code', '=', 'locale']);
$query = ModelAboutUs::where($con)
->field([
'c.i18n_lang_type_code',
'a.i18n_lang_type_guid',
'about_us_id',
'about_us_guid',
'about_us_profile',
'about_us_profile_history',
'about_us_honor',
'about_us_honor_more',
'about_us_factory',
'about_us_exhibition',
])
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid') //i18n
->find();
return [
'code' => 0,
'data' => $query,
'msg' => 'ok'
];
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace app\api\controller\Banners;
use app\BaseController;
use app\common\model\Banners\Banner as ModelBanner;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class Banner extends BaseController
{
/**
* 获取轮播图列表
*/
public function getBannerList(Request $request): array
{
$params = $request->param();
$con = [];
$this->validate($params, ['banner_location|轮播图位置' => 'require', 'locale' => 'require']);
$con = Tool::getOptionalQuery(
['c.i18n_lang_type_code', '=', 'locale'] //i18n,
);
$query = ModelBanner::where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid') //i18n
->field([
'a.banner_img',
'a.banner_location',
'a.banner_link',
'c.i18n_lang_type_code',
'a.i18n_lang_type_guid',
])
->where('a.banner_location', $params['banner_location'])
->order('a.banner_order', 'asc')
->select();
return msg(0, "获取轮播图列表成功!", [
'data' => $query,
'count' => count($query)
]);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace app\api\controller\Banners;
use app\BaseController;
use app\common\model\Banners\Poster as ModelPoster;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class Poster extends BaseController
{
/**
* 获取海报详情
*/
public function getPoster(Request $request): array
{
$params = $request->param();
$this->validate($params, ['poster_location|海报位置' => 'require','locale' => 'require']);
$con = Tool::getOptionalQuery(
['c.i18n_lang_type_code', '=' , 'locale'], //i18n,
['poster_location', '=',$params['poster_location']]
);
$find = ModelPoster::field([
'a.poster_img' => 'imgSrc',
'a.poster_title' => 'title',
'a.poster_describe' => 'text',
'c.i18n_lang_type_code',
'a.i18n_lang_type_guid',
])
->where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid') //i18n
->find();
return msg(0, '获取海报详情成功!', ['data' => $find]);
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace app\api\controller\CommonApi;
use app\BaseController;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
use think\captcha\facade\Captcha;
use think\helper\Arr;
class CommonApi extends BaseController
{
/**
* 获取验证码接口
*
* @return \think\response\Html
* @date 2023-04-26
* @author xjh
* @since 1.0.0
*/
public function getCaptcha(): \think\response\Html
{
return Captcha::create('verify');
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace app\api\controller\ContactUs;
use app\BaseController;
use app\common\model\ContactUs\ContactUs as ModelContactUs;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\exception\Tool;
class ContactUs extends BaseController
{
/**
* 获取联系我们内容
*/
public function getContactUs(Request $request): array
{
$params = $request->param();
$query = ModelContactUs::field([
'contact_us_id',
'contact_us_guid',
'contact_us_address',
'contact_us_phone',
'contact_us_mail',
'contact_us_mobile_phone'
])->where(1)->find();
return [
'code' => 0,
'data' => $query,
'msg' => 'ok'
];
}
}

View File

@ -0,0 +1,112 @@
<?php
namespace app\api\controller\Crawler;
use app\Request;
use app\common\model\Flow\Flow as ModelFlow;
use think\db\Where;
use think\facade\Validate;
use app\BaseController;
use app\exception\ErrorMsg;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use Goutte\Client;
class Crawler extends BaseController
{
/**
* 爬虫测试
*/
public function Test(Request $request)
{
// return 1;
// 创建Goutte客户端对象
$client = new Client();
// 获取目标网站的URL
$base_url = 'http://www.zs521.com/';
$url = 'http://www.zs521.com/article_categories/guangzhou/articles';
// return $url;
// 发起请求并获取响应对象
$crawler = $client->request('GET', $url);
// 选择要解析的HTML元素
$titles = $crawler->filter('.productsBody .productItem .products');
$imgs = $crawler->filter('.productsBody .productItem .products .productImg');
// return $titles;
// dump($titles);
// die;
$title111 = $titles->filter('.productType')->text();
$img111 = $titles->filter('.productImg')->eq(2)->attr('lazyload');
// return $img111;
// return $title111;
// 在全部元素中筛选
// $products = $crawler->filter('.productsBody .productItem .products');
// foreach ($products as $key => $value) {
// // dump($value->filter('.productType')->eq($key)->text());
// // die;
// foreach ($titles->filter('.productType')->eq($key) as $key => $value) {
// $title = $value->textContent;
// }
// // return $title;
// }
$titleArr = [];
// 遍历元素并输出结果
foreach ($titles as $title) {
$titleArr[] = $title->textContent;
}
return $titleArr;
// $imgArr = [];
foreach ($imgs as $img) {
// var_dump($img->getAttribute('lazyload'));
// die;
// return $img->getAttribute('lazyload');
$src = $img->getAttribute('lazyload');
if (strpos($src, 'http') === 0) {
$img_url = $src;
} else {
$img_url = $base_url . $src;
}
// return $img_url;
// 文件夹名称
$dirName = "product" . "Img";
// 文件保存位置
$fileSaveLocation = public_path('uploads') . $dirName . "\\";
// return $fileSaveLocation;
if (true !== $res = Tool::mkdir($fileSaveLocation)) {
return $res;
}
// 获取图片二进制数据
$imageContent = file_get_contents($img_url);
// var_dump($imageContent);
// die;
// return $imageContent;
// 保存图片到本地文件系统
file_put_contents($fileSaveLocation . basename($img_url), $imageContent);
$res_img_url = "/uoloads" . "/" . $dirName . "/" . basename($img_url);
return $res_img_url;
}
// return $imgArr;
return $titleArr;
}
}

View File

@ -0,0 +1,129 @@
<?php
namespace app\api\controller\Crawler;
use app\Request;
use app\common\model\Flow\Flow as ModelFlow;
use app\common\model\Home\HomeEnv as ModelHomeEnv;
use app\common\model\Home\HomeWorks as ModelHomeWorks;
use think\db\Where;
use think\facade\Validate;
use app\BaseController;
use app\exception\ErrorMsg;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use Goutte\Client;
class CrawlerHoude extends BaseController
{
/**
* 爬虫测试
*/
public function Test(Request $request)
{
// return 1;
// 创建Goutte客户端对象
$client = new Client();
// 获取目标网站的URL
// $base_url = 'http://www.zs521.com/';
// $url = 'http://www.zs521.com/article_categories/guangzhou/articles';
$base_url = 'http://www.zs521.com/';
$url = 'http://www.zs521.com/article_categories/guangzhou/articles';
// return $url;
// 发起请求并获取响应对象
$crawler = $client->request('GET', $url);
// 选择要解析的HTML元素
$imgs = $crawler->filter('.grid img');
// return $titles;
// dump($titles);
// die;
// 在全部元素中筛选
// $products = $crawler->filter('.productsBody .productItem .products');
// foreach ($products as $key => $value) {
// // dump($value->filter('.productType')->eq($key)->text());
// // die;
// foreach ($titles->filter('.productType')->eq($key) as $key => $value) {
// $title = $value->textContent;
// }
// // return $title;
// }
$titleArr = [];
// 遍历元素并输出结果
// foreach ($titles as $title) {
// $titleArr[] = $title->textContent;
// }
// return $titleArr;
// $imgArr = [];
foreach ($imgs as $img) {
// var_dump($img->getAttribute('lazyload'));
// die;
// return $img->getAttribute('lazyload');
$src = $img->getAttribute('src');
if (strpos($src, 'http') === 0) {
$img_url = $src;
} else {
$img_url = $base_url . $src;
}
// return $img_url;
// 文件夹名称
$dirName = "HomeWorks" . "Img";
// 文件保存位置
$fileSaveLocation = public_path('uploads') . $dirName . "\\";
// return $fileSaveLocation;
if (true !== $res = Tool::mkdir($fileSaveLocation)) {
return $res;
}
$saveFileSaveLocation = $fileSaveLocation . date('Ymd') . "\\";
if (true !== $res = Tool::mkdir($saveFileSaveLocation)) {
return $res;
}
// 获取图片二进制数据
$imageContent = file_get_contents($img_url);
// var_dump($imageContent);
// die;
// return $imageContent;
// return $saveFileSaveLocation;
// 保存图片到本地文件系统
file_put_contents($saveFileSaveLocation . basename($img_url), $imageContent);
$res_img_url = "/uploads" . "/" . $dirName . "/" . date('Ymd') . "/" . basename($img_url);
// return $res_img_url;
// $model = ModelHomeEnv::create([
// 'home_env_img' => $res_img_url,
// 'home_env_sort' => 1
// ]);
$model = ModelHomeWorks::create([
'home_works_img' => $res_img_url,
'home_works_sort' => 1
]);
// return $res_img_url;
}
// return $imgArr;
return $titleArr;
}
}

View File

@ -0,0 +1,54 @@
<?php
namespace app\api\controller\Faq;
use app\BaseController;
use app\common\model\Faq\Faq as ModelFaq;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class Faq extends BaseController
{
/**
* 获取常见问题列表
*/
public function getFaqList(Request $request): array
{
$params = $request->param();
$this->validate($params, ['locale' => 'require']);
$con = Tool::getOptionalQuery(
['faq_questions', 'LIKE'],
['c.i18n_lang_type_code', '=', 'locale']
);
$query = ModelFaq::where($con)
->field([
'c.i18n_lang_type_code',
'a.i18n_lang_type_guid',
'faq_id',
'faq_guid',
'faq_questions',
'faq_answer',
'faq_sort'
])
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid') //i18n
->order('faq_sort', 'asc')
->select();
return msg(0, "获取常见问题列表成功!", [
'data' => $query,
'count' => count($query)
]);
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace app\api\controller\Flow;
use app\Request;
use app\common\model\Flow\Flow as ModelFlow;
use think\db\Where;
use think\facade\Validate;
use app\BaseController;
use app\exception\ErrorMsg;
use think\facade\Filesystem;
class Flow extends BaseController
{
/**
* 添加流量访问记录
*/
public function AddFlowRecord(Request $request)
{
$params = $request->param();
$this->validate($params, ['flow_target' => 'require']);
$flow_target = $params['flow_target'];
try {
return (new ModelFlow)->track($flow_target);
return json(msg("添加流量访问记录成功"));
} catch (\Throwable $th) {
throwErrorMsg("错误信息:" . $th);
}
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace app\api\controller\Home\CrossBanner;
use app\BaseController;
use app\common\model\CrossBanner\CrossBanner as ModelCrossBanner;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class CrossBanner extends BaseController
{
/**
* 获取亮点列表
*/
public function getCrossBannerList(Request $request): array
{
$params = $request->param();
$con = [];
$query = ModelCrossBanner::field([
'cross_banner_id',
'cross_banner_guid',
'cross_banner_img',
'cross_banner_position',
'cross_banner_sort'
])->order('cross_banner_sort', 'asc')->select();
$data = [];
foreach ($query as $value) {
if ($value['cross_banner_position'] == 1) {
$data['up'][] = $value;
} elseif ($value['cross_banner_position'] == 2) {
$data['down'][] = $value;
}
}
return msg(0, "获取交叉轮播图成功!", [
'data' => $data,
'count' => count($query)
]);
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace app\api\controller\Home\Highlights;
use app\BaseController;
use app\common\model\Home\Highlights\Highlights as ModelHighlights;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class Highlights extends BaseController
{
/**
* 获取亮点列表
*/
public function getHighlightsList(Request $request): array
{
$params = $request->param();
$con = [];
$this->validate($params, ['locale' => 'require']);
$con = Tool::getOptionalQuery(['c.i18n_lang_type_code', '=', 'locale']);
$query = ModelHighlights::where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'a.highlights_id',
'a.highlights_guid',
'a.i18n_lang_type_guid',
'c.i18n_lang_type_code',
'a.highlights_title',
'a.highlights_sort'
])
->order('highlights_sort', 'asc')
->select();
return msg(0, "获取亮点列表成功!", [
'data' => $query,
'count' => count($query)
]);
}
}

View File

@ -0,0 +1,71 @@
<?php
namespace app\api\controller\Home\HomeVideo;
use app\BaseController;
use app\common\model\Home\HomeVideo\HomeVideo as ModelHomeVideo;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class HomeVideo extends BaseController
{
/**
* 获取首页视频列表
*/
public function getHomeVideo(Request $request): array
{
$params = $request->param();
$con = [];
$this->validate($params, ['locale' => 'require']);
$con = Tool::getOptionalQuery(['i18n_lang_type_guid', '='],['c.i18n_lang_type_code', '=', 'locale']);
$query = ModelHomeVideo::where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'a.home_video_id',
'a.home_video_guid',
'a.i18n_lang_type_guid',
'a.home_video_cover',
'c.i18n_lang_type_code',
'a.home_video_url'
])
->order('home_video_create_time', 'desc')
->select();
return msg(0, "获取首页视频列表成功!", [
'data' => $query,
'count' => count($query)
]);
}
/**
* 获取首页视频详情
*/
public function getHomeVideoInfo(Request $request): array
{
$params = $request->param();
$this->validate($params, ['home_video_guid' => 'require']);
$find = ModelHomeVideo::field([
'home_video_id',
'home_video_guid',
'i18n_lang_type_guid',
'home_video_url'
])
->where('home_video_guid', $params['home_video_guid'])
->find();
return msg(0, '获取首页视频详情成功!', ['data' => $find]);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace app\api\controller\Home\Partners;
use app\BaseController;
use app\common\model\Home\Partners\Partners as ModelPartners;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class Partners extends BaseController
{
/**
* 获取合作伙伴列表
*/
public function getPartnersList(Request $request): array
{
$params = $request->param();
$con = [];
$con = Tool::getOptionalQuery();
$query = ModelPartners::where($con)
->field([
'partners_id',
'partners_guid',
'partners_img',
'partners_des',
'partners_sort'
])
->order('partners_sort', 'asc')
->select();
return msg(0, "获取合作伙伴列表成功!", [
'data' => $query,
'count' => count($query)
]);
}
}

View File

@ -0,0 +1,76 @@
<?php
namespace app\api\controller\Home\ProfessionalService;
use app\BaseController;
use app\common\model\Home\ProfessionalService\ProfessionalService as ModelProfessionalService;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class ProfessionalService extends BaseController
{
/**
* 获取专业优质服务列表
*/
public function getProfessionalServiceList(Request $request): array
{
$params = $request->param();
$con = [];
$this->validate($params, ['locale' => 'require']);
$con = Tool::getOptionalQuery(['c.i18n_lang_type_code', '=', 'locale']);
$query = ModelProfessionalService::where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'a.professional_service_id',
'a.professional_service_guid',
'a.professional_service_icon_name',
'a.professional_service_icon',
'a.professional_service_title',
'a.professional_service_link',
'a.professional_service_describe',
'a.professional_service_sort'
])
->order('professional_service_sort', 'asc')
->select();
return msg(0, "获取专业优质服务列表成功!", [
'data' => $query,
'count' => count($query)
]);
}
/**
* 获取专业优质服务详情
*/
public function getProfessionalServiceInfo(Request $request): array
{
$params = $request->param();
$this->validate($params, ['professional_service_guid' => 'require']);
$find = ModelProfessionalService::field([
'professional_service_id',
'professional_service_guid',
'professional_service_icon',
'professional_service_link',
'professional_service_title',
'professional_service_describe',
'professional_service_sort'
])
->where('professional_service_guid', $params['professional_service_guid'])
->find();
return msg(0, '获取专业优质服务详情成功!', ['data' => $find]);
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace app\api\controller\I18n\I18nLang;
use app\BaseController;
use app\common\model\I18n\I18nLang\I18nLang as ModelI18nLang;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class I18nLang extends BaseController
{
/**
* 获取多语言设置详情
*/
public function getLangListByLocale(Request $request): array
{
$params = $request->param();
$this->validate($params, ['code' => 'require']);
$query = ModelI18nLang::alias('a')
->leftjoin('i18n_lang_type b', 'a.i18n_lang_type_guid = b.i18n_lang_type_guid')
->field([
'a.i18n_lang_key',
'a.i18n_lang_name'
])
->where('b.i18n_lang_type_code', $params['code']);
$data = $query->select()->toArray();
$res = [];
foreach ($data as $key => $item) {
$res[$item['i18n_lang_key']] = $item['i18n_lang_name'];
}
return msg(0, '获取多语言设置详情成功!', ['data' => $res]);
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace app\api\controller\LeaveMessage;
use app\BaseController;
use app\common\model\LeaveMessage\LeaveMessage as ModelLeaveMessage;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class LeaveMessage extends BaseController
{
/**
* 添加留言
*/
public function addLeaveMessage(Request $request): array
{
$params = $request->param();
$this->validate($params, [
'leave_message_name|姓名' => 'require',
'leave_message_phone|电话' => 'require',
'leave_message_email|邮箱' => 'require',
'leave_message_info|信息' => 'require'
]);
$model = ModelLeaveMessage::create($params, [
'leave_message_name',
'leave_message_phone',
'leave_message_email',
'leave_message_info',
'leave_message_guid',
]);
return msg('添加成功!');
}
}

View File

@ -0,0 +1,144 @@
<?php
namespace app\api\controller;
use app\common\arw\adjfut\src\Validate;
use app\BaseController;
use app\common\logic\Login as LogicLogin;
use app\Request;
use think\captcha\facade\Captcha;
use think\middleware\SessionInit;
use think\Response;
class Login extends BaseController
{
/**
* 初始化
*
* @date 2022-03-15
* @example
* @author admin
* @since 1.0.0
*/
protected function initialize(): void
{
$this->middleware[SessionInit::class] = [
'only' => ['accountLogin', 'getCaptcha']
];
}
/**
* 验证token
*
* @param Request $request
* @return void
*/
public function validateToken(Request $request)
{
$token = $request->getCurrentToken();
return [
'code' => 0,
'data' => [
'exp_time' => $token->token_exp_time,
],
'msg' => 'ok'
];
}
/**
* 西北政法大学单点登陆
*
* @param Request $request
* @return Response
* @date 2023-01-04
* @example
* @author admin
* @since 1.0.0
*/
public function casOauthLogin(Request $request): Response
{
$url = $request->param('url');
return LogicLogin::casOauthLogin(
LogicLogin::casOauthLoginHandle($url)
);
}
/**
* 西北政法大学单点登出
*
* @param Request $request
* @return Response
* @date 2023-01-04
* @example
* @author admin
* @since 1.0.0
*/
public function casOauthLogout(Request $request): Response
{
$url = $request->param('url');
return LogicLogin::casOauthLogout($url);
}
/**
* 用户账号登录
*
* @param Request $request
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function accountLogin(Request $request): array
{
$param = Validate::param([
'account|账号' => 'require',
'password|密码' => 'require',
'captcha|验证码' => $request->isProd() ? 'require|captcha' : false
]);
$token = LogicLogin::accountLogin(
$param['account'],
$param['password']
);
return [
'code' => 0,
'data' => [
'token' => $token->token_content,
'exp_time' => $token->token_exp_time,
],
'msg' => 'ok'
];
}
/**
* 生成验证码
*
* @date 2022-03-05
* @example
* @author admin
* @since 1.0.0
*/
public function getCaptcha()
{
return Captcha::create();
}
/**
* 用户登出
*
* @param Request $request
* @date 2022-03-09
* @example
* @author admin
* @since 1.0.0
*/
public function userLogout(Request $request): array
{
$token = $request->getCurrentToken();
$token->logout();
return [
'code' => 0,
'msg' => '登出成功'
];
}
}

View File

@ -0,0 +1,118 @@
<?php
namespace app\api\controller\News;
use app\BaseController;
use app\common\model\News\News as ModelNews;
use app\common\model\Dictionary\Dictionary as ModelDictionary;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class News extends BaseController
{
/**
* 获取新闻类型
*/
public function getNewsType(Request $request): array
{
$params = $request->param();
$query = ModelDictionary::getDictionaryData('news_type');
return msg("获取新闻类型成功!", $query);
}
/**
* 获取新闻列表
*/
public function getNewsList(Request $request)
{
$params = $request->param();
$this->validate($params, ['idx' => 'require']);
// 根据字典index获取新闻类型的值
$news_type_arr = ModelDictionary::getDictionaryData('news_type');
$news_type = $news_type_arr[$params['idx']];
if (!$news_type) throwErrorMsg("传值不正确!");
$con = Tool::getOptionalQuery(['news_title', 'LIKE'], ['c.i18n_lang_type_code', '=', 'locale']);
$query = ModelNews::where($con)
->field([
'c.i18n_lang_type_code',
'a.i18n_lang_type_guid',
'news_id',
'news_type',
'news_title',
'news_intro',
'news_cover',
'news_link',
'news_issue_date',
'news_sort',
])
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid') //i18n
->order('news_sort', 'asc');
return msg("获取新闻列表成功!", $query);
}
/**
* 获取新闻详情
*/
public function getNewsInfo(Request $request): array
{
$params = $request->param();
$this->validate($params, ['news_id' => 'require', 'locale' => 'require']);
$find = ModelNews::where('news_id', $params['news_id'])
->field([
'news_id',
'news_type',
'news_title',
'news_intro',
'news_source',
'news_link',
'news_issue_date',
'news_views_num',
'news_sort',
'news_content'
])->find();
$field = [
'news_id',
'news_title',
'c.i18n_lang_type_code',
'a.i18n_lang_type_guid',
];
# 上一篇文章
$find['prev'] = ModelNews::where('news_id', '<', $params['news_id'])
->where('c.i18n_lang_type_code', '=', $params['locale'])
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid') //i18n
->order('news_id', 'desc')
->field($field)
->find();
# 下一篇文章
$find['next'] = ModelNews::where('news_id', '>', $params['news_id'])
->where('c.i18n_lang_type_code', '=', $params['locale'])
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid') //i18n
->order('news_id', 'asc')
->field($field)
->find();
return msg(0, '获取新闻详情成功!', ['data' => $find]);
}
}

View File

@ -0,0 +1,126 @@
<?php
namespace app\api\controller\Products;
use app\BaseController;
use app\common\model\Products\Product as ModelProduct;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class Product extends BaseController
{
/**
* 获取产品列表
*/
public function getProductList(Request $request): array
{
$params = $request->param();
$con = [];
$this->validate($params, ['locale' => 'require']);
$con = Tool::getOptionalQuery(['b.product_type_id', '='], ['c.i18n_lang_type_code', '=', 'locale'], ['product_name', 'LIKE'],);
$locale = $params['locale'];
$query = ModelProduct::where($con)
->alias('a')
->leftjoin('product_type b', 'a.product_type_guid = b.product_type_guid')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->field([
'a.product_id',
'a.product_guid',
'a.product_type_guid',
'c.i18n_lang_type_code',
'b.product_type_id',
'a.product_name',
'a.product_img',
'a.product_description',
'a.product_link',
'a.product_sort'
])
->order('product_sort', 'asc');
// ->select();
return msg("获取产品列表成功!", $query);
// return msg(0, "获取产品列表成功!", [
// 'data' => $query,
// 'count' => count($query)
// ]);
}
/**
* 获取热门产品列表
*/
public function getHotProductList(Request $request): array
{
$params = $request->param();
$con = [];
$this->validate($params, ['locale' => 'require']);
$con = Tool::getOptionalQuery(['c.i18n_lang_type_code', '=', 'locale']);
$query = ModelProduct::where($con)
->alias('a')
->leftjoin('product_type b', 'a.product_type_guid = b.product_type_guid')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid')
->where('a.product_is_hot', 1)
->field([
'a.product_id',
'a.product_guid',
'a.product_type_guid',
'c.i18n_lang_type_code',
'b.product_type_id',
'a.product_name',
'a.product_img',
'a.product_description',
'a.product_link',
'a.product_sort'
])
->order('product_sort', 'asc');
// ->select();
return msg("获取产品列表成功!", $query);
// return msg(0, "获取产品列表成功!", [
// 'data' => $query,
// 'count' => count($query)
// ]);
}
/**
* 获取产品详情
*/
public function getProductInfo(Request $request): array
{
$params = $request->param();
$this->validate($params, ['product_id' => 'require', 'locale' => 'require']);
$find = ModelProduct::field([
'product_id',
'product_guid',
'product_type_guid',
'product_name',
'product_img',
'product_description',
'product_link',
'product_details',
'product_sort'
])
->where('product_id', $params['product_id'])
->find();
return msg(0, '获取产品详情成功!', ['data' => $find]);
}
}

View File

@ -0,0 +1,79 @@
<?php
namespace app\api\controller\Products;
use app\BaseController;
use app\common\model\Products\ProductType as ModelProductType;
use app\common\arw\adjfut\src\Traverse;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use app\common\exception\Tool;
use think\facade\Db;
use think\facade\Env;
class ProductType extends BaseController
{
/**
* 获取产品系列树形列表接口
*
* @param Request request
* @date 2023-04-03
* @example
* @author xjh
* @since 1.0.0
*/
public function getProductTypeTree(Request $request): array
{
$params = $request->param();
$this->validate($params, ['locale' => 'require']);
$con = Tool::getOptionalQuery(
['d.i18n_lang_type_delete_time', 'NULL'],
['b.product_delete_time', 'NULL'],
['a.product_type_name', 'LIKE'],
['c.i18n_lang_type_code', '=', 'locale']
);
$product_type = ModelProductType::field([
'a.product_type_parent_guid',
'd.product_type_lang_name',
'a.product_type_title',
'a.product_type_link',
'b.product_type_name' => "product_type_parent_name",
'c.i18n_lang_type_code',
'a.product_type_order',
'a.product_type_guid',
'a.product_type_id',
'a.product_type_icon',
])
->alias('a')
->leftjoin('product_type b', 'a.product_type_parent_guid = b.product_type_guid')
->leftjoin('product_type_lang d', 'd.product_type_guid = a.product_type_guid')
->leftjoin('i18n_lang_type c', 'd.i18n_lang_type_guid = c.i18n_lang_type_guid')
->where($con)
->order(['product_type_order' => 'asc', 'product_type_id' => 'desc'])
->select()->toArray();
$Traverse = new Traverse('product_type_guid', 'product_type_parent_guid');
$product_type_tree = $Traverse->tree($product_type, '0', function ($v) {
return [
'i18n_lang_type_code' => $v['i18n_lang_type_code'],
'product_type_name' => $v['product_type_lang_name'],
'product_type_title' => $v['product_type_title'],
'product_type_link' => $v['product_type_link'],
'product_type_parent_name' => $v['product_type_parent_name'],
'product_type_guid' => $v['product_type_guid'],
'product_type_id' => $v['product_type_id'],
'product_type_parent_guid' => $v['product_type_parent_guid'],
'product_type_order' => $v['product_type_order'],
'product_type_icon' => $v['product_type_icon'],
];
});
return msg("获取产品系列列表成功!", $product_type_tree);
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace app\api\controller\Tdk;
use app\BaseController;
use app\common\model\Tdk\Tdk as ModelTdk;
use app\Request;
use think\Validate;
use think\exception\ValidateException;
use think\facade\Filesystem;
use app\common\arw\adjfut\src\Excel;
use app\common\arw\adjfut\src\UploadFile;
use think\facade\Db;
use app\common\exception\Tool;
use think\facade\Env;
class Tdk extends BaseController
{
/**
* 获取网站tdk详情
*/
public function getTdkInfo(Request $request): array
{
$params = $request->param();
$this->validate($params, ['tdk_type' => 'require','locale' => 'require']);
$con = Tool::getOptionalQuery(
['tdk_type', '='],
['c.i18n_lang_type_code', '=' , 'locale'] //i18n
);
$find = ModelTdk::field([
'c.i18n_lang_type_code',
'a.i18n_lang_type_guid',
'a.tdk_id',
'a.tdk_type',
'a.tdk_title',
'a.tdk_description',
'a.tdk_keyword'
])
->where($con)
->alias('a')
->leftjoin('i18n_lang_type c', 'a.i18n_lang_type_guid = c.i18n_lang_type_guid') //i18n
->find();
return msg(0, '获取网站tdk详情成功!', ['data' => $find]);
}
}

View File

@ -0,0 +1,54 @@
<?php
namespace app\api\controller\Wechat;
use think\Request;
use app\BaseController;
use app\common\wechat\OfficialAccount;
use think\facade\Db;
class Wechat extends BaseController
{
public function getAccess(Request $request)
{
cookie('wechat_refer_url', $request->param('refer_url'), 5 * 60);
$redirectUrl = OfficialAccount::getInstance()
->getOAuth()
->scopes(['snsapi_userinfo'])
->redirect(config('wechat.redirect_url'));
return redirect($redirectUrl);
}
public function callback(Request $request)
{
$params = $request->param();
$user = OfficialAccount::getInstance()
->getOAuth()
->userFromCode($params['code']);
$targetUrl = empty(cookie('wechat_refer_url')) ? '/' : cookie('wechat_refer_url');
$ip = request()->ip();
$forwarded = request()->header("x-forwarded-for");
if ($forwarded) {
$ip = explode(',', $forwarded)[0];
}
$userInfo = [
'wechat_history_openid' => $user->getId(),
'wechat_history_ip' => $ip,
'wechat_history_useragent' => $request->header('user-agent'),
'wechat_history_nickname' => $user->getNickname(),
'wechat_history_avatar' => $user->getAvatar(),
'wechat_history_refer' => $targetUrl,
'create_time' => date('Y-m-d H:i:s'),
];
Db::name('wechat_history')->insert($userInfo);
return redirect($targetUrl);
}
}

View File

@ -0,0 +1,85 @@
<?php
declare(strict_types=1);
namespace app\api\middleware;
use app\common\exception\NotAuthApi;
use app\common\model\Token;
use app\common\traits\Auth as TraitsAuth;
use app\Request;
use think\Response;
class Auth
{
use TraitsAuth;
/**
* 忽略登录
*
* @var array
* @date 2023-01-07
* @example
* @author admin
* @since 1.0.0
*/
private $ignoreLogin = [
'Login' => ['*'],
'admin' => ['*'],
'Consult' => ['*'],
];
/**
* 处理请求
*
* @param \app\Request $request
* @param \Closure $next
* @return Response
*/
public function handle(Request $request, \Closure $next): Response
{
$this->request = $request;
if ($this->isIgnoreLogin()) {
return $next($request);
}
if ($request->isLogin()) {
$user = $request->getCurrentUser();
if ($user->user_admin) {
return $next($request);
}
}
$api = join('/', [
$request->controller(),
$request->action()
]);
$token = Token::getCurrent();
/**
* 缓存接口权限验证
*/
$validate = $this->validateApi($token->token_api);
/**
* 缓存权限验证不通过
*/
if ($validate === false) {
/**
* 自定义验证权限
* 如果验证通过刷新缓存接口
*/
$validate = $this->validateUser();
if ($validate) {
Token::getCurrentUser()->login();
}
}
/**
* 权限验证通过
*/
if ($validate) {
return $next($request);
}
throw new NotAuthApi("未授权接口 [ $api ]", 1);
}
}

12
app/api/route/route.php Normal file
View File

@ -0,0 +1,12 @@
<?php
// +----------------------------------------------------------------------
// | 路由设置
// +----------------------------------------------------------------------
return [
// 中间件
'middleware' => [
// 接口鉴权
// \app\api\middleware\Auth::class
],
];

178
app/common.php Normal file
View File

@ -0,0 +1,178 @@
<?php
// 应用公共文件
use app\common\arw\adjfut\src\Exception\ErrorMsg;
use app\BaseController;
use think\facade\Request;
use think\facade\Validate;
use think\Collection;
use think\db\Query;
use think\Validate as ThinkValidate;
const DS = DIRECTORY_SEPARATOR;
function fump($var, $echo = true, $label = null, $flags = ENT_SUBSTITUTE)
{
$label = (null === $label) ? '' : rtrim($label) . ':';
ob_start();
var_dump($var);
$output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', ob_get_clean());
if (!extension_loaded('xdebug')) {
$output = htmlspecialchars($output, $flags);
}
$output = '<pre>' . $label . $output . '</pre>';
if ($echo) {
echo ($output);
return;
}
return $output;
}
/**
* 抛出业务异常
*
* @param string $msg
* @param integer $code
* @return void
* @throws ErrorMsg
* @date 2022-12-27
* @example
* @author admin
* @since 1.0.0
*/
function throwErrorMsg(string $msg, int $code = 1): void
{
throw new ErrorMsg($msg, $code);
}
/**
* 计算年龄
*
* @param string $birthday Y-m-d
* @return int
* @date 2022-03-11
* @example
* @author admin
* @since 1.0.0
*/
function sumAge($birthday): int
{
$age = 0;
try {
if (!is_string($birthday)) {
throw new ErrorMsg("非法日期", 1);
}
$birthday = explode("-", date('Y-m-d', strtotime($birthday)));
$date = explode("-", date('Y-m-d'));
if (count($birthday) === 3) {
list($y, $m, $d) = $birthday;
} else {
list($y, $m, $d) = $date;
}
// list($y, $m, $d) = $birthday;
list($dy, $dm, $dd) = $date;
$age = $dy - $y;
if ($dm >= $m) {
if ($dm == $m) {
if ($dd >= $d) {
} else {
$age--;
}
}
} else {
$age--;
}
return $age;
} catch (\Throwable $th) {
}
return $age;
}
Validate::maker(function (ThinkValidate $validate) {
$validate->extend(
'string',
function ($value) {
return is_string($value);
},
':attribute 数据类型非法 不是字符串'
);
});
/**
* 接口返回封装
*/
function msg(...$arr)
{
$msg_data = ['code' => 0];
$default_code_msg = [0 => '操作成功!', 1 => '操作失败!'];
//data数据构建
function constructData(&$msg_data, $code, $msg_str, &$arr2)
{
$msg_data['code'] = $code;
$msg_data['msg'] = $msg_str;
if (is_array($arr2)) { //数组
$msg_data['data'] = $arr2;
}
if (is_object($arr2)) { //查询对象
$obj = $arr2;
$soft_delete_field = '_delete_time'; //软删除默认后缀
//模型层 || Db层
if ($obj instanceof think\db\Query || $obj instanceof think\Collection) {
//join软删除字段过滤补全(暂时只适应软删除为 【前缀名_delete_time】存储为datetime 的设计)
if (isset($obj->getOptions()['join']) && $join_data = $obj->getOptions('join')) {
$join_soft_delete = [];
foreach ($join_data as $key => $join) {
$join_table_name = is_array($join[0]) ? array_keys($join[0])[0] : $join[0]; //联表表名
$join_soft_delete[] = [$join_table_name . $soft_delete_field, 'NULL', null];
}
$obj = $obj->where($join_soft_delete);
}
//select()、count()补全
$msg_data['data'] = $obj->page((int) Request::param('page', 1), (int) Request::param('limit', 10))->select();
$msg_data['count'] = $obj->count();
} else {
return ['code' => 444, 'msg' => '对象只允许传递来自think\db\Query类和instanceof think\Collection类的实例!'];
}
}
};
switch (count($arr)) {
case 1: //单参数
constructData($msg_data, 0, '查询成功!', $arr[0],);
if (is_string($arr[0])) $msg_data['msg'] = $arr[0];
if (is_int($arr[0])) {
$msg_data['code'] = $arr[0];
$msg_data['msg'] = $default_code_msg[$arr[0]];
}
break;
case 2: //双参数
if (is_int($arr[0]) && is_string($arr[1])) {
$msg_data['code'] = $arr[0];
$msg_data['msg'] = $arr[1];
} else {
constructData($msg_data, 0, $arr[0], $arr[1]);
}
break;
case 3: //三参数
$msg_data['code'] = $arr[0];
$msg_data['msg'] = $arr[1];
if (is_object($arr[2])) {
$msg_data['data'] = $arr[2];
} else {
foreach ($arr[2] as $key => $val)
$msg_data[$key] = $val;
}
break;
default:
return ['code' => 444, 'msg' => 'msg()最多参数只允许3个!'];
}
return $msg_data;
}

View File

@ -0,0 +1,39 @@
{
"name": "arw/adjfut",
"type": "library",
"autoload": {
"psr-4": {
"arw\\adjfut\\": "src/"
}
},
"authors": [{
"name": "arw",
"email": "2679599887@qq.com"
}],
"require": {
"php": ">=7.1.0",
"phpoffice/phpspreadsheet": "^1.12",
"topthink/framework": "^6.0.0",
"topthink/think-filesystem": "^2.0"
},
"config": {
"sort-packages": true
},
"repositories": {
"packagist": {
"type": "composer",
"url": "https://mirrors.aliyun.com/composer/"
}
},
"extra": {
"think": {
"services": [
"arw\\adjfut\\Service\\Validate"
],
"config": {
"wechat": "src/Config/wechat.php",
"chunkUpload": "src/Config/chunkUpload.php"
}
}
}
}

View File

@ -0,0 +1,170 @@
<?php
namespace app\common\arw\adjfut\src;
use ArrayAccess;
class ArrayFilter implements ArrayAccess
{
/**
* 数据
*
* @var array
* @date 2023-01-13
* @example
* @author arw
* @since 1.0.0
*/
private $data = [];
/**
* 初始化
*
* @param array $data
* @date 2023-01-13
* @example
* @author arw
* @since 1.0.0
*/
public function __construct(array $data)
{
$this->data = $data;
}
/**
* 二维数组排除字段
*
* @param array $array
* @param array $except
* @return array
* @date 2023-01-13
* @example
* @author arw
* @since 1.0.0
*/
public static function exceptFields(array $array, array $except): array
{
foreach ($array as &$value) {
$self = new self($value);
$value = $self->except($except)->toArray();
unset($value, $self);
}
return $array;
}
/**
* 二维数组指定字段
*
* @param array $array
* @param array $only
* @return array
* @date 2023-01-13
* @example
* @author arw
* @since 1.0.0
*/
public static function onlyFields(array $array, array $only): array
{
foreach ($array as &$value) {
$self = new self($value);
$value = $self->only($only)->toArray();
unset($value, $self);
}
return $array;
}
/**
* 排除某些变量
*
* @param array $fields
* @return self
* @date 2023-01-13
* @example
* @author arw
* @since 1.0.0
*/
public function except(array $fields): self
{
$data = $this->data;
// $fields = [id,name]
foreach ($fields as $field) {
if (isset($data[$field])) {
unset($data[$field]);
}
}
return new self($data);
}
/**
* 获取部分变量
*
* @param array $fields
* @return self
* @date 2023-01-13
* @example
* @author arw
* @since 1.0.0
*/
public function only(array $fields): self
{
$data = $this->data;
$result = [];
// $fields = [id,name]
// $fields = [id=>0,name=>asdasd]
foreach ($fields as $key => $value) {
if (is_int($key)) {
if (isset($data[$value])) {
$result[$value] = $data[$value];
}
} else {
$result[$key] = isset($data[$key]) ? $data[$key] : $value;
}
}
return new self($result);
}
/**
* 获取数据
*
* @return array
* @date 2023-01-13
* @example
* @author arw
* @since 1.0.0
*/
public function toArray(): array
{
return $this->data;
}
public function __get($name)
{
return $this->offsetGet($name);
}
public function __set($name, $value)
{
return $this->offsetSet($name, $value);
}
public function offsetExists($offset): bool
{
return isset($this->data[$offset]);
}
public function offsetGet($offset)
{
return $this->data[$offset];
}
public function offsetSet($offset, $value): void
{
$this->data[$offset] = $value;
}
public function offsetUnset($offset): void
{
unset($this->data[$offset]);
}
}

View File

@ -0,0 +1,174 @@
<?php
namespace app\common\arw\adjfut\src;
use think\helper\Arr;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
class Base64
{
/**
* 类型
*
* @var string
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
private $type = '';
/**
* base64内容
*
* @var string
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
private $body = '';
/**
* base64
*
* @var string
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
private $base64 = '';
/**
* 文件后缀映射
*/
private const FILE_EXT_MAP = [
'text/html' => 'html',
'text/css' => 'css',
'text/javascript' => 'js',
'image/gif' => 'gif',
'image/png' => 'png',
'image/jpeg' => 'jpg',
'image/x-icon' => 'ico',
];
/**
* 实例化
*
* @param string $base64
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
public function __construct(string $base64)
{
$parse = self::parse($base64);
$this->base64 = $base64;
$this->type = $parse['type'];
$this->body = $parse['body'];
}
/**
* 获取文件后缀
*
* @return string
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
public function getFileExt(): string
{
return Arr::get(self::FILE_EXT_MAP, $this->type, '');
}
/**
* 判断是否是base64图片字符串
*
* @return boolean
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
public function isImage(): bool
{
return in_array($this->type, [
'image/gif',
'image/png',
'image/jpeg',
'image/x-icon',
]);
}
/**
* 保存base64图片
*
* @param string $path
* @return void
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
public function saveImage(string $path): void
{
file_put_contents($path, base64_decode($this->body));
}
/**
* 判断是否是base64图片字符串
*
* @param string $base64
* @return boolean
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
public static function isBase64Image(string $base64): bool
{
$ins = new self($base64);
return $ins->isImage();
}
/**
* 保存base64图片
*
* @param string $base64
* @param string $path
* @return void
*/
public static function saveBase64Image(string $base64, string $path): void
{
$ins = new self($base64);
$ins->saveImage($path);
}
/**
* 解析base64
*
* @param string $base64
* @return array
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
private static function parse(string $base64): array
{
$prefix = 'data:';
$validate = substr($base64, 0, strlen($prefix)) === $prefix;
if (!$validate) {
throw new ErrorMsg("非法base64 开头data:", 1);
}
$explode = explode(';base64,', $base64);
if (count($explode) != 2) {
throw new ErrorMsg("非法base64 不存在;base64,", 1);
}
list($type, $body) = $explode;
$type = str_replace('data:', '', $type);
return [
'type' => $type,
'body' => $body
];
}
}

View File

@ -0,0 +1,258 @@
<?php
namespace app\common\arw\adjfut\src;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
use think\facade\Filesystem;
use think\facade\Request;
use think\file\UploadedFile;
use think\filesystem\Driver;
use think\helper\Arr;
class ChunkUpload
{
/**
* 磁盘
*
* @var string
*/
private static $disk = null;
/**
* id
*
* @var string
*/
private $id = null;
/**
* 上传文件
*
* @var UploadedFile
*/
private $file = null;
/**
* 合并文件
*
* @var UploadedFile
*/
private $mergeFile = null;
/**
* 初始化
*
* @param string $id 上传id
* @param string $name 上传id
* @param UploadedFile|string|array $file 文件
* @date 2022-08-21
* @example
* @author arw
* @since 1.0.0
*/
public function __construct(string $id, $file = 'file')
{
$this->id = $id;
if (is_string($file)) {
$file = Request::file($file);
}
if (is_array($file)) {
$file = new UploadedFile(...$file);
}
if (!($file instanceof UploadedFile)) {
throw new ErrorMsg("非法文件", 1);
}
$this->file = $file;
}
/**
* 获取存储配置
*
* @return Driver
* @date 2022-08-21
* @example
* @author arw
* @since 1.0.0
*/
public function getDisk(): Driver
{
return Filesystem::disk(self::$disk);
}
/**
* 分片是否上传完成
*
* @return boolean
* @date 2022-08-22
* @example
* @author arw
* @since 1.0.0
*/
public function isDone(): bool
{
return $this->isDone;
}
/**
* 合并文件
*
* @return self
* @date 2022-08-21
* @example
* @author arw
* @since 1.0.0
*/
public function merge(string $name): self
{
if (!$this->isDone()) {
throw new ErrorMsg("文件未上传完成 禁止合并", 1);
}
$id = $this->id;
$root = self::getDiskConfig('root');
$path = join('', [
$root,
$id,
'.' . pathinfo($name, PATHINFO_EXTENSION)
]);
for ($i = 0; $i <= $this->total; $i++) {
$_path = $root . $id . DIRECTORY_SEPARATOR . $i;
file_put_contents(
$path,
file_get_contents($_path),
FILE_APPEND
);
unlink($_path);
}
rmdir($root . $id);
$this->mergeFile = new UploadedFile($path, $name);
return $this;
}
/**
* 获取合并文件
*
* @return UploadedFile
* @date 2022-08-22
* @example
* @author arw
* @since 1.0.0
*/
public function getMergeFile(): UploadedFile
{
if (!$this->mergeFile) {
throw new ErrorMsg("未合并文件", 1);
}
return $this->mergeFile;
}
/**
* 获取上传文件
*
* @param string $diskName
* @param string $validate
* @return UploadFile
* @date 2022-08-22
* @example
* @author arw
* @since 1.0.0
*/
public function getUploadFile(string $diskName, string $validate = ''): UploadFile
{
return new UploadFile(
$diskName,
$validate,
$this->getMergeFile()
);
}
/**
* 保存文件
*
* @param integer $index
* @param integer $total
* @return self
* @date 2022-08-21
* @example
* @author arw
* @since 1.0.0
*/
public function put(int $index, int $total): self
{
$this->total = $total;
$this->getDisk()->putFileAs(
$this->id,
$this->file,
$index
);
$this->isDone = $index === $total;
return $this;
}
/**
* 删除文件
*
* @return void
* @date 2022-08-22
* @example
* @author arw
* @since 1.0.0
*/
public function delete(): void
{
$this->getDisk()->delete($this->getMergeFile()->getFilename());
}
/**
* 初始化配置
*
* @param array $config
* @return void
* @date 2022-08-21
* @example
* @author arw
* @since 1.0.0
*/
public static function init(array $config): void
{
self::$disk = Arr::get($config, 'disk', '');
$type = self::getDiskConfig('type');
if ($type != 'local') {
throw new ErrorMsg("分片上传仅支持 local类型磁盘", 1);
}
}
/**
* 获取磁盘配置
*
* @param string $name
* @param mixed $default
* @return mixed
* @date 2022-08-22
* @example
* @author arw
* @since 1.0.0
*/
public static function getDiskConfig($name = null, $default = null)
{
return Filesystem::getDiskConfig(self::$disk, $name, $default);
}
/**
* 生成上传唯一id
*
* @return string
* @date 2022-08-21
* @example
* @author arw
* @since 1.0.0
*/
public static function generateUploadId(): string
{
return md5(join('-', [
Request::ip(),
time()
]));
}
}

View File

@ -0,0 +1,9 @@
<?php
// +----------------------------------------------------------------------
// | ChunkUpload配置文件
// +----------------------------------------------------------------------
return [
// 磁盘
'disk' => ''
];

View File

@ -0,0 +1,39 @@
<?php
// +----------------------------------------------------------------------
// | Wechat配置文件
// +----------------------------------------------------------------------
return [
// 中控层 access_key
'access_key' => '',
// 中控层地址
'server_base' => 'http://clique.dszjjt.com:7001/',
// 公众号配置
'gzh' => [
// 缓存key
'cache_key' => 'wechat.gzh',
// 日志通道
'log_channel' => 'wechat/gzh',
// 公众号模板推送
'template' => [
// {{first.DATA}}
// 申请人:{{keyword1.DATA}}
// 申请时间:{{keyword2.DATA}}
// 调课时间:{{keyword3.DATA}}
// {{remark.DATA}}
'申请审核通知' => 'iLuqzUrQM8-v_7ilxageUZoi9v-SQWipkTYVZXB1GeI'
],
'appid' => 'wx99caf571c9fb1cc5',
'secret' => '61100d9c4fff5acf97517f0c8799e2e2',
],
// 小程序配置
'xcx' => [
// 缓存key
'cache_key' => 'wechat.xcx',
// 日志通道
'log_channel' => 'wechat/xcx',
'appid' => 'wx2495492e15854b02',
'secret' => '5b4fcb27324398083fba4a3c39e8a557',
],
];

View File

@ -0,0 +1,790 @@
<?php
namespace app\common\arw\adjfut\src;
use \CurlHandle;
use think\Exception;
class Curl
{
/**
* 请求前缀
*
* @var string
*/
private $baseUrl = '';
/**
* 返回数据类型
*
* @var string
*/
private $dataType = 'json';
/**
* 事件
*
* @var array
*/
private $event = [];
/**
* 绑定
*
* @var array
*/
private $bind = [];
/**
* 配置项
*
* @var array
*/
private $config = [
/**
* http header
*/
CURLOPT_HTTPHEADER => [],
/**
* http 超时
*/
CURLOPT_TIMEOUT => 0,
/**
* http 代理
*/
CURLOPT_PROXY => '',
/**
* http 代理端口
*/
CURLOPT_PROXYPORT => '',
/**
* 来源页面
*/
CURLOPT_REFERER => '',
/**
* 用户代理
*/
CURLOPT_USERAGENT => '',
/**
* 响应中是否显示header
*/
CURLOPT_HEADER => 0
];
/**
* Get请求参数
*
* @var null
*/
private $httpParams = null;
/**
* Post请求参数
*
* @var null
*/
private $httpData = null;
/**
* 异常信息
*
* @var string
*/
private $error = '';
/**
* url是否编码
*
* @var boolean
*/
private $urlEncode = false;
/**
* 验证http请求状态码
*
* @var boolean
*/
private $httpCode = true;
/**
* 请求路径
*
* @var string
*/
private $path = '';
/**
* 请求url
*
* @var string
*/
private $url = '';
/**
* 请求类型
*
* @var string
*/
private $method = 'get';
/**
* 返回内容
*
* @var string
*/
private $content = '';
/**
* 请求信息
*
* @var array
*/
private $status = [];
/**
* 调试模式
*
* @var boolean
*/
private $debug = false;
/**
* 是否上传文件
*
* @var boolean
*/
private $isUploadFile = false;
/**
* 初始化
*
* @date 2022-03-24
* @example
* @author arw
* @since 1.0.0
*/
public function __construct()
{
}
/**
* 初始化请求
*
* @return $this
*/
public static function instance()
{
return new self;
}
/**
* 获取请求url
*/
public function getUrl(): string
{
return $this->url;
}
/**
* 获取请求路径
*/
public function getPath(): string
{
return $this->path;
}
/**
* 获取返回内容
*
* @return string
*/
public function getContent(): string
{
return $this->content;
}
/**
* 格式化返回
*
* @param string $type 返回类型(默认使用 $this->dataType
* @return mixed
* @date 2022-03-24
* @example
* @author arw
* @since 1.0.0
*/
public function formatContent(string $type = '')
{
$content = $this->content;
if (!$type) {
$type = $this->dataType;
}
switch ($type) {
case 'json':
case 'object':
return json_decode($content, $type === 'json');
break;
default:
return $content;
break;
}
}
/**
* 获取请求信息
*/
public function getStatus(): array
{
return $this->status;
}
/**
* 设置是否上传文件
*/
public function setIsUploadFile(bool $isUploadFile): self
{
$this->isUploadFile = $isUploadFile;
return $this;
}
/**
* 设置请求路径
*/
public function setPath(string $path): self
{
if (count(explode('?', $path)) != 1) {
throw new Exception("请求路径不能携带参数 请使用setParams设置请求参数", 1);
}
$this->path = $path;
return $this;
}
/**
* 设置调试模式
*/
public function setDeBug(bool $debug): self
{
$this->debug = $debug;
return $this;
}
/**
* 验证http状态码
*
* @param boolean|int $code
*/
public function setHttpCode($code): self
{
$this->httpCode = $code;
return $this;
}
/**
* 设置url是否编码
*/
public function setUrlEncode(bool $urlEncode): self
{
$this->urlEncode = $urlEncode;
return $this;
}
/**
* 设置请求前缀
*/
public function setBaseUrl(string $baseUrl): self
{
if (count(explode('?', $baseUrl)) != 1) {
throw new Exception("请求前缀不能携带参数 请使用setParams设置请求参数", 1);
}
$this->baseUrl = $baseUrl;
return $this;
}
/**
* 设置返回数据类型
*/
public function setDataType(string $dataType): self
{
$this->dataType = $dataType;
return $this;
}
/**
* 设置http header
*/
public function setHeader(array $header): self
{
$_header = [];
foreach ($header as $key => $value) {
if (is_numeric($key)) {
$_header[] = $value;
} else {
$_header[] = "$key: $value";
}
}
$this->config[CURLOPT_HTTPHEADER] = array_merge($this->config[CURLOPT_HTTPHEADER], $_header);
return $this;
}
/**
* 设置http 超时
*/
public function setTimeout(int $time): self
{
$this->config[CURLOPT_TIMEOUT] = $time <= 0 ? 5 : $time;
return $this;
}
/**
* 设置http 代理
*/
public function setProxy(string $proxy): self
{
$this->config[CURLOPT_PROXY] = $proxy;
return $this;
}
/**
* 设置http 代理端口
*/
public function setProxyPort(int $port): self
{
$this->config[CURLOPT_PROXYPORT] = $port;
return $this;
}
/**
* 设置来源页面
*/
public function setReferer(string $referer = ""): self
{
$this->config[CURLOPT_REFERER] = $referer;
return $this;
}
/**
* 设置用户代理
*/
public function setUserAgent(string $agent = ""): self
{
$this->config[CURLOPT_USERAGENT] = $agent;
return $this;
}
/**
* http响应中是否显示header
*/
public function showResponseHeader(bool $show): self
{
$this->config[CURLOPT_HEADER] = $show ? 1 : 0;
return $this;
}
/**
* 获取get请求参数
*/
public function getParams()
{
return $this->httpParams;
}
/**
* 设置get请求的参数
*/
public function setParams($params): self
{
$_params = $this->trigger('beforeSetParams', [$params]);
$this->httpParams = $_params ? $_params : $params;
return $this;
}
/**
* 获取post请求参数
*/
public function getData()
{
return $this->httpData;
}
/**
* 设置post请求的参数
*/
public function setData($data): self
{
$_data = $this->trigger('beforeSetData', [$data]);
$this->httpData = $_data ? $_data : $data;
return $this;
}
/**
* 设置http请求的cookie信息
*/
public function setCookie(array $cookie): self
{
$_cookie = [];
foreach ($cookie as $key => $value) {
$_cookie[] = "$key=$value";
}
$this->config[CURLOPT_COOKIE] = join(';', $_cookie);
return $this;
}
/**
* 设置证书路径
*/
public function setCainfo(string $file): self
{
$this->config[CURLOPT_CAINFO] = $file;
return $this;
}
/**
* 获取请求异常
*/
public function getError(): string
{
return $this->error;
}
/**
* 绑定
*
* @param string $name
* @param callable $cb
* @date 2022-03-26
* @example
* @author arw
* @since 1.0.0
*/
public function bind(string $name, callable $cb): self
{
$this->bind[$name] = $cb;
return $this;
}
/**
* GET请求
* @param string $path
* @return mixed
*/
public function get(string $path = '')
{
if ($path) {
$this->setPath($path);
}
$this->method = 'get';
$respone = $this->fetch();
if (!$path) {
return $this;
}
return $respone;
}
/**
* POST请求
*
* @param string $path
* @return mixed
*/
public function post(string $path = '')
{
if ($path) {
$this->setPath($path);
}
$this->method = 'post';
$respone = $this->fetch();
if (!$path) {
return $this;
}
return $respone;
}
/**
* PUT请求
*
* @param string $path
* @return mixed
*/
public function put(string $path = '')
{
if ($path) {
$this->setPath($path);
}
$this->method = 'put';
$respone = $this->fetch();
if (!$path) {
return $this;
}
return $respone;
}
/**
* DELETE请求
*
* @param string $path
* @return mixed
*/
public function delete(string $path = '')
{
if ($path) {
$this->setPath($path);
}
$this->method = 'delete';
$respone = $this->fetch();
if (!$path) {
return $this;
}
return $respone;
}
/**
* PATCH请求
*
* @param string $path
* @return mixed
*/
public function patch(string $path = '')
{
if ($path) {
$this->setPath($path);
}
$this->method = 'patch';
$respone = $this->fetch();
if (!$path) {
return $this;
}
return $respone;
}
/**
* 设置get传参前
*
* @param callable $cb($params)
* @param mixed $params 参数
* @date 2022-03-26
* @example
* @author arw
* @since 1.0.0
*/
public function onBeforeSetParams(callable $cb): self
{
return $this->event('beforeSetParams', $cb);
}
/**
* 设置post传参前
*
* @param callable $cb($data)
* @param mixed $data 参数
* @date 2022-03-26
* @example
* @author arw
* @since 1.0.0
*/
public function onBeforeSetData(callable $cb): self
{
return $this->event('beforeSetData', $cb);
}
/**
* 请求前
*
* @param callable $cb($ch)
* @param self $ch
* @date 2022-03-26
* @example
* @author arw
* @since 1.0.0
*/
public function onBeforeFetch(callable $cb): self
{
return $this->event('beforeFetch', $cb);
}
/**
* 请求后
*
* @param callable $cb($ch,$info)
* @param self $ch
* @param array $info
* @param string $info[url] 请求完整url
* @param string $info[content] 返回信息
* @param array $info[status] 请求信息
* @date 2022-03-26
* @example
* @author arw
* @since 1.0.0
*/
public function onAfterFetch(callable $cb)
{
return $this->event('afterFetch', $cb);
}
/**
* 请求异常(返回true阻止抛出异常)
*
* @param callable $cb($ch,$th)
* @param self $ch
* @param \Throwable $th
* @date 2022-03-26
* @example
* @author arw
* @since 1.0.0
*/
public function onFetchError(callable $cb)
{
return $this->event('fetchError', $cb);
}
/**
* 发起请求
*
* @return mixed
* @date 2022-03-25
* @example
* @author arw
* @since 1.0.0
*/
public function fetch()
{
$this->url = $url = $this->baseUrl . $this->path;
$this->trigger('beforeFetch', [$this]);
try {
$httpParams = $this->httpParams;
if (!empty($httpParams) && is_array($httpParams)) {
$url .= (strpos($url, '?') === false ? '?' : '') . http_build_query($httpParams);
}
if ($this->urlEncode === false) {
$url = urldecode($url);
}
$ch = $this->curlInit($url);
// 设为TRUE把curl_exec()结果转化为字串,而不是直接输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$this->content = $content = curl_exec($ch);
$this->status = $status = curl_getinfo($ch);
if ($content === false) {
$this->error = curl_error($ch);
}
if ($this->debug) {
dump([
'ch' => $ch,
'url' => $url,
'httpParams' => $this->httpParams,
'httpData' => $this->httpData,
'contentArray' => json_decode($content, true),
'content' => $content,
'status' => $status
]);
}
curl_close($ch);
$httpCode = $this->httpCode;
if ($httpCode === true) {
$httpCode = 200;
}
if (is_numeric($httpCode)) {
if (!isset($status['http_code'])) {
throw new Exception("服务器未返回状态码", 1);
}
if ($status['http_code'] !== $httpCode) {
throw new Exception(sprintf("服务器返回状态码异常[ %s ]", $status['http_code']), 1);
}
}
$this->trigger('afterFetch', [$this, [
'url' => $url,
'content' => $content,
'status' => $status
]]);
return $this->formatContent();
} catch (\Throwable $th) {
if (!$this->trigger('fetchError', [$this, $th])) {
throw $th;
}
}
}
public function __call($name, $arguments)
{
array_unshift($arguments, $this);
call_user_func_array($this->bind[$name], $arguments);
}
/**
* 事件
*
* @param string $type beforeSetParams | beforeSetData | beforeFetch | AfterFetch
* @param callable $cb
*/
private function event(string $type, callable $cb): self
{
$this->event[strtoupper($type)] = $cb;
return $this;
}
/**
* 事件触发器
*
* @param string $type
* @return mixed
* @date 2022-03-25
* @example
* @author arw
* @since 1.0.0
*/
private function trigger(string $type, array $args = [])
{
$type = strtoupper($type);
if (isset($this->event[$type])) {
return call_user_func_array($this->event[$type], $args);
}
}
/**
* 初始化请求
*
* @param string $url
* @return resource|CurlHandle
* @date 2022-04-24
* @example
* @author arw
* @since 1.0.0
*/
private function curlInit(string $url)
{
$ch = curl_init($url);
if (stripos($url, 'https://') !== false) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSLVERSION, 1);
}
foreach ($this->config as $option => $value) {
if (!$value && $option != CURLOPT_HEADER) {
continue;
}
curl_setopt($ch, $option, $value);
}
switch ($this->method) {
case 'get':
break;
case 'post':
curl_setopt($ch, CURLOPT_POST, true);
break;
default:
// delete put patch
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($this->method));
break;
}
$httpData = $this->httpData;
// 设置post body
if ($httpData) {
$data = null;
if (is_array($httpData)) {
if ($this->isUploadFile) {
$data = $httpData;
} else {
$data = http_build_query($httpData);
}
} else if (is_string($httpData)) {
$data = $httpData;
}
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
return $ch;
}
}

View File

@ -0,0 +1,519 @@
<?php
namespace app\common\arw\adjfut\src;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use think\helper\Arr;
use think\helper\Str;
use think\Validate;
use app\common\arw\adjfut\src\Traits\Event;
use think\facade\Env;
class Excel
{
use Event;
/**
* Spreadsheet
*
* @var Spreadsheet
*/
private $spreadsheet = null;
/**
* 工作表样式
*
* @var array
*/
private $worksheetStyle = [];
/**
* 文件路径
*
* @var string
* @date 2022-04-15
* @example
* @author arw
* @since 1.0.0
*/
private $path = '';
/**
* 初始化
*
* @param string|UploadFile $path
* @date 2022-04-15
* @example
* @author arw
* @since 1.0.0
*/
public function __construct($path = '')
{
if ($path) {
if ($path instanceof UploadFile) {
$path = $path->getRealPath();
}
$this->spreadsheet = self::loadExcel($path);
$this->path = $path;
} else {
$this->spreadsheet = new Spreadsheet();
}
}
/**
* 设置工作表样式
*
* @param array $options
* @param boolean $options[autoBorder] 是否自动添加边框
* @param boolean $options[freezeLine] 是否自动冻结首行
* @return self
*/
public function setWorksheetStyle(array $options): self
{
$this->worksheetStyle = $options;
return $this;
}
/**
* 获取当前Spreadsheet
*
* @return Spreadsheet
* @date 2020-11-23
* @example
* @author arw
* @since 1.0.0
*/
public function getSpreadsheet(): Spreadsheet
{
return $this->spreadsheet;
}
/**
* 读取excel
*
* @param string $path excel路径
* @return Spreadsheet
*/
public static function loadExcel(string $path): Spreadsheet
{
if (!is_file($path)) {
throw new ErrorMsg("文件不存在 $path", 1);
}
$ext = pathinfo($path, PATHINFO_EXTENSION);
return IOFactory::createReader(ucfirst($ext))->load($path);
}
/**
* 获取工作表
* 默认获取当前激活的
*
* @param string $sheet
* @return Worksheet
*/
public function getWorksheet(string $sheet = 'active'): Worksheet
{
$Spreadsheet = $this->getSpreadsheet();
if ($sheet === 'active') {
$Worksheet = $Spreadsheet->getActiveSheet();
} else {
$Worksheet = $Spreadsheet->getSheet($sheet);
}
return $Worksheet;
}
/**
* 获取excel数据
*
* @param string $sheet
* @return array
*/
public function getExcelData(string $sheet = 'active'): array
{
return $this->getWorksheet($sheet)->toArray();
}
/**
* 解析excel
*
* @param array $rules
* @param string $rules[][title] 表头
* @param string $rules[][validate] 验证器
* @param string $rules[][field] 字段名
* @param string $rules[][type] 数据类型 date:日期格式(Y-m-d H:i:s)
* @param array $options
* @param array $options[titleLine] 表头行
* @param boolean $options[autoRemove] 解析后移除文件
* @param boolean $options[ignoreNullRow] 忽略空行
* @return array
* @date 2022-04-11
* @example
* @author arw
* @since 1.0.0
*/
public function parseExcel(array $rules, array $options = []): array
{
$titleLine = Arr::get($options, 'titleLine', [1]);
$autoRemove = Arr::get($options, 'autoRemove', true);
$ignoreNullRow = Arr::get($options, 'ignoreNullRow', true);
if ($autoRemove) {
if (is_file($this->path)) {
unlink($this->path);
}
}
$title = [];
$_title = [];
$_field = [];
$_type = [];
$_validate = [];
foreach ($rules as $rule) {
$_title[] = $rule['title'];
if (isset($rule['field'])) {
$_field[] = $rule['field'];
if (isset($rule['validate'])) {
$_validate[join('|', [
$rule['field'],
$rule['title']
])] = $rule['validate'];
}
} else {
$_field[] = '';
}
if (isset($rule['type'])) {
$_type[] = $rule['type'];
} else {
$_type[] = '';
}
}
$Worksheet = $this->getWorksheet();
$data = $Worksheet->toArray();
// 获取表头 合并复杂表头
foreach ($titleLine as $line) {
$values = $data[$line - 1];
foreach ($values as $key => $value) {
if ($value) {
$title[$key] = $value;
}
}
}
// 验证表头
if ($title != $_title) {
throw new ErrorMsg("表头不一致 请确认excel是否正确", 1);
}
// 去除非数据字段
$i = max($titleLine) - 1;
do {
unset($data[$i]);
$i--;
} while ($i >= 0);
$validate = new Validate;
$validate->rule($_validate)->batch(true)->failException(true);
$result = [];
$error = [];
foreach ($data as $row => $value) {
$index = $row + 1;
$line = "${index}";
$_value = [];
if ($ignoreNullRow && self::isNullRow($value)) {
continue;
}
foreach ($_field as $column => $field) {
if ($field) {
if ($_type[$column]) {
$type = $_type[$column];
if (Str::startsWith($type, 'date') && $value[$column]) {
$format = 'Y-m-d H:i:s';
$types = explode(':', $type);
if (isset($types[1])) {
$format = $types[1];
}
$value[$column] = Tool::conversionDateTime($value[$column], $format);
}
}
$_value[$field] = $value[$column];
}
}
// 验证数据
if ($_validate) {
try {
$validate->check($_value);
} catch (\Throwable $th) {
$error[] = $line . '' . $th->getMessage();
}
}
$result[$line] = $_value;
}
if ($error) {
throw new ErrorMsg(join(PHP_EOL, $error), 1);
}
return $result;
}
/**
* 导出excel
*
* @param array $data 数据
* @param array $options
* @param boolean $options[autoBorder] 是否自动添加边框
* @param string $options[freezeLine] 是否自动冻结首行
* @date 2022-04-11
* @example
* @author arw
* @since 1.0.0
*/
public static function exportSheet(array $data, array $options = [])
{
$excel = new self;
$excel->setWorksheetStyle($options);
$spreadsheet = $excel->getSpreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->fromArray($data);
return $excel;
}
/**
* 导出处理图片字段
*/
public static function ExportImgFiled($value)
{
if(strpos($value,"http") !== false){
$base_url = "";
}else{
$base_url = Env::get('APP.DEFAULT_IMG_URL');
}
return $base_url . $value;
}
/**
* 导出excel 多sheet
*
* @param array $data 数据
* @param array $options
* @param boolean $options[autoBorder] 是否自动添加边框
* @param string $options[freezeLine] 是否自动冻结首行
* @date 2022-04-11
* @example
* @author arw
* @since 1.0.0
*/
public static function exportMoreSheet(array $data, array $options = [])
{
$excel = new self;
$excel->setWorksheetStyle($options);
$spreadsheet = $excel->getSpreadsheet();
$spreadsheet->removeSheetByIndex(0);
foreach ($data as $key => $value) {
$worksheet = new Worksheet($spreadsheet, $key);
$worksheet->fromArray($value);
$spreadsheet->addSheet($worksheet);
}
$spreadsheet->setActiveSheetIndex(0);
return $excel;
}
/**
* 保存excel
*
* @param string $name 文件名
* @param string $save 保存路径
* @date 2022-04-11
* @example
* @author arw
* @since 1.0.0
*/
public function save(string $name, string $save = 'php://output')
{
$spreadsheet = $this->getSpreadsheet();
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
$_name = $name;
if (!preg_match("/\./", $name)) {
$_name .= '.Xlsx';
}
$worksheets = $spreadsheet->getAllSheets();
foreach ($worksheets as $worksheet) {
$this->_setWorksheetStyle($worksheet);
}
// 保存前
$this->trigger('beforeSave', [$spreadsheet]);
// 浏览器下载
if ($save === 'php://output') {
Tool::obEndClean();
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Cache-Control: max-age=0');
header('Content-Disposition:inline;filename="' . $_name . '"');
$writer->save($save);
} else {
Tool::mkdir($save);
// 保存到本地目录
$writer->save(join(DIRECTORY_SEPARATOR, [
$save, $_name,
]));
}
$spreadsheet->disconnectWorksheets();
unset($spreadsheet);
// 保存后
$this->trigger('AfterSave');
}
/**
* 保存前
*
* @param callable $cb
* @date 2022-04-11
* @example
* @author arw
* @since 1.0.0
*/
public function onBeforeSave(callable $cb): self
{
return $this->event('beforeSave', $cb);
}
/**
* 保存后
*
* @param callable $cb
* @date 2022-04-11
* @example
* @author arw
* @since 1.0.0
*/
public function onAfterSave(callable $cb): self
{
return $this->event('afterSave', $cb);
}
/**
* 判断是否空行
*
* @param array $rows
* @return boolean
* @date 2021-11-27
* @example
* @author arw
* @since 1.0.0
*/
public static function isNullRow(array $rows)
{
$rows = array_unique($rows);
$rows = array_filter($rows, function ($v) {
return !is_null($v);
});
return count($rows) == 0;
}
/**
* 快捷设置excel样式
* 首行冻结 自动添加边框
*
* @param Worksheet $worksheet
* @return Worksheet $worksheet
* @date 2021-01-25
* @author arw
* @since 1.0.0
*/
private function _setWorksheetStyle(Worksheet $worksheet): Worksheet
{
$options = $this->worksheetStyle;
$autoBorder = Arr::get($options, 'autoBorder', true);
$freezeLine = Arr::get($options, 'freezeLine', 'A2');
$autoBackground = Arr::get($options, 'autoBackground', true);
if ($freezeLine) {
$worksheet->freezePane($freezeLine);
}
if ($autoBorder) {
$worksheet->getStyle(join(':', [
'A1',
$worksheet->getHighestDataColumn() . $worksheet->getHighestDataRow()
]))->applyFromArray([
'borders' => [
'allBorders' => [
'borderStyle' => Border::BORDER_THIN, //细边框
],
],
]);
}
if($autoBackground){
$style = join(':', [
'A1',
$worksheet->getHighestDataColumn() . "1"
]);
// 列宽
$worksheet -> getDefaultColumnDimension() -> setWidth(25);
// $worksheet -> getColumnDimension('A') -> setWidth(30); //设置A列宽度为30
//行高
// $worksheet -> getRowDimension(1) -> setRowHeight(25);
$worksheet -> getDefaultRowDimension() -> setRowHeight(25);
//样式设置 - 字体
$worksheet -> getStyle($style) -> getFont()
// -> setBold(true)
->setName('微软雅黑')
-> setSize(13);
//样式设置 - 字体颜色
// $worksheet -> getStyle('A1') -> getFont()
// -> getColor() -> setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED); //设置单元格A1的字体颜色
// $font = $worksheet -> getCell('B1') -> getColor() -> setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED);
// if(substr($font,0,1) == "*"){
// }
// $worksheet -> setCellValue('A2', substr($font,0,1) );
//样式设置 - 水平、垂直居中
$styleArray = [
'alignment' => [
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER
],
];
$worksheet -> getStyle($style) -> applyFromArray($styleArray);
//样式设置 - 单元格背景颜色
$worksheet->getStyle($style)->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('FFFFFF00');
}
return $worksheet;
}
/**
* 数字转字母
* 1 => A
*
* @param integer $index
* @return string
* @date 2021-01-23
* @author arw
* @since 1.0.0
*/
public static function stringToIndex(int $index)
{
return Coordinate::stringFromColumnIndex($index);
}
/**
* 字母转数字
* A => 1
*
* @param string $string
* @return int
* @date 2021-01-23
* @author arw
* @since 1.0.0
*/
public static function indexToString(string $string)
{
return Coordinate::columnIndexFromString($string);
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace app\common\arw\adjfut\src\Exception;
/**
* 业务异常
*/
class ErrorMsg extends \Exception
{
}

View File

@ -0,0 +1,258 @@
<?php
namespace app\common\app\common\arw\adjfut\src\Model;
use think\model\Collection;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
/**
* 中间表关联
*
* @date 2022-12-29
* @example
* @author arw
* @since 1.0.0
*/
class Pivot
{
/**
* 中间表
*
* @var string
*/
private $pivotClass = '';
/**
* 主表
*
* @var string
*/
private $masterClass = '';
/**
* 子表
*
* @var string
*/
private $subClass = '';
/**
* 中间表主键
*
* @var string
*/
private $pivotPk = '';
/**
* 主表主键
*
* @var string
*/
private $masterPk = '';
/**
* 子表主键
*
* @var string
*/
private $subPk = '';
/**
* 是否软删除
*
* @var boolean
*/
private $softDelete = false;
/**
* 初始化
*
* @param string $pivotClass 中间表
* @param string $masterClass 主表
* @param string $subClass 子表
* @date 2022-12-29
* @example
* @author arw
* @since 1.0.0
*/
public function __construct(
string $pivotClass,
string $masterClass,
string $subClass,
bool $softDelete = false
) {
$this->pivotClass = $pivotClass;
$this->masterClass = $masterClass;
$this->subClass = $subClass;
$this->softDelete = $softDelete;
$this->pivotPk = (new $pivotClass)->getPk();
$this->masterPk = (new $masterClass)->getPk();
$this->subPk = (new $subClass)->getPk();
}
/**
* 绑定
*
* @param array|Collection $masters
* @param array|Collection $subs
* @param array $extra 中间表额外数据
* @return void
* @date 2022-12-29
* @example
* @author arw
* @since 1.0.0
*/
public function bind($masters, $subs, array $extra = []): void
{
$this->_bind($masters, $subs, $extra, false);
}
/**
* 解绑
*
* @param array|Collection $masters
* @param array|Collection $subs
* @return void
* @date 2022-12-29
* @example
* @author arw
* @since 1.0.0
*/
public function unbind(array $masters, array $subs): void
{
$masters = self::formatModel($masters, $this->masterClass);
$subs = self::formatModel($subs, $this->subClass);
$pivotClass = $this->pivotClass;
$pivotPk = $this->pivotPk;
$masterPk = $this->masterPk;
$subPk = $this->subPk;
foreach ($masters as $master) {
// 查询已绑定的数据
$subPks = $pivotClass::where([
$masterPk => $master->$masterPk
])->column($subPk);
foreach ($subs as $sub) {
if (in_array($sub->$subPk, $subPks)) {
$pivotClass::where([
$subPk => $sub->$subPk,
$masterPk => $master->$masterPk
])->field([
$pivotPk
])->select()->delete();
}
}
}
}
/**
* 重新绑定
*
* @param array|Collection $masters
* @param array|Collection $subs
* @param array $extra 中间表额外数据
* @return void
* @date 2022-12-29
* @example
* @author arw
* @since 1.0.0
*/
public function rebind($masters, $subs, array $extra = []): void
{
$this->_bind($masters, $subs, $extra, true);
}
/**
* 格式化模型
*
* @param array|Collection $models
* @param string $class
* @return Collection
* @date 2022-12-29
* @example
* @author arw
* @since 1.0.0
*/
private static function formatModel($models, string $class): Collection
{
if ($models instanceof Collection) {
return $models;
} else if (is_array($models)) {
$Collection = new Collection();
foreach ($models as $model) {
if ($model instanceof $class) {
} else if (is_string($model) || is_numeric($model)) {
$model = $class::find($model);
}
$Collection->push($model);
}
return $Collection;
} else {
throw new ErrorMsg("类型异常", 1);
}
}
/**
* 绑定数据
*
* @param array|Collection $masters
* @param array|Collection $subs
* @param array $extra
* @param boolean $rebind
* @return void
* @date 2022-12-29
* @example
* @author arw
* @since 1.0.0
*/
private function _bind($masters, $subs, array $extra = [], bool $rebind = false)
{
$masters = self::formatModel($masters, $this->masterClass);
$subs = self::formatModel($subs, $this->subClass);
$pivotClass = $this->pivotClass;
$softDelete = $this->softDelete;
$pivotPk = $this->pivotPk;
$masterPk = $this->masterPk;
$subPk = $this->subPk;
foreach ($masters as $master) {
if ($rebind) {
$pivots = $pivotClass::where([
[$masterPk, '=', $master->$masterPk],
[$subPk, 'not in', $subs->column($subPk)],
])->select();
if (!$pivots->isEmpty()) {
// 重新绑定
$this->unbind([$master], $pivots->column($subPk));
}
}
foreach ($subs as $sub) {
$pivot = null;
if ($softDelete) {
$pivot = $pivotClass::withTrashed()->where([
$subPk => $sub->$subPk,
$masterPk => $master->$masterPk
])->find();
} else {
$pivot = $pivotClass::where([
$subPk => $sub->$subPk,
$masterPk => $master->$masterPk
])->find();
}
if (is_null($pivot) || $pivot->isEmpty()) {
$pivotClass::create($extra + [
$subPk => $sub->$subPk,
$masterPk => $master->$masterPk
]);
} else {
if ($softDelete) {
$pivot->restore();
}
if ($extra) {
$pivotClass::update($extra, [
$pivotPk => $pivot->$pivotPk
]);
}
}
}
}
}
}

View File

@ -0,0 +1,261 @@
<?php
namespace app\common\arw\adjfut\src;
use think\Collection;
use think\db\Query;
use think\facade\Db;
use think\helper\Arr;
/**
* 分割数据表
*
* @date 2022-03-24
* @example
* @author arw
* @since 1.0.0
*/
class PartitionTable
{
/**
* 源表名
*
* @var string
*/
private $originTable = null;
/**
* 目标表名
*
* @var string
*/
private $targetTable = null;
/**
* 唯一字段
*
* @var string
*/
private $uniqueField = null;
/**
* 查询条件
*
* @var think\Db
*/
private $query = null;
/**
* 是否锁表
*
* @var boolean|string
*/
private $lockTable = false;
/**
* 初始化
*
* @param string $table 原数据表
* @param string $suffix 分割表后缀
* @date 2022-03-24
* @example
* @author arw
* @since 1.0.0
*/
public function __construct(string $table, string $suffix)
{
$this->originTable = $table;
$this->targetTable = join('_', [$table, $suffix]);
$this->checkTargetTable();
}
/**
* 是否锁表
*
* @param boolean|string $lock
* @return self
* @date 2023-01-04
* @example
* @author arw
* @since 1.0.0
*/
public function setLockTable($lock): self
{
$this->lockTable = $lock;
return $this;
}
/**
* 设置唯一字段(设置后将删除原表数据)
*
* @param string $uniqueField
* @date 2022-03-24
* @example
* @author arw
* @since 1.0.0
*/
public function setUniqueField(string $uniqueField): self
{
$this->uniqueField = $uniqueField;
return $this;
}
/**
* 设置查询条件
*
* @param callable $cb
* @date 2022-03-24
* @example
* @author arw
* @since 1.0.0
*/
public function setQuery(callable $cb): self
{
$this->query = call_user_func($cb, $this->getOriginDb());
return $this;
}
/**
* 跨月查询
*
* @param string $table
* @param string $field 字段
* @param array $option
* @param array $option[start] 开始时间 Y-m-d H:i:s
* @param array $option[end] 结束时间 Y-m-d H:i:s
* @date 2022-04-06
* @example
* @author arw
* @since 1.0.0
*/
public static function queryForMonth(string $table, string $field, array $option): Query
{
$start = Arr::get($option, 'start');
$end = Arr::get($option, 'end');
if (!$start || !$end) {
throw new \Exception("缺少时间限制", 1);
}
$result = Db::query("SHOW TABLES LIKE '${table}_%'");
$tables = [];
foreach ($result as $value) {
$tables = array_merge($tables, array_values($value));
}
$startYm = date('Ym', strtotime($start));
$endYm = date('Ym', strtotime($end));
$months = [];
$months[] = $startYm;
if ($startYm != $endYm) {
$current = $startYm;
while (true) {
$current = date('Ym', strtotime($current . "01 +1month"));
$months[] = $current;
if ($current === $endYm) {
break;
}
}
// $months[] = $endYm;
}
$temp = array_filter($tables, function ($v) use ($table, $months) {
return in_array(explode("${table}_", $v)[1], $months);
});
$query = Db::table(in_array(date('Ym'), $months) ? $table : array_shift($temp));
$query->union(array_map(function ($v) {
return Db::name($v)->fetchSql()->select();
}, $temp));
return Db::table(join(' ', [
$query->buildSql(),
$table
]))->whereBetweenTime($field, $start, $end);
}
/**
* 迁移数据
*
* @date 2022-03-24
* @example
* @author arw
* @since 1.0.0
*/
public function save()
{
Db::startTrans();
try {
$lockTable = $this->lockTable;
if ($lockTable) {
$this->getOriginDb()->lock($lockTable)->select();
$this->getTargetDb()->lock($lockTable)->select();
}
$target = $this->targetTable;
$originSql = $this->query->fetchSql()->select();
$result = Db::execute("REPLACE INTO `$target` $originSql;");
if ($result === false) {
throw new \Exception("迁移数据失败", 1);
}
$uniqueField = $this->uniqueField;
if ($uniqueField) {
$this->getTargetDb()->field([
$uniqueField
])->chunk(500, function (Collection $ids) use ($uniqueField) {
$this->getOriginDb()->whereIn(
$uniqueField,
$ids->column($uniqueField)
)->delete();
}, $uniqueField);
}
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
}
/**
* 获取原始表
*
* @date 2022-03-24
* @example
* @author arw
* @since 1.0.0
*/
private function getOriginDb(): Query
{
return Db::name($this->originTable);
}
/**
* 获取目标表
*
* @date 2022-03-24
* @example
* @author arw
* @since 1.0.0
*/
private function getTargetDb(): Query
{
return Db::name($this->targetTable);
}
/**
* 检查目标表
*
* @return void
* @date 2022-03-24
* @example
* @author arw
* @since 1.0.0
*/
private function checkTargetTable(): void
{
if (!in_array($this->targetTable, Db::getTables())) {
$origin = $this->originTable;
$target = $this->targetTable;
$result = Db::execute("CREATE TABLE `$target` LIKE `$origin`");
if ($result === false) {
throw new \Exception("创建迁移表失败", 1);
}
}
}
}

View File

@ -0,0 +1,250 @@
<?php
namespace app\common\arw\adjfut\src;
use app\common\arw\adjfut\src\Traits\Event;
class ReTry
{
use Event;
/**
* 执行器
*
* @var callable
*/
private $handle = null;
/**
* 是否执行成功
*
* @var boolean
*/
private $success = false;
/**
* 执行上限
*
* @var integer
*/
private $limit = 3;
/**
* 上次执行原始上限
*
* @var integer
*/
private $last_limit = 3;
/**
* 执行次数
*
* @var integer
*/
private $count = 1;
/**
* 包装器
*
* @param callable $handle
* @param integer $limit
* @return self
* @date 2022-12-30
* @example
* @author arw
* @since 1.0.0
*/
public static function wrapper(callable $handle, int $limit = 3): self
{
$ins = new self;
$ins->setHandle($handle);
$ins->setLimit($limit);
return $ins;
}
/**
* 自增
*
* @param integer $step 步长
* @return self
* @date 2022-12-28
* @example
* @author arw
* @since 1.0.0
*/
public function inc(int $step = 1): self
{
$this->limit += $step;
return $this;
}
/**
* 自减
*
* @param integer $step
* @return self
* @date 2022-12-28
* @example
* @author arw
* @since 1.0.0
*/
public function dec(int $step = 1): self
{
$this->limit -= $step;
return $this;
}
/**
* 获取执行次数
*
* @return integer
* @date 2022-12-30
* @example
* @author arw
* @since 1.0.0
*/
public function getCount(): int
{
return $this->count;
}
/**
* 获取执行上限
*
* @return integer
* @date 2022-12-28
* @example
* @author arw
* @since 1.0.0
*/
public function getLimit(): int
{
return $this->limit;
}
/**
* 设置执行上限
*
* @param integer $limit
* @return self
* @date 2022-12-28
* @example
* @author arw
* @since 1.0.0
*/
public function setLimit(int $limit): self
{
$this->limit = $limit;
$this->last_limit = $limit;
return $this;
}
/**
* 设置执行器
*
* @param callable $cb
* @return self
* @date 2022-12-28
* @example
* @author arw
* @since 1.0.0
*/
public function setHandle(callable $cb): self
{
$this->handle = $cb;
return $this;
}
/**
* 执行是否成功
*
* @param boolean $success
* @return self
* @date 2022-12-28
* @example
* @author arw
* @since 1.0.0
*/
public function success(bool $success): self
{
$this->success = $success;
return $this;
}
/**
* 重试上限
*
* @param callable $cb
* @return self
* @date 2022-12-28
* @example
* @author arw
* @since 1.0.0
*/
public function onRetryMax(callable $cb): self
{
$this->event('reTryMax', $cb);
return $this;
}
/**
* 执行异常
*
* @param callable $cb
* @return self
* @date 2022-12-30
* @example
* @author arw
* @since 1.0.0
*/
public function onError(callable $cb): self
{
$this->event('error', $cb);
return $this;
}
/**
* 执行
*
* @param mixed ...$args
* @return void
* @date 2022-12-30
* @example
* @author arw
* @since 1.0.0
*/
public function run(...$args)
{
$this->reset();
array_unshift($args, $this);
$handle = $this->handle;
$res = null;
while (true) {
try {
$res = call_user_func_array($handle, $args);
} catch (\Throwable $th) {
$this->trigger('error', [$th]);
}
$this->count++;
// 执行成功
if ($this->success) {
break;
}
// 执行上限
if ($this->count > $this->limit) {
// 不减1会导致 获取到的执行次数多1
$this->count--;
$this->trigger('reTryMax');
break;
}
}
return $res;
}
/**
* 重置执行器
*
* @return void
* @date 2022-12-30
* @example
* @author arw
* @since 1.0.0
*/
private function reset(): void
{
$this->count = 1;
$this->setLimit($this->last_limit);
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace app\common\arw\adjfut\src\Service;
use think\helper\Arr;
use think\Model;
use think\Service;
use think\Validate as ThinkValidate;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
class Validate extends Service
{
/**
* 启动方法
* 在所有的系统服务注册完成之后调用,用于定义启动某个系统服务之前需要做的操作
*
* @return void
* @date 2022-07-25
* @example
* @author arw
* @since 1.0.0
*/
public function boot(): void
{
ThinkValidate::maker(function (ThinkValidate $validate) {
/**
* 验证数据
* 验证规则
* 全部数据(数组)
* 字段名
* 字段描述
*/
$validate->extend('string', function ($value) {
return is_string($value);
}, ':attribute 数据类型非法 不是字符串');
$validate->extend('json', function ($value) {
try {
$value = json_decode($value, true);
return is_array($value);
} catch (\Throwable $th) {
// throw $th;
}
return false;
}, ':attribute 数据格式错误 不是json字符串');
$validate->extend('modelHas', function ($value, $rule) {
$rules = explode(',', $rule);
$class = Arr::get($rules, 0);
$pk = Arr::get($rules, 1);
if (!class_exists($class)) {
throw new ErrorMsg("$class 类不存在");
}
/**
* @var \think\Model
*/
$model = new $class;
if (!($model instanceof Model)) {
throw new ErrorMsg("$class 该类未继承 \\think\\Model");
}
if (!$pk) {
$pk = $model->getPk();
}
return (bool) $model->where($pk, $value)->value($pk);
}, ':attribute 数据不存在');
});
}
}

View File

@ -0,0 +1,196 @@
<?php
namespace app\common\arw\adjfut\src;
use DateTime;
use think\facade\Log;
use think\helper\Arr;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
class Tool
{
/**
* 生成配置项
*
* @param array $config
* @param callable|string $cb 自定义合并策略
* @return callable
* @date 2022-07-29
* @example
* @author arw
* @since 1.0.0
*/
public static function generateConfig(array $config, $cb = 'array_merge'): callable
{
return function (...$argv) use ($cb, $config) {
array_unshift($argv, $config);
return call_user_func_array($cb, $argv);
};
}
/**
* 构建url
*
* @param string $url
* @param array $query
* @param boolean $decode
* @return string
* @date 2023-01-04
* @example
* @author arw
* @since 1.0.0
*/
public static function buildUrl(string $url, array $query = [], bool $decode = true): string
{
$parse = parse_url($url);
$parse_query = Arr::get($parse, 'query', '');
$_query = [];
parse_str($parse_query, $_query);
if (!is_array($_query)) {
$_query = [];
}
$_query = array_merge($_query, $query);
$_url = str_replace('?' . $parse_query, '', $url);
$_url .= '?';
$_url .= http_build_query($_query);
if ($decode) {
$_url = urldecode($_url);
}
return $_url;
}
/**
* 写入通道日志
*
* @param string $channel
* @param string $type
* @param array $data
* @return void
* @date 2022-07-29
* @example
* @author arw
* @since 1.0.0
*/
public static function writeChannelLog(string $channel, string $type, array $data): void
{
Log::channel($channel)->$type(json_encode($data, JSON_UNESCAPED_UNICODE));
}
/**
* 字段映射
*
* @param array $data
* @param array $map
* @param array $options
* @return array
* @date 2022-06-23
* @example
* @author arw
* @since 1.0.0
*/
public static function fieldMap(array $data, array $map, array $options = []): array
{
$prefix = Arr::get($options, 'prefix', '');
$result = [];
foreach ($data as $key => $value) {
if (isset($map[$key])) {
$key = $map[$key];
}
if ($prefix) {
$key = $prefix . $key;
}
$result[$key] = $value;
}
return $result;
}
/**
* 转换日期格式
*
* @param string $datetime
* @param string $format
* @return string
* @date 2022-04-20
* @example
* @author arw
* @since 1.0.0
*/
public static function conversionDateTime($datetime, string $format): string
{
try {
$date = new DateTime($datetime);
return $date->format($format);
} catch (\Throwable $th) {
throw new ErrorMsg('日期格式非法', 1);
}
}
/**
* 生成唯一id
*
* @param string|array $value
* @return string
* @date 2022-03-24
* @example
* @author arw
* @since 1.0.0
*/
public static function generateGuid($value = ''): string
{
$str = '';
if (is_array($value)) {
$str = json_encode($value);
}
$charid = strtolower(md5($str . uniqid('', true)));
$hyphen = chr(45); // '-'
$uuid = //chr(123)// '{'
substr($charid, 0, 8) . $hyphen
. substr($charid, 8, 4) . $hyphen
. substr($charid, 12, 4) . $hyphen
. substr($charid, 16, 4) . $hyphen
. substr($charid, 20, 12);
//.chr(125);// '}'
return $uuid;
}
/**
* 清空(擦除)缓冲区并关闭输出缓冲
*
* @return void
*/
public static function obEndClean(): void
{
try {
while (ob_get_level() > 0) {
ob_end_clean();
}
} catch (\Throwable $th) {
//throw $th;
}
}
/**
* 自动创建文件夹
*
* @param string $path 文件夹路径
* @param integer $mode 权限
* @return boolean
*/
public static function mkdir(string $path, int $mode = 0755): bool
{
$path = str_replace('/', DIRECTORY_SEPARATOR, $path);
$temp = explode(DIRECTORY_SEPARATOR, $path);
if (preg_match("/\./", end($temp))) {
// pathinfo 不支持中文
// $path = pathinfo($path, PATHINFO_DIRNAME);
array_splice($temp, count($temp) - 1, 1);
$path = join(DIRECTORY_SEPARATOR, $temp);
}
if (!file_exists($path)) {
mkdir($path, $mode, true);
}
chmod($path, $mode);
return true;
}
}

View File

@ -0,0 +1,223 @@
<?php
declare(strict_types=1);
namespace app\common\arw\adjfut\src\Traits;
use think\exception\ValidateException;
use think\helper\Arr;
use think\Model;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
/**
* 字典类
* @mixin Model
*/
trait Dictionary
{
// /**
// * 字典映射
// *
// * @var array
// * @date 2023-01-10
// * @example
// * @author arw
// * @since 1.0.0
// */
// public static $dictionaryMap = [];
/**
* 字典缓存
*
* @var array
* @date 2023-01-10
* @example
* @author arw
* @since 1.0.0
*/
private static $dictionaryCache = [];
/**
* 获取字典模型映射
*
* @param string $guid
* @return array
* @date 2023-01-10
* @example
* @author arw
* @since 1.0.0
*/
private static function getDictionaryModelMap(string $guid): array
{
return [];
}
/**
* 验证字典
*
* @param bool $ignoreNull 忽略null值
* @param array $ignoreField 忽略字段验证
* @return void
* @throws ValidateException
* @date 2023-01-11
* @example
* @author arw
* @since 1.0.0
*/
public function validateDictionary(bool $ignoreNull = false, array $ignoreField = []): void
{
$map = self::getDictionaryMap();
$errors = [];
foreach ($map as $field => &$dictionary) {
list($field, $title) = self::getDictionaryField($field);
if (in_array($field, $ignoreField)) {
continue;
}
$value = $this->$field;
if (is_null($value) && $ignoreNull) {
continue;
}
$dictionary = self::getDictionaryFieldMap($field);
$keys = array_keys($dictionary);
if (!in_array($value, $keys)) {
$values = array_values($dictionary);
$msg = join(',', $values);
$errors[] = "$title 应在[ $msg ]";
}
unset($dictionary);
}
if ($errors) {
throw new ValidateException($errors);
}
}
/**
* 获取字典值
*
* @param string $field 字段
* @param mixed $value 设置器内调用无法会无法获取当前值 需要手动传入
* @return mixed
* @date 2023-01-11
* @example
* @author arw
* @since 1.0.0
*/
public function getDictionaryValue(string $field, $value = null)
{
$map = self::getDictionaryFieldMap($field);
if (is_null($value)) {
$value = $this->$field;
}
if (isset($map[$value])) {
return $value;
}
$key = array_search($value, $map);
if ($key === false) {
$msg = join(',', array_values($map));
throw new ErrorMsg("$field 应在[ $msg ]", 1);
}
return $key;
}
/**
* 获取字典名称
*
* @param string $field 字段
* @param mixed $default 默认值 如果默认值在字典值内 则返回字典名称
* @return mixed
* @date 2023-01-11
* @example
* @author arw
* @since 1.0.0
*/
public function getDictionaryName(string $field, $default = null)
{
$map = self::getDictionaryFieldMap($field);
if (isset($map[$default])) {
$default = $map[$default];
}
return Arr::get($map, $this->$field, $default);
}
/**
* 获取字典名称(弃用保留兼容)
* 请调用 getDictionaryName
*
* @param string $field 字段
* @param mixed $default 默认值
* @deprecated 1.0.0
* @return mixed
* @date 2023-01-10
* @example
* @author arw
* @since 1.0.0
*/
public function getDictionaryText(string $field, $default = null)
{
return $this->getDictionaryName($field, $default);
}
/**
* 获取字典字段映射
*
* @param string $field 字段
* @return array
* @date 2023-01-10
* @example
* @author arw
* @since 1.0.0
*/
public static function getDictionaryFieldMap(string $field): array
{
list($field) = self::getDictionaryField($field);
$cache = Arr::get(self::$dictionaryCache, $field);
if (is_array($cache)) {
return $cache;
}
$map = Arr::get(self::getDictionaryMap(), $field);
if (!$map) {
throw new ErrorMsg("未定义字段映射", 1);
}
if (is_array($map)) {
self::$dictionaryCache[$field] = $map;
return self::$dictionaryCache[$field];
}
if (is_string($map)) {
self::$dictionaryCache[$field] = self::getDictionaryModelMap($map);
return self::$dictionaryCache[$field];
}
return [];
}
/**
* 获取字典映射
*
* @return array
* @date 2023-01-10
* @example
* @author arw
* @since 1.0.0
*/
public static function getDictionaryMap(): array
{
$self = new self;
$exists = property_exists($self, 'dictionaryMap') && isset($self::$dictionaryMap);
return $exists ? $self::$dictionaryMap : [];
}
/**
* 获取字典字段
*
* @param string $value
* @return array
* @date 2023-01-13
* @example
* @author arw
* @since 1.0.0
*/
private static function getDictionaryField(string $value): array
{
$temp = explode('|', $value);
$field = Arr::get($temp, '0');
$title = Arr::get($temp, '1', $field);
return [$field, $title];
}
}

View File

@ -0,0 +1,62 @@
<?php
declare(strict_types=1);
namespace app\common\arw\adjfut\src\Traits;
/**
* 事件类
*/
trait Event
{
/**
* 事件
*
* @var array
* @date 2022-12-28
* @example
* @author arw
* @since 1.0.0
*/
private $event = [];
/**
* 事件
*
* @param string $type
* @param callable $cb
* @return self
* @date 2022-12-28
* @example
* @author arw
* @since 1.0.0
*/
private function event(string $type, callable $cb): self
{
$this->event[strtoupper($type)] = $cb;
return $this;
}
/**
* 事件触发器
*
* @param string $type
* @param array $args
* @param boolean $withThis
* @return mixed
* @date 2022-12-28
* @example
* @author arw
* @since 1.0.0
*/
private function trigger(string $type, array $args = [], bool $withThis = true)
{
$type = strtoupper($type);
if (isset($this->event[$type])) {
if ($withThis) {
array_unshift($args, $this);
}
return call_user_func_array($this->event[$type], $args);
}
}
}

View File

@ -0,0 +1,240 @@
<?php
namespace app\common\arw\adjfut\src;
class Traverse
{
// 当前id key名称
private $current = 'id';
// 父id key名称
private $parent = 'pid';
// 子集名称
private $children = 'children';
// 数据
private $data = [];
// 格式化函数
private $format = null;
// 是否递归循环
private $loop = false;
public function __construct(string $current, string $parent, string $children = 'children')
{
$this->current = $current;
$this->parent = $parent;
$this->children = $children;
}
/**
* 获取子集
* @access public
* @param array $data 要遍历的数组
* @param integer|string $id 要查找哪个id下的子集
* @param bool $loop 是否循环遍历
* @return array
*/
public function next(array $data = [], $id = 0, bool $loop = false): array
{
$this->setData($data);
$this->setLoop($loop);
return $this->generateNext($id);
}
/**
* 获取父集
* @access public
* @param array $data 要遍历的数组
* @param integer|string $id 要查找哪个id下的父集
* @param bool $loop 是否循环遍历
* @return array
*/
public function prev(array $data = [], $id = 0, bool $loop = false): array
{
$this->setData($data);
$this->setLoop($loop);
return $this->generatePrev($id);
}
/**
* 获取无限层级树状图
*
* @param array $data 要遍历的数组
* @param integer|string $parent_id 起点id
* @param callable $format 自定义树数据
* @return array
* @date 2020-04-09
* @example
* @author arw
* @since 1.0.0
*/
public function tree(array $data, $parent_id, callable $format): array
{
$this->setData($data);
$this->setFormat($format);
return $this->generateTree($parent_id);
}
/**
* 获取全部子集数据
*
* @param integer|string $id
* @return array
* @date 2022-08-08
* @example
* @author arw
* @since 1.0.0
*/
public function getCurrentData($id): array
{
$data = array_filter($this->data, function ($v) use ($id) {
return $v[$this->current] == $id;
});
$data = array_values($data);
return $data;
}
/**
* 获取全部父集数据
*
* @param integer|string $id
* @return array
* @date 2022-08-08
* @example
* @author arw
* @since 1.0.0
*/
public function getParentData($id): array
{
$data = array_filter($this->data, function ($v) use ($id) {
return $v[$this->parent] == $id;
});
$data = array_values($data);
return $data;
}
/**
* 设置循环
*
* @param boolean $loop
* @return self
* @date 2022-08-08
* @example
* @author arw
* @since 1.0.0
*/
public function setLoop(bool $loop): self
{
$this->loop = $loop;
return $this;
}
/**
* 设置数据
*
* @param array $data
* @return self
* @date 2022-08-08
* @example
* @author arw
* @since 1.0.0
*/
public function setData(array $data): self
{
$this->data = $data;
return $this;
}
/**
* 设置格式化函数
*
* @param callable $cb
* @return self
* @date 2022-08-08
* @example
* @author arw
* @since 1.0.0
*/
public function setFormat(callable $cb): self
{
$this->format = $cb;
return $this;
}
/**
* 生成树
*
* @param integer|string $parent_id
* @return array
* @date 2022-08-08
* @example
* @author arw
* @since 1.0.0
*/
public function generateTree($parent_id): array
{
$data = $this->getParentData($parent_id);
foreach ($data as &$value) {
$children = $this->generateTree($value[$this->current]);
$value[$this->children] = $children;
if (is_callable($this->format)) {
$formatReturn = call_user_func($this->format, $value);
if (!isset($formatReturn[$this->children])) {
$formatReturn[$this->children] = $children;
}
if ($formatReturn) {
$value = $formatReturn;
}
}
unset($value);
}
return $data;
}
/**
* 获取子集
*
* @param integer|string $id
* @return array
* @date 2022-08-08
* @example
* @author arw
* @since 1.0.0
*/
public function generateNext($id): array
{
$re = [];
$data = $this->getParentData($id);
foreach ($data as $value) {
$current = $value[$this->current];
$re[] = $current;
if ($this->loop) {
$re = array_merge($re, $this->generateNext($current));
}
}
return array_unique($re);
}
/**
* 获取父集
*
* @param integer|string $id
* @return array
* @date 2022-08-08
* @example
* @author arw
* @since 1.0.0
*/
public function generatePrev($id): array
{
$re = [];
$data = $this->getCurrentData($id);
foreach ($data as $value) {
$parent = $value[$this->parent];
$re[] = $parent;
if ($this->loop) {
$re = array_merge($re, $this->generatePrev($parent));
}
}
return array_unique($re);
}
}

View File

@ -0,0 +1,86 @@
<?php
namespace app\common\arw\adjfut\src\Unit;
use think\helper\Arr;
use think\helper\Str;
/**
* @method static string b2kb(string $number,?int $scale)
* @method static string b2mb(string $number,?int $scale)
* @method static string b2gb(string $number,?int $scale)
* @method static string b2tb(string $number,?int $scale)
*
* @method static string kb2b(string $number,?int $scale)
* @method static string kb2mb(string $number,?int $scale)
* @method static string kb2gb(string $number,?int $scale)
* @method static string kb2tb(string $number,?int $scale)
*
* @method static string mb2b(string $number,?int $scale)
* @method static string mb2kb(string $number,?int $scale)
* @method static string mb2gb(string $number,?int $scale)
* @method static string mb2tb(string $number,?int $scale)
*
* @method static string gb2b(string $number,?int $scale)
* @method static string gb2mb(string $number,?int $scale)
* @method static string gb2kb(string $number,?int $scale)
* @method static string gb2tb(string $number,?int $scale)
*
* @method static string tb2b(string $number,?int $scale)
* @method static string tb2mb(string $number,?int $scale)
* @method static string tb2kb(string $number,?int $scale)
* @method static string tb2gb(string $number,?int $scale)
*/
class File
{
/**
* 间隔
*/
const INTERVAL = 1024;
/**
* 顺序
*/
const ORDER = ['b', 'kb', 'mb', 'gb', 'tb'];
/**
* 获取字典单位
*
* @param string $size
* @return string
* @date 2022-07-23
* @example
* @author arw
* @since 1.0.0
*/
public static function getByteUnit(string $size): string
{
for ($i = 0; $size >= self::INTERVAL && $i < 4; $i++) {
$size = bcdiv($size, self::INTERVAL);
}
return round($size, 2) . self::ORDER[$i];
}
public static function __callStatic($name, $arguments)
{
$number = Arr::get($arguments, 0, 0);
$scale = Arr::get($arguments, 1, 0);
$name = Str::lower($name);
$a = null;
$b = null;
if (Str::contains($name, 2)) {
list($a, $b) = explode('2', $name);
} else {
list($a, $b) = explode('to', $name);
}
$a_index = array_search($a, self::ORDER);
$b_index = array_search($b, self::ORDER);
$type = $a_index < $b_index;
for ($i = 0; $i < abs(bcsub($a_index, $b_index, 0)); $i++) {
if ($type) {
$number = bcdiv($number, self::INTERVAL, $scale);
} else {
$number = bcmul($number, self::INTERVAL, $scale);
}
}
return $number;
}
}

View File

@ -0,0 +1,289 @@
<?php
namespace app\common\arw\adjfut\src;
use think\exception\ValidateException;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
use think\facade\Filesystem;
use think\facade\Request;
use think\file\UploadedFile;
use think\filesystem\Driver;
use think\helper\Arr;
class UploadFile
{
/**
* 磁盘
*
* @var string
*/
private $diskName = '';
/**
* 文件
*
* @var UploadedFile
*/
private $file = null;
/**
* 文件路径
*
* @var string
*/
private $path = '';
/**
* 初始化
*
* @param string $diskName 磁盘
* @param string $validate 验证
* @param UploadedFile|string|array $file 文件
* @date 2022-04-15
* @example
* @author arw
* @since 1.0.0
*/
public function __construct(
string $diskName,
string $validate = '',
$file = 'file'
) {
if (is_string($file)) {
$file = Request::file($file);
}
if (is_array($file)) {
$file = new UploadedFile(...$file);
}
if (!($file instanceof UploadedFile)) {
throw new ErrorMsg("非法文件", 1);
}
if ($validate) {
try {
Validate::check([
'file' => $file
], [
'file|文件' => $validate
]);
} catch (ValidateException $th) {
$this->getDisk()->delete($file->getFilename());
throw $th;
}
}
$this->diskName = $diskName;
$this->file = $file;
}
/**
* 上传base64图片
*
* @param string $diskName 磁盘
* @param string $base64 base64
* @return self
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
public static function uploadBase64Image(
string $diskName,
string $base64
): self {
$Base64 = new Base64($base64);
if (!$Base64->isImage()) {
throw new ErrorMsg("非法图片base64", 1);
}
$path = tempnam(sys_get_temp_dir(), 'saveBase64Image');
$Base64->saveImage($path);
$name = md5(md5_file($path) . Tool::generateGuid() . time()) . '.' . $Base64->getFileExt();
return new self($diskName, '', [
$path,
$name
]);
}
/**
* 获取文件
*
* @return UploadedFile
* @date 2022-07-05
* @example
* @author arw
* @since 1.0.0
*/
public function getFile(): UploadedFile
{
return $this->file;
}
/**
* 获取磁盘名称
*
* @return string
* @date 2022-07-05
* @example
* @author arw
* @since 1.0.0
*/
public function getDiskName(): string
{
return $this->diskName;
}
/**
* 获取配置项
*
* @param string $key
* @param mixed $default
* @return mixed
* @date 2022-04-15
* @example
* @author arw
* @since 1.0.0
*/
public function getConfig(string $key, $default = null)
{
return Arr::get(
Filesystem::getDiskConfig($this->diskName),
$key,
$default
);
}
/**
* 获取文件相对路径
*
* @date 2022-04-15
* @example
* @author arw
* @since 1.0.0
*/
public function getPath(): string
{
if (!$this->path) {
throw new ErrorMsg("请保存文件后使用", 1);
}
return $this->path;
}
/**
* 获取文件真实路径
*
* @return string
* @date 2022-07-19
* @example
* @author arw
* @since 1.0.0
*/
public function getRealPath(): string
{
$path = $this->getPath();
if ($this->getConfig('type') != 'local') {
throw new ErrorMsg("非本地文件类型 无法获取真实路径", 1);
}
return str_replace(['\\', '/'], [DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR], $this->getConfig('root') . DIRECTORY_SEPARATOR . $path);
}
/**
* 获取文件绝对路径
*
* @date 2022-04-15
* @deprecated 1.0.0
* @example
* @author arw
* @since 1.0.0
*/
public function getFullPath(): string
{
return $this->getRealPath();
}
/**
* 保存文件
* @param string $path 路径
* @param null|string|\Closure $rule 文件名规则
* @param array $options 参数
* @return string
*/
public function putFile(
string $path,
$rule = null,
array $options = []
): string {
$this->path = $this->getDisk()->putFile(
$path,
$this->file,
$rule,
$options
);
if (!$this->path) {
throw new ErrorMsg("文件保存失败", 1);
}
return $this->path;
}
/**
* 指定文件名保存文件
* @param string $path 路径
* @param string $name 文件名
* @param array $options 参数
* @return string
*/
public function putFileAs(
string $path,
string $name = '',
array $options = []
): string {
$this->path = $this->getDisk()->putFileAs(
$path,
$this->file,
$name,
$options
);
if (!$this->path) {
throw new ErrorMsg("文件保存失败", 1);
}
return $this->path;
}
/**
* 删除文件
*
* @return void
* @date 2022-08-22
* @example
* @author arw
* @since 1.0.0
*/
public function delete(): void
{
$this->getDisk()->delete($this->file->getFilename());
}
/**
* 移除文件
*
* @date 2022-04-15
* @deprecated 1.0.0
* @example
* @author arw
* @since 1.0.0
*/
public function unlink(): void
{
$this->delete();
}
/**
* 获取存储配置
*
* @return Driver
* @date 2022-04-15
* @example
* @author arw
* @since 1.0.0
*/
public function getDisk(): Driver
{
return Filesystem::disk($this->diskName);
}
}

View File

@ -0,0 +1,254 @@
<?php
namespace app\common\arw\adjfut\src;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
use think\facade\Request;
use think\helper\Arr;
use think\Validate as ThinkValidate;
class Validate
{
private $data = [];
/**
* 设置参数s
*
* @param array $data
* @return self
*/
public function setData(array $data): self
{
$this->data = $data;
return $this;
}
/**
* 当条件满足时 验证
*
* @param array $when
* @param array $validate
* @param array $message
* @param bool $batch
* @return void
*/
public function when(array $when, array $validate, array $message = [], bool $batch = true): void
{
$data = $this->data;
$whenCount = 0;
foreach ($when as $field => $value) {
if (!isset($data[$field])) {
continue;
}
if ($data[$field] == $value) {
$whenCount++;
}
}
$_validate = $whenCount == count($when);
if ($_validate) {
self::check($data, $validate, $message, $batch);
}
}
/**
* 验证是否唯一
*
* @param string $model 模型类
* @param string|int $id 排除主键id
* @param array $rules[field] => name,validateField,pk|其他规则
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @return void
* @throws ValidateException
*/
public static function unique(
string $model,
$id,
array $data,
array $rules = [],
array $message = [],
bool $batch = true
): void {
$_rules = [];
foreach ($rules as $field => $validate) {
$validates = explode('|', $validate);
$_rule = explode(',', $validates[0]);
$name = Arr::get($_rule, 0);
$validateField = Arr::get($_rule, 1);
$pk = Arr::get($_rule, 2);
$validates[0] = self::createUniqueRule($model, [
'field' => $validateField ?: $field,
'id' => $id,
'pk' => $pk,
]);
$_rules[$field . ($name ? "|$name" : '')] = $validates;
}
self::check($data, $_rules, $message, $batch);
}
/**
* 创建数据表唯一验证
*
* @param string $class 模型类
* @param array $options 配置项
* @param string $options[field] 字段名
* @param string $options[id] 排除ID
* @param string $options[pk] 主键名
* @return string
* @date 2022-04-16
* @example
* @author arw
* @since 1.0.0
*/
public static function createUniqueRule(string $class, array $options = []): string
{
$field = Arr::get($options, 'field');
$id = Arr::get($options, 'id');
$pk = Arr::get($options, 'pk');
if (!$field) {
throw new ErrorMsg("字段名不能为空", 1);
}
return 'unique:' . join(',', [
$class,
$field,
$id,
$pk
]);
}
/**
* 类场景验证
*
* @param string $validate
* @param string $scene
* @param boolean $batch
* @return void
* @throws ValidateException
*/
public static function classScene(array $validate, array $data, bool $batch = true): void
{
list($class, $scene) = $validate;
/**
* @var ThinkValidate
*/
$validate = new $class;
$validate->scene($scene)->batch($batch);
$validate->failException(true)->check($data);
}
/**
* 类场景验证 param参数
*
* @param array $validate
* @param boolean $batch
* @return array
* @throws ValidateException
*/
public static function classSceneParam(array $validate, bool $batch = true): array
{
$data = Request::param();
self::classScene($validate, $data, $batch);
return $data;
}
/**
* 类场景验证 get参数
*
* @param array $validate
* @param boolean $batch
* @return array
* @throws ValidateException
*/
public static function classSceneGet(array $validate, bool $batch = true): array
{
$data = Request::get();
self::classScene($validate, $data, $batch);
return $data;
}
/**
* 类场景验证 post参数
*
* @param array $validate
* @param boolean $batch
* @return array
* @throws ValidateException
*/
public static function classScenePost(array $validate, bool $batch = true): array
{
$data = Request::post();
self::classScene($validate, $data, $batch);
return $data;
}
/**
* param参数验证
*
* @param array $validate 验证规则数组
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @return array
* @throws ValidateException
*/
public static function param(array $validate, array $message = [], bool $batch = true): array
{
$data = Request::param();
self::check($data, $validate, $message, $batch);
return $data;
}
/**
* get参数验证
*
* @param array $validate 验证规则数组
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @return array
* @throws ValidateException
*/
public static function get(array $validate, array $message = [], bool $batch = true): array
{
$data = Request::get();
self::check($data, $validate, $message, $batch);
return $data;
}
/**
* post参数验证
*
* @param array $validate 验证规则数组
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @return array
* @throws ValidateException
*/
public static function post(array $validate, array $message = [], bool $batch = true): array
{
$data = Request::post();
self::check($data, $validate, $message, $batch);
return $data;
}
/**
* 验证数据
*
* @param array $data 数据
* @param array $validate 验证规则数组
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @return void
* @throws ValidateException
*/
public static function check(array $data, array $validate, array $message = [], bool $batch = true): void
{
$v = new ThinkValidate();
$v->rule($validate);
$v->message($message);
$v->batch($batch);
$v->failException(true)->check($data);
}
}

View File

@ -0,0 +1,123 @@
<?php
namespace app\common\arw\adjfut\src\WeChat;
use think\facade\Config as FacadeConfig;
use think\helper\Arr;
class Config
{
/**
* 实例
*
* @var $this
* @date 2022-05-19
* @example
* @author arw
* @since 1.0.0
*/
private static $instance = null;
/**
* 配置项
*
* @var array
* @date 2022-05-19
* @example
* @author arw
* @since 1.0.0
*/
private $config = [
// 中控层配置
'access_key' => '',
'server_base' => '',
// 小程序配置
'xcx' => [
'appid' => '',
'secret' => '',
'cache_key' => '',
'log_channel' => '',
],
// 公众号配置
'gzh' => [
'appid' => '',
'secret' => '',
// 推送模板
'template' => [
'模板名称' => '模板id'
],
'cache_key' => '',
'log_channel' => '',
],
];
public function __construct()
{
$setConfig = function (string $key) {
$this->setConfig($key, FacadeConfig::get("wechat.$key"));
};
foreach ([
'access_key', 'server_base',
'xcx.cache_key', 'xcx.log_channel',
'xcx.appid', 'xcx.secret',
'gzh.cache_key', 'gzh.log_channel',
'gzh.appid', 'gzh.secret', 'gzh.template'
] as $key) {
$setConfig($key);
}
}
/**
* 实例
*
* @return self
* @date 2022-05-19
* @example
* @author arw
* @since 1.0.0
*/
public static function instance(): self
{
if (!self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
/**
* 设置配置项
*
* @param string $key
* @param mixed $value
* @return void
* @date 2022-05-19
* @example
* @author arw
* @since 1.0.0
*/
public function setConfig(string $key, $value)
{
Arr::set($this->config, $key, $value);
}
/**
* 获取配置项
*
* @param string $key
* @param mixed $default
* @return mixed
* @date 2022-05-19
* @example
* @author arw
* @since 1.0.0
*/
public static function get(string $key, $default = null)
{
return Arr::get(
self::instance()->config,
$key,
$default
);
}
}

View File

@ -0,0 +1,348 @@
<?php
namespace app\common\arw\adjfut\src\WeChat;
use app\common\arw\adjfut\src\Curl;
use app\common\arw\adjfut\src\WeChat\GzhCommon;
use think\facade\Config;
use think\facade\Request;
use think\helper\Arr;
use think\Response;
class Gzh extends GzhCommon
{
/**
* 当前实例
*
* @var $this
*/
private static $instance = null;
/**
* 推送缓存 防止重复推送同样的数据
*
* @var array
* @date 2021-10-11
* @example
* @author arw
* @since 1.0.0
*/
private static $TemplateMessageInterfaceCache = [];
/**
* 初始化
*
* @date 2022-05-18
* @example
* @author arw
* @since 1.0.0
*/
public function __construct()
{
parent::__construct();
}
/**
* 实例
*
* @return self
* @date 2022-05-18
* @example
* @author arw
* @since 1.0.0
*/
public static function instance(): self
{
if (!self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
/**
* 获取AccessToken
*
* @param boolean $refresh 是否强制刷新
* @return void
* @date 2020-05-29
* @example
* @author arw
* @since 1.0.0
*/
public function GetAccessToken($refresh = false)
{
return $this->_AccessToken($refresh);
}
/**
* 获取JsApiTicket
*
* @param boolean $refresh 是否强制刷新
* @return void
* @date 2020-05-29
* @example
* @author arw
* @since 1.0.0
*/
public function GetJsApiTicket($refresh = false)
{
return $this->_JsApiTicket($refresh);
}
/**
* 网页授权/获取用户基本信息
* https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
* @param array $config 配置项 [
* "scope" => "snsapi_base", 应用授权作用域,
* snsapi_base 不弹出授权页面直接跳转只能获取用户openid
* snsapi_userinfo 弹出授权页面可通过openid拿到昵称、性别、所在地。并且 即使在未关注的情况下,只要用户授权,也能获取其信息
* "state" => "", 重定向后会带上state参数开发者可以填写a-zA-Z0-9的参数值最多128字节
* "lang" => "zh_CN", 当scope等于snsapi_userinfo才生效
* 返回国家地区语言版本zh_CN 简体zh_TW 繁体en 英语
* ]
* @param callable $success 回调用户授权成功调用函数 ($userinfo,$state)
* @param callable $error 执行错误回调 ($msg)
* @return null
*/
public function authorize(array $config, callable $success, callable $error)
{
try {
$config["scope"] = Arr::get($config, "scope", "snsapi_base");
$config["state"] = Arr::get($config, "state", "");
$config["lang"] = Arr::get($config, "lang", "zh_CN");
$config["redirect_uri"] = Arr::get($config, "redirect_uri", Request::url(true));
$code = Arr::get($_GET, "code");
if (!$code) {
$url = "https://open.weixin.qq.com/connect/oauth2/authorize";
$url .= "?" . http_build_query([
"appid" => $this->appid,
"redirect_uri" => $config["redirect_uri"],
"response_type" => "code",
"scope" => $config["scope"],
"state" => $config["state"],
]);
$url .= "#wechat_redirect";
return Response::create($url, 'redirect', 302);
}
$curl = Curl::instance();
$param = [];
$param["appid"] = $this->appid;
$param["secret"] = $this->secret;
$param["code"] = $code;
$param["grant_type"] = "authorization_code";
$url = "https://api.weixin.qq.com/sns/oauth2/access_token";
$access_token = $curl->setParams($param)->get($url);
$judge = (Arr::get($access_token, "access_token") && Arr::get($access_token, "openid"));
if (!$judge || !$access_token) {
$this->log([
'action' => __FUNCTION__,
'url' => $curl->getUrl(),
'params' => $curl->getParams(),
'content' => $curl->getContent(),
'msg' => '获取access_token失败',
], 'error');
return $error("获取access_token失败");
}
if ($config["scope"] === "snsapi_userinfo") {
$curl = Curl::instance();
$url = "https://api.weixin.qq.com/sns/userinfo";
$param = [];
$param["access_token"] = Arr::get($access_token, "access_token");
$param["openid"] = Arr::get($access_token, "openid");
$param["lang"] = $config["lang"];
$user_info = $curl->setParams($param)->get($url);
$errcode = Arr::get($user_info, "errcode", false);
if ($errcode !== false) {
$this->log([
'action' => __FUNCTION__,
'url' => $curl->getUrl(),
'params' => $curl->getParams(),
'result' => $curl->getContent(),
'msg' => '获取用户信息失败',
], 'error');
return $error("获取微信用户信息失败");
}
$access_token = array_merge($access_token, $user_info);
}
return $success($access_token, $_GET["state"]);
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
return $error($th->getMessage());
}
}
/**
* 微信模板消息推送
* 微信返回errcode等于40001会更新缓存AccessToken
* 并重新推送一次
* https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Template_Message_Interface.html#5
* @param string $touser 推送给谁
* @param string $template_id 模板名称
* @param array $data 推送数据
* [
* "touser" => "openid",
* "template_id" => "template_id",
* "url" => "url",
* "miniprogram" => [
* "appid" => "appid",
* "pagepath" => "pagepath",
* ],
* "data" => [
* "first" => [
* "value" => "value",
* "color" => "color",
* ],
* "keyword1" => [
* "value" => "value",
* "color" => "color",
* ],
* "keyword2" => [
* "value" => "value",
* "color" => "color",
* ],
* "keyword3" => [
* "value" => "value",
* "color" => "color",
* ],
* "remark" => [
* "value" => "value",
* "color" => "color",
* ],
* ],
* ]
* @param boolean $refresh 是否刷新【 access_token
* @param integer $limit 调用上限(允许自动重试次数)
* @return bool
* @date 2020-05-26
* @example
* @author arw
* @since 1.1.1
*/
public function TemplateMessageInterface($touser = null, $template_id = null, array $data, $refresh = false, $limit = 3)
{
$this->log([
'action' => __FUNCTION__,
'touser' => $touser,
'template_id' => $template_id,
'data' => $data,
], 'log');
try {
$template = $this->template;
if (!$touser) {
if (isset($data["touser"])) {
$touser = $data["touser"];
}
}
if (!$template_id) {
if (isset($data["template_id"])) {
$template_id = $data["template_id"];
}
}
if (empty($touser)) {
throw new \Exception("data.touser不能为空", 1);
}
if (empty($template_id)) {
throw new \Exception("data.template_id不能为空", 1);
} else {
if (isset($template[$template_id])) {
$template_id = $template[$template_id];
}
}
$data["touser"] = $touser;
$data["template_id"] = $template_id;
$limit--;
if ($limit <= 0) {
throw new \Exception("超过调用上限", 1);
}
$access_token = $this->_AccessToken($refresh);
if (!$access_token) {
return false;
}
$appid = Arr::get($data, "miniprogram.appid");
if ($appid == 'APPID') {
Arr::set($data, 'miniprogram.appid', Config::get('xcx.appid'));
}
$param = json_encode($data);
if (!isset(self::$TemplateMessageInterfaceCache[$param])) {
self::$TemplateMessageInterfaceCache[$param] = [];
}
if (in_array($touser, self::$TemplateMessageInterfaceCache[$param])) {
throw new \Exception("重复推送", 1);
}
$url = "https://api.weixin.qq.com/cgi-bin/message/template/send";
$url .= "?access_token=" . $access_token;
$curl = Curl::instance();
$send = $curl->setData($param)->post($url);
$errcode = Arr::get($send, "errcode", false);
if ($errcode === 0) {
self::$TemplateMessageInterfaceCache[$param][] = $touser;
return true;
}
if ($errcode === 40001) {
return $this->TemplateMessageInterface($touser, $template_id, $data, true, $limit);
}
$this->log([
'action' => __FUNCTION__,
'url' => $curl->getUrl(),
'params' => $curl->getData(),
'content' => $curl->getContent(),
'msg' => '模板消息推送失败',
], 'error');
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
}
return false;
}
/**
* Jssdk授权
* @param string $url 授权url
* @return null
*/
public function JsSdk(string $url = "")
{
$jsapiTicket = $this->_JsApiTicket();
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
if (!$url) {
$url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
}
$timestamp = time();
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$nonceStr = "";
for ($i = 0; $i < 16; $i++) {
$nonceStr .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
// 这里参数的顺序要按照 key 值 ASCII 码升序排序
$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
$signature = sha1($string);
$signPackage = [
"appId" => $this->appid,
"nonceStr" => $nonceStr,
"timestamp" => $timestamp,
"url" => $url,
"signature" => $signature,
"rawString" => $string,
];
return $signPackage;
}
}

View File

@ -0,0 +1,459 @@
<?php
namespace app\common\arw\adjfut\src\WeChat;
use think\facade\Cache;
use app\common\arw\adjfut\src\Curl;
use think\facade\Log;
use think\helper\Arr;
class GzhCommon
{
/**
* 微信公众号 appid
*
* @var string
*/
protected $appid = '';
/**
* 微信公众号 secret
*
* @var string
*/
protected $secret = '';
/**
* 微信推送模板
*
* @var array
*/
protected $template = [];
/**
* 缓存key
*
* @var string
*/
protected $cache_key = '';
/**
* 日志通道
*
* @var string
*/
protected $log_channel = '';
/**
* 异常
*
* @var string
*/
protected $error = '';
/**
* 中控层服务器 access_key
*
* @var string
*/
private $access_key = '';
/**
* 中控层服务器 server_base
*
* @var string
*/
private $server_base = '';
/**
* access_token 缓存
*
* @var string
*/
private $access_token = '';
/**
* 初始化
*
* @date 2022-05-19
* @example
* @author arw
* @since 1.0.0
*/
public function __construct()
{
$this->access_key = Config::get('access_key');
$this->server_base = Config::get('server_base');
$this->appid = Config::get('gzh.appid');
$this->secret = Config::get('gzh.secret');
$this->template = Config::get('gzh.template');
$this->cache_key = Config::get('gzh.cache_key');
$this->log_channel = Config::get('gzh.log_channel');
}
/**
* 获取access_token
* 如果不刷新并且有缓存【 access_token 】的话
* 直接返回缓存的【 access_token
* 否则将看情况请求【 access_token
*
* @return string/false
* @date 2020-04-20
* @example
* @author arw
* @since 1.0.2
*/
protected function _AccessToken($refresh = false)
{
$cache_key = $this->getAccessTokenCacheKey();
if ($refresh && $cache_key) {
Cache::delete($cache_key);
}
if ($refresh === false && $this->access_token) {
return $this->access_token;
}
$access_token = $this->_GetAccessToken($refresh);
if ($access_token) {
$this->access_token = $access_token;
return $access_token;
} else {
$access_token = $this->_GetCacheAccessToken();
if (!$access_token) {
$access_token = $this->_CurlAccessToken();
}
$this->access_token = $access_token;
return $access_token;
}
return false;
}
/**
* 获取jsapiticket
*
* @return string/false
* @date 2020-04-20
* @example
* @author arw
* @since 1.0.0
*/
protected function _JsApiTicket($refresh = false)
{
$cache_key = $this->getJsApiTicketCacheKey();
if ($refresh && $cache_key) {
Cache::delete($cache_key);
}
$ticket = $this->_GetJsApiTicket($refresh);
if ($ticket) {
return $ticket;
} else {
$ticket = $this->_GetCacheJsApiTicket();
if (!$ticket) {
$ticket = $this->_CurlJsApiTicket();
}
return $ticket;
}
return false;
}
/**
* 异常记录
*
* @param array $content
* @param string $level alert | error | warning | notice | info | debug
* @return void
* @date 2020-05-29
* @example
* @author arw
* @since 1.0.0
*/
protected function log(array $data, string $level = 'log')
{
$log_channel = $this->log_channel;
if ($log_channel) {
Log::channel($log_channel)->log($level, json_encode($data));
}
}
/**
* 请求【中控层服务器】 获取access_token
* @param boolean $refresh
* @return string/false
* @date 2020-04-20
* @example
* @author arw
* @since 2.0.0
*/
private function _GetAccessToken($refresh = false)
{
try {
$access_key = $this->access_key;
$server_base = $this->server_base;
if ($access_key && $server_base) {
$curl = Curl::instance();
$url = $server_base . "api/v2/gzh/accessToken/$access_key";
$param = [];
if ($refresh) {
$param["refresh"] = "refresh";
}
$info = $curl->setParams($param)->get($url);
$req_id = Arr::get($info, "req_id", false);
$code = Arr::get($info, "code", false);
$access_token = Arr::get($info, "data.access_token", false);
if (!$access_token) {
$this->log([
'action' => __FUNCTION__,
'url' => $curl->getUrl(),
'params' => $curl->getParams(),
'content' => $curl->getContent(),
'msg' => '获取access_token失败',
], 'error');
}
return $access_token;
}
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
}
return false;
}
/**
* 获取本地缓存【access_token】
*
* @return string|false
* @date 2022-12-26
* @example
* @author arw
* @since 1.0.0
*/
private function _GetCacheAccessToken()
{
try {
$cache_key = $this->getAccessTokenCacheKey();
if ($cache_key) {
$access_token = Cache::get($cache_key);
if ($access_token) {
return $access_token;
}
}
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
}
return false;
}
/**
* 获取本地缓存【jsapiticket】
*
* @return string|false
* @date 2022-12-26
* @example
* @author arw
* @since 1.0.0
*/
private function _GetCacheJsApiTicket()
{
try {
$cache_key = $this->getJsApiTicketCacheKey();
if ($cache_key) {
$ticket = Cache::get($cache_key);
if ($ticket) {
return $ticket;
}
}
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
}
return false;
}
/**
* 请求【微信服务器】 获取access_token
*
* @return string/false
* @date 2020-04-20
* @example
* @author arw
* @since 1.0.0
*/
private function _CurlAccessToken()
{
try {
$cache_key = $this->getAccessTokenCacheKey();
$curl = Curl::instance();
$url = "https://api.weixin.qq.com/cgi-bin/token";
$param = [];
$param["grant_type"] = "client_credential";
$param["appid"] = $this->appid;
$param["secret"] = $this->secret;
$info = $curl->setParams($param)->get($url);
$judge = (isset($info["access_token"]) && isset($info["expires_in"]));
if ($judge) {
$access_token = $info['access_token'];
if ($cache_key) {
$expires_in = $info['expires_in'];
Cache::set($cache_key, $access_token, $expires_in);
}
return $access_token;
} else {
$this->log([
'action' => __FUNCTION__,
'url' => $curl->getUrl(),
'params' => $curl->getParams(),
'content' => $curl->getContent(),
'msg' => '获取access_token失败',
], 'error');
}
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
}
return false;
}
/**
* 请求【中控层服务器】 获取jsapiticket
* @param boolean $refresh
* @return string/false
* @date 2020-04-20
* @example
* @author arw
* @since 2.0.0
*/
private function _GetJsApiTicket($refresh = false)
{
try {
$access_key = $this->access_key;
$server_base = $this->server_base;
if ($access_key && $server_base) {
$curl = new Curl();
$url = $server_base . "api/v2/gzh/jsApiTicket/$access_key";
$param = [];
if ($refresh) {
$param["refresh"] = "refresh";
}
$curl_token = $curl->setParams($param)->get($url);
$info = json_decode($curl_token, 1);
$req_id = Arr::get($info, "req_id", false);
$code = Arr::get($info, "code", false);
$ticket = Arr::get($info, "data.ticket", false);
if (!$ticket) {
$this->log([
'action' => __FUNCTION__,
'url' => $curl->getUrl(),
'params' => $curl->getParams(),
'content' => $curl->getContent(),
'msg' => '获取jsapiticket失败',
], 'error');
}
return $ticket;
}
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
}
return false;
}
/**
* 请求【微信服务器】 获取jsapiticket
*
* @return string/false
* @date 2020-04-20
* @example
* @author arw
* @since 1.0.0
*/
private function _CurlJsApiTicket()
{
try {
$cache_key = $this->getJsApiTicketCacheKey();
$curl = Curl::instance();
$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
$param = [];
$param["access_token"] = $this->_AccessToken();
$param["type"] = "jsapi";
$info = $curl->setParams($param)->get($url);
$judge = (isset($info["ticket"]) && isset($info["expires_in"]));
if ($judge) {
$ticket = $info['ticket'];
if ($cache_key) {
$expires_in = $info['expires_in'];
Cache::set($cache_key, $ticket, $expires_in);
}
return $ticket;
} else {
$this->log([
'action' => __FUNCTION__,
'url' => $curl->getUrl(),
'params' => $curl->getParams(),
'content' => $curl->getContent(),
'msg' => '获取jsapiticket失败',
], 'error');
}
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
}
return false;
}
/**
* 获取access_key缓存key
*
* @return string|false
* @date 2022-12-26
* @example
* @author arw
* @since 1.0.0
*/
private function getAccessTokenCacheKey()
{
if ($this->cache_key) {
return $this->cache_key . '.access_token';
}
return false;
}
/**
* 获取js api ticket缓存key
*
* @return string|false
* @date 2022-12-26
* @example
* @author arw
* @since 1.0.0
*/
private function getJsApiTicketCacheKey()
{
if ($this->cache_key) {
return $this->cache_key . '.js_api_ticket';
}
return false;
}
}

View File

@ -0,0 +1,232 @@
<?php
namespace app\common\arw\adjfut\src\WeChat;
use app\common\arw\adjfut\src\Curl;
use app\common\arw\adjfut\src\WeChat\XcxCommon;
use think\helper\Arr;
class Xcx extends XcxCommon
{
/**
* 当前实例
*
* @var $this
*/
private static $instance = null;
/**
* 初始化
*
* @date 2022-05-18
* @example
* @author arw
* @since 1.0.0
*/
public function __construct()
{
parent::__construct();
}
/**
* 实例
*
* @return self
* @date 2022-05-18
* @example
* @author arw
* @since 1.0.0
*/
public static function instance(): self
{
if (!self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
/**
* 获取AccessToken
*
* @param boolean $refresh 是否强制刷新
* @return void
* @date 2020-05-29
* @example
* @author arw
* @since 1.0.0
*/
public function GetAccessToken($refresh = false)
{
return $this->_AccessToken($refresh);
}
/**
* 获取微信小程序用户openid
*
* @param string $code 微信小程序传过来的code
* @return array|bool $res
* @return string $res[session_key]
* @return string $res[expores_in]
* @return string $res[openid]
* @return string $res[unionid]
*/
public function GetOpenId(string $code)
{
try {
$curl = Curl::instance();
$url = 'https://api.weixin.qq.com/sns/jscode2session';
$param = [];
$param['appid'] = $this->appid;
$param['secret'] = $this->secret;
$param['js_code'] = $code;
$param['grant_type'] = 'authorization_code';
$res = $curl->setParams($param)->get($url);
$openid = Arr::get($res, 'openid', false);
if ($openid) {
return $res;
}
$this->log([
'action' => __FUNCTION__,
'url' => $curl->getUrl(),
'params' => $curl->getParams(),
'content' => $curl->getContent(),
'msg' => '获取小程序用户openid失败微信服务器无返回openid',
], 'error');
$this->error = '获取用户openid失败';
return false;
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
$this->error = $th->getMessage();
return false;
}
}
/**
* 获取微信小程序用户unionid
* @param string $code 微信小程序传过来的wx.login 返回的code
* @param string $encryptedData 微信小程序传过来的wx.getUserInfo 返回的encryptedData
* @param string $iv 微信小程序传过来的wx.getUserInfo 返回的iv
*/
public function GetUnionid(string $code, string $encryptedData, string $iv)
{
try {
$result = $this->GetOpenId($code);
if (!$result) {
return false;
}
$openid = Arr::get($result, 'openid');
$session_key = Arr::get($result, 'session_key');
if (!$openid || !$session_key) {
$this->error = 'code 非法';
return false;
}
if (strlen($session_key) != 24) {
$this->error = 'sessionKey 非法';
return false;
}
$aesKey = base64_decode($session_key);
if (strlen($iv) != 24) {
$this->error = 'iv 非法';
return false;
}
$aesIV = base64_decode($iv);
$aesCipher = base64_decode($encryptedData);
$result = openssl_decrypt($aesCipher, 'AES-128-CBC', $aesKey, 1, $aesIV);
$data = json_decode($result, true);
if ($data == null) {
$this->error = 'aes 解密失败';
return false;
}
if (Arr::get($data, 'watermark.appid') != $this->appid) {
$this->error = 'appid不一致';
return false;
}
return $data;
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
}
}
/**
* 生成微信小程序码
* @param string $type 接口名称 createQRCode/get/getUnlimited
* @param array $data 请求参数
*/
public function QrCode(string $type, array $data)
{
return $this->_QrCode($type, $data);
}
private function _QrCode(string $type, array $data, bool $refresh = false, int $limit = 3)
{
try {
$limit--;
if ($limit <= 0) {
throw new \Exception('超过调用上限', 1);
}
$urls = [
'createQRCode' => 'https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode',
];
$curl = Curl::instance();
$url = $urls[$type];
$url .= '?access_token=' . $this->GetAccessToken($refresh);
$param = json_encode($data);
$res = $curl->setParams($param)->post($url);
$errcode = Arr::get($res, 'errcode', false);
$errmsg = Arr::get($res, 'errmsg', false);
if ($errcode === false && $errmsg === false) {
return base64_encode($res);
} else {
if ($errcode === 40001) {
return $this->_QrCode($type, $data, true, $limit);
}
$this->log([
'action' => __FUNCTION__,
'url' => $curl->getUrl(),
'params' => $curl->getData(),
'content' => $curl->getContent(),
'msg' => '获取小程序二维码失败,微信服务器返回数据异常',
], 'error');
$this->error = '获取小程序二维码失败';
return false;
}
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
$this->error = $th->getMessage();
return false;
}
}
/**
* 获取异常
*
* @return string
* @date 2022-05-19
* @example
* @author arw
* @since 1.0.0
*/
public function getError()
{
return $this->error;
}
}

View File

@ -0,0 +1,279 @@
<?php
namespace app\common\arw\adjfut\src\WeChat;
use think\facade\Cache;
use app\common\arw\adjfut\src\Curl;
use think\facade\Log;
use think\helper\Arr;
class XcxCommon
{
/**
* 微信小程序 appid
*
* @var string
*/
protected $appid = '';
/**
* 微信小程序 secret
*
* @var string
*/
protected $secret = '';
/**
* 缓存key
*
* @var string
*/
protected $cache_key = '';
/**
* 日志通道
*
* @var string
*/
protected $log_channel = '';
/**
* 异常
*
* @var string
*/
protected $error = '';
/**
* 中控层服务器 access_key
*
* @var string
*/
private $access_key = '';
/**
* 中控层服务器 server_base
*
* @var string
*/
private $server_base = '';
/**
* access_token 缓存
*
* @var string
*/
private $access_token = '';
/**
* 初始化
*
* @date 2022-05-18
* @example
* @author arw
* @since 1.0.0
*/
public function __construct()
{
$this->access_key = Config::get('access_key');
$this->server_base = Config::get('server_base');
$this->appid = Config::get('xcx.appid');
$this->secret = Config::get('xcx.secret');
$this->cache_key = Config::get('xcx.cache_key');
$this->log_channel = Config::get('xcx.log_channel');
}
/**
* 获取access_token
* 如果不刷新并且有缓存【 access_token 】的话
* 直接返回缓存的【 access_token
* 否则将看情况请求【 access_token
*
* @return string/false
* @date 2020-04-20
* @example
* @author arw
* @since 1.0.2
*/
protected function _AccessToken($refresh = false)
{
$cache_key = $this->getAccessTokenCacheKey();
if ($refresh && $cache_key) {
Cache::delete($cache_key);
}
if ($refresh === false && $this->access_token) {
return $this->access_token;
}
$access_token = $this->_GetAccessToken($refresh);
if ($access_token) {
$this->access_token = $access_token;
return $access_token;
} else {
$access_token = $this->_GetCacheAccessToken();
if (!$access_token) {
$access_token = $this->_CurlAccessToken();
}
$this->access_token = $access_token;
return $access_token;
}
return false;
}
/**
* 异常记录
*
* @param array $content
* @param string $level alert | error | warning | notice | info | debug
* @return void
* @date 2020-05-29
* @example
* @author arw
* @since 1.0.0
*/
protected function log(array $data, string $level = 'log')
{
$log_channel = $this->log_channel;
if ($log_channel) {
Log::channel($log_channel)->log($level, json_encode($data));
}
}
/**
* 请求【中控层服务器】 获取access_token
* @param boolean $refresh
* @return string/false
* @date 2020-04-20
* @example
* @author arw
* @since 2.0.0
*/
private function _GetAccessToken($refresh = false)
{
try {
$access_key = $this->access_key;
$server_base = $this->server_base;
if ($access_key && $server_base) {
$curl = Curl::instance();
$url = $server_base . "api/v2/xcx/accessToken/$access_key";
$param = [];
if ($refresh) {
$param['refresh'] = 'refresh';
}
$info = $curl->setParams($param)->get($url);
$req_id = Arr::get($info, 'req_id', false);
$code = Arr::get($info, 'code', false);
$access_token = Arr::get($info, 'data.access_token', false);
if ($access_token) {
return $access_token;
}
$this->log([
'action' => __FUNCTION__,
'url' => $curl->getUrl(),
'params' => $curl->getParams(),
'content' => $curl->getContent(),
'msg' => '获取access_token失败',
], 'error');
}
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
}
return false;
}
/**
* 获取本地缓存【access_token】
*
* @return string|false
* @date 2022-12-26
* @example
* @author arw
* @since 1.0.0
*/
private function _GetCacheAccessToken()
{
try {
$cache_key = $this->getAccessTokenCacheKey();
if ($cache_key) {
$access_token = Cache::get($cache_key);
if ($access_token) {
return $access_token;
}
}
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
}
return false;
}
/**
* 请求【微信服务器】 获取access_token
*
* @return string/false
* @date 2020-04-20
* @example
* @author arw
* @since 1.0.0
*/
private function _CurlAccessToken()
{
try {
$cache_key = $this->getAccessTokenCacheKey();
$curl = Curl::instance();
$url = 'https://api.weixin.qq.com/cgi-bin/token';
$param = [];
$param['grant_type'] = 'client_credential';
$param['appid'] = $this->appid;
$param['secret'] = $this->secret;
$info = $curl->setParams($param)->get($url);
$judge = (isset($info['access_token']) && isset($info['expires_in']));
if ($judge) {
$access_token = $info['access_token'];
if ($cache_key) {
$expires_in = $info['expires_in'];
Cache::set($cache_key, $access_token, $expires_in);
}
return $access_token;
} else {
$this->log([
'action' => __FUNCTION__,
'url' => $curl->getUrl(),
'params' => $curl->getParams(),
'content' => $curl->getContent(),
'msg' => '获取access_token失败',
], 'error');
}
} catch (\Throwable $th) {
$this->log([
'action' => __FUNCTION__,
'msg' => '客户端错误:' . $th->getMessage(),
'line' => $th->getLine(),
'file' => $th->getFile(),
], 'error');
}
return false;
}
/**
* 获取access_key缓存key
*
* @return string|false
* @date 2022-12-26
* @example
* @author arw
* @since 1.0.0
*/
private function getAccessTokenCacheKey()
{
if ($this->cache_key) {
return $this->cache_key . '.access_token';
}
return false;
}
}

View File

@ -0,0 +1,174 @@
<?php
namespace app\common\exception;
use think\helper\Arr;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
class Base64
{
/**
* 类型
*
* @var string
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
private $type = '';
/**
* base64内容
*
* @var string
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
private $body = '';
/**
* base64
*
* @var string
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
private $base64 = '';
/**
* 文件后缀映射
*/
private const FILE_EXT_MAP = [
'text/html' => 'html',
'text/css' => 'css',
'text/javascript' => 'js',
'image/gif' => 'gif',
'image/png' => 'png',
'image/jpeg' => 'jpg',
'image/x-icon' => 'ico',
];
/**
* 实例化
*
* @param string $base64
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
public function __construct(string $base64)
{
$parse = self::parse($base64);
$this->base64 = $base64;
$this->type = $parse['type'];
$this->body = $parse['body'];
}
/**
* 获取文件后缀
*
* @return string
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
public function getFileExt(): string
{
return Arr::get(self::FILE_EXT_MAP, $this->type, '');
}
/**
* 判断是否是base64图片字符串
*
* @return boolean
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
public function isImage(): bool
{
return in_array($this->type, [
'image/gif',
'image/png',
'image/jpeg',
'image/x-icon',
]);
}
/**
* 保存base64图片
*
* @param string $path
* @return void
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
public function saveImage(string $path): void
{
file_put_contents($path, base64_decode($this->body));
}
/**
* 判断是否是base64图片字符串
*
* @param string $base64
* @return boolean
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
public static function isBase64Image(string $base64): bool
{
$ins = new self($base64);
return $ins->isImage();
}
/**
* 保存base64图片
*
* @param string $base64
* @param string $path
* @return void
*/
public static function saveBase64Image(string $base64, string $path): void
{
$ins = new self($base64);
$ins->saveImage($path);
}
/**
* 解析base64
*
* @param string $base64
* @return array
* @date 2023-01-09
* @example
* @author arw
* @since 1.0.0
*/
private static function parse(string $base64): array
{
$prefix = 'data:';
$validate = substr($base64, 0, strlen($prefix)) === $prefix;
if (!$validate) {
throw new ErrorMsg("非法base64 开头data:", 1);
}
$explode = explode(';base64,', $base64);
if (count($explode) != 2) {
throw new ErrorMsg("非法base64 不存在;base64,", 1);
}
list($type, $body) = $explode;
$type = str_replace('data:', '', $type);
return [
'type' => $type,
'body' => $body
];
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace app\common\exception;
/**
* 登录超时
*/
class LoginTimeOut extends \Exception
{
}

View File

@ -0,0 +1,37 @@
<?php
namespace app\common\exception;
/**
* 地图扩展类
*/
class Map extends \Exception
{
/**
* 通过地址名获取经纬度
* @address 地址
*/
public static function getLongitudeAndLatitude($address)
{
//创建应用生成的key
$key = '5f059c7c7346c00474804e260979e0b3';
//根据开发文档获取经纬度
$url = "https://restapi.amap.com/v3/geocode/geo?key=" . $key . "&address=" . $address;
$json = file_get_contents($url);
$GaoDeArr = json_decode($json, true);
if ($GaoDeArr['infocode'] != '10000') {
return throwErrorMsg("{$address} 地址信息输入错误");
}
$location = explode(',', $GaoDeArr['geocodes'][0]['location']);
//经度
$longitude = $location[0];
//纬度
$latitude = $location[1];
return [
'longitude' => $longitude,
'latitude' => $latitude,
];
}
}

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