first commit
This commit is contained in:
@@ -0,0 +1,262 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Common\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Modules\AnnoRoute\Attribute\DeleteRoute;
|
||||
use Modules\AnnoRoute\Attribute\GetRoute;
|
||||
use Modules\AnnoRoute\Attribute\PostRoute;
|
||||
use Modules\AnnoRoute\Attribute\PutRoute;
|
||||
use Modules\AnnoRoute\Attribute\RequestAttribute;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
class GenerateRouteHelperCommand extends Command
|
||||
{
|
||||
protected $signature = 'route:helper';
|
||||
|
||||
protected $description = 'Scan annotation routes and generate IDE route helper files for Laravel Idea';
|
||||
|
||||
private static array $mapping = [
|
||||
GetRoute::class,
|
||||
PostRoute::class,
|
||||
PutRoute::class,
|
||||
DeleteRoute::class,
|
||||
];
|
||||
|
||||
private static array $httpMethodMap = [
|
||||
GetRoute::class => 'get',
|
||||
PostRoute::class => 'post',
|
||||
PutRoute::class => 'put',
|
||||
DeleteRoute::class => 'delete',
|
||||
];
|
||||
|
||||
/** @var array<string, list<array{method: string, uri: string, controller: string, action: string, middleware: array}>> */
|
||||
private array $controllerRoutes = [];
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$paths = [
|
||||
app_path('Http/Controllers'),
|
||||
base_path('modules'),
|
||||
];
|
||||
|
||||
$totalRoutes = 0;
|
||||
|
||||
foreach ($paths as $path) {
|
||||
if (!is_dir($path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$finder = new Finder();
|
||||
$finder->files()->in($path)->name('*Controller.php');
|
||||
|
||||
foreach ($finder as $file) {
|
||||
$className = $this->getClassNameFromFile(
|
||||
$file->getRealPath(),
|
||||
$file->getPath()
|
||||
);
|
||||
|
||||
if ($className && class_exists($className)) {
|
||||
$routes = $this->scanController($className);
|
||||
if (!empty($routes)) {
|
||||
$this->controllerRoutes[$className] = $routes;
|
||||
$totalRoutes += count($routes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->controllerRoutes)) {
|
||||
$this->warn('No annotation routes found.');
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$this->writeHelperFile();
|
||||
$this->info("Routes generated to: " . base_path('routes/api.php'));
|
||||
$this->info("Found {$totalRoutes} routes.");
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function scanController(string $className): array
|
||||
{
|
||||
$routes = [];
|
||||
|
||||
try {
|
||||
$classRef = new ReflectionClass($className);
|
||||
} catch (ReflectionException) {
|
||||
return $routes;
|
||||
}
|
||||
|
||||
$classAttrs = collect($classRef->getAttributes());
|
||||
if ($classAttrs->isEmpty()) {
|
||||
return $routes;
|
||||
}
|
||||
|
||||
$hasRequestAttr = $classAttrs->some(
|
||||
fn($attr) => $attr->getName() === RequestAttribute::class
|
||||
);
|
||||
if (!$hasRequestAttr) {
|
||||
return $routes;
|
||||
}
|
||||
|
||||
$requestAttr = $classAttrs->first(
|
||||
fn($attr) => $attr->getName() === RequestAttribute::class
|
||||
);
|
||||
$requestInstance = $requestAttr->newInstance();
|
||||
$routePrefix = $requestInstance->routePrefix ?? '';
|
||||
$authGuard = $requestInstance->authGuard ?? null;
|
||||
$abilitiesPrefix = $requestInstance->abilitiesPrefix ?? '';
|
||||
$classMiddleware = $this->normalizeMiddleware($requestInstance->middleware);
|
||||
|
||||
foreach ($classRef->getMethods() as $method) {
|
||||
$attrs = $method->getAttributes();
|
||||
if (empty($attrs)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$methodName = $method->getName();
|
||||
|
||||
foreach ($attrs as $attr) {
|
||||
if (in_array($attr->getName(), self::$mapping)) {
|
||||
$instance = $attr->newInstance();
|
||||
|
||||
$authMiddleware = $this->buildAuthMiddleware(
|
||||
$instance->authorize,
|
||||
$authGuard,
|
||||
$abilitiesPrefix,
|
||||
);
|
||||
|
||||
$allMiddleware = array_values(array_unique(array_merge(
|
||||
$authMiddleware,
|
||||
$this->normalizeMiddleware($instance->middleware),
|
||||
$classMiddleware,
|
||||
)));
|
||||
|
||||
$routes[] = [
|
||||
'method' => self::$httpMethodMap[$attr->getName()],
|
||||
'uri' => $instance->route,
|
||||
'prefix' => trim($routePrefix, '/'),
|
||||
'controller' => $className,
|
||||
'action' => $methodName,
|
||||
'middleware' => $allMiddleware,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $routes;
|
||||
}
|
||||
|
||||
private function buildAuthMiddleware(string|bool $authorize, ?string $authGuard, string $abilitiesPrefix): array
|
||||
{
|
||||
if (empty($authorize) || $authorize === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$authMiddleware = ['auth:sanctum'];
|
||||
|
||||
if (!empty($authGuard)) {
|
||||
$authMiddleware[] = 'authGuard:' . $authGuard;
|
||||
} else {
|
||||
$authMiddleware[] = 'authGuard';
|
||||
}
|
||||
|
||||
if (is_string($authorize) && !empty($abilitiesPrefix)) {
|
||||
$authMiddleware[] = 'abilities:' . $abilitiesPrefix . '.' . $authorize;
|
||||
} else if ($authorize !== true) {
|
||||
$authMiddleware[] = 'abilities:' . $authorize ;
|
||||
}
|
||||
|
||||
return $authMiddleware;
|
||||
}
|
||||
|
||||
private function normalizeMiddleware(string|array $middleware): array
|
||||
{
|
||||
if (empty($middleware)) {
|
||||
return [];
|
||||
}
|
||||
if (is_array($middleware)) {
|
||||
return $middleware;
|
||||
}
|
||||
return [$middleware];
|
||||
}
|
||||
|
||||
private function getClassNameFromFile(string $filePath, string $fileDir): ?string
|
||||
{
|
||||
$content = file_get_contents($filePath);
|
||||
|
||||
if (!preg_match('/namespace\s+([^;]+);/', $content, $namespaceMatch)) {
|
||||
return $this->guessClassNameFromPath($filePath, $fileDir);
|
||||
}
|
||||
|
||||
$namespace = trim($namespaceMatch[1]);
|
||||
$className = basename($filePath, '.php');
|
||||
|
||||
return $namespace . '\\' . $className;
|
||||
}
|
||||
|
||||
private function guessClassNameFromPath(string $filePath, string $fileDir): ?string
|
||||
{
|
||||
$basePath = base_path();
|
||||
$relativePath = str_replace($basePath, '', $fileDir);
|
||||
$namespace = str_replace('/', '\\', ltrim($relativePath, '/'));
|
||||
$namespace = trim($namespace, '\\');
|
||||
$className = basename($filePath, '.php');
|
||||
|
||||
return empty($namespace) ? $className : $namespace . '\\' . $className;
|
||||
}
|
||||
|
||||
private function writeHelperFile(): void
|
||||
{
|
||||
$outputPath = base_path('routes/api.php');
|
||||
|
||||
$lines = [
|
||||
'<?php',
|
||||
'',
|
||||
'use Illuminate\Support\Facades\Route;',
|
||||
'',
|
||||
'Route::get(\'/\', function () {',
|
||||
' return "Hello, thank you for using XinAdmin. ";',
|
||||
'});',
|
||||
'',
|
||||
];
|
||||
|
||||
// Each controller gets its own Route::controller group
|
||||
foreach ($this->controllerRoutes as $className => $routes) {
|
||||
$prefix = $routes[0]['prefix'];
|
||||
|
||||
$shortName = substr(strrchr($className, '\\'), 1);
|
||||
$lines[] = "// {$shortName}";
|
||||
|
||||
$chain = "Route::controller({$className}::class)";
|
||||
if ($prefix !== '') {
|
||||
$chain .= "->prefix('{$prefix}')";
|
||||
}
|
||||
$chain .= '->group(function () {';
|
||||
$lines[] = $chain;
|
||||
|
||||
foreach ($routes as $route) {
|
||||
$uri = $route['uri'];
|
||||
if ($uri === '') {
|
||||
$uri = '/';
|
||||
}
|
||||
|
||||
$middlewareStr = '';
|
||||
if (!empty($route['middleware'])) {
|
||||
$middlewareStr = "->middleware(['" . implode("', '", $route['middleware']) . "'])";
|
||||
}
|
||||
|
||||
$lines[] = " Route::{$route['method']}('{$uri}', '{$route['action']}'){$middlewareStr};";
|
||||
}
|
||||
|
||||
$lines[] = '});';
|
||||
$lines[] = '';
|
||||
}
|
||||
|
||||
File::put($outputPath, implode("\n", $lines));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace Modules\Common\Enum;
|
||||
|
||||
/**
|
||||
* 响应状态枚举类
|
||||
*/
|
||||
enum ShowType: int
|
||||
{
|
||||
// 成功响应
|
||||
case SUCCESS_MESSAGE = 0;
|
||||
|
||||
// 警告响应
|
||||
case WARN_MESSAGE = 1;
|
||||
|
||||
// 错误响应
|
||||
case ERROR_MESSAGE = 2;
|
||||
|
||||
// 成功通知
|
||||
case SUCCESS_NOTIFICATION = 3;
|
||||
|
||||
// 警告通知
|
||||
case WARN_NOTIFICATION = 4;
|
||||
|
||||
// 错误通知
|
||||
case ERROR_NOTIFICATION = 5;
|
||||
|
||||
// 静默响应
|
||||
case SILENT = 99;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Common\Http\Controllers;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Modules\Common\Trait\RequestJson;
|
||||
|
||||
abstract class BaseController extends Controller
|
||||
{
|
||||
use RequestJson;
|
||||
|
||||
/**
|
||||
* 查询字符串
|
||||
* The fields queried by the current model
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $searchField = [];
|
||||
|
||||
/**
|
||||
* 快速搜索字段
|
||||
* Quick search field
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $quickSearchField = [];
|
||||
|
||||
|
||||
/** 构建查询方法 */
|
||||
protected function buildSearch(array $params, Builder $model): Builder
|
||||
{
|
||||
// 构建筛选
|
||||
if (isset($params['filter']) && $params['filter'] != '') {
|
||||
if(is_array($params['filter'])) {
|
||||
$filter = $params['filter'];
|
||||
} else {
|
||||
$filter = json_decode($params['filter'], true);
|
||||
}
|
||||
foreach ($filter as $k => $v) {
|
||||
if (! $v) {
|
||||
continue;
|
||||
}
|
||||
$model->whereIn($k, $v);
|
||||
}
|
||||
unset($params['filter']);
|
||||
}
|
||||
|
||||
// 构建查询
|
||||
foreach ($this->searchField ?? [] as $key => $op) {
|
||||
if (isset($params[$key]) && $params[$key] != '') {
|
||||
if (in_array($op, ['=', '>', '<>', '<', '>=', '<='])) {
|
||||
$model->where($key, $op, $params[$key]);
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($op == 'like') {
|
||||
$model->where($key, $op, '%'.$params[$key].'%');
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($op == 'afterLike') {
|
||||
$model->where($key, $op, $params[$key].'%');
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($op == 'beforeLike') {
|
||||
$model->where($key, $op, '%'.$params[$key]);
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($op == 'date') {
|
||||
$date = date('Y-m-d', strtotime($params[$key]));
|
||||
$model->whereDate($key, $date);
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($op == 'betweenDate') {
|
||||
if (is_array($params[$key])) {
|
||||
$start = $params[$key][0];
|
||||
$end = $params[$key][1];
|
||||
$model->whereDate($key, '>=', $start);
|
||||
$model->whereDate($key, '<=', $end);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 快速搜索
|
||||
if (isset($params['keywordSearch']) && $params['keywordSearch'] != '') {
|
||||
$quickSearchArr = $this->quickSearchField ?? [];
|
||||
if (count($quickSearchArr) > 0) {
|
||||
$model->whereAny(
|
||||
$quickSearchArr,
|
||||
'like',
|
||||
'%'.str_replace('%', '\%', $params['keywordSearch']).'%'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 构建排序
|
||||
if (isset($params['sorter']) && $params['sorter']) {
|
||||
if(is_array($params['sorter'])) {
|
||||
$sorter = $params['sorter'];
|
||||
} else {
|
||||
$sorter = json_decode($params['sorter'], true);
|
||||
}
|
||||
if (count($sorter) > 0) {
|
||||
$column = array_keys($sorter)[0];
|
||||
$direction = $sorter[$column] == 'ascend' ? 'asc' : 'desc';
|
||||
$model->orderBy($column, $direction);
|
||||
}
|
||||
}
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Common\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class BaseFormRequest extends FormRequest
|
||||
{
|
||||
|
||||
/**
|
||||
* 是否为更新请求
|
||||
* @return bool
|
||||
*/
|
||||
protected function isUpdate(): bool
|
||||
{
|
||||
if ($this->isMethod('PUT') || $this->isMethod('PATCH')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Common\Middlewares;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class AllowCrossDomainMiddleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param Closure(Request): (Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
$response = $next($request);
|
||||
|
||||
// 添加跨域头
|
||||
$response->headers->set('Access-Control-Allow-Origin', '*');
|
||||
$response->headers->set('Access-Control-Allow-Credentials', 'true');
|
||||
$response->headers->set('Access-Control-Max-Age', 1800);
|
||||
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
||||
$response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, User-Language');
|
||||
|
||||
// 如果是预检请求, 返回 204
|
||||
if ($request->isMethod('OPTIONS')) {
|
||||
return response()->json([], 204, $response->headers->all());
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Common\Middlewares;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class LanguageMiddleware
|
||||
{
|
||||
/**
|
||||
* 支持的语言列表
|
||||
*/
|
||||
protected array $supportedLanguages = [
|
||||
'en' => 'en', // 英语
|
||||
'zh' => 'zh', // 简体中文
|
||||
'jp' => 'ja', // 日语
|
||||
];
|
||||
|
||||
/**
|
||||
* 默认语言
|
||||
*/
|
||||
protected string $defaultLanguage = 'zh';
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
// 获取当前语言
|
||||
$locale = $this->getLocale($request);
|
||||
// 设置应用语言
|
||||
App::setLocale($locale);
|
||||
// 让请求继续处理
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前语言设置
|
||||
*/
|
||||
protected function getLocale(Request $request): string
|
||||
{
|
||||
// 优先级 1: URL 参数 (例如 ?lang=en)
|
||||
if ($request->has('lang')) {
|
||||
$lang = $request->get('lang');
|
||||
if ($this->isSupported($lang)) {
|
||||
return $lang;
|
||||
}
|
||||
}
|
||||
|
||||
// 优先级 2: User-Language 头
|
||||
$browserLocale = $this->getBrowserLocale($request);
|
||||
if ($browserLocale && $this->isSupported($browserLocale)) {
|
||||
return $browserLocale;
|
||||
}
|
||||
|
||||
// 优先级 3: Session 中存储的语言
|
||||
if (Session::has('locale')) {
|
||||
$lang = Session::get('locale');
|
||||
if ($this->isSupported($lang)) {
|
||||
return $lang;
|
||||
}
|
||||
}
|
||||
|
||||
// 优先级 4: 配置文件中的默认语言
|
||||
return config('app.locale', $this->defaultLanguage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 User-Language 头中获取浏览器偏好语言
|
||||
*/
|
||||
protected function getBrowserLocale(Request $request): ?string
|
||||
{
|
||||
$acceptLanguage = $request->header('User-Language');
|
||||
|
||||
if (!$acceptLanguage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $acceptLanguage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查语言是否被支持
|
||||
*/
|
||||
protected function isSupported(string $locale): bool
|
||||
{
|
||||
return array_key_exists($locale, $this->supportedLanguages);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Common\Providers;
|
||||
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class PaginationProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
$this->app->bind('Illuminate\Pagination\LengthAwarePaginator', function ($app, $options) {
|
||||
return new class(
|
||||
$options['items'],
|
||||
$options['total'],
|
||||
$options['perPage'],
|
||||
$options['currentPage'],
|
||||
$options['options']
|
||||
) extends LengthAwarePaginator {
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'data' => $this->items(),
|
||||
'total' => $this->total(),
|
||||
'pageSize' => $this->perPage(),
|
||||
'current' => $this->currentPage(),
|
||||
];
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
namespace Modules\Common\Trait;
|
||||
|
||||
use App\Exceptions\HttpResponseException;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Modules\Common\Enum\ShowType as ShopTypeEnum;
|
||||
|
||||
/**
|
||||
* 响应 trait
|
||||
* 支持 throw 响应
|
||||
*/
|
||||
trait RequestJson
|
||||
{
|
||||
/**
|
||||
* 成功响应
|
||||
*
|
||||
* @param string|array $data 响应数据
|
||||
* @param string $message 响应内容
|
||||
*/
|
||||
protected function success(string|array $data = [], string $message = 'ok'): JsonResponse
|
||||
{
|
||||
if (is_array($data)) {
|
||||
return self::renderJson(true, $data, $message);
|
||||
}
|
||||
|
||||
return self::renderJson(true, [], $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 抛出成功响应,中断程序运行
|
||||
*
|
||||
* @param string|array $data 响应数据
|
||||
* @param string $message 响应内容
|
||||
*/
|
||||
protected function throwSuccess(string|array $data = [], string $message = 'ok'): void
|
||||
{
|
||||
if (is_array($data)) {
|
||||
self::renderThrow(true, $data, $message);
|
||||
}
|
||||
self::renderThrow(true, [], $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回失败响应
|
||||
*
|
||||
* @param string|array $data 响应数据
|
||||
* @param string $message 响应内容
|
||||
*/
|
||||
protected function error(string|array $data = [], string $message = ''): JsonResponse
|
||||
{
|
||||
if (is_array($data)) {
|
||||
return self::renderJson(false, $data, $message, ShopTypeEnum::ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
return self::renderJson(false, [], $data, ShopTypeEnum::ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 抛出失败响应,中断程序运行
|
||||
*
|
||||
* @param string|array $data 响应数据
|
||||
* @param string $message 响应内容
|
||||
*/
|
||||
protected function throwError(string|array $data = [], string $message = ''): void
|
||||
{
|
||||
if (is_array($data)) {
|
||||
self::renderThrow(false, $data, $message, ShopTypeEnum::ERROR_MESSAGE);
|
||||
}
|
||||
self::renderThrow(false, [], $data, ShopTypeEnum::ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回警告响应
|
||||
*
|
||||
* @param string|array $data 响应数据
|
||||
* @param string $message 响应内容
|
||||
*/
|
||||
protected function warn(string|array $data = [], string $message = ''): JsonResponse
|
||||
{
|
||||
if (is_array($data)) {
|
||||
return self::renderJson(false, $data, $message, ShopTypeEnum::WARN_MESSAGE);
|
||||
}
|
||||
|
||||
return self::renderJson(false, [], $data, ShopTypeEnum::WARN_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 抛出失败警告,中断程序运行
|
||||
*
|
||||
* @param string|array $data 响应数据
|
||||
* @param string $message 响应内容
|
||||
*/
|
||||
protected function throwWarn(string|array $data = [], string $message = ''): void
|
||||
{
|
||||
if (is_array($data)) {
|
||||
self::renderThrow(false, $data, $message, ShopTypeEnum::WARN_MESSAGE);
|
||||
}
|
||||
self::renderThrow(false, [], $data, ShopTypeEnum::WARN_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知响应
|
||||
*
|
||||
* @param string $msg 通知标题
|
||||
* @param string $description 通知描述
|
||||
* @param string $placement 通知位置 top topLeft topRight bottom bottomLeft bottomRight
|
||||
* @param ShopTypeEnum $showTypeEnum 通知类型
|
||||
*/
|
||||
protected function notification(
|
||||
string $msg,
|
||||
string $description,
|
||||
ShopTypeEnum $showTypeEnum = ShopTypeEnum::SUCCESS_NOTIFICATION,
|
||||
string $placement = 'topRight'
|
||||
): JsonResponse {
|
||||
$showType = $showTypeEnum->value;
|
||||
$success = false;
|
||||
return response()->json(compact('description', 'success', 'msg', 'showType', 'placement'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回 Json 响应
|
||||
*
|
||||
* @param bool $success 响应状态
|
||||
* @param array $data 响应数据
|
||||
* @param string $msg 响应内容
|
||||
*/
|
||||
protected static function renderJson(
|
||||
bool $success = true,
|
||||
array $data = [],
|
||||
string $msg = '',
|
||||
ShopTypeEnum $showTypeEnum = ShopTypeEnum::SUCCESS_MESSAGE
|
||||
): JsonResponse {
|
||||
$showType = $showTypeEnum->value;
|
||||
|
||||
return response()->json(compact('data', 'success', 'msg', 'showType'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 抛出 API 数据
|
||||
*
|
||||
* @param bool $success 响应状态
|
||||
* @param mixed $data 返回数据
|
||||
* @param string $msg 响应内容
|
||||
* @param ShopTypeEnum $showTypeEnum
|
||||
*/
|
||||
public static function renderThrow(
|
||||
bool $success = true,
|
||||
array $data = [],
|
||||
string $msg = '',
|
||||
ShopTypeEnum $showTypeEnum = ShopTypeEnum::SUCCESS_MESSAGE
|
||||
) {
|
||||
$showType = $showTypeEnum->value;
|
||||
throw new HttpResponseException(compact('data', 'success', 'msg', 'showType'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
use Modules\SystemTool\Services\SysSiteConfigService;
|
||||
|
||||
if (! function_exists('site_config')) {
|
||||
/**
|
||||
* 获取或设置系统配置
|
||||
*
|
||||
* @param string|null $name 配置名称,格式:'group.key' 或 'group',为null时返回所有配置
|
||||
* @param mixed|null $default 默认值(仅在获取时使用)
|
||||
* @return mixed
|
||||
*
|
||||
* @example
|
||||
* site_config('site.name') // 获取配置
|
||||
* site_config('site.name', 'Default') // 带默认值获取
|
||||
* site_config('site') // 获取整个组
|
||||
* site_config() // 获取所有配置
|
||||
*/
|
||||
function site_config(?string $name = null, mixed $default = null): mixed
|
||||
{
|
||||
return SysSiteConfigService::getSiteConfig($name, $default);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('web_path')) {
|
||||
/**
|
||||
* Get the path to the web of the install.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function web_path(string $path = ''): string
|
||||
{
|
||||
return base_path('web'. DIRECTORY_SEPARATOR . $path);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('getTreeData')) {
|
||||
/**
|
||||
* 获取树形数据
|
||||
*
|
||||
* @param array $list
|
||||
* @param int $parentId
|
||||
* @param string[] $params
|
||||
* @return array
|
||||
*/
|
||||
function getTreeData(
|
||||
array &$list,
|
||||
int $parentId = 0,
|
||||
array $params = []
|
||||
): array
|
||||
{
|
||||
$params = array_merge($params, [
|
||||
'id' => 'id',
|
||||
'parent_id' => 'parent_id',
|
||||
'children' => 'children'
|
||||
]);
|
||||
$data = [];
|
||||
foreach ($list as $k => $item) {
|
||||
if ($item[$params['parent_id']] == $parentId) {
|
||||
$children = getTreeData($list, $item[$params['id']]);
|
||||
!empty($children) && $item[$params['children']] = $children;
|
||||
$data[] = $item;
|
||||
unset($list[$k]);
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user