1.修复矿建鉴权报错
2.优化登录跳转接口 3.优化登录跳转接口 4.修复CURD生成代码模块表不加前缀访问返回404问题 5.系统级报错***优化报错Fatal error: Type of app\common\library\token\TokenExpirationException::$message
This commit is contained in:
@@ -802,8 +802,8 @@ class Helper
|
||||
$indexVueData['defaultItems'] = self::getJsonFromArray($indexVueData['defaultItems'] ?? []);
|
||||
$indexVueData['tableColumn'] = self::buildTableColumn($indexVueData['tableColumn'] ?? []);
|
||||
$indexVueData['dblClickNotEditColumn'] = self::buildSimpleArray($indexVueData['dblClickNotEditColumn'] ?? ['undefined']);
|
||||
$controllerFile['path'][] = $controllerFile['originalLastName'];
|
||||
$indexVueData['controllerUrl'] = '\'/admin/' . ($controllerFile['path'] ? implode('.', $controllerFile['path']) : '') . '/\'';
|
||||
$urlSegments = array_merge($controllerFile['path'], [$controllerFile['originalLastName']]);
|
||||
$indexVueData['controllerUrl'] = '\'/admin/' . ($urlSegments ? implode('.', array_map('strtolower', $urlSegments)) : '') . '/\'';
|
||||
$indexVueData['componentName'] = ($webViewsDir['path'] ? implode('/', $webViewsDir['path']) . '/' : '') . $webViewsDir['originalLastName'];
|
||||
$indexVueContent = self::assembleStub('html/index', $indexVueData);
|
||||
self::writeFile(root_path() . $webViewsDir['views'] . '/' . 'index.vue', $indexVueContent);
|
||||
|
||||
@@ -668,7 +668,7 @@ class Install extends Api
|
||||
|
||||
/**
|
||||
* 获取安装完成后的访问地址(根据请求来源区分 API 与前端开发模式)
|
||||
* - 通过 API 访问(8787):index.html#/admin、index.html#/
|
||||
* - 通过 API 访问(8787):index#/admin、index#/(无 index 与 # 之间的斜杠)
|
||||
* - 通过前端开发服务访问(1818):/#/admin、/#/
|
||||
*/
|
||||
public function accessUrls(Request $request): Response
|
||||
@@ -680,7 +680,8 @@ class Install extends Api
|
||||
$port = substr($host, strrpos($host, ':') + 1);
|
||||
}
|
||||
$scheme = $request->header('x-forwarded-proto', 'http');
|
||||
$base = rtrim($scheme . '://' . $host, '/');
|
||||
$basePath = $request instanceof \support\Request ? $request->publicBasePath() : '';
|
||||
$base = rtrim($scheme . '://' . $host, '/') . $basePath;
|
||||
|
||||
if ($port === '1818') {
|
||||
$adminUrl = $base . '/#/admin';
|
||||
|
||||
@@ -142,9 +142,14 @@ class Backend extends Api
|
||||
|
||||
if ($needLogin) {
|
||||
if (!$this->auth->isLogin()) {
|
||||
if ($request->method() === 'GET' && !$this->expectsApiJsonResponse($request)) {
|
||||
$location = $this->adminSpaLoginUrl($request);
|
||||
return redirect($location);
|
||||
}
|
||||
// 必须使用 HTTP 200 返回 JSON:若用 HTTP 303,axios 会跟随重定向,拿不到 JSON,前端无法跳转登录
|
||||
return $this->error(__('Please login first'), [
|
||||
'type' => Auth::NEED_LOGIN,
|
||||
], 0, ['statusCode' => Auth::LOGIN_RESPONSE_CODE]);
|
||||
], 0);
|
||||
}
|
||||
if ($needPermission) {
|
||||
$controllerPath = $this->getControllerPath($request);
|
||||
@@ -167,6 +172,37 @@ class Backend extends Api
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否应按 API 返回 JSON(前端 axios 会带 server: true;纯浏览器地址栏访问多为 HTML Accept)
|
||||
*/
|
||||
protected function expectsApiJsonResponse(WebmanRequest $request): bool
|
||||
{
|
||||
$server = $request->header('server', '');
|
||||
if ($server === 'true' || $server === '1') {
|
||||
return true;
|
||||
}
|
||||
if (strtolower($request->header('x-requested-with', '')) === 'xmlhttprequest') {
|
||||
return true;
|
||||
}
|
||||
$accept = strtolower($request->header('accept', ''));
|
||||
if (str_contains($accept, 'application/json')) {
|
||||
return true;
|
||||
}
|
||||
// 浏览器地址栏/点击链接触发的主文档请求,优先 302 到前端登录(避免误判为 API)
|
||||
if (strtolower((string) $request->header('sec-fetch-mode', '')) === 'navigate') {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台 Vue 为 hash 路由时的登录页(相对路径,与 web/src/router 一致)
|
||||
*/
|
||||
protected function adminSpaLoginUrl(WebmanRequest $request): string
|
||||
{
|
||||
return '/#/admin/login';
|
||||
}
|
||||
|
||||
/**
|
||||
* 子类可覆盖,用于初始化 model 等(替代原 initialize)
|
||||
* @return Response|null 需直接返回时返回 Response,否则 null
|
||||
|
||||
@@ -11,12 +11,15 @@ use Exception;
|
||||
*/
|
||||
class TokenExpirationException extends Exception
|
||||
{
|
||||
protected array $data = [];
|
||||
|
||||
public function __construct(
|
||||
protected string $message = '',
|
||||
protected int $code = 409,
|
||||
protected array $data = [],
|
||||
string $message = '',
|
||||
int $code = 409,
|
||||
array $data = [],
|
||||
?\Throwable $previous = null
|
||||
) {
|
||||
$this->data = $data;
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
|
||||
@@ -204,7 +204,24 @@ if (!function_exists('get_controller_path')) {
|
||||
if (count($parts) < 2) {
|
||||
return $parts[0] ?? null;
|
||||
}
|
||||
return implode('/', array_slice($parts, 1, -1)) ?: $parts[1];
|
||||
$segments = array_slice($parts, 1, -1);
|
||||
if ($segments === []) {
|
||||
return $parts[1] ?? null;
|
||||
}
|
||||
// ThinkPHP 风格段 game.Config -> game/config,与 $request->controller 解析结果一致(否则权限节点对不上)
|
||||
$normalized = [];
|
||||
foreach ($segments as $seg) {
|
||||
if (str_contains($seg, '.')) {
|
||||
$dotPos = strpos($seg, '.');
|
||||
$mod = substr($seg, 0, $dotPos);
|
||||
$ctrl = substr($seg, $dotPos + 1);
|
||||
$normalized[] = strtolower($mod);
|
||||
$normalized[] = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $ctrl));
|
||||
} else {
|
||||
$normalized[] = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $seg));
|
||||
}
|
||||
}
|
||||
return implode('/', $normalized);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user