From 40af7a6b05045c83d5723b52a35d397635b8e35b Mon Sep 17 00:00:00 2001 From: "Mr.April" Date: Tue, 5 Aug 2025 15:47:16 +0800 Subject: [PATCH 1/6] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=9B=AA=E8=8A=B1?= =?UTF-8?q?ID=E9=87=8D=E5=A4=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/composer.lock | 104 ++----------------------- server/config/bootstrap.php | 1 - server/config/thinkorm.php | 34 -------- server/core/abstract/BaseModel.php | 33 +------- server/core/context/TenantContext.php | 1 + server/core/db/DataImporterService.php | 37 +-------- 6 files changed, 15 insertions(+), 195 deletions(-) delete mode 100644 server/config/thinkorm.php diff --git a/server/composer.lock b/server/composer.lock index 03edd61..a240ef6 100644 --- a/server/composer.lock +++ b/server/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4806b22e8df2fffa7d8a434576d791e0", + "content-hash": "f817c0f2a5ba81575320f7454197f6df", "packages": [ { "name": "aliyuncs/oss-sdk-php", @@ -2873,11 +2873,11 @@ }, { "name": "madong/helper", - "version": "v1.1.0", + "version": "v1.1.1", "source": { "type": "git", "url": "https://gitcode.com/motion-code/helper.git", - "reference": "d13e1d7715b02d87342419643094b53b2218adaf" + "reference": "7d6029c0e8d3e09414e5db7bae0aa8b398267276" }, "require": { "illuminate/collections": "*", @@ -2904,9 +2904,8 @@ } ], "description": "The ingen Helper Package", - "time": "2025-07-04T01:40:03+00:00" + "time": "2025-08-05T03:16:37+00:00" }, - { "name": "maennchen/zipstream-php", "version": "3.1.2", @@ -7105,64 +7104,6 @@ }, "time": "2025-04-07T06:55:59+00:00" }, - { - "name": "topthink/think-orm", - "version": "v3.0.34", - "source": { - "type": "git", - "url": "https://github.com/top-think/think-orm.git", - "reference": "715e55da149fe32a12d68ef10e5b00e70bd3dbec" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/top-think/think-orm/zipball/715e55da149fe32a12d68ef10e5b00e70bd3dbec", - "reference": "715e55da149fe32a12d68ef10e5b00e70bd3dbec", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pdo": "*", - "php": ">=8.0.0", - "psr/log": ">=1.0", - "psr/simple-cache": ">=1.0", - "topthink/think-helper": "^3.1" - }, - "require-dev": { - "phpunit/phpunit": "^9.6|^10" - }, - "suggest": { - "ext-mongodb": "provide mongodb support" - }, - "type": "library", - "autoload": { - "files": [ - "stubs/load_stubs.php" - ], - "psr-4": { - "think\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "liu21st", - "email": "liu21st@gmail.com" - } - ], - "description": "the PHP Database&ORM Framework", - "keywords": [ - "database", - "orm" - ], - "support": { - "issues": "https://github.com/top-think/think-orm/issues", - "source": "https://github.com/top-think/think-orm/tree/v3.0.34" - }, - "time": "2025-01-14T06:03:33+00:00" - }, { "name": "topthink/think-template", "version": "v3.0.2", @@ -7831,39 +7772,6 @@ }, "time": "2025-01-24T12:56:01+00:00" }, - { - "name": "webman/think-orm", - "version": "v1.1.6", - "source": { - "type": "git", - "url": "https://github.com/webman-php/think-orm.git", - "reference": "32b464f44e727b8a687ddd707ddb84e6f8a2ce74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webman-php/think-orm/zipball/32b464f44e727b8a687ddd707ddb84e6f8a2ce74", - "reference": "32b464f44e727b8a687ddd707ddb84e6f8a2ce74", - "shasum": "" - }, - "require": { - "topthink/think-orm": "^2.0.53 || ^3.0.0 || ^4.0.0 || dev-master" - }, - "type": "library", - "autoload": { - "psr-4": { - "Webman\\ThinkOrm\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "support": { - "issues": "https://github.com/webman-php/think-orm/issues", - "source": "https://github.com/webman-php/think-orm/tree/v1.1.6" - }, - "time": "2024-11-22T03:17:44+00:00" - }, { "name": "workerman/coroutine", "version": "v1.1.3", @@ -8269,7 +8177,7 @@ "packages-dev": [], "aliases": [], "minimum-stability": "dev", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { @@ -8278,6 +8186,6 @@ "ext-pdo": "*", "ext-gd": "*" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/server/config/bootstrap.php b/server/config/bootstrap.php index ce7bfb2..95d2e87 100644 --- a/server/config/bootstrap.php +++ b/server/config/bootstrap.php @@ -14,5 +14,4 @@ return [ support\bootstrap\Session::class, - Webman\ThinkOrm\ThinkOrm::class, ]; diff --git a/server/config/thinkorm.php b/server/config/thinkorm.php deleted file mode 100644 index 8cb83de..0000000 --- a/server/config/thinkorm.php +++ /dev/null @@ -1,34 +0,0 @@ - 'mysql', - 'connections' => [ - 'mysql' => [ - // 数据库类型 - 'type' => 'mysql', - // 服务器地址 - 'hostname' => '127.0.0.1', - // 数据库名 - 'database' => 'test', - // 数据库用户名 - 'username' => 'root', - // 数据库密码 - 'password' => '123456', - // 数据库连接端口 - 'hostport' => '3306', - // 数据库连接参数 - 'params' => [ - // 连接超时3秒 - \PDO::ATTR_TIMEOUT => 3, - ], - // 数据库编码默认采用utf8 - 'charset' => 'utf8', - // 数据库表前缀 - 'prefix' => '', - // 断线重连 - 'break_reconnect' => true, - // 自定义分页类 - 'bootstrap' => '' - ], - ], -]; diff --git a/server/core/abstract/BaseModel.php b/server/core/abstract/BaseModel.php index 22879c3..be84f11 100644 --- a/server/core/abstract/BaseModel.php +++ b/server/core/abstract/BaseModel.php @@ -20,16 +20,14 @@ use app\common\scopes\global\TenantSharedTableScope; use app\common\services\system\SysRecycleBinService; use Carbon\Carbon; use core\exception\handler\AdminException; +use core\uuid\Snowflake; use Illuminate\Database\Eloquent\SoftDeletes; use core\context\TenantContext; -use madong\helper\Snowflake; use support\Container; use support\Model; class BaseModel extends Model { - private const WORKER_ID = 1; - private const DATA_CENTER_ID = 1; /** * 指明模型的ID是否自动递增。 @@ -109,7 +107,7 @@ class BaseModel extends Model //注册创建事件 static::creating(function ($model) { if (!isset($model->{$model->getKeyName()})) { - $model->{$model->getKeyName()} = self::generateSnowflakeID(); // 生成雪花 ID + $model->{$model->getKeyName()} = Snowflake::generate(); // 生成雪花 ID } self::setCreatedBy($model); self::setTenantId($model); @@ -238,6 +236,8 @@ class BaseModel extends Model * 删除事件 * * @param \support\Model $model + * + * @throws \core\exception\handler\AdminException */ public static function onAfterDelete(Model $model) { @@ -342,31 +342,6 @@ class BaseModel extends Model } } - /** - * 实例化雪花算法 - * - * @return Snowflake - */ - private static function createSnowflake(): Snowflake - { - if (self::$snowflake == null) { - self::$snowflake = new Snowflake(self::WORKER_ID, self::DATA_CENTER_ID); - } - return self::$snowflake; - } - - /** - * 生成雪花ID - * - * @return int - * @throws \Exception - */ - private static function generateSnowflakeID(): int - { - $snowflake = self::createSnowflake(); - return $snowflake->nextId(); - } - private static function prepareRecycleBinData($tableData, $table, $prefix): array { return [ diff --git a/server/core/context/TenantContext.php b/server/core/context/TenantContext.php index 9130803..91a4c5a 100644 --- a/server/core/context/TenantContext.php +++ b/server/core/context/TenantContext.php @@ -35,6 +35,7 @@ use support\Container; * @method static bool isExpired() * @method static getTenantId() * @method static db() + * @method static getDatabaseConnection() */ class TenantContext { diff --git a/server/core/db/DataImporterService.php b/server/core/db/DataImporterService.php index 01b5e71..5617cba 100644 --- a/server/core/db/DataImporterService.php +++ b/server/core/db/DataImporterService.php @@ -12,7 +12,7 @@ namespace core\db; -use madong\helper\Snowflake; +use core\uuid\Snowflake; use PDO; /** @@ -24,35 +24,6 @@ use PDO; class DataImporterService { - private const WORKER_ID = 1; - private const DATA_CENTER_ID = 1; - - /** - * 雪花算法实例 - * - * @var Snowflake|null - */ - protected ?Snowflake $snowflake = null; - - - public function __construct() - { - $this->snowflake = new Snowflake(self::WORKER_ID, self::DATA_CENTER_ID); - } - - /** - * 生成雪花ID - * - * @return int - * @throws \Exception - */ - public function generateSnowflakeId(): int - { - $snowflake = $this->snowflake; - return $snowflake->nextId(); - } - - /** * 获取 PDO 连接的方法 * @@ -115,7 +86,7 @@ class DataImporterService if ($options['useSnowflakeId']) { $fields[] = $options['idKey']; if (empty($row[$options['idKey']])) { - $row[$options['idKey']] = $this->generateSnowflakeId(); + $row[$options['idKey']] = Snowflake::generate(); } } elseif ($options['useAutoIncrement']) { unset($row[$options['idKey']]); @@ -195,7 +166,7 @@ class DataImporterService foreach ($data as $key => $item) { // 如果需要使用雪花ID if ($options['useSnowflakeId']) { - $item[$options['idKey']] = $this->generateSnowflakeId(); // 生成雪花ID + $item[$options['idKey']] = Snowflake::generate(); // 生成雪花ID } elseif ($options['useAutoIncrement']) { unset($item[$options['idKey']]); // 自增ID由数据库处理 } @@ -244,7 +215,7 @@ class DataImporterService foreach ($data as $item) { // 如果需要使用雪花ID if ($options['useSnowflakeId']) { - $item[$options['idKey']] = $this->generateSnowflakeId(); // 生成雪花ID + $item[$options['idKey']] = Snowflake::generate(); // 生成雪花ID } elseif ($options['useAutoIncrement']) { unset($item[$options['idKey']]); // 自增ID由数据库处理 } -- Gitee From 1ba0a5de73c0b01ac879663283fef77001af9607 Mon Sep 17 00:00:00 2001 From: "Mr.April" Date: Tue, 5 Aug 2025 15:47:51 +0800 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=80=80=E5=87=BA?= =?UTF-8?q?Token=E6=B7=BB=E5=8A=A0=E9=BB=91=E5=90=8D=E5=8D=95=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/app/functions.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/app/functions.php b/server/app/functions.php index e8fbac0..af88f16 100644 --- a/server/app/functions.php +++ b/server/app/functions.php @@ -18,6 +18,12 @@ use support\Container; */ function getCurrentUser(bool $fullInfo = false, bool $refresh = false): mixed { + $request = request(); + $rule = $request->path(); + if (in_array($rule, ['/system/logout'])) { + return null; + } + // 1. 验证请求和授权令牌 $token = resolveAuthorizationToken(); if ($token === null) { -- Gitee From 52ca4ad4de5f571e6ddaba7c3db2038f6c9783b4 Mon Sep 17 00:00:00 2001 From: "Mr.April" Date: Tue, 5 Aug 2025 15:48:31 +0800 Subject: [PATCH 3/6] =?UTF-8?q?chore=EF=BC=9A=E6=9B=B4=E6=96=B0=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E5=AD=97=E6=AE=B5app=E9=BB=98=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/scripts/sql/install.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/scripts/sql/install.sql b/server/scripts/sql/install.sql index 7257d35..1778230 100644 --- a/server/scripts/sql/install.sql +++ b/server/scripts/sql/install.sql @@ -456,7 +456,7 @@ CREATE TABLE `ma_sys_menu` ( `id` bigint(20) NOT NULL COMMENT '菜单ID', `pid` bigint(20) NOT NULL DEFAULT 0 COMMENT '父ID', - `app` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '应用编码', + `app` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'admin' COMMENT '应用编码', `title` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '菜单名称', `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '唯一编码', `level` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父ID集合', -- Gitee From 1b02ded77ac68d172a3efc7a1b3618307365021b Mon Sep 17 00:00:00 2001 From: "Mr.April" Date: Tue, 5 Aug 2025 15:48:53 +0800 Subject: [PATCH 4/6] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E5=A4=8D=E9=9B=AA?= =?UTF-8?q?=E8=8A=B1ID=E9=87=8D=E5=A4=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/config/core/utils/app.php | 15 ++++ server/config/core/uuid/app.php | 15 ++++ server/config/core/uuid/snowflake.php | 20 +++++ server/core/uuid/Snowflake.php | 106 ++++++++++++++++++++++++++ 4 files changed, 156 insertions(+) create mode 100644 server/config/core/utils/app.php create mode 100644 server/config/core/uuid/app.php create mode 100644 server/config/core/uuid/snowflake.php create mode 100644 server/core/uuid/Snowflake.php diff --git a/server/config/core/utils/app.php b/server/config/core/utils/app.php new file mode 100644 index 0000000..c9afe2b --- /dev/null +++ b/server/config/core/utils/app.php @@ -0,0 +1,15 @@ + true, +]; diff --git a/server/config/core/uuid/app.php b/server/config/core/uuid/app.php new file mode 100644 index 0000000..c9afe2b --- /dev/null +++ b/server/config/core/uuid/app.php @@ -0,0 +1,15 @@ + true, +]; diff --git a/server/config/core/uuid/snowflake.php b/server/config/core/uuid/snowflake.php new file mode 100644 index 0000000..c4c1f62 --- /dev/null +++ b/server/config/core/uuid/snowflake.php @@ -0,0 +1,20 @@ + true, + 'node_id' => 1, + 'worker_id' => null,//使用线程id + 'node_id_bits' => 3, + 'worker_id_bits' => 7, + 'sequence_bits' => 12, +]; diff --git a/server/core/uuid/Snowflake.php b/server/core/uuid/Snowflake.php new file mode 100644 index 0000000..133dab6 --- /dev/null +++ b/server/core/uuid/Snowflake.php @@ -0,0 +1,106 @@ +id ?: 0) : 0; + self::$instance = new SnowflakeGenerator( + $nodeId, + $workerId, + array_merge([ + 'node_id_bits' => 3, + 'worker_id_bits' => 7, + 'sequence_bits' => 12, + ], config('core.uuid.snowflake', [])) + + ); + } + + return self::$instance; + } + + /** + * 静态代理调用:将所有静态方法调用转发到真正的 Snowflake 实例上 + * + * @param string $method 方法名,比如 "generate" + * @param array $args 参数列表 + * + * @return mixed + * @throws \core\exception\handler\AdminException + */ + public static function __callStatic(string $method, array $args) + { + $instance = self::instance(); + + if (!method_exists($instance, $method)) { + throw new AdminException(sprintf( + 'Call to undefined method %s::%s()', + static::class, + $method + )); + } + + return $instance->{$method}(...$args); + } +} + -- Gitee From a4dfc56bb1f0bb7618abf08136cdfef746212aa2 Mon Sep 17 00:00:00 2001 From: "Mr.April" Date: Tue, 5 Aug 2025 16:01:27 +0800 Subject: [PATCH 5/6] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E5=A4=8D=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E4=B8=8A=E4=BC=A0=E5=9B=9E=E6=98=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/.env.development | 2 +- web/.env.production | 17 +--- web/src/api/dev/terminal/index.ts | 6 +- web/src/api/request.ts | 25 +++++- web/src/components/form/components/avatar.vue | 80 ++++++++++++++----- web/src/store/modules/site-config.ts | 2 +- web/src/utils/tool.ts | 64 ++++++++++----- .../core/profile/components/update-avatar.vue | 3 +- 8 files changed, 134 insertions(+), 65 deletions(-) diff --git a/web/.env.development b/web/.env.development index 8c77c4f..c99ba3a 100644 --- a/web/.env.development +++ b/web/.env.development @@ -33,6 +33,6 @@ VITE_PROXY_URL = 'http://localhost:5566' VITE_AXIOS_BASE_URL = 'http://127.0.0.1:8899' -VITE_WSS_URL='ws://127.0.0.1:3898' +VITE_WSS_URL='ws://127.0.0.1:3998' diff --git a/web/.env.production b/web/.env.production index 0ed97cd..b512175 100644 --- a/web/.env.production +++ b/web/.env.production @@ -1,10 +1,9 @@ VITE_BASE=/ + # 接口地址 # VITE_GLOB_API_URL=/api - -#后端模式 -VITE_GLOB_API_URL=/ +VITE_GLOB_API_URL=useCurrentDomain #useCurrentDomain 为自动获取当前域名为base地址 # 是否开启压缩,可以设置为 none, brotli, gzip VITE_COMPRESS=none @@ -25,16 +24,8 @@ VITE_GLOB_CLIENT_KEY= X-Client-ID VITE_GLOB_ENABLE_WSS=true # wss接口地址 -# VITE_GLOB_WSS_URL=/ws - -#后端模式写全路径 -VITE_GLOB_WSS_URL=ws://127.0.0.1:3898 +# VITE_GLOB_WSS_URL=/ws +VITE_GLOB_WSS_URL=ws://127.0.0.1:3898 #useCurrentDomain 模式使用绝对url # WSS KEY VITE_GLOB_WSS_APPKEY = 60756ede2a9737a05384aad849e220f8 - - -# 线上环境接口地址 -VITE_AXIOS_BASE_URL = fetchCurrentDomain - -# VITE_AXIOS_BASE_URL = 'https://api.admin.madong.tech' \ No newline at end of file diff --git a/web/src/api/dev/terminal/index.ts b/web/src/api/dev/terminal/index.ts index 96219bd..e336c30 100644 --- a/web/src/api/dev/terminal/index.ts +++ b/web/src/api/dev/terminal/index.ts @@ -1,6 +1,6 @@ -import { requestClient } from "#/api/request"; +import { getApiBaseUrl, requestClient } from "#/api/request"; import { useAccessStore } from "#/components/common/stores"; -import { getUrl } from "#/utils" + @@ -27,7 +27,7 @@ export class TerminalApi { const accessStore = useAccessStore(); const token = this.formatToken(accessStore.accessToken); return ( - getUrl() + this.baseUrl + '?command=' + commandKey + '&uuid=' + uuid + '&extend=' + extend + '&token=' + token + '&server=crmd' + getApiBaseUrl() + this.baseUrl + '?command=' + commandKey + '&uuid=' + uuid + '&extend=' + extend + '&token=' + token + '&server=crmd' ) } diff --git a/web/src/api/request.ts b/web/src/api/request.ts index 57c4a66..570d0f5 100644 --- a/web/src/api/request.ts +++ b/web/src/api/request.ts @@ -15,7 +15,7 @@ import { message } from 'ant-design-vue'; import { refreshTokenApi } from './core'; -const apiURL = import.meta.env.VITE_GLOB_API_URL; + const clientKey = import.meta.env.VITE_GLOB_CLIENT_KEY; @@ -135,9 +135,28 @@ function createRequestClient(baseURL: string, options?: RequestClientOptions) { return client; } -export const requestClient = createRequestClient(apiURL, { + +export const getApiBaseUrl = (customValue?: string | null): string => { + if (customValue) { + return customValue === 'useCurrentDomain' + ? window.location.protocol + '//' + window.location.host + : customValue; + } + + const envValue = import.meta.env.VITE_GLOB_API_URL; + if (envValue) { + return envValue === 'useCurrentDomain' + ? window.location.protocol + '//' + window.location.host + : envValue; + } + return window.location.protocol + '//' + window.location.host; +} + + +export const requestClient = createRequestClient(getApiBaseUrl(null), { responseReturn: 'data', }); -export const baseRequestClient = new RequestClient({ baseURL: apiURL }); + +export const baseRequestClient = new RequestClient({ baseURL: getApiBaseUrl(null) }); diff --git a/web/src/components/form/components/avatar.vue b/web/src/components/form/components/avatar.vue index c05f558..c5e58a8 100644 --- a/web/src/components/form/components/avatar.vue +++ b/web/src/components/form/components/avatar.vue @@ -1,59 +1,89 @@ + + diff --git a/web/src/store/modules/site-config.ts b/web/src/store/modules/site-config.ts index 471d3f8..0346920 100644 --- a/web/src/store/modules/site-config.ts +++ b/web/src/store/modules/site-config.ts @@ -47,7 +47,7 @@ export const useSiteConfigStore = defineStore('site-config', () => { }, logo: { enable: true, - source: state.site_logo, + source: fullUrl(state.site_logo), }, copyright: { companyName: state?.site_name||'', diff --git a/web/src/utils/tool.ts b/web/src/utils/tool.ts index 8b63f7b..84bf962 100644 --- a/web/src/utils/tool.ts +++ b/web/src/utils/tool.ts @@ -1,4 +1,5 @@ +import { getApiBaseUrl } from '#/api/request'; import { useSiteConfigStore } from '#/store/modules/site-config'; import type { App, Component } from 'vue'; @@ -116,24 +117,6 @@ const padStart = (str: string, maxLength: number, fillString = ' ') => { return fillString.slice(0, fillLength) + str } -/** - * 根据环境获取基础URL - * @returns - */ -export const getUrl = (): string => { - const value: string = import.meta.env.VITE_AXIOS_BASE_URL as string - return value == 'fetchCurrentDomain' ? window.location.protocol + '//' + window.location.host : value -} - - -/** - * 根据环境获取基础请求URL的端口 - */ -export const getPort = (): string => { - const url = getUrl() - return new URL(url).port -} - /** @@ -144,10 +127,9 @@ export const getPort = (): string => { */ export const fullUrl = (relativeUrl: string, domain: string = ''): string => { const siteConfig = useSiteConfigStore(); - // 1. 处理空路径直接返回域名 - if (!relativeUrl) return domain || getUrl(); + if (!relativeUrl) return domain || getApiBaseUrl(null); @@ -157,7 +139,7 @@ export const fullUrl = (relativeUrl: string, domain: string = ''): string => { if (isAbsoluteUrl || isDataUrl) return relativeUrl; // 3. 确定最终使用的域名 - const finalDomain = domain || siteConfig.state.cdn_url || getUrl(); + const finalDomain = domain || siteConfig.state.cdn_url || getApiBaseUrl(); if (!finalDomain) return relativeUrl; // 保底返回原路径 // 4. 拼接URL @@ -176,6 +158,46 @@ export const fullUrl = (relativeUrl: string, domain: string = ''): string => { }; +/** + * 移除URL中的公共路径前缀 + * @param url 待处理的URL + * @param domain 可选指定要移除的特定域名(默认自动检测) + * @returns 移除前缀后的相对路径 + */ +export const stripBaseUrl = (url: string, domain: string = ''): string => { + const siteConfig = useSiteConfigStore(); + + // 1. 处理空值 + if (!url) return ''; + + // 2. 检测不需要处理的URL类型 + const isDataUrl = /^data:image\//i.test(url); + if (isDataUrl) return url; + + // 3. 确定要移除的域名(优先级:参数指定 > CDN域名 > API域名) + const baseDomain = domain || siteConfig.state.cdn_url || getApiBaseUrl(); + if (!baseDomain) return url; + + // 4. 标准化待移除的域名(移除尾部斜杠) + const normalizedDomain = baseDomain.replace(/\/+$/, ''); + + // 5. 移除域名部分(包括协议头可选匹配) + let result = url + .replace(new RegExp(`^https?:\\/\\/${normalizedDomain}\\/?`), '') + .replace(new RegExp(`^${normalizedDomain}\\/?`), ''); + + // 6. 移除可能的CDN参数(如果来自同一CDN) + if (normalizedDomain === siteConfig.state.cdn_url && siteConfig.state.cdn_url_params) { + const paramStr = `[?&]${siteConfig.state.cdn_url_params.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`; + result = result.replace(new RegExp(`${paramStr}(?:&|$)`), ''); + } + + // 7. 确保不会返回空路径(至少保留原文件名) + return result || url.split('/').pop() || ''; +}; + + + /** * 获取一组资源的完整地址(支持字符串或数组输入) * @param relativeUrls 相对路径(支持逗号分隔字符串或数组) diff --git a/web/src/views/core/profile/components/update-avatar.vue b/web/src/views/core/profile/components/update-avatar.vue index bbf660c..f1819ca 100644 --- a/web/src/views/core/profile/components/update-avatar.vue +++ b/web/src/views/core/profile/components/update-avatar.vue @@ -13,6 +13,7 @@ import { import { Icon } from '#/components/icon'; import { SystemProfileApi } from '#/api/system/profile'; import { joinUrls } from '#/utils'; +import { getApiBaseUrl } from '#/api/request'; const api= new SystemProfileApi(); @@ -31,7 +32,7 @@ const authStore = useAuthStore(); const getAction = computed(() => { //@ts-ignore - return joinUrls(import.meta.env.VITE_GLOB_API_URL, 'system/files/upload-image') + return joinUrls(getApiBaseUrl(null), 'system/files/upload-image') }); const headers = { -- Gitee From ad1aacd0a863489bdda542dcd81984a7b2a61e34 Mon Sep 17 00:00:00 2001 From: "Mr.April" Date: Tue, 5 Aug 2025 16:03:25 +0800 Subject: [PATCH 6/6] =?UTF-8?q?chore=EF=BC=9Av4.0.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/config/core/app.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/config/core/app.php b/server/config/core/app.php index 77b2a13..ade2795 100644 --- a/server/config/core/app.php +++ b/server/config/core/app.php @@ -12,5 +12,5 @@ return [ 'enable' => true, - 'version' => '4.0.4', + 'version' => '4.0.5', ]; -- Gitee