使用 Cursor 从 0 到 1 开发一个全栈 chatbox 项目

大家好,我是 luckySnail,你肯定用过 AI 聊天工具。例如: Gemini,ChatGPT,claude AI 等产品,我们通过它们的 web 网站或者手机应用提出问题,得到答案。在之前如果你想要构建一个这样的 AI 聊天应用程序,是需要大量时间才能开发出来,但是接下来,我将使用 cursor + vercel 的 Next.js 和 ai-sdk 快速搭建属于你自己的 AI chat 工具,通过这篇文章你可以看到 AI 强大的辅助编程能力和 vercel 家超赞的工具!同时也能了解如何使用 AI 从 0 到 1 构建一个 web 应用,先看一下最终的产品:

image.png

如果你想直接看源码: https://github.com/coderPerseus/easyChat 我还使用 deepwiki 生成了对应的项目文档: https://deepwiki.com/coderPerseus/easyChat

环境准备

在正式开发前,你的设备需要有如下环境:

  • Node >= 18.18,pnpm 作为依赖管理工具

  • postgreSQL ,可以是本地或者在线

  • Curosr ,用作 AI 辅助编程

  • chrome 游览器,其他游览器也可

你需要具备的知识:

  • 前端基础

  • 数据库基础

  • 计算机网络基础

  • 熟悉 React 开发 当然,你还需要有良好的软件开发素养,否则你会发现写的代码不好维护,或者不易理解

项目初始化

在真正开发项目之前,让我们先进行需求分析 和 技术选型

需求分析

  • 聊天页面开发(基础能力)
    • 包含提示的输入框和发送 / 停止按钮

    • 实现一个聊天区域来显示对话记录,一个列表展示会话历史

    • 开发 /agent API 来处理请求

    • 确保每个对话的数据都被持久存储

    • 通过流式传输返回所有结果

  • 高级能力
    • 增强聊天组件,支持 markdown 渲染、自动滚动、图片上传等

    • 实现函数调用,例如检索当前时间

技术选型

根据需求,我选择了我喜欢的并且也是主流的技术:

  • Next.js 作为全栈开发基础框架

  • hono.js 作为后端框架,优化在 Next.js 中后端开发体验

  • PostgreSQL 作为数据库存储对话记录

  • DrizzleORM 作为 ORM ,更为便捷和高效的方式与数据库进行交互

  • shadcn/ui 作为 UI 组件库,tailwindcss 作为 css 框架

  • Vercel AI SDK 快速开发 AI 相关的服务,如果你也在开发 AI 相关的服务,强烈推荐使用它,能帮你减少 80% 的工作

  • Biome 进行代码格式化和检测(代替 ESLint + Prettier),需要你安装 Biome 插件哦

  • zod : TypeScript 优先的数据验证库

对了,我们使用 Github 进行版本控制,维护代码。使用 vercel 进行项目部署上线。

初始化

下面进行初始化项目,初始化项目完成后,我们应该就可以进行业务开发

1)根据 Next.js 官方文档我们创建一个 Next.js 项目:

npx create-next-app@latest

image.png

2)下面,根据官方文档集成 shadcn/ui:

pnpm dlx shadcn@latest init
pnpm dlx shadcn@latest add button

image.png

然后尝试使用 Button 按钮,发现集成成功!

注意这里有一个小细节就是我在入口的 layout 组件为 body 标签添加了 suppressHydrationWarning ,作用是:抑制 React 在客户端和服务器端渲染不匹配时产生的警告信息,这在处理动态内容(如日期、时间等)时特别有用,因为这些内容在服务器端和客户端可能会有差异。

image.png

3)下面集成 Biome,保证相关代码风格一致

pnpm i @biomejs/biome -D

然后在 package.json 添加对应的脚本:

{"scripts": {"lint": "next lint","format": "biome format --write .","lint:biome": "biome check --apply.",}
}

下面设置编辑器的 Format Document With ,选择 Configure Default Formatter 设置为 Biome。现在你的项目就又了格式化能力,你还可以在 git 提交的链路上进行预先 format 和 lint 等操作,保证提交的代码是格式化的。 4)下面继续集成 hono.js,我参考了文章思路: https://kuizuo.cn/blog/nextjs-with-hono/ 。首先根据官方文档进行安装

pnpm i hono
# 让 hono 接管所有接口服务
mkdir -p "src/app/api/[[...route]]" && touch "src/app/api/[[...route]]/route.ts"

下面,开发 route.ts 内容,让 hono 来接管接口服务

// src/app/api/[[...route]]/route.ts
import api from "@/server/api";
import { handle } from "hono/vercel";
const handler = handle(api);
export {handler as GET,handler as POST,handler as PUT,handler as DELETE,handler as PATCH,
};

因为 Next.js 会自动扫描 app 下的文件夹进行热更新,所以我们可以将服务端代码放在根目录的 server 文件夹下(其实你可以使用任何名称),这里写我们所有的服务端逻辑和接口,下面初始化一下服务端的基础逻辑, 5)创建自定义校验器,它的作用是进行请求数据验证的工具函数,确保数据符合预期的格式和类型规范,并提供类型安全的验证结果

// src/server/api/validator.ts
import type {Context,MiddlewareHandler,Env,ValidationTargets,TypedResponse,Input,
} from "hono";
import { validator } from "hono/validator";
import type { z, ZodSchema, ZodError } from "zod";export type Hook<T,E extends Env,P extends string,Target extends keyof ValidationTargets = keyof ValidationTargets,// biome-ignore lint/complexity/noBannedTypes: <explanation>O = {}
> = (result: (| { success: true; data: T }| { success: false; error: ZodError; data: T }) & {target: Target;},c: Context<E, P>
) =>| Response| void| TypedResponse<O>// biome-ignore lint/suspicious/noConfusingVoidType: <explanation>| Promise<Response | void | TypedResponse<O>>;type HasUndefined<T> = undefined extends T ? true : false;export const zValidator = <T extends ZodSchema,Target extends keyof ValidationTargets,E extends Env,P extends string,In = z.input<T>,Out = z.output<T>,I extends Input = {in: HasUndefined<In> extends true? {[K in Target]?: K extends "json"? In: HasUndefined<keyof ValidationTargets[K]> extends true? { [K2 in keyof In]?: ValidationTargets[K][K2] }: { [K2 in keyof In]: ValidationTargets[K][K2] };}: {[K in Target]: K extends "json"? In: HasUndefined<keyof ValidationTargets[K]> extends true? { [K2 in keyof In]?: ValidationTargets[K][K2] }: { [K2 in keyof In]: ValidationTargets[K][K2] };};out: { [K in Target]: Out };},V extends I = I
>(target: Target,schema: T,hook?: Hook<z.infer<T>, E, P, Target>
): MiddlewareHandler<E, P, V> =>// @ts-expect-error not typed wellvalidator(target, async (value, c) => {const result = await schema.safeParseAsync(value);if (hook) {const hookResult = await hook({ data: value, ...result, target }, c);if (hookResult) {if (hookResult instanceof Response) {return hookResult;}if ("response" in hookResult) {return hookResult.response;}}}if (!result.success) {throw result.error;}return result.data as z.infer<T>;});

6)创建错误处理文件,给到客户端更好的错误提示:

// src/server/api/error.ts
import { z } from "zod";
import type { Context } from "hono";
import { HTTPException } from "hono/http-exception";
import type { ContentfulStatusCode } from "hono/utils/http-status";export class ApiError extends HTTPException {public readonly code?: ContentfulStatusCode;constructor({code,message,}: {code?: ContentfulStatusCode;message: string;}) {super(code, { message });this.code = code;}
}export function handleError(err: Error, c: Context): Response {if (err instanceof z.ZodError) {const firstError = err.errors[0];return c.json({ code: 422, message: `\`${firstError.path}\`: ${firstError.message}` },422);}/*** This is a generic error, we should log it and return a 500*/return c.json({code: 500,message: "服务端错误, 请稍后再试。",},{ status: 500 });
}

下面我们创建我们的第一个接口,验证 honojs 是否引入成功:

// src/server/api/routes/hello.ts
import { Hono } from "hono";
const app = new Hono().get("/hello", (c) =>c.json({ message: "Hello, luckyChat" })
);
export default app;

7)最后,开发入口文件:

// src/server/api/index.ts
import { handleError } from "./error";
import { Hono } from "hono";
import helloRoute from "./routes/hello";
const app = new Hono().basePath("/api");
app.onError(handleError);
const routes = app.route("/", helloRoute);
export default app;
export type AppType = typeof routes;

现在我们不仅有了接口,还有了服务端接口的类型声明,我们可以非常方便的在客户端进行类型安全的接口请求,我们不需要写路由,也不需要写类型相关的内容,真的是 amazing,我们赶紧在客户端调用第一个接口吧!在调用接口前, 8)我们先封装一个 fetch 方法:

// src/lib/fetch.ts
import type { AppType } from "@/server/api";
import { hc } from "hono/client";
import ky from "ky";const baseUrl =process.env.NODE_ENV === "development"? "http://localhost:3000": process.env.NEXT_PUBLIC_APP_URL;export const fetch = ky.extend({hooks: {afterResponse: [async (_, __, response: Response) => {if (response.ok) {return response;// biome-ignore lint/style/noUselessElse: <explanation>} else {throw await response.json();}},],},
});export const client = hc<AppType>(baseUrl as string, {fetch: fetch,
});

ky 库是一个基于浏览器原生 Fetch API 的轻量级HTTP客户端库,提供了更简洁友好的接口,使用它更好的与 honojs 集成,这里我们使用 hc 和 AppType 创建了一个安全的接口请求方式:

// src/app/page.tsx
import { Button } from "@/components/ui/button";
import { Heart } from "lucide-react";
import { client } from "@/lib/fetch";
async function getData() {try {const res = await client.api.hello.$get();if (!res.ok) {// This will activate the closest `error.js` Error Boundarythrow new Error("Failed to fetch data");}return res.json();} catch (error) {console.error("获取数据失败:", error);return { message: "AI 助手" };}
}
export default async function Home() {const { message } = await getData();return (<div><div>{message}</div><Button><Heart className="mr-2 h-4 w-4" /> lucky Snail</Button></div>);
}

当我们在使用 client 的时候它会进行代码提示告诉你目前可以使用哪些接口,并且在后面我们可以借助 InferResponseType 和 typeof 等 ts 关键字来使用接口对应的 ts 类型,我们只需要在服务端定义好类型声明,在客户端直接消费即可 👍。

9)下面进行最重要的一步,也就是数据库初始化,有开发经验的应该都知道数据库设计的好,可以大大降低系统复杂度,减少不必要的代码,这么重要的事情肯定是需要 AI 的参与的,我们把需求给到 AI,然后让 AI 帮忙进行初步数据库设计,下面在 cursor 中进行 ask:

提示词:现在集成 DrizzleORM, and AI SDK.使用 postgreSQL 作为数据库,驱动使用 postgres,数据库名字叫 chatAI ,数据库就一张表,存储 AI 对话记录,设计良好的数据库表结构,最后开发 /agent API 来处理聊天请求,这里使用大模型为 Deepseek ,大模型的 key 存在 环境变量的 DEEPSEEK_API_KEY ,数据库集成参考 @https://orm.drizzle.team/docs/get-started-postgresql ,先梳理需求,然后一步步进行实现

AI 给到的数据库结构如下:

// src/lib/db/schema.ts
import { pgTable, serial, text, timestamp, varchar } from 'drizzle-orm/pg-core';// 聊天消息类型
export const chatMessages = pgTable('chat_messages', {id: serial('id').primaryKey(),sessionId: varchar('session_id', { length: 255 }).notNull(),role: varchar('role', { length: 50 }).notNull(), // 'user' 或 'assistant'content: text('content').notNull(),createdAt: timestamp('created_at').defaultNow().notNull(),
});// 会话信息
export const chatSessions = pgTable('chat_sessions', {id: serial('id').primaryKey(),sessionId: varchar('session_id', { length: 255 }).unique().notNull(),title: varchar('title', { length: 255 }),createdAt: timestamp('created_at').defaultNow().notNull(),updatedAt: timestamp('updated_at').defaultNow().notNull(),
});

这里 AI 帮我们创建好了数据库的表结构,它能理解需求,并给出合理的数据库设计:

  • chat_sessions 表:存储聊天会话信息

  • chat_messages 表:存储聊天消息 还帮我们在 package.json 添加了生成和运行迁移的脚本,我们在 env 配置到 DATABASE_URL,执行脚本即可初始化数据库

现在我们完成了项目初始化,我们可以使用 cursor 提供的 /generate Cursor Rules 来生成项目开发指导,在后面业务能力开发中,我们每次都携带上这条 rules ,它能帮 AI 更好的生成内容

image.png

现在已经搭建好了前端和后端基础能力,并且生成了项目开发的 rules ,下面就全部交给 AI 来进行业务开发,我们只需要做一个合格的测试和 code review 就好了!

核心能力开发

一个聊天应用最核心的就是输入提示词 => AI 大模型响应内容 => 展示内容 => 继续对话

1)开发 chat,提示词如下

下面 @project-structure.mdc 就是我们生成的项目开发 rules

@project-structure.mdc 使用 ai-sdk 开发 /agent API 来处理聊天请求,遵循 RESTful API 风格,这里使用大模型为 Deepseek ,大模型的 key 存在 环境变量的 DEEPSEEK_API_KEY ,然后在开发对应的 chat 页面,一个输入框,右侧有发送和暂停按钮,支持接收用户的输入,支持发送和停止能力,这里使用 @ai-sdk/react 快速进行开发,需要流式输出 AI 生成内容。代码组件化,模块化,尽可能使用 shadui/cn 组件开发,先梳理需求,然后一步步进行实现

AI 可能需要比较漫长时间完成工作,在这个过程中,我们可以思考下一个提示词,在 AI 生成完成后,我们需要进行检查和修复 bug,当然你是可以借助 AI 来 fix error。这里需要额外注意的是当我们 chat 中断的时候应该把已经生成的内容进行存储数据库

2)开发创建新会话能力,支持会话缓存到本地

@project-structure.mdc 支持创建新会话,并且会话 id 存储 localStorage ,在页面刷新的时候会话 id 依然存在,注意点击停止需要把当前会话进行存储

3)开发历史会话列表展示,支持切换会话

@project-structure.mdc 开发历史对话记录功能,先进行接口开发,这里两个接口:获取所有会话列表和获取指定 id 的会话信息,前端需要将会话列表封装为单独组件,点击会话列表项能进入该对话,数据接口逻辑使用自定义 hooks,保证代码清晰易理解。 注意客户端需要使用封装的 fetch 导出的 client 进行接口请求

4)支持 markdown 渲染 AI 生成的内容,优化页面布局 UI,支持内容自动滚动底部 上面完成后,我们有了基本的 chat 功能页面,但是可能这时候页面比较丑不太美观,现在进行优化

@project-structure.mdc 你是资深 UI 设计师,现在进行项目优化:
1,实现 markdown 渲染流式内容。添加在对话中自动滚动到底部的能力
2. 优化目前的页面 UI,页面布局为左边的侧边栏,展示历史记录和新对话能力都放在左边,当屏幕宽度小于 tailwindcss 的 lg 的时候就不展示侧边栏,右侧对话框 UI ,也需要进行优化,注意不要新增元素和修改逻辑,仅仅是对元素布局和 UI进行优化,参考优秀的 chatbox UI 设计

5)支持 function call 能力,获取当前时间

@project-structure.mdc @web 参考文档支持 function call 能力,以获取最新时间为例

优化

如果你做到这里,相信你的项目肯定还有一些 bug 和 UI 细节需要进行优化,你可以和 AI 一起进行优化,给大家看一下我和 AI 的 chat

image.png

不断的修复和优化,最终我的 chatbox 就出现啦!

image.png

你打几分呢?

总结

  1. AI 目前编程能力已经超过 90% 的工程师了,它在开发功能安全性和兼容性考虑上十分的全面,但是它也有能力边界,在面对复杂系统,奇怪的需求上是不如人的。所以程序员以后更多是做决策,做 AI 与需求的桥梁,通过我们的经验和直觉去选择接受还是拒绝 AI 的生成

  2. 日常 AI 编程开发中,推荐使用方式为 gemini 做设计和文档类工作,写代码部分交给 claude

  3. 需要我们能够合理的进行模块拆分,能够识别 AI 代码是不是合理的

  4. 系统设计是 AI 时代程序员的必须要提升的技能,推荐一本书《软件设计的哲学》第二版

  5. 知识广度,全栈能力对前端有很大的帮助,借助 AI 快速将想法变成现实是程序员的红利

  6. 持续学习,跟进最新的 AI 是保证自己有竞争力的关键

  7. Vibe Coding 必然会成为新的编码方式,纯手工编程必然会像 php 一样成为历史

  8. 目前来看,编程智能体(Agent)真的很成功,让我这种普通人能够快速 开发出产品。

参考:

  1. https://claude.ai/chat/fd4c29a3-3b5c-4965-9670-4380dcc28f98

  2. https://www.youtube.com/watch?v=tlrf4lu8Myc

  3. https://bigbang.easykol.com/search/following?platform=TIKTOK&url=https://www.tiktok.com/@meditationbuddhism

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/907114.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式学习的第二十六天-系统编程-文件IO+目录

一、文件IO相关函数 1.read/write cp #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <stdio.h> #include<unistd.h> #include<string.h>int main(int argc, char **argv) {if(argc<3){fprintf(stderr, …

SCADA|KingSCADA信创4.0-Win10安装过程

哈喽,你好啊,我是雷工! 现如今很多地方开始要求信创版, 最近就遇到一个现场要求用信创。 首先找官方要了最新的信创版安装包。 由于有之前安装组态王授权驱动装蓝屏的经历,此次特意问了下该标识win10的软件是否可以在win11系统上安装。 技术反馈win11专业版上可以安装…

AI时代新词-人工智能伦理审查(AI Ethics Review)

一、什么是人工智能伦理审查&#xff08;AI Ethics Review&#xff09;&#xff1f; 人工智能伦理审查&#xff08;AI Ethics Review&#xff09;是指在人工智能&#xff08;AI&#xff09;系统的开发、部署和使用过程中&#xff0c;对其可能涉及的伦理、法律和社会问题进行系…

GitLab 从 17.10 到 18.0.1 的升级指南

本文分享从 GitLab 中文本 17.10.0 升级到 18.0.1 的完整过程。 升级前提 查看当前安装实例的版本。有多种方式可以查看&#xff1a; 方式一&#xff1a; /help页面 可以直接在 /help页面查看当前实例的版本。以极狐GitLab SaaS 为例&#xff0c;在浏览器中输入 https://ji…

python:基础爬虫、搭建简易网站

一、基础爬虫代码&#xff1a; # 导包 import requests # 从指定网址爬取数据 response requests.get("http://192.168.34.57:8080") print(response) # 获取数据 print(response.text)二、使用FastAPI快速搭建网站&#xff1a; # TODO FastAPI 是一个现代化、快速…

从0开始学习R语言--Day10--时间序列分析数据

在数据分析中&#xff0c;我们经常会看到带有时间属性的数据&#xff0c;比如股价波动&#xff0c;各种商品销售数据&#xff0c;网站的网络用户活跃度等。一般来说&#xff0c;根据需求我们会分为两种&#xff0c;分析历史数据的特点和预测未来时间段的数据。 移动平均 移动平…

倚光科技在二元衍射面加工技术上的革新:引领光学元件制造新方向​

倚光科技二元衍射面加工技术&#xff08;呈现出细腻的光碟反射纹路&#xff09; 在光学元件制造领域&#xff0c;二元衍射面的加工技术一直是行业发展的关键驱动力之一。其精准的光相位调制能力&#xff0c;在诸多前沿光学应用中扮演着不可或缺的角色。然而&#xff0c;长期以来…

【redis原理篇】底层数据结构

SDS Redis是基于C语言实现的&#xff0c;但是Redis中大量使用的字符串并没有直接使用C语言字符串。 一、SDS 的设计动机 传统 C 字符串以 \0 结尾&#xff0c;存在以下问题&#xff1a; 性能瓶颈&#xff1a;获取长度需遍历字符数组&#xff0c;时间复杂度 O(n)。缓冲区溢出…

尚硅谷redis7 20-redis10大类型之zset

zset是redis中的有序集合【sorted set】 zset就是在set基础上&#xff0c;每个val值前加一个score分数值。 之前set是k1 v1 v2 v3现在zset是k1 score1 v1 score2 v2 向有序集合中加入一个元素和该元素的分数 ZADD key score member [score member...] 添加元素 127. 0. 0. …

STM32 SPI通信(软件)

一、SPI简介 SPI&#xff08;Serial Peripheral Interface&#xff09;是由Motorola公司开发的一种通用数据总线四根通信线&#xff1a;SCK&#xff08;Serial Clock&#xff09;、MOSI&#xff08;Master Output Slave Input&#xff09;、MISO&#xff08;Master Input Slav…

Kotlin Native与C/C++高效互操作:技术原理与性能优化指南

一、互操作基础与性能瓶颈分析 1.1 Kotlin Native调用原理 Kotlin Native通过LLVM编译器生成机器码,与C/C++的互操作基于以下核心机制: CInterop工具:解析C头文件生成Kotlin/Native绑定(.klib),自动生成类型映射和包装函数双向调用约定: Kotlin调用C:直接通过生成的绑…

云原生安全 SaaS :从基础到实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 1. 基础概念 什么是 SaaS&#xff1f; SaaS&#xff08;Software as a Service&#xff0c;软件即服务&#xff09;是一种基于云计算的软件交付模式。用…

git clone 提速

git上的项目时间久了 .git文件夹非常大&#xff0c;这时候更新一次项目需要花费很长的时间&#xff0c;解决方法也很简单&#xff0c;加一个depth参数&#xff0c;命令如下&#xff1a; git clone --depth 1 https://github.com/xxxxxx/xxxxxx指定了 depth 1 的时候&#xff0…

Redis 性能优化:核心技术、技巧与最佳实践

Redis 作为高性能的内存数据库,其性能优化是系统设计中的关键环节。本文结合 Redis 官方文档及实践经验,从内存管理、延迟优化、CPU 效率、网络配置等多个维度,系统性地阐述 Redis 性能优化的核心技术与最佳实践。 通过以下优化手段,Redis 可在高并发、低延迟场景中发挥极致…

PostgreSQL 14 pacemaker 高可用集群

核心架构原理 集群组成&#xff08;典型三节点结构&#xff09;&#xff1a; [Node1] PostgreSQL Pacemaker Corosync pcsd [Node2] PostgreSQL Pacemaker Corosync pcsd [Node3] PostgreSQL Pacemaker Corosync pcsd ↕ ↕ ↕ ← Corosync 多…

影刀Fun叉鸟-2048

文章目录 仅为自动化演示&#xff0c;实际2048判定逻辑需要更加严谨 参考代码 # 使用提醒: # 1. xbot包提供软件自动化、数据表格、Excel、日志、AI等功能 # 2. package包提供访问当前应用数据的功能&#xff0c;如获取元素、访问全局变量、获取资源文件等功能 # 3. 当此模块作…

Vue3.5 企业级管理系统实战(二十):角色菜单

本篇聚焦于角色菜单权限分配功能的实现&#xff0c;围绕“给角色赋予菜单权限”这一核心场景&#xff0c;从接口设计、组件封装到页面集成展开完整技术方案的阐述。主要内容包括&#xff1a; 1. 角色权限接口开发&#xff1a;定义获取角色权限、分配权限等接口&#xff0c;规范…

go实现钉钉三方登录

钉钉的的官方开发文档中只给出了java实现三方登录的&#xff0c;我们准备用go语言来实现 实现网页方式登录应用&#xff08;登录第三方网站&#xff09; - 钉钉开放平台 首先就是按照文档进行操作&#xff0c;备注好网站的信息 获得应用凭证&#xff0c;我们后面会用到 之后…

一、OpenCV的基本操作

目录 1、OpenCV的模块 2、OpenCV的基础操作 2.1图像的IO操作 2.2绘制几何图形 2.3获取并修改图像中的像素点 2.4 获取图像的属性 2.5图像通道的拆分与合并 2.6色彩空间的改变 3、OpenCV的算数操作 3.1图像的加法 3.2图像的混合 3.3总结 1、OpenCV的模块 2、OpenCV的基…

虚拟机配置桥接,远程工具直接访问

虚拟机网络配置 前言windows下安装linux虚拟机配置网络1、设置虚拟机网络模式&#xff1a;桥接模式2、配置网络参数1、查看本机电脑连接的网络情况2、打开虚拟机&#xff0c;编辑配置文件3、编辑虚拟网络 3、测试连通性 前言 好不容易装上了虚拟机&#xff0c;输入命令时又发现…