Merge branch 'develop' into feature/crmAdmin
This commit is contained in:
@@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\controller;
|
||||||
|
|
||||||
|
use app\common\service\OssService;
|
||||||
|
use app\common\traits\ResponseTrait;
|
||||||
|
use support\Request;
|
||||||
|
use Shopwwi\WebmanFilesystem\Facade\Storage;
|
||||||
|
|
||||||
|
class UploadController
|
||||||
|
{
|
||||||
|
|
||||||
|
use ResponseTrait;
|
||||||
|
|
||||||
|
public function upload(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$scene = $request->input('scene', 'image');
|
||||||
|
$file = $request->file('file');
|
||||||
|
if ($file && $file->isValid()) {
|
||||||
|
$pathUrl = '/uploads/'.$scene.'/'.date('Ymd').'/'.md5($file->getUploadName() . time()).'.'.$file->getUploadExtension();
|
||||||
|
$fullPathUrl = public_path() . $pathUrl;
|
||||||
|
$file->move($fullPathUrl);
|
||||||
|
$data = [
|
||||||
|
'domain' => getenv('MAIN_DOMAIN'),
|
||||||
|
'file_url' => $pathUrl,
|
||||||
|
'full_url' => getenv('MAIN_DOMAIN') . $pathUrl,
|
||||||
|
'scene' => $scene,
|
||||||
|
];
|
||||||
|
return $this->success($data, 'upload success');
|
||||||
|
}
|
||||||
|
return $this->error('file not found');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $this->error($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传单文件附件
|
||||||
|
public function uploadFile(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$file = $request->file('file');
|
||||||
|
|
||||||
|
if (!$file || !$file->isValid()) {
|
||||||
|
return $this->error('上传失败');
|
||||||
|
}
|
||||||
|
$originalName = $file->getUploadName();
|
||||||
|
|
||||||
|
$result = Storage::adapter('oss')
|
||||||
|
->path('vehicle_album/'.date('Ymd'))
|
||||||
|
->size(1024*1024*5)
|
||||||
|
->upload($file);
|
||||||
|
|
||||||
|
$ossservice = new OssService();
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'original_name' => $originalName,
|
||||||
|
'file_name' => $result->file_name,
|
||||||
|
'file_url' => $ossservice->generatePrivateUrl($result->file_name)
|
||||||
|
];
|
||||||
|
|
||||||
|
return $this->success($data);
|
||||||
|
}catch (\Throwable $e){
|
||||||
|
return $this->error($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传单文件图片
|
||||||
|
public function uploadImage(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$file = $request->file('image');
|
||||||
|
|
||||||
|
if (!$file || !$file->isValid()) {
|
||||||
|
return $this->error('上传失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = Storage::adapter('oss')
|
||||||
|
->path('vehicle_album/'.date('Ymd'))
|
||||||
|
->size(1024*1024*5)
|
||||||
|
->extYes(['image/jpeg','image/png'])
|
||||||
|
->extNo(['image/gif'])
|
||||||
|
->upload($file);
|
||||||
|
|
||||||
|
$ossservice = new OssService();
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'href' => $result->file_name,
|
||||||
|
'alt' => '',
|
||||||
|
'url' => $ossservice->generatePrivateUrl($result->file_name)
|
||||||
|
];
|
||||||
|
|
||||||
|
return json(['errno' => 0, 'data' => $data]);
|
||||||
|
// return $this->success($data);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return json(['errno' => 1, 'message' => $e->getMessage()]);
|
||||||
|
// return $this->error($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function proxy(Request $request)
|
||||||
|
{
|
||||||
|
$filePath = $request->get('file'); // 原OSS文件路径
|
||||||
|
try {
|
||||||
|
// 生成签名URL
|
||||||
|
$signedUrl = (new \app\common\service\OssService())->generatePrivateUrl($filePath);
|
||||||
|
|
||||||
|
// 获取图片数据并返回
|
||||||
|
$imageData = file_get_contents($signedUrl);
|
||||||
|
|
||||||
|
// 根据文件类型设置Content-Type
|
||||||
|
$mime = mime_content_type('data://application/octet-stream;base64,'.base64_encode($imageData));
|
||||||
|
|
||||||
|
return response($imageData, 200, [
|
||||||
|
'Content-Type' => $mime,
|
||||||
|
'Cache-Control' => 'public, max-age=600' // 客户端缓存10分钟
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response('Image not found '.$e->getMessage(), 404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\service;
|
||||||
|
|
||||||
|
use OSS\OssClient;
|
||||||
|
use OSS\Core\OssException;
|
||||||
|
use support\exception\BusinessException;
|
||||||
|
|
||||||
|
class OssService
|
||||||
|
{
|
||||||
|
private $accessKeyId;
|
||||||
|
private $accessKeySecret;
|
||||||
|
private $bucket;
|
||||||
|
private $endpoint;
|
||||||
|
private $ossClient;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->accessKeyId = getenv('OSS_ACCESSID');
|
||||||
|
$this->accessKeySecret = getenv('OSS_ACCESSSECRET');
|
||||||
|
$this->bucket = getenv('OSS_BUCKET');
|
||||||
|
$this->endpoint = getenv('OSS_ENDPOINT');
|
||||||
|
$this->ossClient = new OssClient($this->accessKeyId, $this->accessKeySecret, $this->endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传图片到 OSS
|
||||||
|
* @param string $filePath 本地文件路径
|
||||||
|
* @param string $objectKey OSS上存储的对象名称
|
||||||
|
* @return string 图片的 URL
|
||||||
|
*/
|
||||||
|
public function uploadImage($filePath, $objectKey)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 上传文件到 OSS
|
||||||
|
$this->ossClient->uploadFile($this->bucket, $objectKey, $filePath);
|
||||||
|
// 构造图片的私有 URL
|
||||||
|
$url = $this->generatePrivateUrl($objectKey);
|
||||||
|
return $url;
|
||||||
|
} catch (OssException $e) {
|
||||||
|
// 错误处理
|
||||||
|
throw new \RuntimeException('OSS Error: ' . $e->getMessage());
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
// 错误处理
|
||||||
|
throw new BusinessException('Error: ' . $th->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成图片的私有访问 URL
|
||||||
|
* @param string $objectKey
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function generatePrivateUrl($objectKey, $expireTime = 3600)
|
||||||
|
{
|
||||||
|
// 生成 OSS 私有 URL(有效期为 3600 秒)
|
||||||
|
return $this->ossClient->signUrl($this->bucket, $objectKey, $expireTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,3 +2,25 @@
|
|||||||
/**
|
/**
|
||||||
* Here is your custom functions.
|
* Here is your custom functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use support\exception\BusinessException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取配置
|
||||||
|
*/
|
||||||
|
function getConfig($filePath = null)
|
||||||
|
{
|
||||||
|
// 构建文件路径
|
||||||
|
$config_file = app_path($filePath);
|
||||||
|
// 检查文件是否存在
|
||||||
|
if (!file_exists($config_file)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
// 包含文件并获取返回的数组
|
||||||
|
$config = include $config_file;
|
||||||
|
// 验证是否为数组
|
||||||
|
if (!is_array($config)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\middleware;
|
||||||
|
|
||||||
|
use Webman\MiddlewareInterface;
|
||||||
|
use Webman\Http\Response;
|
||||||
|
use Webman\Http\Request;
|
||||||
|
|
||||||
|
class AccessControl implements MiddlewareInterface
|
||||||
|
{
|
||||||
|
public function process(Request $request, callable $handler) : Response
|
||||||
|
{
|
||||||
|
// 如果是options请求则返回一个空响应,否则继续向洋葱芯穿越,并得到一个响应
|
||||||
|
$response = $request->method() == 'OPTIONS' ? response('') : $handler($request);
|
||||||
|
|
||||||
|
// 给响应添加跨域相关的http头
|
||||||
|
$response->withHeaders([
|
||||||
|
'Access-Control-Allow-Credentials' => 'true',
|
||||||
|
'Access-Control-Allow-Origin' => $request->header('origin', '*'),
|
||||||
|
'Access-Control-Allow-Methods' => $request->header('access-control-request-method', '*'),
|
||||||
|
'Access-Control-Allow-Headers' => $request->header('access-control-request-headers', '*'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
// 定义所有需要多语言支持的实体
|
||||||
|
'entities' => [
|
||||||
|
'ticket_categorie' => [
|
||||||
|
'translation_model' => \app\ticket\model\CategorieTranslation::class,
|
||||||
|
'foreign_key' => 'categorie_id',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
// 默认支持的目标语种列表
|
||||||
|
'locales' => ['zh','en','ru','ar'],
|
||||||
|
];
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\queue\translation\jobs;
|
||||||
|
|
||||||
|
use support\Log;
|
||||||
|
use app\queue\translation\service\TranslatorClient;
|
||||||
|
|
||||||
|
class TranslationJob
|
||||||
|
{
|
||||||
|
protected $config = [];
|
||||||
|
protected array $payload;
|
||||||
|
|
||||||
|
public function __construct(array $payload)
|
||||||
|
{
|
||||||
|
$this->config = getConfig('/queue/translation/config/trans.php');
|
||||||
|
$this->payload = $payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
$cfgAll = $this->config['entities'];
|
||||||
|
$pt = $this->payload;
|
||||||
|
$type = $pt['entityType'];
|
||||||
|
$id = $pt['entityId'];
|
||||||
|
$locale = $pt['locale'];
|
||||||
|
$sourceLocale = $pt['sourceLocale'];
|
||||||
|
$sourceFields = $pt['sourceFields'];
|
||||||
|
$clientFields = $pt['clientFields'];
|
||||||
|
|
||||||
|
if (! isset($cfgAll[$type])) {
|
||||||
|
Log::warning("TranslationJob: 未配置实体 {$type}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cfg = $cfgAll[$type];
|
||||||
|
$modelClass = $cfg['translation_model'];
|
||||||
|
$foreignKey = $cfg['foreign_key'];
|
||||||
|
|
||||||
|
// 决定采用前端提供、源语种还是第三方翻译
|
||||||
|
if (! empty($clientFields)) {
|
||||||
|
$fields = $clientFields;
|
||||||
|
} elseif ($locale === $sourceLocale) {
|
||||||
|
$fields = $sourceFields;
|
||||||
|
} else {
|
||||||
|
$translator = new TranslatorClient();
|
||||||
|
$fields = [];
|
||||||
|
foreach ($sourceFields as $key => $text) {
|
||||||
|
$fields[$key] = $translator->translate($text, $sourceLocale, $locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写库
|
||||||
|
try {
|
||||||
|
$modelClass::updateOrCreate(
|
||||||
|
[
|
||||||
|
$foreignKey => $id,
|
||||||
|
'locale' => $locale,
|
||||||
|
],
|
||||||
|
array_merge($fields, ['locale' => $locale])
|
||||||
|
);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error("TranslationJob 保存失败: {$type}#{$id} locale={$locale}: ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\queue\translation\queue;
|
||||||
|
|
||||||
|
use support\Log;
|
||||||
|
use Webman\RedisQueue\Consumer;
|
||||||
|
use app\queue\translation\jobs\TranslationJob;
|
||||||
|
|
||||||
|
class Translation implements Consumer
|
||||||
|
{
|
||||||
|
// 要消费的队列名
|
||||||
|
public $queue = 'transTask';
|
||||||
|
|
||||||
|
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
||||||
|
public $connection = 'default';
|
||||||
|
|
||||||
|
// 消费
|
||||||
|
public function consume($data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 无需反序列化
|
||||||
|
// var_export($data); // 输出 ['to' => 'tom@gmail.com', 'content' => 'hello']
|
||||||
|
|
||||||
|
$job = new TranslationJob($data);
|
||||||
|
$job->handle();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error("TranslationService 异步任务异常: ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 消费失败回调
|
||||||
|
/*
|
||||||
|
$package = [
|
||||||
|
'id' => 1357277951, // 消息ID
|
||||||
|
'time' => 1709170510, // 消息时间
|
||||||
|
'delay' => 0, // 延迟时间
|
||||||
|
'attempts' => 2, // 消费次数
|
||||||
|
'queue' => 'send-mail', // 队列名
|
||||||
|
'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容
|
||||||
|
'max_attempts' => 5, // 最大重试次数
|
||||||
|
'error' => '错误信息' // 错误信息
|
||||||
|
]
|
||||||
|
*/
|
||||||
|
public function onConsumeFailure(\Throwable $e, $package)
|
||||||
|
{
|
||||||
|
echo "consume failure\n";
|
||||||
|
echo $e->getMessage() . "\n";
|
||||||
|
// 无需反序列化
|
||||||
|
var_export($package);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\queue\translation\service;
|
||||||
|
|
||||||
|
// use Webman\RedisQueue\Client;
|
||||||
|
use Webman\RedisQueue\Redis;
|
||||||
|
|
||||||
|
class TranslationService
|
||||||
|
{
|
||||||
|
|
||||||
|
// 配置
|
||||||
|
protected $config = [];
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->config = getConfig('/queue/translation/config/trans.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步排队所有语种的翻译任务
|
||||||
|
*
|
||||||
|
* @param string $entityType 实体名,如 'vehicle'
|
||||||
|
* @param int $entityId 主表 ID
|
||||||
|
* @param string $sourceLocale 源语种,如 'zh'
|
||||||
|
* @param array $sourceFields 源语种字段 ['name'=>…,'condition_desc'=>…]
|
||||||
|
* @param array $clientFields 前端已传翻译 ['en'=>[...], …]
|
||||||
|
*/
|
||||||
|
public function queueTranslations(string $entityType, int $entityId, string $sourceLocale, array $sourceFields, array $clientFields = []): void
|
||||||
|
{
|
||||||
|
foreach ($this->config['locales'] as $locale) {
|
||||||
|
$payload = [
|
||||||
|
'entityType' => $entityType,
|
||||||
|
'entityId' => $entityId,
|
||||||
|
'locale' => $locale,
|
||||||
|
'sourceLocale' => $sourceLocale,
|
||||||
|
'sourceFields' => $sourceFields,
|
||||||
|
'clientFields' => $clientFields[$locale] ?? [],
|
||||||
|
];
|
||||||
|
Redis::send('transTask', $payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\queue\translation\service;
|
||||||
|
|
||||||
|
use app\queue\utils\XunfeiFanyi;
|
||||||
|
use support\Log;
|
||||||
|
|
||||||
|
class TranslatorClient
|
||||||
|
{
|
||||||
|
|
||||||
|
// protected string $endpoint;
|
||||||
|
// protected string $apiKey;
|
||||||
|
|
||||||
|
// public function __construct()
|
||||||
|
// {
|
||||||
|
// $this->endpoint = env('TRANSLATION_API_URL');
|
||||||
|
// $this->apiKey = env('TRANSLATION_API_KEY');
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 翻译文本
|
||||||
|
* @throws \RuntimeException
|
||||||
|
*/
|
||||||
|
public function translate(string $text, string $from = 'cn', string $to = 'ru'): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$xunfei = new XunfeiFanyi();
|
||||||
|
$rst_dst = $xunfei->fanyi($text, $from, $to);
|
||||||
|
if ($rst_dst) {
|
||||||
|
return $rst_dst["trans_result"]["dst"];
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error("TranslatorClient 错误: ".$e->getMessage());
|
||||||
|
throw new \RuntimeException('翻译服务调用失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\queue\utils;
|
||||||
|
|
||||||
|
class Translat
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 从$data中提取出源文本字段,并从$data里删除它们
|
||||||
|
*/
|
||||||
|
public static function extractSourceFields(array &$data,array $translat): array
|
||||||
|
{
|
||||||
|
$source = [];
|
||||||
|
foreach ($translat as $field) {
|
||||||
|
if (array_key_exists($field, $data)) {
|
||||||
|
$source[$field] = $data[$field];
|
||||||
|
unset($data[$field]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $source;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\queue\utils;
|
||||||
|
|
||||||
|
|
||||||
|
class XunfeiFanyi
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $error = "";
|
||||||
|
|
||||||
|
public function tocurl($url, $header, $content)
|
||||||
|
{
|
||||||
|
$ch = curl_init();
|
||||||
|
if(substr($url,0,5)=='https'){
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
|
||||||
|
curl_setopt($ch, CURLOPT_SSLVERSION, 1);
|
||||||
|
}
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $url);
|
||||||
|
if (is_array($header)) {
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||||
|
}
|
||||||
|
curl_setopt($ch, CURLOPT_POST, true);
|
||||||
|
if (!empty($content)) {
|
||||||
|
if (is_array($content)) {
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($content));
|
||||||
|
} else if (is_string($content)) {
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$response = curl_exec($ch);
|
||||||
|
$error=curl_error($ch);
|
||||||
|
//var_dump($error);
|
||||||
|
if($error){
|
||||||
|
die($error);
|
||||||
|
}
|
||||||
|
$header = curl_getinfo($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
$data = array('header' => $header,'body' => $response);
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function xfyun($text = "中华人民共和国于1949年成立", $from = "cn", $to = "en")
|
||||||
|
{
|
||||||
|
//在控制台-我的应用-机器翻译获取
|
||||||
|
$app_id = "3d46198c";
|
||||||
|
//在控制台-我的应用-机器翻译获取
|
||||||
|
$api_sec = "ZWY2MmUyNjJjYmFkOTFlYTVmYWVhMGYy";
|
||||||
|
//在控制台-我的应用-机器翻译获取
|
||||||
|
$api_key = "b6d805f240176ecaea85130cb5f2bca1";
|
||||||
|
// 机器翻译接口地址
|
||||||
|
$url = "https://ntrans.xfyun.cn/v2/ots";
|
||||||
|
//body组装
|
||||||
|
// $text = "中华人民共和国于1949年成立";//待翻译文本
|
||||||
|
$body = json_encode($this->getBody($app_id, $from, $to, $text));
|
||||||
|
|
||||||
|
// 组装http请求头
|
||||||
|
$date =gmdate('D, d M Y H:i:s') . ' GMT';
|
||||||
|
|
||||||
|
$digestBase64 = "SHA-256=".base64_encode(hash("sha256", $body, true));
|
||||||
|
$builder = sprintf("host: %s
|
||||||
|
date: %s
|
||||||
|
POST /v2/ots HTTP/1.1
|
||||||
|
digest: %s", "ntrans.xfyun.cn", $date, $digestBase64);
|
||||||
|
// echo($builder);
|
||||||
|
$sha = base64_encode(hash_hmac("sha256", $builder, $api_sec, true));
|
||||||
|
|
||||||
|
$authorization = sprintf("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", $api_key,"hmac-sha256",
|
||||||
|
"host date request-line digest", $sha);
|
||||||
|
|
||||||
|
$header = [
|
||||||
|
"Authorization: ".$authorization,
|
||||||
|
'Content-Type: application/json',
|
||||||
|
'Accept: application/json,version=1.0',
|
||||||
|
'Host: ntrans.xfyun.cn',
|
||||||
|
'Date: ' .$date,
|
||||||
|
'Digest: '.$digestBase64
|
||||||
|
];
|
||||||
|
$response = $this->tocurl($url, $header, $body);
|
||||||
|
|
||||||
|
// var_dump($response['body']);
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getBody($app_id, $from, $to, $text)
|
||||||
|
{
|
||||||
|
$common_param = [
|
||||||
|
'app_id' => $app_id
|
||||||
|
];
|
||||||
|
|
||||||
|
$business = [
|
||||||
|
'from' => $from,
|
||||||
|
'to' => $to,
|
||||||
|
];
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
"text" => base64_encode($text)
|
||||||
|
];
|
||||||
|
|
||||||
|
return $body = [
|
||||||
|
'common' => $common_param,
|
||||||
|
'business' => $business,
|
||||||
|
'data' => $data
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 翻译
|
||||||
|
public function fanyi($text = "", $from = "", $to = "")
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$res = $this->xfyun($text, $from, $to);
|
||||||
|
$data = json_decode($res["body"], true);
|
||||||
|
if ($data["code"] === 0) {
|
||||||
|
return $data["data"]["result"];
|
||||||
|
} else {
|
||||||
|
$this->error = $data["message"];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
$this->error = $th->getMessage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异常
|
||||||
|
public function error()
|
||||||
|
{
|
||||||
|
return $this->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\controller;
|
||||||
|
|
||||||
|
use app\ticket\service\TicketService;
|
||||||
|
use support\Request;
|
||||||
|
|
||||||
|
class AttachmentController extends BaseController
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\controller;
|
||||||
|
|
||||||
|
use support\Request;
|
||||||
|
use support\Response;
|
||||||
|
use support\exception\BusinessException;
|
||||||
|
use app\common\traits\ResponseTrait;
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
abstract class BaseController
|
||||||
|
{
|
||||||
|
use ResponseTrait;
|
||||||
|
|
||||||
|
protected mixed $validator = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证数据
|
||||||
|
*
|
||||||
|
* @param Validate $validator 验证器实例
|
||||||
|
* @param array $data 待验证的数据
|
||||||
|
* @param string $scene 验证场景
|
||||||
|
* @return array 验证后的数据
|
||||||
|
* @throws BusinessException 验证失败时抛出业务异常
|
||||||
|
*/
|
||||||
|
public function validate(Validate $validator, array $data, string $scene = ''): array
|
||||||
|
{
|
||||||
|
// 如果指定了验证场景,并且验证器支持场景方法,则设置验证场景
|
||||||
|
if ($scene && method_exists($validator, 'scene')) {
|
||||||
|
$validator->scene($scene);
|
||||||
|
}
|
||||||
|
// 执行数据验证
|
||||||
|
if (!$validator->check($data)) {
|
||||||
|
// 验证失败,抛出业务异常,异常信息为验证器返回的错误信息
|
||||||
|
throw new BusinessException($validator->getError());
|
||||||
|
}
|
||||||
|
// 验证成功,返回原始数据
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function page($result){
|
||||||
|
$current = $result->currentPage();
|
||||||
|
$total = $result->total();
|
||||||
|
$size = $result->perPage();
|
||||||
|
$result = $result->toArray();
|
||||||
|
$result['current'] = $current;
|
||||||
|
$result['total'] = $total;
|
||||||
|
$result['size'] = $size;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\controller;
|
||||||
|
|
||||||
|
use app\ticket\service\CategorieService;
|
||||||
|
use support\Request;
|
||||||
|
|
||||||
|
class CategorieController extends BaseController
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$result = (new CategorieService())->list($request->all());
|
||||||
|
return $this->success($this->page($result));
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $this->error($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAll(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$result = (new CategorieService())->getAll($request->all());
|
||||||
|
return $this->success($result);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $this->error($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function add(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return (new CategorieService())->add($request->all())
|
||||||
|
? $this->success()
|
||||||
|
: $this->error();
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return $this->error($th->getMessage().' '.$th->getLine().' '.$th->getFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$result = (new CategorieService())->edit($request->all());
|
||||||
|
return $result
|
||||||
|
? $this->success($result)
|
||||||
|
: $this->error();
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return $this->error($th->getMessage().' '.$th->getLine().' '.$th->getFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$result = (new CategorieService())->delete($request->input('id'));
|
||||||
|
return $result
|
||||||
|
? $this->success($result)
|
||||||
|
: $this->error();
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return $this->error($th->getMessage().' '.$th->getLine().' '.$th->getFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\controller;
|
||||||
|
|
||||||
|
use app\ticket\service\ConversationService;
|
||||||
|
use support\Request;
|
||||||
|
|
||||||
|
class ConversationController extends BaseController
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$ticket_id = $request->input('ticket_id');
|
||||||
|
if(empty($ticket_id)){
|
||||||
|
return $this->error('ticket_id不能为空');
|
||||||
|
}
|
||||||
|
$result = (new ConversationService())->list($request->all());
|
||||||
|
return $this->success($this->page($result));
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $this->error($e->getMessage().$e->getLine().$e->getFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function add(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$request->setPost('user_id', 1);
|
||||||
|
return (new ConversationService())->add($request->all())
|
||||||
|
? $this->success()
|
||||||
|
: $this->error();
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return $this->error($th->getMessage().' '.$th->getLine().' '.$th->getFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function edit(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$request->setPost('user_id', 1);
|
||||||
|
$result = (new ConversationService())->edit($request->all());
|
||||||
|
return $result
|
||||||
|
? $this->success($result)
|
||||||
|
: $this->error();
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return $this->error($th->getMessage().' '.$th->getLine().' '.$th->getFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\controller;
|
||||||
|
|
||||||
|
use app\ticket\service\TicketService;
|
||||||
|
use support\Request;
|
||||||
|
|
||||||
|
class TicketController extends BaseController
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$result = (new TicketService())->list($request->all());
|
||||||
|
return $this->success($this->page($result));
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $this->error($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function add(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$request->setPost('user_id', 1);
|
||||||
|
|
||||||
|
return (new TicketService())->add($request->all())
|
||||||
|
? $this->success()
|
||||||
|
: $this->error();
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return $this->error($th->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$request->setPost('user_id', 1);
|
||||||
|
$result = (new TicketService())->edit($request->all());
|
||||||
|
return $result
|
||||||
|
? $this->success($result)
|
||||||
|
: $this->error();
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return $this->error($th->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function status(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$request->setPost('user_id', 1);
|
||||||
|
$result = (new TicketService())->status($request->all());
|
||||||
|
return $result
|
||||||
|
? $this->success($result)
|
||||||
|
: $this->error();
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return $this->error($th->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function getStatus(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$result = (new TicketService())->getStatus($request->all());
|
||||||
|
return $result
|
||||||
|
? $this->success($result)
|
||||||
|
: $this->error();
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return $this->error($th->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\logic;
|
||||||
|
|
||||||
|
use app\common\model\UserTokenLog;
|
||||||
|
use app\common\model\Systems;
|
||||||
|
use app\common\model\User;
|
||||||
|
use app\common\model\UserSn;
|
||||||
|
use app\common\utils\Jwt;
|
||||||
|
use app\ticket\model\Attachment;
|
||||||
|
use app\ticket\model\Ticket;
|
||||||
|
use support\Redis;
|
||||||
|
use support\exception\BusinessException;
|
||||||
|
use support\Log;
|
||||||
|
|
||||||
|
class AttachmentLogic
|
||||||
|
{
|
||||||
|
public function adds(array $data,int $ticket_id,int $user_id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
foreach ($data as $k=>$v){
|
||||||
|
$v['ticket_id'] = $ticket_id;
|
||||||
|
$v['user_id'] = $user_id;
|
||||||
|
$res = Attachment::create($v);
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('工单创建失败', [
|
||||||
|
'data' => $data,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
throw new BusinessException('工单创建失败,请稍后重试', 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(array $data,int $ticket_id,int $user_id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$attachmentsId = [];
|
||||||
|
foreach ($data as $k=>$v){
|
||||||
|
$v['ticket_id'] = $ticket_id;
|
||||||
|
$v['user_id'] = $user_id;
|
||||||
|
if(!empty($v['id'])){ //修改附件
|
||||||
|
$attachmentId = $v['id'];
|
||||||
|
$attachmentsId[] = $attachmentId;
|
||||||
|
// $v_res = Attachment::update($attachmentId, $v);
|
||||||
|
$v_res = Attachment::updateOrCreate(['id' => $v['id']],$v);
|
||||||
|
if (!$v_res) {
|
||||||
|
throw new BusinessException('附件保存失败');
|
||||||
|
}
|
||||||
|
} else { //新增附件
|
||||||
|
unset($v['id']);
|
||||||
|
$v_res = Attachment::create($v);
|
||||||
|
if (!$v_res) {
|
||||||
|
throw new BusinessException('附件创建失败');
|
||||||
|
}
|
||||||
|
$vId = $v_res->id;
|
||||||
|
$attachmentsId[] = $vId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除本次没有出现的附件
|
||||||
|
$res = Attachment::whereNotIn('id', $attachmentsId)->where('ticket_id',$ticket_id)->delete();
|
||||||
|
return $res;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('工单编辑(附件)失败', [
|
||||||
|
'data' => $data,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
throw new BusinessException('工单编辑失败,请稍后重试', 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function generateSimpleTicketNo(): string
|
||||||
|
{
|
||||||
|
$date = date('Ymd'); // 日期
|
||||||
|
$prefix = 'GD'; // 前缀
|
||||||
|
$random = strtoupper(substr(md5(uniqid()), 0, 5)); // 5位随机字母数字
|
||||||
|
|
||||||
|
return $prefix . $date . '-' . $random; // 如 GD20240702-AB3X9Z
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\logic;
|
||||||
|
|
||||||
|
use app\ticket\model\Categorie;
|
||||||
|
use support\Log;
|
||||||
|
use support\exception\BusinessException;
|
||||||
|
|
||||||
|
class CategorieLogic
|
||||||
|
{
|
||||||
|
public function list($params)
|
||||||
|
{
|
||||||
|
$where = [];
|
||||||
|
$size = $params['size'] ?? 10;
|
||||||
|
$current = $params['current'] ?? 1;
|
||||||
|
return Categorie::with('translation')->where($where)->paginate($size, ['*'], 'page', $current);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAll($params)
|
||||||
|
{
|
||||||
|
$where = [];
|
||||||
|
$where[] = ['status', '=', 1];
|
||||||
|
return Categorie::with('translation')->where($where)->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function add(array $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return Categorie::create($data);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('分类创建失败', [
|
||||||
|
'data' => $data,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
throw new BusinessException('分类创建失败,请稍后重试', 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(array $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$categorie = Categorie::updateOrCreate(['id' => $data['id']], $data);
|
||||||
|
return $categorie;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('分类编辑失败', [
|
||||||
|
'data' => $data,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
throw new BusinessException('分类编辑失败,请稍后重试', 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(int $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$categorie = Categorie::where(['id'=>$id])->delete();
|
||||||
|
return $categorie;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('分类删除失败', [
|
||||||
|
'id' => $id,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
throw new BusinessException('分类删除失败,请稍后重试', 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\logic;
|
||||||
|
|
||||||
|
use app\ticket\model\Conversation;
|
||||||
|
use support\Log;
|
||||||
|
use support\exception\BusinessException;
|
||||||
|
|
||||||
|
class ConversationLogic
|
||||||
|
{
|
||||||
|
public function list($params)
|
||||||
|
{
|
||||||
|
$where = [];
|
||||||
|
if (!empty($params['ticket_id'])) {
|
||||||
|
$where['ticket_id'] = $params['ticket_id'];
|
||||||
|
}
|
||||||
|
$size = $params['size'] ?? 10;
|
||||||
|
$current = $params['current'] ?? 1;
|
||||||
|
return Conversation::where($where)->paginate($size, ['*'], 'page', $current);
|
||||||
|
}
|
||||||
|
public function add(array $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return Conversation::create($data);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('会话创建失败', [
|
||||||
|
'data' => $data,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
throw new BusinessException('会话创建失败,请稍后重试', 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function edit(array $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$conversation = Conversation::updateOrCreate(['id' => $data['id']], $data);
|
||||||
|
return $conversation;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('会话编辑失败', [
|
||||||
|
'data' => $data,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
throw new BusinessException('会话编辑失败,请稍后重试', 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\logic;
|
||||||
|
|
||||||
|
use app\common\model\UserTokenLog;
|
||||||
|
use app\common\model\Systems;
|
||||||
|
use app\common\model\User;
|
||||||
|
use app\common\model\UserSn;
|
||||||
|
use app\common\utils\Jwt;
|
||||||
|
use app\ticket\model\Ticket;
|
||||||
|
use support\Redis;
|
||||||
|
use support\exception\BusinessException;
|
||||||
|
use support\Log;
|
||||||
|
|
||||||
|
class TicketLogic
|
||||||
|
{
|
||||||
|
public function list($params)
|
||||||
|
{
|
||||||
|
$where = [];
|
||||||
|
if(!empty($params['categorie_id'])){
|
||||||
|
$where[] = ['categorie_id', '=', $params['categorie_id']];
|
||||||
|
}
|
||||||
|
if(!empty($params['status'])){
|
||||||
|
$where[] = ['status', '=', $params['status']];
|
||||||
|
}
|
||||||
|
$size = $params['size'];
|
||||||
|
$current = $params['current'];
|
||||||
|
return Ticket::with('attachments')->with('categorie')->with('categorie.translation')->where($where)->orderBy('id','desc')->paginate($size, ['*'], 'page', $current);
|
||||||
|
}
|
||||||
|
public function add(array $data)
|
||||||
|
{
|
||||||
|
$data['status'] = 1;
|
||||||
|
$data['code'] = self::generateSimpleTicketNo();
|
||||||
|
try {
|
||||||
|
return Ticket::create($data);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('工单创建失败', [
|
||||||
|
'data' => $data,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
throw new BusinessException('工单创建失败,请稍后重试', 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function edit(array $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
unset($data['code']);
|
||||||
|
$ticket = Ticket::updateOrCreate(['id' => $data['id']],$data);
|
||||||
|
return $ticket;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('工单编辑失败', [
|
||||||
|
'data' => $data,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
throw new BusinessException('工单编辑失败,请稍后重试', 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function find(int $id)
|
||||||
|
{
|
||||||
|
$ticket = Ticket::find($id);
|
||||||
|
return $ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function generateSimpleTicketNo(): string
|
||||||
|
{
|
||||||
|
$date = date('Ymd'); // 日期
|
||||||
|
$prefix = 'GD'; // 前缀
|
||||||
|
$random = strtoupper(substr(md5(uniqid()), 0, 5)); // 5位随机字母数字
|
||||||
|
|
||||||
|
return $prefix . $date . '-' . $random; // 如 GD20240702-AB3X9Z
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\model;
|
||||||
|
|
||||||
|
use app\common\model\Resource;
|
||||||
|
use app\common\model\Role;
|
||||||
|
use app\common\model\Systems;
|
||||||
|
use support\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* users 用户表
|
||||||
|
* @property integer $id 用户ID(主键)
|
||||||
|
* @property string $ticket_id 工单编号
|
||||||
|
* @property string $user_id 分类id
|
||||||
|
* @property string $original_name 内容
|
||||||
|
* @property string $storage_path 排序
|
||||||
|
* @property string $mime_type 状态
|
||||||
|
* @property integer $file_size 创建人id
|
||||||
|
* @property string $created_at
|
||||||
|
* @property string $updated_at
|
||||||
|
*/
|
||||||
|
class Attachment extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The connection name for the model.
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
protected $connection = 'mysql';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The table associated with the model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $table = 'tkt_ticket_attachment';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The primary key associated with the table.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $primaryKey = 'id';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the model should be timestamped.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $timestamps = true;
|
||||||
|
|
||||||
|
protected $dateFormat = 'U';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'ticket_id',
|
||||||
|
'user_id',
|
||||||
|
'original_name',
|
||||||
|
'storage_path',
|
||||||
|
'mime_type',
|
||||||
|
'file_size'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function ticket(){
|
||||||
|
return $this->belongsTo(Ticket::class, 'ticket_id', 'id');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\model;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use support\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ticket_categorie 工单分类表
|
||||||
|
* @property integer $id 主键
|
||||||
|
* @property string $name 分类名称
|
||||||
|
* @property string $description 分类描述
|
||||||
|
* @property string $created_at 创建时间
|
||||||
|
* @property string $updated_at 更新时间
|
||||||
|
* @property string $deleted_at 删除时间
|
||||||
|
*/
|
||||||
|
class Categorie extends Model
|
||||||
|
{
|
||||||
|
use SoftDeletes;
|
||||||
|
protected $connection = 'mysql';
|
||||||
|
protected $table = 'tkt_ticket_categorie';
|
||||||
|
protected $primaryKey = 'id';
|
||||||
|
public $timestamps = true;
|
||||||
|
protected $dateFormat = 'U';
|
||||||
|
protected $dates = ['created_at', 'updated_at'];
|
||||||
|
protected $casts = [
|
||||||
|
'updated_at' => 'datetime:Y-m-d H:i:s',
|
||||||
|
'created_at' => 'datetime:Y-m-d H:i:s',
|
||||||
|
];
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'description',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单条翻译
|
||||||
|
*/
|
||||||
|
public function translation()
|
||||||
|
{
|
||||||
|
return $this->hasOne(CategorieTranslation::class, 'categorie_id')->where('locale', locale());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多条翻译
|
||||||
|
*/
|
||||||
|
public function translations()
|
||||||
|
{
|
||||||
|
return $this->hasMany(CategorieTranslation::class, 'categorie_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ticket(){
|
||||||
|
return $this->hasOne(Ticket::class, 'categorie_id', 'id');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\model;
|
||||||
|
|
||||||
|
use support\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ticket_categorie_translation 工单分类多语言表
|
||||||
|
* @property integer $id 主键
|
||||||
|
* @property integer $categorie_id 分类ID
|
||||||
|
* @property string $locale 语言
|
||||||
|
* @property string $name 分类名称
|
||||||
|
* @property string $description 分类描述
|
||||||
|
* @property string $created_at 创建时间
|
||||||
|
* @property string $updated_at 更新时间
|
||||||
|
*/
|
||||||
|
class CategorieTranslation extends Model
|
||||||
|
{
|
||||||
|
protected $connection = 'mysql';
|
||||||
|
protected $table = 'tkt_ticket_categorie_translation';
|
||||||
|
protected $primaryKey = 'id';
|
||||||
|
public $timestamps = true;
|
||||||
|
protected $dateFormat = 'U';
|
||||||
|
protected $dates = ['created_at', 'updated_at'];
|
||||||
|
protected $casts = [
|
||||||
|
'updated_at' => 'datetime:Y-m-d H:i:s',
|
||||||
|
'created_at' => 'datetime:Y-m-d H:i:s',
|
||||||
|
];
|
||||||
|
protected $fillable = [
|
||||||
|
'categorie_id',
|
||||||
|
'locale',
|
||||||
|
'name',
|
||||||
|
'description',
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\model;
|
||||||
|
|
||||||
|
use support\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ticket_conversation 工单会话表
|
||||||
|
* @property integer $id 主键
|
||||||
|
* @property integer $ticket_id 工单ID
|
||||||
|
* @property integer $user_id 用户ID
|
||||||
|
* @property string $content 会话内容
|
||||||
|
* @property string $created_at 创建时间
|
||||||
|
* @property string $updated_at 更新时间
|
||||||
|
*/
|
||||||
|
class Conversation extends Model
|
||||||
|
{
|
||||||
|
protected $connection = 'mysql';
|
||||||
|
protected $table = 'tkt_ticket_conversation';
|
||||||
|
protected $primaryKey = 'id';
|
||||||
|
public $timestamps = true;
|
||||||
|
protected $dateFormat = 'U';
|
||||||
|
protected $dates = ['created_at', 'updated_at'];
|
||||||
|
protected $casts = [
|
||||||
|
'updated_at' => 'datetime:Y-m-d H:i:s',
|
||||||
|
'created_at' => 'datetime:Y-m-d H:i:s',
|
||||||
|
];
|
||||||
|
protected $fillable = [
|
||||||
|
'ticket_id',
|
||||||
|
'user_id',
|
||||||
|
'content',
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\model;
|
||||||
|
|
||||||
|
use app\common\model\Resource;
|
||||||
|
use app\common\model\Role;
|
||||||
|
use app\common\model\Systems;
|
||||||
|
use support\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* users 用户表
|
||||||
|
* @property integer $id 用户ID(主键)
|
||||||
|
* @property string $code 工单编号
|
||||||
|
* @property string $categorie_id 分类id
|
||||||
|
* @property string $content 内容
|
||||||
|
* @property string $sort 排序
|
||||||
|
* @property integer $status 状态
|
||||||
|
* @property string $user_id 创建人id
|
||||||
|
* @property string $created_at
|
||||||
|
* @property string $updated_at
|
||||||
|
*/
|
||||||
|
class Ticket extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The connection name for the model.
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
protected $connection = 'mysql';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The table associated with the model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $table = 'tkt_ticket';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The primary key associated with the table.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $primaryKey = 'id';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the model should be timestamped.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $timestamps = true;
|
||||||
|
|
||||||
|
protected $dateFormat = 'U';
|
||||||
|
|
||||||
|
protected $dates = ['created_at', 'updated_at'];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'updated_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||||
|
'created_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'code',
|
||||||
|
'categorie_id',
|
||||||
|
'content',
|
||||||
|
'sort',
|
||||||
|
'status',
|
||||||
|
'user_id'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function attachments(){
|
||||||
|
return $this->hasMany(Attachment::class, 'ticket_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function categorie(){
|
||||||
|
return $this->belongsTo(Categorie::class, 'categorie_id', 'id');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\service;
|
||||||
|
|
||||||
|
use app\queue\translation\service\TranslationService;
|
||||||
|
use app\queue\utils\Translat;
|
||||||
|
use app\ticket\logic\CategorieLogic;
|
||||||
|
use support\Db;
|
||||||
|
use support\exception\BusinessException;
|
||||||
|
|
||||||
|
class CategorieService
|
||||||
|
{
|
||||||
|
public function list($params)
|
||||||
|
{
|
||||||
|
$result = (new CategorieLogic())->list($params);
|
||||||
|
$value=$result[0]->toArray();
|
||||||
|
foreach ($result as $key => &$value) {
|
||||||
|
$value['name'] = isset($value['translation']) ? $value['translation']['name'] : '';
|
||||||
|
unset($value['translation']);
|
||||||
|
}
|
||||||
|
unset($value);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAll($params)
|
||||||
|
{
|
||||||
|
$result = (new CategorieLogic())->getAll($params);
|
||||||
|
foreach ($result as $key => &$value) {
|
||||||
|
$value['name'] = isset($value['translation']) ? $value['translation']['name'] : '';
|
||||||
|
unset($value['translation']);
|
||||||
|
}
|
||||||
|
unset($value);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public $translatFields = ['name'];
|
||||||
|
|
||||||
|
public function add(array $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Db::beginTransaction();
|
||||||
|
$sourceLocale = locale();
|
||||||
|
$traitsourceFields = Translat::extractSourceFields($data, $this->translatFields);
|
||||||
|
|
||||||
|
$result = (new CategorieLogic())->add($data);
|
||||||
|
|
||||||
|
(new TranslationService())->queueTranslations(
|
||||||
|
'ticket_categorie',
|
||||||
|
$result->id,
|
||||||
|
$sourceLocale,
|
||||||
|
$traitsourceFields
|
||||||
|
);
|
||||||
|
|
||||||
|
Db::commit();
|
||||||
|
return $result;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Db::rollback();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function edit(array $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Db::beginTransaction();
|
||||||
|
$sourceLocale = locale();
|
||||||
|
$traitsourceFields = Translat::extractSourceFields($data, $this->translatFields);
|
||||||
|
|
||||||
|
$result = (new CategorieLogic())->edit($data);
|
||||||
|
|
||||||
|
(new TranslationService())->queueTranslations(
|
||||||
|
'ticket_categorie',
|
||||||
|
$data['id'],
|
||||||
|
$sourceLocale,
|
||||||
|
$traitsourceFields
|
||||||
|
);
|
||||||
|
Db::commit();
|
||||||
|
return $result;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Db::rollback();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function delete(int $id)
|
||||||
|
{
|
||||||
|
if(empty($id)){
|
||||||
|
throw new BusinessException('id不能为空');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$result = (new CategorieLogic())->delete($id);
|
||||||
|
return $result;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\service;
|
||||||
|
|
||||||
|
use app\ticket\logic\ConversationLogic;
|
||||||
|
use config\constants\Constants;
|
||||||
|
use support\Db;
|
||||||
|
use support\exception\BusinessException;
|
||||||
|
|
||||||
|
class ConversationService
|
||||||
|
{
|
||||||
|
public function list($params)
|
||||||
|
{
|
||||||
|
$locale = locale();
|
||||||
|
// $locale = 'zh';
|
||||||
|
$ticket_status = $locale == 'zh'? Constants::TICKET_STATUS_ZH:Constants::TICKET_STATUS_EN;
|
||||||
|
// $ticket_status = Constants::TICKET_STATUS_ZH;
|
||||||
|
// $params['locale'] = locale();
|
||||||
|
$result = (new ConversationLogic())->list($params);
|
||||||
|
|
||||||
|
$status_fanyi = array_map(fn($v) => "{{{$v}}}", array_flip(Constants::TICKET_STATUS));
|
||||||
|
foreach ($result as $key => $value) {
|
||||||
|
$result[$key]['content'] = str_replace($status_fanyi,$ticket_status,$value['content']);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function add(array $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return (new ConversationLogic())->add($data);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(array $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Db::beginTransaction();
|
||||||
|
$result = (new ConversationLogic())->edit($data);
|
||||||
|
Db::commit();
|
||||||
|
return $result;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Db::rollback();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\ticket\service;
|
||||||
|
|
||||||
|
use app\ticket\logic\AttachmentLogic;
|
||||||
|
use app\ticket\logic\ConversationLogic;
|
||||||
|
use app\ticket\logic\TicketLogic;
|
||||||
|
use app\ticket\model\Ticket;
|
||||||
|
use config\constants\Constants;
|
||||||
|
use support\Db;
|
||||||
|
use support\exception\BusinessException;
|
||||||
|
use support\Log;
|
||||||
|
|
||||||
|
class TicketService
|
||||||
|
{
|
||||||
|
|
||||||
|
public function list($params)
|
||||||
|
{
|
||||||
|
$res = (new TicketLogic())->list($params);
|
||||||
|
foreach ($res as $k => &$v) {
|
||||||
|
$name = isset($v['categorie']['translation']) ? $v['categorie']['translation']['name'] : '';
|
||||||
|
if(isset($res[$k]['categorie'])){
|
||||||
|
$res[$k]['categorie']['name'] = $name;
|
||||||
|
}
|
||||||
|
if (isset($v['categorie']['translation'])){
|
||||||
|
unset($res[$k]['categorie']['translation']);
|
||||||
|
}
|
||||||
|
foreach ($v['attachments'] as &$attachments) {
|
||||||
|
$attachments['storage_path_full'] = (new \app\common\service\OssService())->generatePrivateUrl($attachments['storage_path']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($v);
|
||||||
|
unset($attachments);
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function add(array $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$attachment = $data['attachment']??[];
|
||||||
|
$logic = new TicketLogic();
|
||||||
|
$result = $logic->add($data);
|
||||||
|
if(!empty($attachment)){
|
||||||
|
(new AttachmentLogic())->adds($attachment, $result->id, $data['user_id']);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Db::rollback();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(array $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Db::beginTransaction();
|
||||||
|
$attachment = $data['attachment']??[];
|
||||||
|
$logic = new TicketLogic();
|
||||||
|
$result = $logic->edit($data);
|
||||||
|
|
||||||
|
if(!empty($attachment)){
|
||||||
|
(new AttachmentLogic())->edit($attachment, $result->id, $data['user_id']);
|
||||||
|
}
|
||||||
|
Db::commit();
|
||||||
|
return $result;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Db::rollback();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function status(array $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Db::beginTransaction();
|
||||||
|
$msg = $data['msg']??[];
|
||||||
|
$ticket = (new TicketLogic())->find($data['id']);
|
||||||
|
if(empty($ticket)){
|
||||||
|
throw new BusinessException('工单不存在');
|
||||||
|
}
|
||||||
|
if($data['status'] <= $ticket->status){
|
||||||
|
throw new BusinessException(trans('status_not_modified'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(!in_array($ticket->status, [Constants::TICKET_STATUS['PENDING'], Constants::TICKET_STATUS['CONFIRM']])
|
||||||
|
// && empty($msg)){
|
||||||
|
// throw new BusinessException('提交失败');
|
||||||
|
// }
|
||||||
|
|
||||||
|
$ticket->status = $data['status'];
|
||||||
|
$result = $ticket->save();
|
||||||
|
|
||||||
|
if(!empty($msg)){
|
||||||
|
$conversation = [
|
||||||
|
'ticket_id' => $ticket->id,
|
||||||
|
'user_id' => $data['user_id'],
|
||||||
|
'content' => '状态更新为{{'.array_search($data['status'],Constants::TICKET_STATUS).'}}:'.$msg
|
||||||
|
];
|
||||||
|
$res = (new ConversationLogic())->add($conversation);
|
||||||
|
}
|
||||||
|
|
||||||
|
Db::commit();
|
||||||
|
return $result;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Db::rollback();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStatus(array $data)
|
||||||
|
{
|
||||||
|
$locale = locale();
|
||||||
|
$ticket_status = $locale == 'zh'? Constants::TICKET_STATUS_ZH:Constants::TICKET_STATUS_EN;
|
||||||
|
|
||||||
|
$status = [];
|
||||||
|
foreach ($ticket_status as $key => $value) {
|
||||||
|
$status[] = ['value' => $key, 'text' => $value];
|
||||||
|
}
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-1
@@ -37,7 +37,11 @@
|
|||||||
"vlucas/phpdotenv": "^5.6",
|
"vlucas/phpdotenv": "^5.6",
|
||||||
"firebase/php-jwt": "^6.11",
|
"firebase/php-jwt": "^6.11",
|
||||||
"league/oauth2-server": "^9.2",
|
"league/oauth2-server": "^9.2",
|
||||||
"topthink/think-validate": "^3.0"
|
"topthink/think-validate": "^3.0",
|
||||||
|
"shopwwi/webman-filesystem": "1.1",
|
||||||
|
"shopwwi/filesystem-oss": "^1.0",
|
||||||
|
"webman/redis-queue": "^1.3",
|
||||||
|
"symfony/translation": "^7.3"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-event": "For better performance. "
|
"ext-event": "For better performance. "
|
||||||
|
|||||||
Generated
+504
-2
@@ -4,8 +4,59 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "eecf8b50860214e48bdcb8407fd40e14",
|
"content-hash": "acb636fcb8774558a04bd674f9f95f55",
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "aliyuncs/oss-sdk-php",
|
||||||
|
"version": "v2.7.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/aliyun/aliyun-oss-php-sdk.git",
|
||||||
|
"reference": "483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/aliyun/aliyun-oss-php-sdk/zipball/483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5",
|
||||||
|
"reference": "483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"php-coveralls/php-coveralls": "*",
|
||||||
|
"phpunit/phpunit": "*"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"OSS\\": "src/OSS"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Aliyuncs",
|
||||||
|
"homepage": "http://www.aliyun.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Aliyun OSS SDK for PHP",
|
||||||
|
"homepage": "http://www.aliyun.com/product/oss/",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/aliyun/aliyun-oss-php-sdk/issues",
|
||||||
|
"source": "https://github.com/aliyun/aliyun-oss-php-sdk/tree/v2.7.2"
|
||||||
|
},
|
||||||
|
"time": "2024-10-28T10:41:12+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
"version": "0.13.1",
|
"version": "0.13.1",
|
||||||
@@ -1997,6 +2048,212 @@
|
|||||||
},
|
},
|
||||||
"time": "2024-09-04T16:06:53+00:00"
|
"time": "2024-09-04T16:06:53+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "league/flysystem",
|
||||||
|
"version": "3.29.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/thephpleague/flysystem.git",
|
||||||
|
"reference": "0adc0d9a51852e170e0028a60bd271726626d3f0"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/0adc0d9a51852e170e0028a60bd271726626d3f0",
|
||||||
|
"reference": "0adc0d9a51852e170e0028a60bd271726626d3f0",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"league/flysystem-local": "^3.0.0",
|
||||||
|
"league/mime-type-detection": "^1.0.0",
|
||||||
|
"php": "^8.0.2"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"async-aws/core": "<1.19.0",
|
||||||
|
"async-aws/s3": "<1.14.0",
|
||||||
|
"aws/aws-sdk-php": "3.209.31 || 3.210.0",
|
||||||
|
"guzzlehttp/guzzle": "<7.0",
|
||||||
|
"guzzlehttp/ringphp": "<1.1.1",
|
||||||
|
"phpseclib/phpseclib": "3.0.15",
|
||||||
|
"symfony/http-client": "<5.2"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"async-aws/s3": "^1.5 || ^2.0",
|
||||||
|
"async-aws/simple-s3": "^1.1 || ^2.0",
|
||||||
|
"aws/aws-sdk-php": "^3.295.10",
|
||||||
|
"composer/semver": "^3.0",
|
||||||
|
"ext-fileinfo": "*",
|
||||||
|
"ext-ftp": "*",
|
||||||
|
"ext-mongodb": "^1.3",
|
||||||
|
"ext-zip": "*",
|
||||||
|
"friendsofphp/php-cs-fixer": "^3.5",
|
||||||
|
"google/cloud-storage": "^1.23",
|
||||||
|
"guzzlehttp/psr7": "^2.6",
|
||||||
|
"microsoft/azure-storage-blob": "^1.1",
|
||||||
|
"mongodb/mongodb": "^1.2",
|
||||||
|
"phpseclib/phpseclib": "^3.0.36",
|
||||||
|
"phpstan/phpstan": "^1.10",
|
||||||
|
"phpunit/phpunit": "^9.5.11|^10.0",
|
||||||
|
"sabre/dav": "^4.6.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"League\\Flysystem\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Frank de Jonge",
|
||||||
|
"email": "info@frankdejonge.nl"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "File storage abstraction for PHP",
|
||||||
|
"keywords": [
|
||||||
|
"WebDAV",
|
||||||
|
"aws",
|
||||||
|
"cloud",
|
||||||
|
"file",
|
||||||
|
"files",
|
||||||
|
"filesystem",
|
||||||
|
"filesystems",
|
||||||
|
"ftp",
|
||||||
|
"s3",
|
||||||
|
"sftp",
|
||||||
|
"storage"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/thephpleague/flysystem/issues",
|
||||||
|
"source": "https://github.com/thephpleague/flysystem/tree/3.29.0"
|
||||||
|
},
|
||||||
|
"time": "2024-09-29T11:59:11+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "league/flysystem-local",
|
||||||
|
"version": "3.29.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/thephpleague/flysystem-local.git",
|
||||||
|
"reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e0e8d52ce4b2ed154148453d321e97c8e931bd27",
|
||||||
|
"reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-fileinfo": "*",
|
||||||
|
"league/flysystem": "^3.0.0",
|
||||||
|
"league/mime-type-detection": "^1.0.0",
|
||||||
|
"php": "^8.0.2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"League\\Flysystem\\Local\\": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Frank de Jonge",
|
||||||
|
"email": "info@frankdejonge.nl"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Local filesystem adapter for Flysystem.",
|
||||||
|
"keywords": [
|
||||||
|
"Flysystem",
|
||||||
|
"file",
|
||||||
|
"files",
|
||||||
|
"filesystem",
|
||||||
|
"local"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/thephpleague/flysystem-local/tree/3.29.0"
|
||||||
|
},
|
||||||
|
"time": "2024-08-09T21:24:39+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "league/mime-type-detection",
|
||||||
|
"version": "1.15.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/thephpleague/mime-type-detection.git",
|
||||||
|
"reference": "ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301",
|
||||||
|
"reference": "ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-fileinfo": "*",
|
||||||
|
"php": "^7.4 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"friendsofphp/php-cs-fixer": "^3.2",
|
||||||
|
"phpstan/phpstan": "^0.12.68",
|
||||||
|
"phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"League\\MimeTypeDetection\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Frank de Jonge",
|
||||||
|
"email": "info@frankdejonge.nl"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Mime-type detection for Flysystem",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/thephpleague/mime-type-detection/issues",
|
||||||
|
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.15.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/frankdejonge",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/league/flysystem",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-01-28T23:22:08+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "league/oauth2-server",
|
"name": "league/oauth2-server",
|
||||||
"version": "9.2.0",
|
"version": "9.2.0",
|
||||||
@@ -3267,6 +3524,124 @@
|
|||||||
},
|
},
|
||||||
"time": "2019-03-08T08:55:37+00:00"
|
"time": "2019-03-08T08:55:37+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "shopwwi/filesystem-oss",
|
||||||
|
"version": "v1.0.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/shopwwi/filesystem-oss.git",
|
||||||
|
"reference": "85cb385d1a5d11ca3c22bc485a7b18c588fe7645"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/shopwwi/filesystem-oss/zipball/85cb385d1a5d11ca3c22bc485a7b18c588fe7645",
|
||||||
|
"reference": "85cb385d1a5d11ca3c22bc485a7b18c588fe7645",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"aliyuncs/oss-sdk-php": "^2.4",
|
||||||
|
"league/flysystem": "^2.1|^3.0",
|
||||||
|
"php": ">=7.3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Shopwwi\\FilesystemOss\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Tycoon Song",
|
||||||
|
"email": "8988354@qq.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "AliYun OSS adapter for flysystem V2. aliyuncs/oss-sdk-php ~2.4",
|
||||||
|
"homepage": "https://github.com/phcent/filesystem-oss",
|
||||||
|
"keywords": [
|
||||||
|
"Flysystem",
|
||||||
|
"aliyun-oss",
|
||||||
|
"flysystem-aliyun-oss"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/shopwwi/filesystem-oss/issues",
|
||||||
|
"source": "https://github.com/shopwwi/filesystem-oss/tree/v1.0.3"
|
||||||
|
},
|
||||||
|
"time": "2022-10-01T03:00:18+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shopwwi/webman-filesystem",
|
||||||
|
"version": "v1.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/shopwwi/webman-filesystem.git",
|
||||||
|
"reference": "26ac82515d3787943573c50d1a6f0ca339f0d3d4"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/shopwwi/webman-filesystem/zipball/26ac82515d3787943573c50d1a6f0ca339f0d3d4",
|
||||||
|
"reference": "26ac82515d3787943573c50d1a6f0ca339f0d3d4",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"league/flysystem": "^2.3|^3.0",
|
||||||
|
"php": ">=7.2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Shopwwi\\WebmanFilesystem\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Tycoon Song",
|
||||||
|
"email": "8988354@qq.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Flysystem V2 adapter for the webman",
|
||||||
|
"keywords": [
|
||||||
|
"cos",
|
||||||
|
"filesystem",
|
||||||
|
"oss",
|
||||||
|
"qiniu",
|
||||||
|
"webman"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/shopwwi/webman-filesystem/issues",
|
||||||
|
"source": "https://github.com/shopwwi/webman-filesystem/tree/v1.1.0"
|
||||||
|
},
|
||||||
|
"time": "2024-01-21T08:03:36+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/cache",
|
"name": "symfony/cache",
|
||||||
"version": "v7.3.0",
|
"version": "v7.3.0",
|
||||||
@@ -4990,7 +5365,13 @@
|
|||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/translation/zipball/4aba29076a29a3aa667e09b791e5f868973a8667",
|
"url": "https://api.github.com/repos/symfony/translation/zipball/4aba29076a29a3aa667e09b791e5f868973a8667",
|
||||||
"reference": "4aba29076a29a3aa667e09b791e5f868973a8667",
|
"reference": "4aba29076a29a3aa667e09b791e5f868973a8667",
|
||||||
"shasum": ""
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.2",
|
"php": ">=8.2",
|
||||||
@@ -5772,6 +6153,43 @@
|
|||||||
},
|
},
|
||||||
"time": "2025-03-14T03:52:14+00:00"
|
"time": "2025-03-14T03:52:14+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "webman/redis-queue",
|
||||||
|
"version": "v1.3.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/webman-php/redis-queue.git",
|
||||||
|
"reference": "6fd491b19acb006d60931724aa2577a046ccb612"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/webman-php/redis-queue/zipball/6fd491b19acb006d60931724aa2577a046ccb612",
|
||||||
|
"reference": "6fd491b19acb006d60931724aa2577a046ccb612",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"workerman/redis-queue": "^1.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Webman\\RedisQueue\\": "./src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"description": "Redis message queue plugin for webman.",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/webman-php/redis-queue/issues",
|
||||||
|
"source": "https://github.com/webman-php/redis-queue/tree/v1.3.1"
|
||||||
|
},
|
||||||
|
"time": "2024-02-28T07:21:52+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "workerman/coroutine",
|
"name": "workerman/coroutine",
|
||||||
"version": "v1.1.3",
|
"version": "v1.1.3",
|
||||||
@@ -5811,6 +6229,90 @@
|
|||||||
},
|
},
|
||||||
"time": "2025-02-17T03:34:21+00:00"
|
"time": "2025-02-17T03:34:21+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "workerman/redis",
|
||||||
|
"version": "v2.0.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/walkor/redis.git",
|
||||||
|
"reference": "82b398c5bdd5d683a3458aaf645b159b7b39b84e"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/walkor/redis/zipball/82b398c5bdd5d683a3458aaf645b159b7b39b84e",
|
||||||
|
"reference": "82b398c5bdd5d683a3458aaf645b159b7b39b84e",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7",
|
||||||
|
"workerman/workerman": "^4.1.0||^5.0.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Workerman\\Redis\\": "./src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"homepage": "http://www.workerman.net",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/walkor/redis/issues",
|
||||||
|
"source": "https://github.com/walkor/redis/tree/v2.0.4"
|
||||||
|
},
|
||||||
|
"time": "2025-04-05T07:45:12+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workerman/redis-queue",
|
||||||
|
"version": "v1.2.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/walkor/redis-queue.git",
|
||||||
|
"reference": "75dbf7ed2ea228c45dc0df82c0fea35879b715d0"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/walkor/redis-queue/zipball/75dbf7ed2ea228c45dc0df82c0fea35879b715d0",
|
||||||
|
"reference": "75dbf7ed2ea228c45dc0df82c0fea35879b715d0",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.0",
|
||||||
|
"workerman/redis": "^1.0||^2.0",
|
||||||
|
"workerman/workerman": ">=4.0.20"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Workerman\\RedisQueue\\": "./src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "Message queue system written in PHP based on workerman and backed by Redis.",
|
||||||
|
"homepage": "http://www.workerman.net",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/walkor/redis-queue/issues",
|
||||||
|
"source": "https://github.com/walkor/redis-queue/tree/v1.2.1"
|
||||||
|
},
|
||||||
|
"time": "2025-01-02T09:21:45+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "workerman/webman-framework",
|
"name": "workerman/webman-framework",
|
||||||
"version": "v2.1.2",
|
"version": "v2.1.2",
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
namespace config\constants;
|
||||||
|
|
||||||
|
class Constants
|
||||||
|
{
|
||||||
|
//工单状态
|
||||||
|
public const TICKET_STATUS = [
|
||||||
|
'PENDING' => 1, // 待受理
|
||||||
|
'PROCESS' => 2, //处理中
|
||||||
|
'CONFIRM' => 3, // 待确认
|
||||||
|
'FINISH' => 4, // 已完成
|
||||||
|
'REJECTED' => 5, // 已驳回
|
||||||
|
];
|
||||||
|
|
||||||
|
public const TICKET_STATUS_ZH = [
|
||||||
|
self::TICKET_STATUS['PENDING'] => '待受理',
|
||||||
|
self::TICKET_STATUS['PROCESS'] => '处理中',
|
||||||
|
self::TICKET_STATUS['CONFIRM'] => '待确认',
|
||||||
|
self::TICKET_STATUS['FINISH'] => '已完成',
|
||||||
|
self::TICKET_STATUS['REJECTED'] => '关闭',
|
||||||
|
];
|
||||||
|
public const TICKET_STATUS_EN = [
|
||||||
|
self::TICKET_STATUS['PENDING'] => 'Pending acceptance',
|
||||||
|
self::TICKET_STATUS['PROCESS'] => 'Processing',
|
||||||
|
self::TICKET_STATUS['CONFIRM'] => 'To be confirmed',
|
||||||
|
self::TICKET_STATUS['FINISH'] => 'Completed',
|
||||||
|
self::TICKET_STATUS['REJECTED'] => 'close',
|
||||||
|
];
|
||||||
|
public const TICKET_STATUS_RU = [
|
||||||
|
self::TICKET_STATUS['PENDING'] => 'Подлежит рассмотрению',
|
||||||
|
self::TICKET_STATUS['PROCESS'] => 'В процессе обработки',
|
||||||
|
self::TICKET_STATUS['CONFIRM'] => 'Подлежит подтверждению',
|
||||||
|
self::TICKET_STATUS['FINISH'] => 'Завершено',
|
||||||
|
self::TICKET_STATUS['REJECTED'] => 'Закрыть',
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
@@ -12,4 +12,8 @@
|
|||||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return [];
|
return [
|
||||||
|
'' => [
|
||||||
|
app\middleware\AccessControl::class
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
*-------------------------------------------------------------------------p*
|
||||||
|
* 配置文件
|
||||||
|
*-------------------------------------------------------------------------h*
|
||||||
|
* @copyright Copyright (c) 2015-2022 Shopwwi Inc. (http://www.shopwwi.com)
|
||||||
|
*-------------------------------------------------------------------------c*
|
||||||
|
* @license http://www.shopwwi.com s h o p w w i . c o m
|
||||||
|
*-------------------------------------------------------------------------e*
|
||||||
|
* @link http://www.shopwwi.com by 象讯科技 phcent.com
|
||||||
|
*-------------------------------------------------------------------------n*
|
||||||
|
* @since shopwwi象讯·PHP商城系统Pro
|
||||||
|
*-------------------------------------------------------------------------t*
|
||||||
|
*/
|
||||||
|
|
||||||
|
return [
|
||||||
|
'enable' => true,
|
||||||
|
'default' => 'local',
|
||||||
|
'max_size' => 1024 * 1024 * 10, //单个文件大小10M
|
||||||
|
'ext_yes' => [], //允许上传文件类型 为空则为允许所有
|
||||||
|
'ext_no' => [], // 不允许上传文件类型 为空则不限制
|
||||||
|
'storage' => [
|
||||||
|
'public' => [
|
||||||
|
'driver' => \Shopwwi\WebmanFilesystem\Adapter\LocalAdapterFactory::class,
|
||||||
|
'root' => public_path(),
|
||||||
|
'url' => '//127.0.0.1:8787' // 静态文件访问域名
|
||||||
|
],
|
||||||
|
'local' => [
|
||||||
|
'driver' => \Shopwwi\WebmanFilesystem\Adapter\LocalAdapterFactory::class,
|
||||||
|
'root' => runtime_path(),
|
||||||
|
'url' => '//127.0.0.1:8787' // 静态文件访问域名
|
||||||
|
],
|
||||||
|
'ftp' => [
|
||||||
|
'driver' => \Shopwwi\WebmanFilesystem\Adapter\FtpAdapterFactory::class,
|
||||||
|
'host' => 'ftp.example.com',
|
||||||
|
'username' => 'username',
|
||||||
|
'password' => 'password',
|
||||||
|
'url' => '' // 静态文件访问域名
|
||||||
|
// 'port' => 21,
|
||||||
|
// 'root' => '/path/to/root',
|
||||||
|
// 'passive' => true,
|
||||||
|
// 'ssl' => true,
|
||||||
|
// 'timeout' => 30,
|
||||||
|
// 'ignorePassiveAddress' => false,
|
||||||
|
// 'timestampsOnUnixListingsEnabled' => true,
|
||||||
|
],
|
||||||
|
'memory' => [
|
||||||
|
'driver' => \Shopwwi\WebmanFilesystem\Adapter\MemoryAdapterFactory::class,
|
||||||
|
],
|
||||||
|
's3' => [
|
||||||
|
'driver' => \Shopwwi\WebmanFilesystem\Adapter\S3AdapterFactory::class,
|
||||||
|
'credentials' => [
|
||||||
|
'key' => 'S3_KEY',
|
||||||
|
'secret' => 'S3_SECRET',
|
||||||
|
],
|
||||||
|
'region' => 'S3_REGION',
|
||||||
|
'version' => 'latest',
|
||||||
|
'bucket_endpoint' => false,
|
||||||
|
'use_path_style_endpoint' => false,
|
||||||
|
'endpoint' => 'S3_ENDPOINT',
|
||||||
|
'bucket_name' => 'S3_BUCKET',
|
||||||
|
'url' => '' // 静态文件访问域名
|
||||||
|
],
|
||||||
|
'minio' => [
|
||||||
|
'driver' => \Shopwwi\WebmanFilesystem\Adapter\S3AdapterFactory::class,
|
||||||
|
'credentials' => [
|
||||||
|
'key' => 'S3_KEY',
|
||||||
|
'secret' => 'S3_SECRET',
|
||||||
|
],
|
||||||
|
'region' => 'S3_REGION',
|
||||||
|
'version' => 'latest',
|
||||||
|
'bucket_endpoint' => false,
|
||||||
|
'use_path_style_endpoint' => true,
|
||||||
|
'endpoint' => 'S3_ENDPOINT',
|
||||||
|
'bucket_name' => 'S3_BUCKET',
|
||||||
|
'url' => '' // 静态文件访问域名
|
||||||
|
],
|
||||||
|
'oss' => [
|
||||||
|
'driver' => \Shopwwi\WebmanFilesystem\Adapter\AliyunOssAdapterFactory::class,
|
||||||
|
'accessId' => getenv('OSS_ACCESSID'),
|
||||||
|
'accessSecret' => getenv('OSS_ACCESSSECRET'),
|
||||||
|
'bucket' => getenv('OSS_BUCKET'),
|
||||||
|
'endpoint' => getenv('OSS_ENDPOINT'),
|
||||||
|
'url' => getenv('OSS_STATIC_URL'), // 静态文件访问域名
|
||||||
|
// 'timeout' => 3600,
|
||||||
|
// 'connectTimeout' => 10,
|
||||||
|
// 'isCName' => false,
|
||||||
|
// 'token' => null,
|
||||||
|
// 'proxy' => null,
|
||||||
|
],
|
||||||
|
'qiniu' => [
|
||||||
|
'driver' => \Shopwwi\WebmanFilesystem\Adapter\QiniuAdapterFactory::class,
|
||||||
|
'accessKey' => 'QINIU_ACCESS_KEY',
|
||||||
|
'secretKey' => 'QINIU_SECRET_KEY',
|
||||||
|
'bucket' => 'QINIU_BUCKET',
|
||||||
|
'domain' => 'QINBIU_DOMAIN',
|
||||||
|
'url' => '' // 静态文件访问域名
|
||||||
|
],
|
||||||
|
'cos' => [
|
||||||
|
'driver' => \Shopwwi\WebmanFilesystem\Adapter\CosAdapterFactory::class,
|
||||||
|
'region' => 'COS_REGION',
|
||||||
|
'app_id' => 'COS_APPID',
|
||||||
|
'secret_id' => 'COS_SECRET_ID',
|
||||||
|
'secret_key' => 'COS_SECRET_KEY',
|
||||||
|
// 可选,如果 bucket 为私有访问请打开此项
|
||||||
|
// 'signed_url' => false,
|
||||||
|
'bucket' => 'COS_BUCKET',
|
||||||
|
'read_from_cdn' => false,
|
||||||
|
'url' => '' // 静态文件访问域名
|
||||||
|
// 'timeout' => 60,
|
||||||
|
// 'connect_timeout' => 60,
|
||||||
|
// 'cdn' => '',
|
||||||
|
// 'scheme' => 'https',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
'enable' => true,
|
||||||
|
];
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Webman\RedisQueue\Command\MakeConsumerCommand;
|
||||||
|
|
||||||
|
return [
|
||||||
|
MakeConsumerCommand::class
|
||||||
|
];
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of webman.
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @author walkor<walkor@workerman.net>
|
||||||
|
* @copyright walkor<walkor@workerman.net>
|
||||||
|
* @link http://www.workerman.net/
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
return [
|
||||||
|
'default' => [
|
||||||
|
'handlers' => [
|
||||||
|
[
|
||||||
|
'class' => Monolog\Handler\RotatingFileHandler::class,
|
||||||
|
'constructor' => [
|
||||||
|
runtime_path() . '/logs/redis-queue/queue.log',
|
||||||
|
7, //$maxFiles
|
||||||
|
Monolog\Logger::DEBUG,
|
||||||
|
],
|
||||||
|
'formatter' => [
|
||||||
|
'class' => Monolog\Formatter\LineFormatter::class,
|
||||||
|
'constructor' => [null, 'Y-m-d H:i:s', true],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
]
|
||||||
|
];
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
'consumer' => [
|
||||||
|
'handler' => Webman\RedisQueue\Process\Consumer::class,
|
||||||
|
'count' => getenv('REDIS_QUEUE_PROCESS_COUNT'), // 可以设置多进程同时消费
|
||||||
|
'constructor' => [
|
||||||
|
// 消费者类目录
|
||||||
|
// 'consumer_dir' => app_path() . '/queue/redis'
|
||||||
|
'consumer_dir' => app_path() . getenv('REDIS_QUEUE_CONSUMER_DIR')
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
'default' => [
|
||||||
|
// 'host' => 'redis://127.0.0.1:6379',
|
||||||
|
'host' => getenv('REDIS_QUEUE_HOST'),
|
||||||
|
'options' => [
|
||||||
|
'auth' => getenv('REDIS_QUEUE_AUTH'), // 密码,字符串类型,可选参数
|
||||||
|
'db' => getenv('REDIS_QUEUE_DB'), // 数据库
|
||||||
|
'prefix' => getenv('REDIS_QUEUE_PREFIX'), // key 前缀
|
||||||
|
'max_attempts' => getenv('REDIS_QUEUE_MAX_ATTEMPTS'), // 消费失败后,重试次数
|
||||||
|
'retry_seconds' => getenv('REDIS_QUEUE_RETRY_SECONDS'), // 重试间隔,单位秒
|
||||||
|
],
|
||||||
|
// Connection pool, supports only Swoole or Swow drivers.
|
||||||
|
'pool' => [
|
||||||
|
'max_connections' => 5,
|
||||||
|
'min_connections' => 1,
|
||||||
|
'wait_timeout' => 3,
|
||||||
|
'idle_timeout' => 60,
|
||||||
|
'heartbeat_interval' => 50,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -32,3 +32,30 @@ Route::group('/common', function () {
|
|||||||
Route::post('/register', [app\common\controller\AuthController::class, 'register']);
|
Route::post('/register', [app\common\controller\AuthController::class, 'register']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Route::group('/ticket', function () {
|
||||||
|
//工单
|
||||||
|
Route::any('/ticket/add', [app\ticket\controller\TicketController::class, 'add']);
|
||||||
|
Route::any('/ticket/edit', [app\ticket\controller\TicketController::class, 'edit']);
|
||||||
|
Route::any('/ticket/list', [app\ticket\controller\TicketController::class, 'index']);
|
||||||
|
Route::any('/ticket/status', [app\ticket\controller\TicketController::class, 'status']);
|
||||||
|
Route::any('/ticket/getStatus', [app\ticket\controller\TicketController::class, 'getStatus']);
|
||||||
|
|
||||||
|
Route::any('/upload', [app\common\controller\UploadController::class, 'uploadFile']);
|
||||||
|
Route::any('/upload/image', [app\common\controller\UploadController::class, 'uploadImage']);
|
||||||
|
|
||||||
|
//工单沟通记录
|
||||||
|
Route::any('/conversation/add', [app\ticket\controller\ConversationController::class, 'add']);
|
||||||
|
Route::any('/conversation/edit', [app\ticket\controller\ConversationController::class, 'edit']);
|
||||||
|
Route::any('/conversation/list', [app\ticket\controller\ConversationController::class, 'index']);
|
||||||
|
|
||||||
|
//工单分类
|
||||||
|
Route::any('/categorie/add', [app\ticket\controller\CategorieController::class, 'add']);
|
||||||
|
Route::any('/categorie/edit', [app\ticket\controller\CategorieController::class, 'edit']);
|
||||||
|
Route::any('/categorie/list', [app\ticket\controller\CategorieController::class, 'index']);
|
||||||
|
Route::any('/categorie/getAll', [app\ticket\controller\CategorieController::class, 'getAll']);
|
||||||
|
Route::any('/categorie/delete', [app\ticket\controller\CategorieController::class, 'delete']);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'status_not_modified' => 'الدولة لا يمكن تعديلها عكسيا',
|
||||||
|
];
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'status_not_modified' => 'The status cannot be reversed for modification',
|
||||||
|
];
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'status_not_modified' => 'Статус не может быть изменен в обратном направлении',
|
||||||
|
];
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'status_not_modified' => '状态不能逆向修改',
|
||||||
|
];
|
||||||
Reference in New Issue
Block a user