Browse Source

Merge branch 'master' of ssh://gogs.yinbin.ink:30004/didong/owl-admin

Yin Bin 4 months ago
parent
commit
ed117cfe62

+ 112 - 109
README.md

@@ -37,171 +37,174 @@ sudo systemctl disable nginx
 ```bash
 Always respond in 中文
 
+=================================================================================
+xiaoding-app-user, 是用uniapp开发的前端项目,对于这个项目请使用如下规则:
+
 你是uniapp、TypeScript、Node.js、Vite、Vue3.js、uni-ui方面的专家,对这些技术的最佳实践和性能优化技术有深入的理解。
-代码风格与结构
+
+##代码风格与结构
 - 编写简洁、易维护且技术上准确的 TypeScript 代码,并提供相关示例。
 - 使用函数式和声明式编程模式;避免使用类。
 - 遵循 DRY 原则,使用迭代和模块化避免代码重复。
 - 使用描述性变量名,并使用辅助动词(如 isLoading、hasError 等)。
 - 系统地组织文件:每个文件只包含相关的内容,例如导出的组件、子组件、辅助函数、静态内容和类型。
-命名约定:
+
+##命名约定:
 - 使用小写字母和连字符来命名目录(例如,components/auth-wizard)。
 - 优先使用命名出口来命名函数。
-TypeScript 使用方法
+
+##TypeScript 使用方法
 - 使用 TypeScript 编写所有代码;优先使用接口而不是类型,因为它们具有可扩展性和合并能力。
 - 避免使用枚举;使用映射来获得更好的类型安全性和灵活性。
 - 使用 TypeScript 接口来编写函数组件。
-语法与格式
+
+##语法与格式
 - 使用“function”关键字来声明纯函数,以便利用提升和提高代码的可读性。
 - 始终使用Vue Composition API的脚本设置风格。
 - 不要使用jsx、flow等EmcaScript特性
-UI 和样式
+
+##UI 和样式
 - 使用uin-ui 构建组件和样式。
 - 使用 flex布局 实现响应式设计;采用移动优先的方法。
 
-```bash
-Always respond in 中文
-
 
-# 您是 Laravel、PHP 及相关网络开发技术的专家。
+=================================================================================
+owl-admin,是基于php语言的laraval框架的owl-admin快速开发框架的后端项目,对于这个项目请使用如下规则:
 
+您是 Laravel、PHP 及相关网络开发技术的专家。
 
 ## 核心原则
-编写简洁、技术性的回答,并提供准确的 PHP/Laravel 示例。
-优先考虑面向对象编程和清晰架构的 SOLID 原则。
-遵循 PHP 和 Laravel 的最佳实践,确保一致性和可读性。
-为可扩展性和可维护性设计,确保系统能够轻松成长。
-倾向于迭代和模块化而不是重复,以促进代码复用。
-为变量、方法和类使用一致和描述性的名称,以提高可读性。
-
+- 编写简洁、技术性的回答,并提供准确的 PHP/Laravel 示例。
+- 优先考虑面向对象编程和清晰架构的 SOLID 原则。
+- 遵循 PHP 和 Laravel 的最佳实践,确保一致性和可读性。
+- 为可扩展性和可维护性设计,确保系统能够轻松成长。
+- 倾向于迭代和模块化而不是重复,以促进代码复用。
+- 为变量、方法和类使用一致和描述性的名称,以提高可读性。
 
 ## 依赖
-Composer 用于依赖管理
-PHP 8.2+
-Laravel 11.0+
-owl-admin Laravel后台管理框架
-
+- Composer 用于依赖管理
+- PHP 8.2+
+- Laravel 11.0+
+- owl-admin Laravel后台管理框架
 
 ## PHP 和 Laravel 标准
-在适当的情况下利用 PHP 8.2+ 的特性(例如,类型属性、匹配表达式)。
-遵守 PSR-12 编码标准,以保持代码风格的一致性。
-始终使用严格类型:declare(strict_types=1);
-利用 Laravel 的内置功能和助手,以最大化效率。
-遵循 Laravel 的目录结构和文件命名约定。
-实施健壮的错误处理和日志记录:
-适合处理前置条件验证的优先请使用abort_if
-使用 Laravel 的异常处理和日志记录功能。
-在必要时创建自定义异常。
-对预期的异常使用 try-catch 块。
-使用 Laravel 的验证功能处理表单和请求数据。
-实施中间件进行请求过滤和修改。
-利用 Laravel 的 Eloquent ORM 进行数据库交互。
-使用 Laravel 的查询构建器进行复杂的数据库操作。
-创建和维护适当的数据库迁移和种子文件。
-
+- 在适当的情况下利用 PHP 8.2+ 的特性(例如,类型属性、匹配表达式)。
+- 遵守 PSR-12 编码标准,以保持代码风格的一致性。
+- 始终使用严格类型:declare(strict_types=1);
+- 利用 Laravel 的内置功能和助手,以最大化效率。
+- 遵循 Laravel 的目录结构和文件命名约定。
+- 实施健壮的错误处理和日志记录:
+- 适合处理前置条件验证的优先请使用abort_if
+- 使用 Laravel 的异常处理和日志记录功能。
+- 在必要时创建自定义异常。
+- 对预期的异常使用 try-catch 块。
+- 使用 Laravel 的验证功能处理表单和请求数据。
+- 实施中间件进行请求过滤和修改。
+- 利用 Laravel 的 Eloquent ORM 进行数据库交互。
+- 使用 Laravel 的查询构建器进行复杂的数据库操作。
+- 创建和维护适当的数据库迁移和种子文件。
 
 ## Laravel 最佳实践
-在可能的情况下使用 Eloquent ORM 和查询构建器代替原始 SQL 查询
-实施仓库和服务模式,以获得更好的代码组织和可复用性
-利用 Laravel 的内置身份验证和授权功能(Sanctum)
-利用 Laravel 的缓存机制(Redis)提高性能
-使用任务队列处理长时间运行的任务和后台处理
-使用 API 资源和版本控制构建健壮且可维护的 API
-使用 Laravel 的异常处理程序和日志门面实现适当的错误处理和日志记录
-利用 Laravel 的验证功能,包括表单请求,确保数据完整性
-实施数据库索引并使用 Laravel 的查询优化功能提高性能
-实施适当的安全措施,包括 CSRF 保护、XSS 防范和输入消毒
-
+- 在可能的情况下使用 Eloquent ORM 和查询构建器代替原始 SQL 查询
+- 实施仓库和服务模式,以获得更好的代码组织和可复用性
+- 利用 Laravel 的内置身份验证和授权功能(Sanctum)
+- 利用 Laravel 的缓存机制(Redis)提高性能
+- 使用任务队列处理长时间运行的任务和后台处理
+- 使用 API 资源和版本控制构建健壮且可维护的 API
+- 使用 Laravel 的异常处理程序和日志门面实现适当的错误处理和日志记录
+- 利用 Laravel 的验证功能,包括表单请求,确保数据完整性
+- 实施数据库索引并使用 Laravel 的查询优化功能提高性能
+- 实施适当的安全措施,包括 CSRF 保护、XSS 防范和输入消毒
 
 ##  代码架构
 
 ### 命名约定:
-文件夹、类和文件使用一致的命名约定。
-遵循 Laravel 的约定:模型使用单数,控制器使用复数(例如,User.php,UsersController.php)。
-类名使用 PascalCase,方法名使用 camelCase,数据库列使用 snake_case。
+- 文件夹、类和文件使用一致的命名约定。
+- 遵循 Laravel 的约定:模型使用单数,控制器使用复数(例如,User.php,UsersController.php)。
+- 类名使用 PascalCase,方法名使用 camelCase,数据库列使用 snake_case。
 
 ### 控制器设计:
-控制器应该是 final 类,以防止继承。
-控制器应该是只读的(即,没有属性变异)。
-避免直接在控制器中注入依赖。相反,使用方法注入或服务类。
+- 控制器应该是 final 类,以防止继承。
+- 控制器应该是只读的(即,没有属性变异)。
+- 避免直接在控制器中注入依赖。相反,使用方法注入或服务类。
 
 ### 模型设计:
-模型应该是 final 类,以确保数据完整性并防止继承导致意外行为。
-不要自定义模型和字段,如果不确定请参照 doc/系统设计/数据库设计/物理模型/xiaoding_test.md 寻找,仍然无法确定,请告知我。
+- 模型应该是 final 类,以确保数据完整性并防止继承导致意外行为。
+- 不要自定义模型和字段,如果不确定请参照 doc/系统设计/数据库设计/物理模型/xiaoding_test.md 寻找,仍然无法确定,请告知我。
 
 ### 服务:
-在 app 目录中创建一个 Services 文件夹。
-将服务组织成特定于模型的服务和其他所需服务。
-服务类应该是 final 和只读的。
-使用服务处理复杂的业务逻辑,保持控制器轻薄。
+- 在 app 目录中创建一个 Services 文件夹。
+- 将服务组织成特定于模型的服务和其他所需服务。
+- 服务类应该是 final 和只读的。
+- 使用服务处理复杂的业务逻辑,保持控制器轻薄。
 
 ### 路由:
-保持路由的一致性和组织性。
-为每个主要模型或功能区域创建单独的路由文件。
-将相关路由分组在一起(例如,所有与用户相关的路由在 routes/user.php 中)。
-用户端添加到routes/api.php文件中client前缀下
-技师端添加到routes/api.php文件中coach前缀下
-管理端添加到routes/web.php文件中,分别在admin前缀和admin-api前缀中添加
+- 保持路由的一致性和组织性。
+- 为每个主要模型或功能区域创建单独的路由文件。
+- 将相关路由分组在一起(例如,所有与用户相关的路由在 routes/user.php 中)。
+- 路由位置约定:
+    - 用户端路由应在routes/api.php文件中client前缀下
+    - 技师端路由应在routes/api.php文件中coach前缀下
+    - 管理端路由应在routes/web.php文件中,分别在admin前缀和admin-api前缀中添加
 
 ### 类型声明:
-方法和方法总是使用显式的返回类型声明。
-使用适当的 PHP 类型提示作为方法参数。
-在必要时利用 PHP 8.1+ 的特性,如联合类型和可空类型。
+- 方法和方法总是使用显式的返回类型声明。
+- 使用适当的 PHP 类型提示作为方法参数。
+- 在必要时利用 PHP 8.1+ 的特性,如联合类型和可空类型。
 
 ### 数据类型一致性:
-在整个代码库中保持数据类型声明的一致性和明确性。
-使用类型提示属性、方法参数和返回类型。
-利用 PHP 的严格类型早期捕获类型相关错误。
+- 在整个代码库中保持数据类型声明的一致性和明确性。
+- 使用类型提示属性、方法参数和返回类型。
+- 利用 PHP 的严格类型早期捕获类型相关错误。
 
 ### 错误处理:
-使用 Laravel 的异常处理和日志记录功能处理异常。
-在必要时创建自定义异常。
-对预期的异常使用 try-catch 块。
-以优雅的方式处理异常并返回适当的响应。
+- 使用 Laravel 的异常处理和日志记录功能处理异常。
+- 在必要时创建自定义异常。
+- 对预期的异常使用 try-catch 块。
+- 以优雅的方式处理异常并返回适当的响应。
 
 ### 关键点
-遵循 Laravel 的 MVC 架构,明确分离业务逻辑、数据和表示层。
-使用表单请求实现请求验证
-
-### 代码生成位置约定
-用户端controller代码生成到 app/Http/Controllers/Client
-用户端service代码生成到 app/Services/Client
-技师端controller代码生成到 app/Http/Controllers/Coach
-技师端service代码生成到 app/Services/Coach
-管理端controller代码生成到 app/Admin/Controllers/
-管理端service代码生成到 app/Services
-
-### 枚举文件查找规则
-定位并识别位于 app/Enums 目录下的所有枚举文件。
+- 遵循 Laravel 的 MVC 架构,明确分离业务逻辑、数据和表示层。
+- 使用表单请求实现请求验证
+
+### 业务代码位置约定
+- 用户端
+    - controller代码目录位置是: app/Http/Controllers/Client
+    - service代码目录位置是: app/Services/Client
+- 技师端
+    - controller代码目录位置是: app/Http/Controllers/Coach
+    - service代码目录位置是: app/Services/Coach
+- 管理端
+    - controller代码目录位置是: app/Admin/Controllers
+    - service代码目录位置是: app/Services
+
+### 枚举使用规则
+- 尽可能利用 app/Enums 目录下的枚举,而不是数字。
 
 ### 注解优化规则
-1. Controller层API文档注解优化规则:
-生成scribe的API文档注解时,确保方法注释名称前添加分组名,格式为分组名-方法名。
-不使用@group注解关键字,而是在方法注释中明确分组信息。
-添加@description注解,详细描述API功能。
-对于请求参数,使用@param注解,并提供参数类型、描述和默认值(Example)。
-对于响应,使用@response注解,并提供响应类型、描述和示例数据。
-
-2. Service层PHPDoc注解优化规则:
-为Service层的每个方法添加PHPDoc注解,包括方法功能描述、参数说明、返回值说明等。
+- Controller层API文档注解优化规则:
+    - 生成scribe的API文档注解时,确保方法注释名称前添加分组名,格式为分组名-方法名。
+    - 不使用@group注解关键字,而是在方法注释中明确分组信息。
+    - 添加@description注解,详细描述API功能。
+    - 对于请求参数,使用@param注解,并提供参数类型、描述和默认值(Example)。
+    - 对于响应,使用@response注解,并提供响应类型、描述和示例数据。
 
-3. 方法体内逻辑注解优化规则:
-在每个方法体内,对每行逻辑代码添加详细注解,说明该行代码的功能和目的
+- Service层PHPDoc注解优化规则:
+    - 为Service层的每个方法添加PHPDoc注解,包括方法功能描述、参数说明、返回值说明等。
 
-4. 注解中文字符串空格检查优化规则:
-检查所有中文注解字符串,确保不包含空格,避免中文编码问题
+- 方法体内逻辑注解优化规则:
+    - 在每个方法体内,对每行逻辑代码添加详细注解,说明该行代码的功能和目的
 
+- 注解中文字符串空格检查优化规则:
+    - 检查所有中文注解字符串,确保不包含空格,避免中文编码问题。
 
 ### 事务处理规则详细说明
-检测增删改方法:AI应能够识别哪些方法涉及数据的增加、删除或修改。
-自动添加事务逻辑:在识别到增删改方法后,AI应在方法开始处添加事务开始的代码,并在方法结束前添加事务提交的代码。同时,AI需要添加异常处理逻辑,以便在发生错误时回滚事务。
-异常处理:AI应确保在事务中捕获所有可能的异常,并在异常发生时回滚事务
-
+- 检测增删改方法:识别哪些方法涉及数据的增加、删除或修改,并自动添加事务开始的代码,并在方法结束前添加事务提交的代码。
+- 同时,确保在事务中捕获所有可能的异常,并在异常发生时回滚事务,并记录日志。
 
 ### Sanctum规则详细说明
-替换Auth::id():AI应扫描代码中所有使用 Auth::id() 的地方,并将其替换为 Auth::user()->id。
-检查上下文:在替换过程中,AI需要检查上下文以确保替换不会破坏现有逻辑。
-保持代码整洁:替换完成后,AI应确保代码格式保持整洁,避免引入新的错误。
+- 不要使用Auth::id(),而是使用Auth::user()->id。
+
 
 ```
 

+ 0 - 0
app/Http/Controllers/Auth/LoginController.php


+ 2 - 2
app/Http/Controllers/Client/WechatController.php

@@ -53,7 +53,7 @@ class WechatController extends Controller
         $validated = $request->validated();
 
         $result = $this->wechatService->getAuthUrl(
-            $validated['redirect_url'],
+            $validated['redirect_uri'],
             $validated['scope'] ?? 'snsapi_userinfo'
         );
 
@@ -87,7 +87,7 @@ class WechatController extends Controller
      * }
      * @response 422 scenario="参数验证失败" {
      *   "code": 422,
-     *   "message": "授权码不能为空|状码长度必须为32位"
+     *   "message": "授权码不能为空|状���码长度必须为32位"
      * }
      * @response 400 scenario="无效的state" {
      *   "code": 400,

+ 2 - 2
app/Http/Requests/Client/Wechat/GetAuthUrlRequest.php

@@ -22,7 +22,7 @@ class GetAuthUrlRequest extends FormRequest
     public function rules(): array
     {
         return [
-            'redirect_url' => ['required', 'url'],
+            'redirect_uri' => ['required', 'url'],
             'scope' => ['nullable', 'string', 'in:snsapi_base,snsapi_userinfo'],
         ];
     }
@@ -35,7 +35,7 @@ class GetAuthUrlRequest extends FormRequest
     public function attributes(): array
     {
         return [
-            'redirect_url' => '回调地址',
+            'redirect_uri' => '回调地址',
             'scope' => '授权范围',
         ];
     }

+ 25 - 3
app/Models/MemberSocialAccount.php

@@ -10,9 +10,31 @@ use Slowlyo\OwlAdmin\Models\BaseModel as Model;
  */
 class MemberSocialAccount extends Model
 {
-	use SoftDeletes;
+    use SoftDeletes;
 
-	protected $table = 'member_social_accounts';
+    protected $table = 'member_social_accounts';
+
+    /**
+     * 允许批量赋值的属性
+     *
+     * @var array<string>
+     */
+    protected $fillable = [
+        'user_id',
+        'platform',
+        'openid',
+        'unionid',
+        'nickname',
+        'avatar',
+        'gender',
+        'country',
+        'province',
+        'city',
+        'access_token',
+        'refresh_token',
+        'expires_in',
+        'state',
+    ];
 
     /**
      * @Author FelixYin
@@ -22,4 +44,4 @@ class MemberSocialAccount extends Model
     {
         return $this->belongsTo('App\Models\MemberUser', 'user_id');
     }
-}
+}

+ 1 - 0
app/Models/User.php

@@ -0,0 +1 @@
+ 

+ 2 - 4
app/Services/Client/AccountService.php

@@ -233,7 +233,7 @@ class AccountService
     private function storeVerifyCode(string $mobile, int $code): void
     {
         // 构建缓存键名(verify_code:手机号)
-        $key = self::VERIFY_CODE_PREFIX.$mobile;
+        $key = self::VERIFY_CODE_PREFIX . $mobile;
 
         // 将验证码存入缓存,并设置过期时间
         Cache::put($key, $code, self::VERIFY_CODE_EXPIRE);
@@ -284,7 +284,7 @@ class AccountService
     private function verifyCode(string $mobile, string $code): void
     {
         // 使用手机号和前缀构建缓存键,获取存储的验证码
-        $cacheCode = Cache::get(self::VERIFY_CODE_PREFIX.$mobile);
+        $cacheCode = Cache::get(self::VERIFY_CODE_PREFIX . $mobile);
 
         // 验证码不存在或不匹配则抛出业务异常
         if (! $cacheCode || $cacheCode != $code) {
@@ -357,7 +357,6 @@ class AccountService
             'avatar' => $userInfo['avatar'] ?? null,      // 设置微信头像,可选
             'gender' => $userInfo['gender'] ?? null,      // 设置性别,可选
         ]);
-
     }
 
     /**
@@ -566,7 +565,6 @@ class AccountService
                     'status' => 1,                    // 设置状态为有效
                 ]);
             });
-
         } catch (\Exception $e) {
             // 记录处理邀请关系时的错误日志
             Log::error('Failed to handle invite relation', [

+ 39 - 17
app/Services/Client/WechatService.php

@@ -85,7 +85,6 @@ class WechatService
 
             // 执行登录
             return $this->accountService->wxLogin($user->getId(), $userInfo);
-
         } catch (BusinessException $e) {
             throw $e;
         } catch (\Exception $e) {
@@ -98,24 +97,22 @@ class WechatService
         }
     }
 
-    /**
-     * 生成随机state
-     */
-    protected function generateState(): string
-    {
-        return md5(uniqid(microtime(true), true));
-    }
-
     /**
      * 缓存授权state
      */
     protected function cacheAuthState(string $state): void
     {
-        Cache::put(
-            $this->getAuthStateKey($state),
-            true,
-            config('wechat.auth.cache_ttl')
-        );
+        try {
+            $states = Cache::get('wechat_auth_states', []);
+            $states[$state] = true;
+            Cache::put('wechat_auth_states', $states, now()->addMinutes(30));
+        } catch (\Exception $e) {
+            Log::error('缓存微信授权state失败', [
+                'state' => $state,
+                'error' => $e->getMessage()
+            ]);
+            throw new BusinessException('系统错误,请稍后重试');
+        }
     }
 
     /**
@@ -125,11 +122,36 @@ class WechatService
      */
     protected function validateState(string $state): void
     {
-        if (! Cache::pull($this->getAuthStateKey($state))) {
-            throw new BusinessException('无效的授权请求');
+        try {
+            $states = Cache::get('wechat_auth_states', []);
+
+            if (!isset($states[$state])) {
+                Log::warning('微信授权state无效', ['state' => $state]);
+                throw new BusinessException('授权已过期,请重新授权');
+            }
+
+            // 移除已使用的state
+            unset($states[$state]);
+            Cache::put('wechat_auth_states', $states, now()->addMinutes(30));
+        } catch (BusinessException $e) {
+            throw $e;
+        } catch (\Exception $e) {
+            Log::error('验证微信授权state失败', [
+                'state' => $state,
+                'error' => $e->getMessage()
+            ]);
+            throw new BusinessException('系统错误,请稍后重试');
         }
     }
 
+    /**
+     * 生成随机state
+     */
+    protected function generateState(): string
+    {
+        return md5(uniqid((string)mt_rand(), true));
+    }
+
     /**
      * 格式化用户信息
      *
@@ -182,7 +204,7 @@ class WechatService
 
     protected function getAuthStateKey(string $state): string
     {
-        return config('wechat.auth.cache_prefix').$state;
+        return config('wechat.auth.cache_prefix') . $state;
     }
 
     /**

+ 1 - 0
resources/views/auth/login.blade.php

@@ -0,0 +1 @@
+ 

+ 8 - 16
routes/api.php

@@ -31,11 +31,18 @@ Route::prefix('client')->group(function () {
         // 发验证码
         Route::post('send-code', [AccountController::class, 'sendVerifyCode']);
         // 手机号登录
-        Route::post('login', [AccountController::class, 'login']);
+        Route::post('login', [AccountController::class, 'login'])->name('login');
         // 微信登录
         Route::post('wx-login', [AccountController::class, 'wxLogin']);
     });
 
+    // 微信相关路由(无需认证)
+    Route::prefix('wechat')->group(function () {
+        Route::get('auth-url', [WechatController::class, 'getAuthUrl']);
+        Route::post('callback', [WechatController::class, 'handleCallback']);
+        Route::get('js-config', [WechatController::class, 'getJsConfig']);
+    });
+
     // 需要认证的路由组
     Route::middleware('auth:sanctum')->group(function () {
         // 账号相关
@@ -127,27 +134,12 @@ Route::prefix('client')->group(function () {
             Route::get('{id}/code', [OrderController::class, 'generateCode']);
         });
 
-        // 钱包相关
-        Route::prefix('wallet')->group(function () {
-            Route::get('records', [WalletController::class, 'records']);
-            // 取钱包信息
-            Route::get('wallet', [WalletController::class, 'wallet']);
-            // 提现
-            Route::post('withdraw', [WalletController::class, 'withdraw']);
-        });
 
         // 团队管理路由
         Route::prefix('team')->group(function () {
             Route::get('list', [MarketDistTeamController::class, 'index'])->name('team.list');
         });
 
-        // 微信相关路由
-        Route::prefix('wechat')->group(function () {
-            Route::get('auth-url', [WechatController::class, 'getAuthUrl']);
-            Route::post('callback', [WechatController::class, 'handleCallback']);
-            Route::get('js-config', [WechatController::class, 'getJsConfig']);
-        });
-
         // 评价管理
         Route::post('comments', [CommentController::class, 'store'])->name('client.comments.store');
         Route::get('comments', [CommentController::class, 'index'])->name('client.comments.index');

+ 0 - 1
routes/web.php

@@ -124,7 +124,6 @@ Route::group(
         Route::get('shop/{shop_id}/review-records', [ShopInfoController::class, 'reviewRecords']);
         // 店铺余额冻结
         Route::post('shop/freeze-balance', [ShopInfoController::class, 'freezeBalance']);
-
     }
 );
 

+ 1 - 1
script/bin/mylog

@@ -60,7 +60,7 @@ interactive_mode() {
                     errors=$(cat storage/logs/laravel.log | grep "ERROR")
                     if [ -n "$errors" ]; then
                         echo "正在复制错误信息到剪贴板..."
-                        cat storage/logs/laravel.log | grep -m8 "ERROR" | \
+                        cat storage/logs/laravel.log | grep -m1 "ERROR" | \
                         awk '{print $0,"\n\n","上面是错误日志,请帮我修复这个bug,并始终用中文语言回答。"}' | xclip -selection clipboard
                         echo "已复制错误信息到剪贴板,你可以问AI助手,他会给你解决错误。"
                     else