--- title: "04-项目初始化" created: 2025-12-02 tags: - 项目 aliases: - 项目初始化 --- # 项目初始化 ## 本节重点 从 0 开‍始搭建后端和前端项⁡目,会后续正式开发‎项目打好基础。 包括: - 后端项目初始化 - 前端项目初始化 本节教程的‍后端和前端互不影响⁡,可以按需独立学习‎,建议优先学习自己‎求职方向的内容。 ## 一、后端项目初始化 ### 环境准备 **1)安装的 JDK 版本必须 >= 17,推荐使用 21 版本!** 可参考视频安装 JDK: 2)MyS‍QL 数据库最好安⁡装 8.x 版本,‎或者 5.7 版本‎。 ### 新建项目 在 IDE‍A 中新建项目,选⁡择 Spring ‎Boot 模板、M‎aven、JDK 21,配置如图: ![[image-d5147bce.png]] 选择 Sprin‍g Boot 3.5.x 版本,⁡必须添加的依赖包括 Spring‎ Web、MySQL、Lombo‎k,Spring Boot DevTools 可以按需选取: ![[image-86b1de0e.png]] 当然,后续通过修改 Maven 配置添加依赖也是可以的。 💡 小提示,如果 Lombok 依赖报错的话,可以手动指定 Lombok 的版本,修改 `pom.xml` 的代码: ```xml org.projectlombok lombok 1.18.36 true ``` 点击创建,‍就得到了一个 Sp⁡ring Boot‎ 项目,需要等待 ‎Maven 为我们安装依赖。 修改资源目录下的配置文件为 `application.yml`,指定项目启动的端口号和访问地址前缀、项目名称,代码如下: ```yaml spring: application: name: yu-ai-code-mother-backend server: port: 8123 servlet: context-path: /api ``` 然后尝试启动项目,确保能正常启动再进行后续操作。 ### 整合依赖 接下来我们要整合一些开发项目常用的依赖。 ### Hutool 工具库 Hutool 是主流的 Java 工具类库,集合了丰富的工具类,涵盖字符串处理、日期操作、文件处理、加解密、反射、正则匹配等常见功能。它的轻量化和无侵入性让开发者能够专注于业务逻辑而不必编写重复的工具代码。例如,`DateUtil.formatDate(new Date())` 可以快速将当前日期格式化为字符串。 参考官方文档引入:[https://doc.hutool.cn/pages/index/#🍊maven](https://doc.hutool.cn/pages/index/#%F0%9F%8D%8Amaven) 在 Maven 的 pom.xml 中添加依赖: ```xml cn.hutool hutool-all 5.8.38 ``` ### Knife4j 接口文档 Knife4j 是基于 S‍wagger 接口文档的增强工具,提供了更加友好的⁡ API 文档界面和功能扩展,例如动态参数调试、分组文‎档等。它适合用于 Spring Boot 项目‎中,能够通过简单的配置自动生成接口文档,让开发者和前端快速了解和调试接口,提高协作效率。 参考官方文档引入: **由于使用的是 Spring Boot 3.x,注意要选择 OpenAPI 3 的版本!** 1)在 Maven 的 pom.xml 中添加依赖: ```xml com.github.xiaoymin knife4j-openapi3-jakarta-spring-boot-starter 4.4.0 ``` 2)在 `application.yml` 中追加接口文档配置,重点是指定扫描 Controller 包的路径: ```yaml # springdoc-openapi springdoc: group-configs: - group: 'default' packages-to-scan: com.yupi.yuaicodemother.controller # knife4j knife4j: enable: true setting: language: zh_cn ``` 3)在 controller 包下新建一个测试接口: ```java @RestController @RequestMapping("/health") public class HealthController { @GetMapping("/") public String healthCheck() { return "ok"; } } ``` 重启项目,访问 能够看到接口文档,可以测试调用接口: ![[image-86b1de0e.png]] ### 其他依赖 可以按需引入其他依赖,比如 AOP 切面编程: ```xml org.springframework.boot spring-boot-starter-aop ``` 给启动类添加注解(可选): ```java @EnableAspectJAutoProxy(exposeProxy = true) ``` 解释一下 `exposeProxy = true` 的作用:通过 Spring AOP 提供对当前代理对象的访问,使得可以在业务逻辑中访问到当前的代理对象。你可以在方法执行时通过 `AopContext.currentProxy()` 获取当前的代理对象。 还有更多的依赖,后续我们随用随装。 ### 通用基础代码 通用基础代码‍是指:无论在任何后端项目⁡中,都可以复用的代码。这‎种代码一般 “一辈子只用‎写一次”,了解作用之后复制粘贴即可,无需记忆。 目录结构如下: ![[image-66a86138.png]] ### 1、自定义异常 自定义错误码,对错误进行收敛,便于前端统一处理。 💡 这里‍有 2 个小技巧:⁡         ‎         ‎ 1. 自定义错误码时,建议跟主流的错误码(比如 HTTP 错误码)的含义保持一致,比如 “未登录” 定义为 40100,和 HTTP 401 错误(用户需要进行身份认证)保持一致,会更容易理解。 2. 错误码不要完全连续,预留一些间隔,便于后续扩展。 在 `exception` 包下新建错误码枚举类: ```java @Getter public enum ErrorCode { SUCCESS(0, "ok"), PARAMS_ERROR(40000, "请求参数错误"), NOT_LOGIN_ERROR(40100, "未登录"), NO_AUTH_ERROR(40101, "无权限"), NOT_FOUND_ERROR(40400, "请求数据不存在"), FORBIDDEN_ERROR(40300, "禁止访问"), SYSTEM_ERROR(50000, "系统内部异常"), OPERATION_ERROR(50001, "操作失败"); /** * 状态码 */ private final int code; /** * 信息 */ private final String message; ErrorCode(int code, String message) { this.code = code; this.message = message; } } ``` 一般不建议直接‍抛出 Java 内置的 R⁡untimeExcepti‎on,而是自定义一个业务异‎常,和内置的异常类区分开,便于定制化输出错误信息: ```java @Getter public class BusinessException extends RuntimeException { /** * 错误码 */ private final int code; public BusinessException(int code, String message) { super(message); this.code = code; } public BusinessException(ErrorCode errorCode) { super(errorCode.getMessage()); this.code = errorCode.getCode(); } public BusinessException(ErrorCode errorCode, String message) { super(message); this.code = errorCode.getCode(); } } ``` 为了更方便‍地根据情况抛出异常⁡,可以封装一个 T‎hrowUtils‎,类似断言类,简化抛异常的代码: ```java public class ThrowUtils { /** * 条件成立则抛异常 * * @param condition 条件 * @param runtimeException 异常 */ public static void throwIf(boolean condition, RuntimeException runtimeException) { if (condition) { throw runtimeException; } } /** * 条件成立则抛异常 * * @param condition 条件 * @param errorCode 错误码 */ public static void throwIf(boolean condition, ErrorCode errorCode) { throwIf(condition, new BusinessException(errorCode)); } /** * 条件成立则抛异常 * * @param condition 条件 * @param errorCode 错误码 * @param message 错误信息 */ public static void throwIf(boolean condition, ErrorCode errorCode, String message) { throwIf(condition, new BusinessException(errorCode, message)); } } ``` ### 2、响应包装类 一般情况下‍,每个后端接口都要⁡返回调用码、数据、‎调用信息等,前端可‎以根据这些信息进行相应的处理。 我们可以封装统一的响应结果类,便于前端统一获取这些信息。 通用响应类: ```java @Data public class BaseResponse implements Serializable { private int code; private T data; private String message; public BaseResponse(int code, T data, String message) { this.code = code; this.data = data; this.message = message; } public BaseResponse(int code, T data) { this(code, data, ""); } public BaseResponse(ErrorCode errorCode) { this(errorCode.getCode(), null, errorCode.getMessage()); } } ``` 但之后每次接口返回值时,‍都要手动 new 一个 BaseRespons⁡e 对象并传入参数,比较麻烦,我们可以新建一个‎工具类,提供成功调用和失败调用的方法,支持灵活‎地传参,简化调用。 ```java public class ResultUtils { /** * 成功 * * @param data 数据 * @param 数据类型 * @return 响应 */ public static BaseResponse success(T data) { return new BaseResponse<>(0, data, "ok"); } /** * 失败 * * @param errorCode 错误码 * @return 响应 */ public static BaseResponse error(ErrorCode errorCode) { return new BaseResponse<>(errorCode); } /** * 失败 * * @param code 错误码 * @param message 错误信息 * @return 响应 */ public static BaseResponse error(int code, String message) { return new BaseResponse<>(code, null, message); } /** * 失败 * * @param errorCode 错误码 * @return 响应 */ public static BaseResponse error(ErrorCode errorCode, String message) { return new BaseResponse<>(errorCode.getCode(), null, message); } } ``` ### 3、全局异常处理器 为了防止意‍料之外的异常,利用⁡ AOP 切面全局‎对业务异常和 Ru‎ntimeException 进行捕获: ```java @Hidden @RestControllerAdvice @Slf4j public class GlobalExceptionHandler { @ExceptionHandler(BusinessException.class) public BaseResponse businessExceptionHandler(BusinessException e) { log.error("BusinessException", e); return ResultUtils.error(e.getCode(), e.getMessage()); } @ExceptionHandler(RuntimeException.class) public BaseResponse runtimeExceptionHandler(RuntimeException e) { log.error("RuntimeException", e); return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统错误"); } } ``` 注意!由于本项目使用的 Spring Boot 版本 >= 3.4、并且是 OpenAPI 3 版本的 Knife4j,这会导致 `@RestControllerAdvice` 注解不兼容,所以必须给这个类加上 `@Hidden` 注解,不被 Swagger 加载。虽然网上也有其他的解决方案,但这种方法是最直接有效的。 ### 4、请求包装类 对于 “分页”‍、“删除某条数据” 这类通⁡用的请求,可以封装统一的请‎求包装类,用于接受前端传来‎的参数,之后相同参数的请求就不用专门再新建一个类了。 分页请求包‍装类,包括当前页号⁡、页面大小、排序字‎段、排序顺序参数: ```java @Data public class PageRequest { /** * 当前页号 */ private int pageNum = 1; /** * 页面大小 */ private int pageSize = 10; /** * 排序字段 */ private String sortField; /** * 排序顺序(默认降序) */ private String sortOrder = "descend"; } ``` 删除请求包装类,接受要删除数据的 id 作为参数: ```java @Data public class DeleteRequest implements Serializable { /** * id */ private Long id; private static final long serialVersionUID = 1L; } ``` ### 5、全局跨域配置 跨域是指浏览‍器访问的 URL(前端⁡地址)和后端接口地址的‎域名(或端口号)不一致‎导致的,浏览器为了安全,默认禁止跨域请求访问。 假设前端: 后端接口: 这就是跨域! 为了开发调‍试方便,我们可以通⁡过全局跨域配置,让‎整个项目所有的接口‎支持跨域,解决跨域报错。 新建 co‍nfig 包,用于⁡存放所有的配置相关‎代码。全局跨域配置‎代码如下: ```java @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { // 覆盖所有请求 registry.addMapping("/**") // 允许发送 Cookie .allowCredentials(true) // 放行哪些域名(必须用 patterns,否则 * 会和 allowCredentials 冲突) .allowedOriginPatterns("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .exposedHeaders("*"); } } ``` ### 测试验证 最后让我们‍修改示例接口的返回⁡值,然后再次验证接‎口文档的效果: ```java @RestController @RequestMapping("/health") public class HealthController { @GetMapping("/") public BaseResponse healthCheck() { return ResultUtils.success( "ok"); } } ``` 访问接口文档,能够正常响应: ![[image-caf64303.png]] 后端项目初始化完成,此时的项目结构如图 ![[image-f4c14be1.png]] ## 二、前端项目初始化 ### 环境准备 **前端 Node.js 版本必须 >= 20**,鱼皮教程中使用 20 版本。在官网安装好 Node 后会自动安装 NPM 前端包管理器。 可参考视频安装 Node.js: ### 创建项目 使用 Vue 官方推荐的脚手架 create-vue 快速创建 Vue3 的项目: 💡 Vue 提供了在线编码测试,可以通过 Playground 来学习 Vue: 为了便于项目代码的统一管理,我们直接在后端项目根目录 `yu-ai-code-mother` 下新建前端项目 `yu-ai-code-mother-frontend`。 在终端进入后端项目根目录,输入命令: ```bash npm create vue@latest ``` NPM 会自动安装 create-vue 工具并执行命令: ![[image-b41168f5.png]] **注意本教程使用的版本号是 3.17.0,如果之后版本更新导致跟鱼皮的教程不一致,记得安装特定版本的工具,而不是 latest 最新版!** 接下来按照‍如下选项创建项目,脚⁡手架会自动帮我们安装‎ Vue Route‎r 路由、Pinia 全局状态管理等实用类库: ![[image-ae68fac6.png]]![[image-3f39ecc5.png]] 然后用 WebStorm 打开项目,先在终端执行 `npm install` 安装依赖,然后执行 `npm run dev` 能访问网页就成功了。 ![[image-d28f97a9.png]] 💡 可以看到 Vue 脚手架提供了一个 [调试工具 devtools](http://localhost:5173/__devtools__/),你可以使用它来调试分析项目: ![[image-09ebb642.png]] ### 前端工程化配置 脚手架已经帮‍我们整合了 Prett⁡ier 代码美化、ES‎Lint 自动校验、T‎ypeScript 类型校验,无需再自行整合。 但是需要在 WebStorm 里开启代码美化插件: ![[image-929c0c0c.png]] 在 vue‍ 文件中执行格式化⁡快捷键,不报错,表‎示配置工程化成功。 如果发现格‍式化效果不好,也没⁡关系,之后可以使用‎另外一种格式化快捷‎键: ![[image-a993ea87.png]] 为了开发效‍率更高,你可能想关闭⁡由于 ESLint ‎校验导致的编译错误,‎同样可以在开发工具中禁用 ESLint: ![[image-a993ea87.png]] 修改 eslint.config.js、.prettierrc.json、tsconfig.json 文件可以改变校验规则。 如果不使用脚手架,就需要自己整合这些工具: - 代码规范: - 代码美化: - 直接整合:[https://github.com/prettier/eslint-plugin-prettier#recommended-configuration(包括了](https://github.com/prettier/eslint-plugin-prettier#recommended-configuration%EF%BC%88%E5%8C%85%E6%8B%AC%E4%BA%86) [https://github.com/prettier/eslint-config-prettier#installation)](https://github.com/prettier/eslint-config-prettier#installation%EF%BC%89) 对于前端新‍手来说,你不需要深⁡入了解这些,纯当工‎具去使用即可,应该‎尽快上手项目。 ### 引入组件库 引入 Ant Design Vue 组件库,参考 [官方文档](https://antdv.com/docs/vue/getting-started-cn) 快速上手。 注意,**本教程使用的是 v4.2.6 的组件库版本**,如果后续阅读本教程中发现有组件或语法不一致,以官方文档为主,或者在网站右上角切换对应版本的文档即可: ![[image-82ab40e7.png]] 执行安装: ```bash npm i --save ant-design-vue@4.x ``` 改变主入口文件 main.ts,为了方便,选择全局注册组件: ```python import './assets/main.css' import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' import router from './router' import Antd from 'ant-design-vue' import 'ant-design-vue/dist/reset.css' const app = createApp(App) app.use(createPinia()) app.use(router) app.use(Antd) app.mount('#app') ``` 随便引入一个组件,如果显示出来,就表示引入成功。比如在 `App.vue` 中引入按钮: ```html Primary Button ``` 效果如图: ![[image-4f21b7fe.png]] ### 开发规范 建议遵循 Vue3 的 [组合式 API](https://cn.vuejs.org/guide/introduction#composition-api) (Composition API),而不是 [选项式 API](https://cn.vuejs.org/guide/introduction#options-api),开发更自由高效一些。 示例代码: ```html ``` ### 页面基本信息 可以修改项目根目录下的 `index.html` 文件,来定义页面的元信息,比如修改标题: ```html 鱼皮 AI 零代码应用生成平台
``` 还可以替换 public 目录下默认的 ico 图标为自己的。先用 AI 生成了个 Logo,保存到 assets 目录下 `logo.png`: ![[image-b550acfe.png]] 然后用 [现成的网站](https://www.bitbug.net/) 可以制作 ico 图标,替换 public 目录下的 `favicon.ico` 文件,效果如图: ![[image-cd21b609.png]] ### 全局通用布局 - Vibe Coding 由于这个项‍目包含多个页面,每⁡个页面都包含导航栏‎、内容和底部栏,可‎以准备一套全局通用布局,给各页面复用。 如果是以前,我‍们需要自己利用组件库编写布⁡局代码;但现在有了 AI,‎我们只需把需求描述清楚,剩‎下的交给 AI 就好,Vibe Coding 启动! 如果你想自己开发布局,可以参考 [编程导航智能协同云图库项目](https://www.codefather.cn/course/1864210260732116994) 的前端项目初始化部分。 我们预期的布局大概是这样的: ![[image-024991ca.png]] 使用 Cu‍rsor 打开前端⁡项目,编写给 AI‎ 的提示词 ,其实‎就是把自己开发的思路告诉 AI: ```text 你是一位前端程序员专家,帮我给项目生成通用的全局基础布局,要求如下: 1)文件名 layouts/BasicLayout.vue,并且在 App.vue 全局页面入口文件中引入 2)移除 main.css 默认样式文件,以及对该文件的引用 3)整体结构为上中下布局,支持响应式,使用 Ant Design Vue 组件库的 Layout 组件实现 - 上方展示导航栏:独立创建 GlobalHeader 组件。左侧展示 logo.png 和网站标题,然后是菜单项,右侧展示登录用户的头像和昵称(暂时先用登录按钮替代)。导航栏使用 Menu 组件实现,支持通过配置设置菜单项。 - 中间展示内容区域:根据路由切换页面 - 下方展示版权信息:独立创建 GlobalFooter 组件。位置始终固定在底部,内容为:编程导航原创项目 by 程序员鱼皮(添加超链接 ) ``` 注意,由于 ‍AI 生成的代码是随机的⁡,本项目可能会出现视频教‎程跟鱼皮提供的源码不同的‎情况,完全不用担心,以鱼皮最终提供的代码为准就好。 对前端比较‍熟悉的同学,建议使⁡用 Cursor ‎Rules 指定自‎己理想的规范,确保每次生成的代码风格一致。 可以到 Cursor 官方网站找一些规范: 举个例子,配置下面这个规则: ```text 生成前端 Vue 代码时,使用 Vue3 的 组合式 API 语法 ``` 配置过程如图: ![[image-3c1bf83d.png]] 会在项目下生成 `.cursor/rules` 目录和规则文件: ![[image-c8cc9312.png]] 这里鱼皮就‍先不配置了,简单一⁡点,Cursor ‎也支持在对话过程中‎自动帮你生成规则。 💡 建议‍执行 AI 生成前⁡先提交一下当前代码‎,便于观察 AI ‎生成了哪些代码,出了问题也好及时回滚。 执行生成: ![[image-c8cc9312.png]] 效果如图,可以尝试缩小浏览器窗口观察导航条的变化: ![[image-1c67d4ed.png]] 建议在生成‍后看一下 AI 的⁡思考过程和生成的代‎码,学习一下,如果‎有不满意的地方,可以自己修改。 ![[image-75d2dfea.png]] 生成的代码: ```javascript ``` ```html ``` ```html ``` ```html ``` ### 路由 所谓路由,就‍是根据 URL 展示对⁡应的页面。我们希望点击‎菜单项后,可以跳转到对‎应的页面;并且刷新页面后,对应的菜单自动高亮。 ### 1、修改路由配置 按需修改 router/index.ts 文件的 routes 配置,定义我们需要的页面路由,每个 path 对应一个 component(要加载的组件): ```java routes: [ { path: '/', name: 'home', component: HomeView, }, { path: '/about', name: 'about', // route level code-splitting // this generates a separate chunk (About.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import('../views/AboutView.vue'), }, ], ``` 观察上述代码,‍会发现 component⁡ 支持直接传入组件、或者使‎用 import 按需懒加‎载组件,按需加载是一种优化首次打开站点性能的方式。 ### 2、路由跳转 给 GlobalHeader 的菜单组件绑定跳转事件: ```javascript import { useRouter } from "vue-router"; const router = useRouter(); // 处理菜单点击 const handleMenuClick: MenuProps['onClick'] = (e) => { const key = e.key as string selectedKeys.value = [key] // 跳转到对应页面 if (key.startsWith('/')) { router.push(key) } } ``` 修改 HT‍ML 模板,绑定事⁡件:       ‎         ‎ ```html ``` ### 3、高亮同步 刷新页面后‍,你会发现当前菜单⁡项并没有高亮,所以‎需要同步路由的更新‎到菜单项高亮。 同步高亮原理: 1. 点击菜单时,Ant Design 组件已经通过 v-model 绑定 current 变量实现了高亮。 2. 刷新页面时,需要获取到当前 URL 路径,然后修改 current 变量的值,从而实现同步。 使用 Vue ‍Router 的 afte⁡rEach 路由钩子实现,‎每次改变路由或刷新页面时都‎会自动更新 current 的值,从而实现高亮: ```javascript const router = useRouter() // 当前选中菜单 const selectedKeys = ref(['/']) // 监听路由变化,更新当前选中菜单 router.afterEach((to, from, next) => { selectedKeys.value = [to.path] }) ``` 💡思考:大家有没有发现,路由和菜单配置中,有一些是重复的呢?有没有更好地方式来配置路由和菜单项,不用每次修改时都要改两边的代码呢?答案就是将路由配置数组传递给菜单组件,大家可以尝试自行实现。(鱼皮编程导航的 [OJ 判题系统项目](https://www.codefather.cn/course)、[鱼答答 AI 答题应用平台项目](https://www.codefather.cn/course) 中有讲过) ### 请求 一般情况下,前端‍只负责界面展示和动效交互,尽量⁡避免写复杂的逻辑;当需要获取数‎据时,通常是向后端提供的接口发‎送请求,由后端执行操作(比如保存数据)并响应数据给前端。 前端如何向后端发送请求呢? 最传统的方式‍是使用 AJAX 技⁡术。但其代码有些复杂,我们可‎以使用第三方的封装库,来‎简化发送请求的代码,比如主流的请求工具库 Axios。 ### 1、请求工具库 安装请求工具类 Axios,[参考官方文档](https://axios-http.com/docs/intro) 执行命令: ```bash npm install axios ``` ### 2、全局自定义请求 需要自定义全局请求地址等,参考 Axios 官方文档,编写请求配置文件 `request.ts`。包括全局接口请求地址、超时时间、自定义请求响应拦截器等。 响应拦截器的应用场景:我们需要对接口的 **通用响应** 进行统一处理,比如从 response 中取出 data;或者根据 code 去集中处理错误。这样不用在每个接口请求中都去写相同的逻辑。 比如可以在‍全局响应拦截器中,读⁡取出结果中的 dat‎a,并校验 code‎ 是否合法,如果是未登录状态,则自动登录。 示例代码如下,其中 `withCredentials: true` 一定要写,否则无法在发请求时携带 Cookie,就无法完成登录。 代码如下: ```javascript import axios from 'axios' import { message } from 'ant-design-vue' // 创建 Axios 实例 const myAxios = axios.create({ baseURL: '', timeout: 60000, withCredentials: true, }) // 全局请求拦截器 myAxios.interceptors.request.use( function (config) { // Do something before request is sent return config }, function (error) { // Do something with request error return Promise.reject(error) }, ) // 全局响应拦截器 myAxios.interceptors.response.use( function (response) { const { data } = response // 未登录 if (data.code === 40100) { // 不是获取用户信息的请求,并且用户目前不是已经在用户登录页面,则跳转到登录页面 if ( !response.request.responseURL.includes('user/get/login') && !window.location.pathname.includes('/user/login') ) { message.warning('请先登录') window.location.href = `/user/login?redirect=${window.location.href}` } } return response }, function (error) { // Any status codes that falls outside the range of 2xx cause this function to trigger // Do something with response error return Promise.reject(error) }, ) export default myAxios ``` ### 3、自动生成请求代码 如果采用传‍统开发方式,针对每⁡个请求都要单独编写‎代码,很麻烦。 推荐使用 [OpenAPI 工具](https://www.npmjs.com/package/@umijs/openapi),直接根据后端接口文档自动生成前端请求代码即可,这种方式会比 AI 生成更可控。 按照官方文档的步骤,先安装: ```bash npm i --save-dev @umijs/openap ``` 还需要安装依赖库: ```bash npm i --save-dev tslib ``` 在 **前端项目根目录** 新建 `openapi2ts.config.ts`,根据自己的需要定制生成的代码: ```javascript export default { requestLibPath: "import request from '@/request'", schemaPath: '', serversPath: './src', } ``` 注意,要将‍ schemaPat⁡h 改为自己后端服务‎提供的 Swagge‎r 接口文档的地址,生成前确保后端已启动! 在 `package.json` 的 scripts 中添加 `"openapi2ts": "openapi2ts"`。 执行脚本即‍可生成请求代码,还⁡包括 TypeSc‎ript 类型: ![[image-75d2dfea.png]] 以后每次后端接口变更时,只需要重新生成一遍就好,非常方便~ ### 4、测试请求 可以尝试在任意页面代码中调用 API: ```javascript import { healthCheck } from '@/api/healthController.ts' healthCheck().then((res) => { console.log(res) }) ``` 按 F12‍ 打开开发者工具查⁡看请求,由于我们后‎端已经添加了全局跨‎域配置,正常情况下应该能看到如下响应: ![[image-7e9067f5.png]] ### 清理项目 最后,我们‍需要移除脚手架自动⁡生成的多余内容,并‎且把 views ‎目录重命名为 pages 目录(便于理解): ![[image-0e1efab8.png]] 移除内容后,修改‍主页名称为 HomePage,⁡之后所有页面名称都用 Page‎ 作为结尾,更语义化。还需要相‎应地移除主页和路由中已经删除的组件引用,让项目能正常运行。 ![[image-27040af1.png]] 至此项目就初始化完成了。 ### 扩展思路 在后续开发中你会发现,Ant Design Vue 默认使用的是英文文案,如果需要替换为中文,可以参考 [国际化文档](https://antdv.com/docs/vue/i18n-cn),只需给整个应用包裹一层组件即可完成。 --- 本节教程到‍这里就结束了,建议⁡大家从 0 实操下‎项目初始化,以后自‎己搭建一个新项目,也不会觉得困难啦~ --- **项目分区导航**:⬅️ [[03-AI_零代码应用生成平台大纲|03-AI_零代码应用生成平台大纲]] | 04-项目初始化 | ➡️ [[05-Mynotes|05-Mynotes]]