first commit
This commit is contained in:
11
.example.env
Normal file
11
.example.env
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
APP_DEBUG = true
|
||||||
|
|
||||||
|
DB_TYPE = mysql
|
||||||
|
DB_HOST = 127.0.0.1
|
||||||
|
DB_NAME = test
|
||||||
|
DB_USER = username
|
||||||
|
DB_PASS = password
|
||||||
|
DB_PORT = 3306
|
||||||
|
DB_CHARSET = utf8
|
||||||
|
|
||||||
|
DEFAULT_LANG = zh-cn
|
||||||
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
*.log
|
||||||
|
.env
|
||||||
|
composer.phar
|
||||||
|
composer.lock
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
/.idea
|
||||||
|
/.vscode
|
||||||
|
/vendor
|
||||||
|
/.settings
|
||||||
|
/.buildpath
|
||||||
|
/.project
|
||||||
42
.travis.yml
Normal file
42
.travis.yml
Normal 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
32
LICENSE.txt
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
|
||||||
|
版权所有Copyright © 2006-2025 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.
|
||||||
77
README.md
Normal file
77
README.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|

|
||||||
|
|
||||||
|
ThinkPHP 8
|
||||||
|
===============
|
||||||
|
|
||||||
|
## 特性
|
||||||
|
|
||||||
|
* 基于PHP`8.0+`重构
|
||||||
|
* 升级`PSR`依赖
|
||||||
|
* 依赖`think-orm`3.0+版本
|
||||||
|
* 全新的`think-dumper`服务,支持远程调试
|
||||||
|
* 支持`6.0`/`6.1`无缝升级
|
||||||
|
|
||||||
|
> ThinkPHP8的运行环境要求PHP8.0+
|
||||||
|
|
||||||
|
现在开始,你可以使用官方提供的[ThinkChat](https://chat.topthink.com/),让你在学习ThinkPHP的旅途中享受私人AI助理服务!
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
ThinkPHP生态服务由[顶想云](https://www.topthink.com)(TOPThink Cloud)提供,为生态提供专业的开发者服务和价值之选。
|
||||||
|
|
||||||
|
## 文档
|
||||||
|
|
||||||
|
[完全开发手册](https://doc.thinkphp.cn)
|
||||||
|
|
||||||
|
|
||||||
|
## 赞助
|
||||||
|
|
||||||
|
全新的[赞助计划](https://www.thinkphp.cn/sponsor)可以让你通过我们的网站、手册、欢迎页及GIT仓库获得巨大曝光,同时提升企业的品牌声誉,也更好保障ThinkPHP的可持续发展。
|
||||||
|
|
||||||
|
[](https://www.thinkphp.cn/sponsor/special)
|
||||||
|
|
||||||
|
[](https://www.thinkphp.cn/sponsor)
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
~~~
|
||||||
|
composer create-project topthink/think tp
|
||||||
|
~~~
|
||||||
|
|
||||||
|
启动服务
|
||||||
|
|
||||||
|
~~~
|
||||||
|
cd tp
|
||||||
|
php think run
|
||||||
|
~~~
|
||||||
|
|
||||||
|
然后就可以在浏览器中访问
|
||||||
|
|
||||||
|
~~~
|
||||||
|
http://localhost:8000
|
||||||
|
~~~
|
||||||
|
|
||||||
|
如果需要更新框架使用
|
||||||
|
~~~
|
||||||
|
composer update topthink/framework
|
||||||
|
~~~
|
||||||
|
|
||||||
|
## 命名规范
|
||||||
|
|
||||||
|
`ThinkPHP`遵循PSR-2命名规范和PSR-4自动加载规范。
|
||||||
|
|
||||||
|
## 参与开发
|
||||||
|
|
||||||
|
直接提交PR或者Issue即可
|
||||||
|
|
||||||
|
## 版权信息
|
||||||
|
|
||||||
|
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
|
||||||
|
|
||||||
|
本项目包含的第三方源码和二进制文件之版权信息另行标注。
|
||||||
|
|
||||||
|
版权所有Copyright © 2006-2024 by ThinkPHP (http://thinkphp.cn) All rights reserved。
|
||||||
|
|
||||||
|
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
|
||||||
|
|
||||||
|
更多细节参阅 [LICENSE.txt](LICENSE.txt)
|
||||||
1
app/.htaccess
Normal file
1
app/.htaccess
Normal file
@@ -0,0 +1 @@
|
|||||||
|
deny from all
|
||||||
22
app/AppService.php
Normal file
22
app/AppService.php
Normal 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()
|
||||||
|
{
|
||||||
|
// 服务启动
|
||||||
|
}
|
||||||
|
}
|
||||||
94
app/BaseController.php
Normal file
94
app/BaseController.php
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app;
|
||||||
|
|
||||||
|
use think\App;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
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, string|array $validate, array $message = [], bool $batch = false)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
58
app/ExceptionHandle.php
Normal file
58
app/ExceptionHandle.php
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用异常处理类
|
||||||
|
*/
|
||||||
|
class ExceptionHandle extends Handle
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 不需要记录信息(日志)的异常类列表
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $ignoreReport = [
|
||||||
|
HttpException::class,
|
||||||
|
HttpResponseException::class,
|
||||||
|
ModelNotFoundException::class,
|
||||||
|
DataNotFoundException::class,
|
||||||
|
ValidateException::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 \think\Request $request
|
||||||
|
* @param Throwable $e
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function render($request, Throwable $e): Response
|
||||||
|
{
|
||||||
|
// 添加自定义异常处理机制
|
||||||
|
|
||||||
|
// 其他错误交给系统处理
|
||||||
|
return parent::render($request, $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
8
app/Request.php
Normal file
8
app/Request.php
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
namespace app;
|
||||||
|
|
||||||
|
// 应用请求对象类
|
||||||
|
class Request extends \think\Request
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
2
app/admin/common.php
Normal file
2
app/admin/common.php
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
// 这是系统自动生成的公共文件
|
||||||
34
app/admin/controller/AccountManagement.php
Normal file
34
app/admin/controller/AccountManagement.php
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\BaseController;
|
||||||
|
use app\admin\service\AccountService;
|
||||||
|
|
||||||
|
class AccountManagement extends BaseController
|
||||||
|
{
|
||||||
|
public function addAccount(AccountService $accountService)
|
||||||
|
{
|
||||||
|
|
||||||
|
# 获取数据
|
||||||
|
$params = $this->request->post();
|
||||||
|
|
||||||
|
# 参数校验
|
||||||
|
if (empty($params['real_name'])) {
|
||||||
|
return json(['code' => 400, 'message' => '缺少必要参数']);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 业务逻辑
|
||||||
|
try {
|
||||||
|
$result = $accountService->createAccount($params);
|
||||||
|
return json(['code' => 200, 'message' => '账户创建成功', 'data' => $result]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
'data' => null
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
84
app/admin/controller/Ticket.php
Normal file
84
app/admin/controller/Ticket.php
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
|
||||||
|
use app\BaseController;
|
||||||
|
use app\common\model\Tickets;
|
||||||
|
use app\common\service\TicketService;
|
||||||
|
use think\facade\Session;
|
||||||
|
|
||||||
|
class Ticket extends BaseController
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询工单
|
||||||
|
*/
|
||||||
|
public function ticketsFind(TicketService $ticketService)
|
||||||
|
{
|
||||||
|
|
||||||
|
// 在控制器明确接收参数
|
||||||
|
$params = [
|
||||||
|
"page" => $this->request->param('page', 1, 'intval'),
|
||||||
|
"limit" => $this->request->param('limit', 20, 'intval'),
|
||||||
|
"status" => $this->request->param('status', null),
|
||||||
|
"operator_name" => $this->request->param('operator_name', null),
|
||||||
|
"searchKeyword" => $this->request->param('search', null),
|
||||||
|
"sortOrder" => $this->request->param('sort_order', 'desc'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = $ticketService->getTicketList($params);
|
||||||
|
|
||||||
|
|
||||||
|
return json(['code' => 200, 'msg' => '查询成功', 'data' => $result]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增工单
|
||||||
|
*/
|
||||||
|
public function createTicket(TicketService $ticketService)
|
||||||
|
{
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $ticketService->createTicket($data);
|
||||||
|
return json(['code' => 200, 'msg' => '创建成功', 'data' => $result]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json(['code' => 400, 'msg' => $e->getMessage(), 'data' => null]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新工单(后台调用)
|
||||||
|
*/
|
||||||
|
public function updateTicket(TicketService $ticketService, $id)
|
||||||
|
{
|
||||||
|
|
||||||
|
$adminId = Session::get('id'); // 获取当前登录管理员ID
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
$allowFields = ['company_id', 'operator_id', 'user_id', 'website', 'datanum', 'progress', 'status', 'remark'];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $ticketService->updateTicket($id, $data, $allowFields, $adminId, true);
|
||||||
|
return json(['code' => 200, 'msg' => '更新成功', 'data' => $result]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json(['code' => 400, 'msg' => $e->getMessage(), 'data' => []]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除一个工单(仅后台可调用)
|
||||||
|
*/
|
||||||
|
public function deleteTicket($id)
|
||||||
|
{
|
||||||
|
$ticket = Tickets::find($id);
|
||||||
|
if (!$ticket) return json(['code' => false, 'msg' => '工单不存在', 'data' => []]);
|
||||||
|
|
||||||
|
return $ticket->delete()
|
||||||
|
? json(['code' => true, 'msg' => '删除成功', 'data' => []])
|
||||||
|
: json(['code' => false, 'msg' => '删除失败', 'data' => []]);
|
||||||
|
}
|
||||||
|
}
|
||||||
30
app/admin/controller/TicketFilter.php
Normal file
30
app/admin/controller/TicketFilter.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\BaseController;
|
||||||
|
use app\common\service\TicketService;
|
||||||
|
|
||||||
|
class TicketFilter extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取所有运营人员名称 (下拉筛选用)
|
||||||
|
*/
|
||||||
|
public function getAllOperators(TicketService $ticketService)
|
||||||
|
{
|
||||||
|
|
||||||
|
$result = $ticketService->getAllOperators();
|
||||||
|
|
||||||
|
return json(['code' => 200, 'msg' => '查询成功', 'data' => $result]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取我方员工列表 (下拉选择用)
|
||||||
|
*/
|
||||||
|
public function getStaffList(TicketService $ticketService)
|
||||||
|
{
|
||||||
|
$result = $ticketService->getStaffList();
|
||||||
|
return json(['code' => 200, 'msg' => '查询成功', 'data' => $result]);
|
||||||
|
}
|
||||||
|
}
|
||||||
5
app/admin/event.php
Normal file
5
app/admin/event.php
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
// 这是系统自动生成的event定义文件
|
||||||
|
return [
|
||||||
|
|
||||||
|
];
|
||||||
5
app/admin/middleware.php
Normal file
5
app/admin/middleware.php
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
// \app\admin\middleware\Cors::class, // 全局中间件
|
||||||
|
// \app\middleware\Auth::class,
|
||||||
|
];
|
||||||
31
app/admin/middleware/Auth.php
Normal file
31
app/admin/middleware/Auth.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\middleware;
|
||||||
|
|
||||||
|
use thans\jwt\facade\JWTAuth;
|
||||||
|
use thans\jwt\exception\TokenExpiredException;
|
||||||
|
|
||||||
|
class Auth
|
||||||
|
{
|
||||||
|
public function handle($request, \Closure $next)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 1. 核心:必须先执行 auth(),它会自动从 Header 读取 Bearer Token 并验证
|
||||||
|
// 如果过期或非法,这里会直接抛出异常
|
||||||
|
|
||||||
|
$payload = JWTAuth::auth();
|
||||||
|
// $payload = JWTAuth::getPayload(); 这个是获取数据,进行解码token
|
||||||
|
$request->login_user_id = (int)$payload['user_id'] ?? null;
|
||||||
|
$request->login_role = $payload['role'] ?? null;
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}catch (TokenExpiredException $e){
|
||||||
|
// 捕获token过期异常
|
||||||
|
return json(['code' => 401, 'msg' => '登录已过期,请重新登录'],401);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// 如果报错,返回具体的错误信息,方便我们排查
|
||||||
|
return json(['code' => 400, 'msg' => '权限校验失败:' . $e->getMessage()], 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/admin/route/app.php
Normal file
19
app/admin/route/app.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
use app\admin\middleware\Auth;
|
||||||
|
|
||||||
|
Route::get('ticketsfind', 'Ticket/ticketsFind'); // 通用查询方法
|
||||||
|
// Route::group(function () {
|
||||||
|
// // Route::get('ticketsfind', 'Ticket/ticketsFind'); // 通用查询方法
|
||||||
|
// Route::post('addticket', 'Ticket/save'); // 保存工单
|
||||||
|
// Route::put('ticket/:id', 'Ticket/updateTicket'); // 更新工单
|
||||||
|
// Route::delete('ticket/:id', 'Ticket/deleteTicket'); // 删除工单
|
||||||
|
// Route::get('operators', 'Ticket/getAllOperators'); // 根据运营人员查询
|
||||||
|
// Route::get('customers', 'Customers/getList');
|
||||||
|
// Route::post('addcustomername', 'Customers/addCustomer'); //添加客户名称
|
||||||
|
// Route::post('addemployee', 'Customers/addEmployee');
|
||||||
|
// Route::get('getStaffList', 'Ticket/getStaffList');
|
||||||
|
// Route::delete('deleteemployee/:empId', 'Customers/deleteEmployee');
|
||||||
|
// Route::delete('deletecustomer/:customerId', 'Customers/deleteCustomer');
|
||||||
|
// Route::get('getticketstatuscount', 'Ticket/getTicketStatusCount');
|
||||||
|
// })->middleware(Auth::class); // 只有这里需要 Token
|
||||||
34
app/admin/service/AccountService.php
Normal file
34
app/admin/service/AccountService.php
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\service;
|
||||||
|
|
||||||
|
use app\common\model\User as UserModel;
|
||||||
|
|
||||||
|
class AccountService
|
||||||
|
{
|
||||||
|
public function createAccount($data)
|
||||||
|
{
|
||||||
|
if (empty($data['username'])) {
|
||||||
|
$data['username'] = $data['real_name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查数据库中是否有相同用户名账户
|
||||||
|
$exist = UserModel::where('username', $data['username'])->find();
|
||||||
|
if ($exist) {
|
||||||
|
throw new \Exception('用户名已存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
$insertData = [
|
||||||
|
'username' => $data['username'] ?? $data['real_name'],
|
||||||
|
'real_name' => $data['real_name'],
|
||||||
|
'password' => password_hash('123456', PASSWORD_DEFAULT),
|
||||||
|
'role' => $data['role'] ?? 'user',
|
||||||
|
'status' => 1,
|
||||||
|
];
|
||||||
|
|
||||||
|
$user = UserModel::create($insertData);
|
||||||
|
|
||||||
|
/** @var \think\Model $user */
|
||||||
|
return $user->visible(['id', 'username', 'real_name', 'role', 'status'])->toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
48
app/admin/service/CustomersService.php
Normal file
48
app/admin/service/CustomersService.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\service;
|
||||||
|
|
||||||
|
use app\common\model\Customers as CustomersModel;
|
||||||
|
use app\common\model\CustomerEmployees;
|
||||||
|
|
||||||
|
class CustomersService
|
||||||
|
{
|
||||||
|
public function selectCustomersWithEmployees()
|
||||||
|
{
|
||||||
|
//with 预载入 ,解决N+1问题
|
||||||
|
$list = CustomersModel::with('employees')->select();
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addCustomer($companyName)
|
||||||
|
{
|
||||||
|
$id = CustomersModel::create([
|
||||||
|
'company_name' => $companyName
|
||||||
|
]);
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addEmployee($empName, $Id)
|
||||||
|
{
|
||||||
|
$id = CustomersModel::where('id', $Id)->find()->employees()->save([
|
||||||
|
'employee_name' => $empName
|
||||||
|
]);
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function deleteEmployee($empId)
|
||||||
|
{
|
||||||
|
$result = CustomerEmployees::destroy($empId);
|
||||||
|
return $result; // 返回受影响的行数,删除一行就1,没有删除就是0
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteCustomer($customerId)
|
||||||
|
{
|
||||||
|
// 删除客户单位会自动删除关联的员工(假设你在模型中设置了级联删除)
|
||||||
|
$result = CustomersModel::destroy($customerId);
|
||||||
|
return $result; // 返回受影响的行数,删除一行就1,没有删除就是0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
2
app/common.php
Normal file
2
app/common.php
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
// 应用公共文件
|
||||||
66
app/common/Trait/ApiResponse.php
Normal file
66
app/common/Trait/ApiResponse.php
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\Trait;
|
||||||
|
|
||||||
|
use think\Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API 响应 Trait
|
||||||
|
* 提供统一的 JSON 响应格式
|
||||||
|
*/
|
||||||
|
trait ApiResponse
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 成功响应
|
||||||
|
*
|
||||||
|
* @param mixed $data 响应数据
|
||||||
|
* @param string $msg 响应消息
|
||||||
|
* @param int $code 响应码
|
||||||
|
* @param int $httpCode HTTP状态码
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
protected function successResponse($data = [], $msg = '成功', $code = 200, $httpCode = 200)
|
||||||
|
{
|
||||||
|
return json([
|
||||||
|
'code' => $code,
|
||||||
|
'msg' => $msg,
|
||||||
|
'data' => $data
|
||||||
|
], $httpCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误响应
|
||||||
|
*
|
||||||
|
* @param string $msg 错误消息
|
||||||
|
* @param mixed $data 错误数据
|
||||||
|
* @param int $code 错误码
|
||||||
|
* @param int $httpCode HTTP状态码
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
protected function errorResponse($msg = '失败', $data = null, $code = 400, $httpCode = 400)
|
||||||
|
{
|
||||||
|
return json([
|
||||||
|
'code' => $code,
|
||||||
|
'msg' => $msg,
|
||||||
|
'data' => $data
|
||||||
|
], $httpCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义响应
|
||||||
|
*
|
||||||
|
* @param int $code 响应码
|
||||||
|
* @param string $msg 响应消息
|
||||||
|
* @param mixed $data 响应数据
|
||||||
|
* @param int $httpCode HTTP状态码
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
protected function customResponse($code, $msg, $data = [], $httpCode = 200)
|
||||||
|
{
|
||||||
|
return json([
|
||||||
|
'code' => $code,
|
||||||
|
'msg' => $msg,
|
||||||
|
'data' => $data
|
||||||
|
], $httpCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
app/common/middleware/Cors.php
Normal file
26
app/common/middleware/Cors.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
// app/middleware/Cors.php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\middleware;
|
||||||
|
|
||||||
|
class Cors
|
||||||
|
{
|
||||||
|
public function handle($request, \Closure $next)
|
||||||
|
{
|
||||||
|
// 设置CORS响应头
|
||||||
|
header('Access-Control-Allow-Origin: *'); // 允许的源
|
||||||
|
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS');
|
||||||
|
header('Access-Control-Allow-Headers: Authorization, Content-Type, X-Requested-With, X-CSRF-Token');
|
||||||
|
header('Access-Control-Allow-Credentials: true');
|
||||||
|
header('Access-Control-Max-Age: 1728000');
|
||||||
|
|
||||||
|
// 处理CORS预检请求
|
||||||
|
if ($request->isOptions()) {
|
||||||
|
return response()->code(200); // 预检请求,允许通过
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request); // 继续处理请求
|
||||||
|
}
|
||||||
|
}
|
||||||
22
app/common/model/CompanyOperators.php
Normal file
22
app/common/model/CompanyOperators.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
|
||||||
|
class CompanyOperators extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'company_operators';
|
||||||
|
|
||||||
|
public function company()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Companys::class, 'company_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getCompanyNameAttr($value, $data)
|
||||||
|
{
|
||||||
|
return $this->company->company_name ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
app/common/model/Companys.php
Normal file
12
app/common/model/Companys.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
|
||||||
|
class Companys extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'companys';
|
||||||
|
|
||||||
|
}
|
||||||
32
app/common/model/Customers(待删除).php
Normal file
32
app/common/model/Customers(待删除).php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
use app\common\model\CustomerEmployees;
|
||||||
|
|
||||||
|
class Customers extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'customers';
|
||||||
|
|
||||||
|
public function employees()
|
||||||
|
{
|
||||||
|
return $this->hasMany(CustomerEmployees::class, 'customer_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 模型事件:在删除客户记录之后执行 */
|
||||||
|
public static function onAfterDelete($customer)
|
||||||
|
{
|
||||||
|
// 删除与该客户相关的员工记录
|
||||||
|
$customer->employees()->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getCompanyOfAccount(){
|
||||||
|
return $this->hasMany(User::class,'company_id','id');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
94
app/common/model/Tickets.php
Normal file
94
app/common/model/Tickets.php
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
|
||||||
|
class Tickets extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'tickets';
|
||||||
|
|
||||||
|
# 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
# 定义时间戳字段名
|
||||||
|
protected $createTime = 'create_time';
|
||||||
|
protected $updateTime = 'update_time';
|
||||||
|
|
||||||
|
|
||||||
|
# 定义字段类型
|
||||||
|
protected $type = [
|
||||||
|
'id' => 'integer',
|
||||||
|
'company_id' => 'integer',
|
||||||
|
'operator_id' => 'integer',
|
||||||
|
'user_id' => 'integer',
|
||||||
|
'website' => 'string',
|
||||||
|
'datanum' => 'string',
|
||||||
|
'progress' => 'integer',
|
||||||
|
'status' => 'integer',
|
||||||
|
'remark' => 'string',
|
||||||
|
'lock_time' => 'integer',
|
||||||
|
'create_time' => 'integer',
|
||||||
|
'update_time' => 'integer',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
时间戳获取器
|
||||||
|
*/
|
||||||
|
public function getCreateTimeAttr($value)
|
||||||
|
{
|
||||||
|
return date('Y-m-d H:i', $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUpdateTimeAttr($value)
|
||||||
|
{
|
||||||
|
return date('Y-m-d H:i', $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLockTimeAttr($value)
|
||||||
|
{
|
||||||
|
if (empty($value)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return date('Y-m-d H:i', $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联:工单关联负责人
|
||||||
|
*/
|
||||||
|
public function ticketStaff()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'user_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ticketCompany()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Companys::class, 'company_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ticketOperator()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(CompanyOperators::class, 'operator_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --- 定义虚拟属性 (获取关联表的值) ---
|
||||||
|
|
||||||
|
public function getUsernameAttr($value, $data)
|
||||||
|
{
|
||||||
|
return $this->ticketStaff->username ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCompanyNameAttr($value, $data)
|
||||||
|
{
|
||||||
|
return $this->ticketCompany->company_name ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOperatorNameAttr($value, $data)
|
||||||
|
{
|
||||||
|
return $this->ticketOperator->operator_name ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
16
app/common/model/User.php
Normal file
16
app/common/model/User.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
|
||||||
|
class User extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'users';
|
||||||
|
|
||||||
|
public function company(){
|
||||||
|
return $this->belongsTo(Companys::class,'company_id','id');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
42
app/common/service/AuthService.php
Normal file
42
app/common/service/AuthService.php
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\service;
|
||||||
|
|
||||||
|
use app\common\model\User;
|
||||||
|
use think\facade\Session;
|
||||||
|
|
||||||
|
class AuthService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 验证用户登录状态
|
||||||
|
* @return array|false 返回用户信息数组或false
|
||||||
|
*/
|
||||||
|
public function login(string $username, string $password)
|
||||||
|
{
|
||||||
|
$user = User::with(['company'])
|
||||||
|
->where('username', $username)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!$user || !password_verify($password, $user['password'])) {
|
||||||
|
throw new \Exception('用户名或密码错误');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user['status'] != 1) {
|
||||||
|
throw new \Exception('账户已禁用');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$userInfo = [
|
||||||
|
'company_name' => $user['company']['company_name'], // 所属公司名称
|
||||||
|
'username' => $user['username'],
|
||||||
|
'role' => $user['role'],
|
||||||
|
];
|
||||||
|
|
||||||
|
Session::set('user_info', $user);
|
||||||
|
|
||||||
|
return $userInfo;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
186
app/common/service/TicketService.php
Normal file
186
app/common/service/TicketService.php
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\service;
|
||||||
|
|
||||||
|
use app\common\model\Tickets;
|
||||||
|
use app\common\model\CompanyOperators;
|
||||||
|
use app\common\model\User;
|
||||||
|
|
||||||
|
use think\facade\Cache;
|
||||||
|
|
||||||
|
class TicketService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取工单列表业务逻辑
|
||||||
|
* @param array $params 外部传入的过滤参数
|
||||||
|
*/
|
||||||
|
|
||||||
|
public function getTicketList(array $params)
|
||||||
|
{
|
||||||
|
|
||||||
|
$query = Tickets::with(['ticketStaff', 'ticketCompany', 'ticketOperator']); // 查询构造器
|
||||||
|
|
||||||
|
// 状态筛选
|
||||||
|
if ($params['status'] !== null) {
|
||||||
|
$query->where('status', $params['status']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 运营人员筛选
|
||||||
|
if (!empty($params['operator_name'])) {
|
||||||
|
$query->where('operator_name', $params['operator_name']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 负责人筛选
|
||||||
|
if (!empty($params['username'])) {
|
||||||
|
$query->where('username', $params['username']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关键词搜索
|
||||||
|
if (!empty($params['searchKeyword'])) {
|
||||||
|
$query->where(function ($q) use ($params) {
|
||||||
|
$q->where('website', 'like', '%' . $params['searchKeyword'] . '%')
|
||||||
|
->whereOr('operator_name', 'like', '%' . $params['searchKeyword'] . '%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$order = strtolower($params['sortOrder']) === 'asc' ? 'asc' : 'desc';
|
||||||
|
|
||||||
|
|
||||||
|
// order -- 排序 , paginate -- 分页(查询当前页的数据,还会自动计算总记录数)
|
||||||
|
$list = $query->order('create_time', $order)->paginate(
|
||||||
|
$params['limit'],
|
||||||
|
false,
|
||||||
|
[
|
||||||
|
'page' => $params['page'],
|
||||||
|
'query' => $params // 保持分页链接的查询参数
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$list->each(function ($item) {
|
||||||
|
$item->hidden(['ticketStaff', 'ticketCompany', 'ticketOperator', 'company_id', 'operator_id', 'user_id']);
|
||||||
|
$item->append(['username', 'company_name', 'operator_name']);
|
||||||
|
|
||||||
|
return $item;
|
||||||
|
});
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增工单
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function createTicket($data)
|
||||||
|
{
|
||||||
|
if (empty($data['website'])) {
|
||||||
|
throw new \Exception('网站不能为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
$website = trim($data['website']);
|
||||||
|
|
||||||
|
// 并发锁
|
||||||
|
$lockKey = 'create_ticket_lock_' . md5($website);
|
||||||
|
|
||||||
|
if (Cache::has($lockKey)) {
|
||||||
|
throw new \Exception('当前该网址正在被创建工单中,请稍后重试');
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache::set($lockKey, 1, 5); // 锁定5秒
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 查找是否有未完成的同网站工单
|
||||||
|
$unfinishedTicket = Tickets::where('website', $website)
|
||||||
|
->whereIn('status', [0, 1])
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if ($unfinishedTicket) {
|
||||||
|
Cache::delete($lockKey);
|
||||||
|
throw new \Exception('已存在未完成的同网站工单,无法创建');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当前无相同网站
|
||||||
|
$ticketResult = Tickets::create($data);
|
||||||
|
return $ticketResult;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Cache::delete($lockKey);
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新工单
|
||||||
|
* @param $id 工单id
|
||||||
|
* @param $data 外部传入的更新数据
|
||||||
|
* @param $uid 当前登录用户id
|
||||||
|
* @param $role 当前登录用户角色
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function updateTicket($id, $data, $allowFields, $uid, $isSuper = false)
|
||||||
|
{
|
||||||
|
$ticket = Tickets::where('id', $id)->find();
|
||||||
|
|
||||||
|
if (!$ticket) {
|
||||||
|
throw new \Exception('工单不存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当不是管理员,进入判断
|
||||||
|
if (!$isSuper) {
|
||||||
|
if (!is_null($ticket->user_id) && $ticket->user_id != $uid) {
|
||||||
|
throw new \Exception('没有权限修改该工单');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 提取 $allowFields 允许修改的字段
|
||||||
|
$updateData = [];
|
||||||
|
foreach ($allowFields as $field) {
|
||||||
|
if (array_key_exists($field, $data)) {
|
||||||
|
$updateData[$field] = $data[$field];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有有效数据需要更新
|
||||||
|
if (empty($updateData)) {
|
||||||
|
throw new \Exception('没有合法的更新字段');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $ticket->save($updateData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有运营人员名称 (下拉筛选用)-仅限后台使用
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function getAllOperators()
|
||||||
|
{
|
||||||
|
$operators = CompanyOperators::with('company')->select();
|
||||||
|
|
||||||
|
$operators->each(function ($item) {
|
||||||
|
$item->hidden(['company_id', 'company', 'create_time', 'status']);
|
||||||
|
|
||||||
|
$item->append(['company_name']);
|
||||||
|
return $item;
|
||||||
|
});
|
||||||
|
|
||||||
|
return $operators;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取员工列表(下拉筛选用)
|
||||||
|
*/
|
||||||
|
public function getStaffList()
|
||||||
|
{
|
||||||
|
$map = [
|
||||||
|
'role' => 'user',
|
||||||
|
'status' => 1
|
||||||
|
];
|
||||||
|
|
||||||
|
$staffs = User::where($map)->field('id, username', 'real_name')->select();
|
||||||
|
return $staffs;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
app/event.php
Normal file
17
app/event.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
// 事件定义文件
|
||||||
|
return [
|
||||||
|
'bind' => [
|
||||||
|
],
|
||||||
|
|
||||||
|
'listen' => [
|
||||||
|
'AppInit' => [],
|
||||||
|
'HttpRun' => [],
|
||||||
|
'HttpEnd' => [],
|
||||||
|
'LogLevel' => [],
|
||||||
|
'LogWrite' => [],
|
||||||
|
],
|
||||||
|
|
||||||
|
'subscribe' => [
|
||||||
|
],
|
||||||
|
];
|
||||||
2
app/index/common.php
Normal file
2
app/index/common.php
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
// 这是系统自动生成的公共文件
|
||||||
43
app/index/controller/Login.php
Normal file
43
app/index/controller/Login.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\index\controller;
|
||||||
|
|
||||||
|
use app\BaseController;
|
||||||
|
use app\common\service\AuthService;
|
||||||
|
use think\facade\Session;
|
||||||
|
|
||||||
|
|
||||||
|
// 已完成
|
||||||
|
class Login extends BaseController
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
处理登录请求(已完成)
|
||||||
|
*/
|
||||||
|
public function login(AuthService $authService)
|
||||||
|
{
|
||||||
|
$params = $this->request->only(['username', 'password'], 'post');
|
||||||
|
|
||||||
|
// 验证数据
|
||||||
|
if (empty($params['username']) || empty($params['password'])) {
|
||||||
|
return json(['code' => 400, 'message' => '用户名和密码不能为空']);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $authService->login($params['username'], $params['password']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json(['code' => 400, 'message' => $e->getMessage(),'data' => []]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json(['code' => 200, 'message' => '登录成功', 'data' => $result]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
退出登录(已完成)
|
||||||
|
*/
|
||||||
|
protected function logout()
|
||||||
|
{
|
||||||
|
Session::clear();
|
||||||
|
return json(['code' => 200, 'message' => '退出成功']);
|
||||||
|
}
|
||||||
|
}
|
||||||
29
app/index/controller/Ticket.php
Normal file
29
app/index/controller/Ticket.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\index\controller;
|
||||||
|
|
||||||
|
use app\BaseController;
|
||||||
|
use app\common\service\TicketService;
|
||||||
|
use think\facade\Session;
|
||||||
|
|
||||||
|
class Ticket extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 更新工单(前台调用)
|
||||||
|
*/
|
||||||
|
public function updateTicket(TicketService $ticketService, $id)
|
||||||
|
{
|
||||||
|
|
||||||
|
$adminId = Session::get('id'); // 获取当前登录ID
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
$allowFields = ['datanum', 'progress', 'status', 'remark', 'lock_time'];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $ticketService->updateTicket($id, $data, $allowFields, $adminId, false);
|
||||||
|
return json(['code' => 200, 'msg' => '更新成功', 'data' => $result]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json(['code' => 400, 'msg' => $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
app/index/event.php
Normal file
5
app/index/event.php
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
// 这是系统自动生成的event定义文件
|
||||||
|
return [
|
||||||
|
|
||||||
|
];
|
||||||
5
app/index/middleware.php
Normal file
5
app/index/middleware.php
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
// 这是系统自动生成的middleware定义文件
|
||||||
|
return [
|
||||||
|
|
||||||
|
];
|
||||||
6
app/index/route/app.php
Normal file
6
app/index/route/app.php
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
|
||||||
|
Route::post('api/login', 'Login/login'); // 登录
|
||||||
10
app/middleware.php
Normal file
10
app/middleware.php
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
// 全局中间件定义文件
|
||||||
|
return [
|
||||||
|
// 全局请求缓存
|
||||||
|
// \think\middleware\CheckRequestCache::class,
|
||||||
|
// 多语言加载
|
||||||
|
// \think\middleware\LoadLangPack::class,
|
||||||
|
// Session初始化
|
||||||
|
\think\middleware\SessionInit::class
|
||||||
|
];
|
||||||
23
app/middleware/CheckLogin.php
Normal file
23
app/middleware/CheckLogin.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app\middleware;
|
||||||
|
use think\facade\Session;
|
||||||
|
class CheckLogin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 处理请求
|
||||||
|
*
|
||||||
|
* @param \think\Request $request
|
||||||
|
* @param \Closure $next
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function handle($request, \Closure $next)
|
||||||
|
{
|
||||||
|
if (!Session::has('user_info')) {
|
||||||
|
return json(['code' => 401, 'message' => '未登录']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
app/provider.php
Normal file
9
app/provider.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
use app\ExceptionHandle;
|
||||||
|
use app\Request;
|
||||||
|
|
||||||
|
// 容器Provider定义文件
|
||||||
|
return [
|
||||||
|
'think\Request' => Request::class,
|
||||||
|
'think\exception\Handle' => ExceptionHandle::class,
|
||||||
|
];
|
||||||
9
app/service.php
Normal file
9
app/service.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use app\AppService;
|
||||||
|
|
||||||
|
// 系统服务定义文件
|
||||||
|
// 服务在完成全局初始化之后执行
|
||||||
|
return [
|
||||||
|
AppService::class,
|
||||||
|
];
|
||||||
50
composer.json
Normal file
50
composer.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "topthink/think",
|
||||||
|
"description": "the new thinkphp framework",
|
||||||
|
"type": "project",
|
||||||
|
"keywords": [
|
||||||
|
"framework",
|
||||||
|
"thinkphp",
|
||||||
|
"ORM"
|
||||||
|
],
|
||||||
|
"homepage": "https://www.thinkphp.cn/",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "liu21st",
|
||||||
|
"email": "liu21st@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "yunwuxin",
|
||||||
|
"email": "448901948@qq.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.0.0",
|
||||||
|
"topthink/framework": "^8.0",
|
||||||
|
"topthink/think-orm": "^3.0|^4.0",
|
||||||
|
"topthink/think-filesystem": "^2.0|^3.0",
|
||||||
|
"topthink/think-multi-app": "^1.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"topthink/think-dumper": "^1.0",
|
||||||
|
"topthink/think-trace": "^2.0"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"app\\": "app"
|
||||||
|
},
|
||||||
|
"psr-0": {
|
||||||
|
"": "extend/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"preferred-install": "dist"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"post-autoload-dump": [
|
||||||
|
"@php think service:discover",
|
||||||
|
"@php think vendor:publish"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
30
config/app.php
Normal file
30
config/app.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 应用设置
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
return [
|
||||||
|
// 应用的命名空间
|
||||||
|
'app_namespace' => '',
|
||||||
|
// 是否启用路由
|
||||||
|
'with_route' => true,
|
||||||
|
// 默认应用
|
||||||
|
'default_app' => 'index',
|
||||||
|
// 默认时区
|
||||||
|
'default_timezone' => 'Asia/Shanghai',
|
||||||
|
|
||||||
|
// 应用映射(自动多应用模式有效)
|
||||||
|
'app_map' => [],
|
||||||
|
// 域名绑定(自动多应用模式有效)
|
||||||
|
'domain_bind' => [],
|
||||||
|
// 禁止URL访问的应用列表(自动多应用模式有效)
|
||||||
|
'deny_app_list' => [],
|
||||||
|
|
||||||
|
// 异常页面的模板文件
|
||||||
|
'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl',
|
||||||
|
|
||||||
|
// 错误显示信息,非调试模式有效
|
||||||
|
'error_message' => '页面错误!请稍后再试~',
|
||||||
|
// 显示错误信息
|
||||||
|
'show_error_msg' => false,
|
||||||
|
];
|
||||||
29
config/cache.php
Normal file
29
config/cache.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 缓存设置
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
return [
|
||||||
|
// 默认缓存驱动
|
||||||
|
'default' => 'file',
|
||||||
|
|
||||||
|
// 缓存连接方式配置
|
||||||
|
'stores' => [
|
||||||
|
'file' => [
|
||||||
|
// 驱动方式
|
||||||
|
'type' => 'File',
|
||||||
|
// 缓存保存目录
|
||||||
|
'path' => '',
|
||||||
|
// 缓存前缀
|
||||||
|
'prefix' => '',
|
||||||
|
// 缓存有效期 0表示永久缓存
|
||||||
|
'expire' => 0,
|
||||||
|
// 缓存标签前缀
|
||||||
|
'tag_prefix' => 'tag:',
|
||||||
|
// 序列化机制 例如 ['serialize', 'unserialize']
|
||||||
|
'serialize' => [],
|
||||||
|
],
|
||||||
|
// 更多的缓存连接
|
||||||
|
],
|
||||||
|
];
|
||||||
9
config/console.php
Normal file
9
config/console.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 控制台配置
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
return [
|
||||||
|
// 指令定义
|
||||||
|
'commands' => [
|
||||||
|
],
|
||||||
|
];
|
||||||
20
config/cookie.php
Normal file
20
config/cookie.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Cookie设置
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
return [
|
||||||
|
// cookie 保存时间
|
||||||
|
'expire' => 0,
|
||||||
|
// cookie 保存路径
|
||||||
|
'path' => '/',
|
||||||
|
// cookie 有效域名
|
||||||
|
'domain' => '',
|
||||||
|
// cookie 启用安全传输
|
||||||
|
'secure' => false,
|
||||||
|
// httponly设置
|
||||||
|
'httponly' => false,
|
||||||
|
// 是否使用 setcookie
|
||||||
|
'setcookie' => true,
|
||||||
|
// samesite 设置,支持 'strict' 'lax'
|
||||||
|
'samesite' => '',
|
||||||
|
];
|
||||||
63
config/database.php
Normal file
63
config/database.php
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
// 默认使用的数据库连接配置
|
||||||
|
'default' => env('DB_DRIVER', 'mysql'),
|
||||||
|
|
||||||
|
// 自定义时间查询规则
|
||||||
|
'time_query_rule' => [],
|
||||||
|
|
||||||
|
// 自动写入时间戳字段
|
||||||
|
// true为自动识别类型 false关闭
|
||||||
|
// 字符串则明确指定时间字段类型 支持 int timestamp datetime date
|
||||||
|
'auto_timestamp' => true,
|
||||||
|
|
||||||
|
// 时间字段取出后的默认时间格式
|
||||||
|
'datetime_format' => 'Y-m-d H:i:s',
|
||||||
|
|
||||||
|
// 时间字段配置 配置格式:create_time,update_time
|
||||||
|
'datetime_field' => '',
|
||||||
|
|
||||||
|
// 数据库连接配置信息
|
||||||
|
'connections' => [
|
||||||
|
'mysql' => [
|
||||||
|
// 数据库类型
|
||||||
|
'type' => env('DB_TYPE', 'mysql'),
|
||||||
|
// 服务器地址
|
||||||
|
'hostname' => env('DB_HOST', '127.0.0.1'),
|
||||||
|
// 数据库名
|
||||||
|
'database' => env('DB_NAME', ''),
|
||||||
|
// 用户名
|
||||||
|
'username' => env('DB_USER', 'root'),
|
||||||
|
// 密码
|
||||||
|
'password' => env('DB_PASS', ''),
|
||||||
|
// 端口
|
||||||
|
'hostport' => env('DB_PORT', '3306'),
|
||||||
|
// 数据库连接参数
|
||||||
|
'params' => [],
|
||||||
|
// 数据库编码
|
||||||
|
'charset' => env('DB_CHARSET', 'utf8mb4'),
|
||||||
|
// 数据库表前缀
|
||||||
|
'prefix' => env('DB_PREFIX', ''),
|
||||||
|
|
||||||
|
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
|
||||||
|
'deploy' => 0,
|
||||||
|
// 数据库读写是否分离 主从式有效
|
||||||
|
'rw_separate' => false,
|
||||||
|
// 读写分离后 主服务器数量
|
||||||
|
'master_num' => 1,
|
||||||
|
// 指定从服务器序号
|
||||||
|
'slave_no' => '',
|
||||||
|
// 是否严格检查字段是否存在
|
||||||
|
'fields_strict' => true,
|
||||||
|
// 是否需要断线重连
|
||||||
|
'break_reconnect' => false,
|
||||||
|
// 监听SQL
|
||||||
|
'trigger_sql' => env('APP_DEBUG', true),
|
||||||
|
// 开启字段缓存
|
||||||
|
'fields_cache' => false,
|
||||||
|
],
|
||||||
|
|
||||||
|
// 更多的数据库配置信息
|
||||||
|
],
|
||||||
|
];
|
||||||
24
config/filesystem.php
Normal file
24
config/filesystem.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
// 默认磁盘
|
||||||
|
'default' => 'local',
|
||||||
|
// 磁盘列表
|
||||||
|
'disks' => [
|
||||||
|
'local' => [
|
||||||
|
'type' => 'local',
|
||||||
|
'root' => app()->getRuntimePath() . 'storage',
|
||||||
|
],
|
||||||
|
'public' => [
|
||||||
|
// 磁盘类型
|
||||||
|
'type' => 'local',
|
||||||
|
// 磁盘路径
|
||||||
|
'root' => app()->getRootPath() . 'public/storage',
|
||||||
|
// 磁盘路径对应的外部URL路径
|
||||||
|
'url' => '/storage',
|
||||||
|
// 可见性
|
||||||
|
'visibility' => 'public',
|
||||||
|
],
|
||||||
|
// 更多的磁盘配置信息
|
||||||
|
],
|
||||||
|
];
|
||||||
29
config/lang.php
Normal file
29
config/lang.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 多语言设置
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
return [
|
||||||
|
// 默认语言
|
||||||
|
'default_lang' => env('DEFAULT_LANG', 'zh-cn'),
|
||||||
|
// 自动侦测浏览器语言
|
||||||
|
'auto_detect_browser' => true,
|
||||||
|
// 允许的语言列表
|
||||||
|
'allow_lang_list' => [],
|
||||||
|
// 多语言自动侦测变量名
|
||||||
|
'detect_var' => 'lang',
|
||||||
|
// 是否使用Cookie记录
|
||||||
|
'use_cookie' => true,
|
||||||
|
// 多语言cookie变量
|
||||||
|
'cookie_var' => 'think_lang',
|
||||||
|
// 多语言header变量
|
||||||
|
'header_var' => 'think-lang',
|
||||||
|
// 扩展语言包
|
||||||
|
'extend_list' => [],
|
||||||
|
// Accept-Language转义为对应语言包名称
|
||||||
|
'accept_language' => [
|
||||||
|
'zh-hans-cn' => 'zh-cn',
|
||||||
|
],
|
||||||
|
// 是否支持语言分组
|
||||||
|
'allow_group' => false,
|
||||||
|
];
|
||||||
45
config/log.php
Normal file
45
config/log.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 日志设置
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
return [
|
||||||
|
// 默认日志记录通道
|
||||||
|
'default' => 'file',
|
||||||
|
// 日志记录级别
|
||||||
|
'level' => [],
|
||||||
|
// 日志类型记录的通道 ['error'=>'email',...]
|
||||||
|
'type_channel' => [],
|
||||||
|
// 关闭全局日志写入
|
||||||
|
'close' => false,
|
||||||
|
// 全局日志处理 支持闭包
|
||||||
|
'processor' => null,
|
||||||
|
|
||||||
|
// 日志通道列表
|
||||||
|
'channels' => [
|
||||||
|
'file' => [
|
||||||
|
// 日志记录方式
|
||||||
|
'type' => 'File',
|
||||||
|
// 日志保存目录
|
||||||
|
'path' => '',
|
||||||
|
// 单文件日志写入
|
||||||
|
'single' => false,
|
||||||
|
// 独立日志级别
|
||||||
|
'apart_level' => [],
|
||||||
|
// 最大日志文件数量
|
||||||
|
'max_files' => 0,
|
||||||
|
// 使用JSON格式记录
|
||||||
|
'json' => false,
|
||||||
|
// 日志处理
|
||||||
|
'processor' => null,
|
||||||
|
// 关闭通道日志写入
|
||||||
|
'close' => false,
|
||||||
|
// 日志输出格式化
|
||||||
|
'format' => '[%s][%s] %s',
|
||||||
|
// 是否实时写入
|
||||||
|
'realtime_write' => false,
|
||||||
|
],
|
||||||
|
// 其它日志通道配置
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
8
config/middleware.php
Normal file
8
config/middleware.php
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
// 中间件配置
|
||||||
|
return [
|
||||||
|
// 别名或分组
|
||||||
|
'alias' => [],
|
||||||
|
// 优先级设置,此数组中的中间件会按照数组中的顺序优先执行
|
||||||
|
'priority' => [],
|
||||||
|
];
|
||||||
55
config/route.php
Normal file
55
config/route.php
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 路由设置
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
return [
|
||||||
|
// pathinfo分隔符
|
||||||
|
'pathinfo_depr' => '/',
|
||||||
|
// 是否开启路由延迟解析
|
||||||
|
'url_lazy_route' => false,
|
||||||
|
// 是否强制使用路由
|
||||||
|
'url_route_must' => false,
|
||||||
|
// 是否区分大小写
|
||||||
|
'url_case_sensitive' => false,
|
||||||
|
// 自动扫描子目录分组
|
||||||
|
'route_auto_group' => false,
|
||||||
|
// 合并路由规则
|
||||||
|
'route_rule_merge' => false,
|
||||||
|
// 路由是否完全匹配
|
||||||
|
'route_complete_match' => false,
|
||||||
|
// 去除斜杠
|
||||||
|
'remove_slash' => false,
|
||||||
|
// 默认的路由变量规则
|
||||||
|
'default_route_pattern' => '[\w\.]+',
|
||||||
|
// URL伪静态后缀
|
||||||
|
'url_html_suffix' => 'html',
|
||||||
|
// 访问控制器层名称
|
||||||
|
'controller_layer' => 'controller',
|
||||||
|
// 空控制器名
|
||||||
|
'empty_controller' => 'Error',
|
||||||
|
// 是否使用控制器后缀
|
||||||
|
'controller_suffix' => false,
|
||||||
|
// 默认模块名(开启自动多模块有效)
|
||||||
|
'default_module' => 'index',
|
||||||
|
// 默认控制器名
|
||||||
|
'default_controller' => 'Index',
|
||||||
|
// 默认操作名
|
||||||
|
'default_action' => 'index',
|
||||||
|
// 操作方法后缀
|
||||||
|
'action_suffix' => '',
|
||||||
|
// 非路由变量是否使用普通参数方式(用于URL生成)
|
||||||
|
'url_common_param' => true,
|
||||||
|
// 操作方法的参数绑定方式 route get param
|
||||||
|
'action_bind_param' => 'get',
|
||||||
|
// 请求缓存规则 true为自动规则
|
||||||
|
'request_cache_key' => true,
|
||||||
|
// 请求缓存有效期
|
||||||
|
'request_cache_expire' => null,
|
||||||
|
// 全局请求缓存排除规则
|
||||||
|
'request_cache_except' => [],
|
||||||
|
// 请求缓存的Tag
|
||||||
|
'request_cache_tag' => '',
|
||||||
|
// API版本header变量
|
||||||
|
'api_version' => 'Api-Version',
|
||||||
|
];
|
||||||
19
config/session.php
Normal file
19
config/session.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 会话设置
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
return [
|
||||||
|
// session name
|
||||||
|
'name' => 'PHPSESSID',
|
||||||
|
// SESSION_ID的提交变量,解决flash上传跨域
|
||||||
|
'var_session_id' => '',
|
||||||
|
// 驱动方式 支持file cache
|
||||||
|
'type' => 'file',
|
||||||
|
// 存储连接标识 当type使用cache的时候有效
|
||||||
|
'store' => null,
|
||||||
|
// 过期时间
|
||||||
|
'expire' => 86400,
|
||||||
|
// 前缀
|
||||||
|
'prefix' => '',
|
||||||
|
];
|
||||||
10
config/trace.php
Normal file
10
config/trace.php
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Trace设置 开启调试模式后有效
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
return [
|
||||||
|
// 内置Html和Console两种方式 支持扩展
|
||||||
|
'type' => 'Html',
|
||||||
|
// 读取的日志通道名
|
||||||
|
'channel' => '',
|
||||||
|
];
|
||||||
25
config/view.php
Normal file
25
config/view.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 模板设置
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
return [
|
||||||
|
// 模板引擎类型使用Think
|
||||||
|
'type' => 'Think',
|
||||||
|
// 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法
|
||||||
|
'auto_rule' => 1,
|
||||||
|
// 模板目录名
|
||||||
|
'view_dir_name' => 'view',
|
||||||
|
// 模板后缀
|
||||||
|
'view_suffix' => 'html',
|
||||||
|
// 模板文件名分隔符
|
||||||
|
'view_depr' => DIRECTORY_SEPARATOR,
|
||||||
|
// 模板引擎普通标签开始标记
|
||||||
|
'tpl_begin' => '{',
|
||||||
|
// 模板引擎普通标签结束标记
|
||||||
|
'tpl_end' => '}',
|
||||||
|
// 标签库标签开始标记
|
||||||
|
'taglib_begin' => '{',
|
||||||
|
// 标签库标签结束标记
|
||||||
|
'taglib_end' => '}',
|
||||||
|
];
|
||||||
2
extend/.gitignore
vendored
Normal file
2
extend/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
0
public/.htaccess
Normal file
0
public/.htaccess
Normal file
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
25
public/index.php
Normal file
25
public/index.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006-2019 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
use think\App;
|
||||||
|
|
||||||
|
// [ 应用入口文件 ]
|
||||||
|
|
||||||
|
require __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
// 执行HTTP应用并响应
|
||||||
|
$http = (new App())->http;
|
||||||
|
|
||||||
|
$response = $http->run();
|
||||||
|
|
||||||
|
$response->send();
|
||||||
|
|
||||||
|
$http->end($response);
|
||||||
9
public/nginx.htaccess
Normal file
9
public/nginx.htaccess
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
location ~* (runtime|application)/{
|
||||||
|
return 403;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
if (!-e $request_filename){
|
||||||
|
rewrite ^(.*)$ /index.php?s=$1 last; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
2
public/robots.txt
Normal file
2
public/robots.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
19
public/router.php
Normal file
19
public/router.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// $Id$
|
||||||
|
|
||||||
|
if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$_SERVER["SCRIPT_FILENAME"] = __DIR__ . '/index.php';
|
||||||
|
|
||||||
|
require __DIR__ . "/index.php";
|
||||||
|
}
|
||||||
2
public/static/.gitignore
vendored
Normal file
2
public/static/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
5
route/app.php
Normal file
5
route/app.php
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
|
||||||
|
// Route::post('api/login', 'index/Login/login'); // 登录
|
||||||
2
runtime/.gitignore
vendored
Normal file
2
runtime/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
11
think
Normal file
11
think
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use think\App;
|
||||||
|
|
||||||
|
// 命令行入口文件
|
||||||
|
// 加载基础文件
|
||||||
|
require __DIR__ . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
// 应用初始化
|
||||||
|
(new App())->console->run();
|
||||||
1
view/README.md
Normal file
1
view/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
如果不使用模板,可以删除该目录
|
||||||
Reference in New Issue
Block a user