【02】从0到1构建AI生成思维导图应用 -- 编写主页

news2024/12/22 20:35:32

【02】从0到1构建AI生成思维导图应用 – 编写主页

大家好!最近自己做了一个完全免费的AI生成思维导图的网站,支持下载,编辑和对接微信公众号,可以在这里体验:https://lt2mind.zeabur.app/

上一章:https://blog.csdn.net/m0_56699208/article/details/140006789?spm=1001.2014.3001.5501

构建好nextjs,并配置了tailwindcss和shadcn-ui后,我们就可以开始编写主页的前端代码了:
在这里插入图片描述
在编写代码之前,先通过 shadcn-ui 安装一些组件:

npx shadcn-ui@latest add button input tooltip textarea skeleton

安装 react-simple-typewriter 打字机效果插件:

npm install react-simple-typewriter

修改layout.tsx,改变元数据和字体:

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";

const inter = Inter({
  subsets: ["latin"],
  display: "swap",
  adjustFontFallback: false,
});

export const metadata: Metadata = {
  title: "LT2Mind",
  description:
    "Transform your text and links into beautiful mind maps with ease.",
  icons: {
    icon: '/favicon.ico'
  }
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
      <html lang="en">
        <body className={inter.className}>
        </body>
      </html>
  );
}

globals.css 里配置一些通用样式:

@tailwind base;
@tailwind components;
@tailwind utilities;

  @layer base {
    :root {
      --background: 0 0% 100%;
      --foreground: 222.2 84% 4.9%;

      --card: 0 0% 100%;
      --card-foreground: 222.2 84% 4.9%;

      --popover: 0 0% 100%;
      --popover-foreground: 222.2 84% 4.9%;

      --primary: 222.2 47.4% 11.2%;
      --primary-foreground: 210 40% 98%;

      --secondary: 210 40% 96.1%;
      --secondary-foreground: 222.2 47.4% 11.2%;

      --muted: 210 40% 96.1%;
      --muted-foreground: 215.4 16.3% 46.9%;

      --accent: 210 40% 96.1%;
      --accent-foreground: 222.2 47.4% 11.2%;

      --destructive: 0 84.2% 60.2%;
      --destructive-foreground: 210 40% 98%;

      --border: 214.3 31.8% 91.4%;
      --input: 214.3 31.8% 91.4%;
      --ring: 222.2 84% 4.9%;

      --radius: 0.5rem;
    }

    .dark {
      --background: 222.2 84% 4.9%;
      --foreground: 210 40% 98%;

      --card: 222.2 84% 4.9%;
      --card-foreground: 210 40% 98%;

      --popover: 222.2 84% 4.9%;
      --popover-foreground: 210 40% 98%;

      --primary: 210 40% 98%;
      --primary-foreground: 222.2 47.4% 11.2%;

      --secondary: 217.2 32.6% 17.5%;
      --secondary-foreground: 210 40% 98%;

      --muted: 217.2 32.6% 17.5%;
      --muted-foreground: 215 20.2% 65.1%;

      --accent: 217.2 32.6% 17.5%;
      --accent-foreground: 210 40% 98%;

      --destructive: 0 62.8% 30.6%;
      --destructive-foreground: 210 40% 98%;

      --border: 217.2 32.6% 17.5%;
      --input: 217.2 32.6% 17.5%;
      --ring: 212.7 26.8% 83.9%;
    }
  }

  @layer base {
    * {
      @apply border-border;
    }
    body {
      @apply bg-background text-foreground;
    }
  }

  .bg {
    @apply bg-gradient-to-r from-blue-100 via-purple-100 to-pink-100
  } 

在 components 文件夹下创建一个 hero 组件,作为应用的主页:
hero.tsx:

"use client";
import { useState } from "react";
import { Textarea } from "./ui/textarea";
import { Button } from "@/components/ui/button";
import Link from "next/link";
import { Typewriter } from "react-simple-typewriter";
import { Skeleton } from "@/components/ui/skeleton";
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../components/ui/tooltip";

export default function Hero() {
  const { isSignedIn } = useUser();
  const [imgUrl, setImgUrl] = useState("");
  const [editUrl, setEditUrl] = useState("");
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (event: any) => {
    event.preventDefault(); // Prevent the default form submission behavior
    if (!isSignedIn) {
      //router.push('/sign-in');
      return;
    }
    setLoading(true);
    const inputValue = event.target.elements.textOrLink.value; // Get the value from the textarea
    const result = await toMind(inputValue); // Call the toMind function with the input value
    if (result) {
      setImgUrl(result.imgUrl);
      setEditUrl(result.editUrl);
    }
    setLoading(false);
  };

  return (
    <div className="flex flex-col bg">
      <header className="text-blue-500">
        <section className="container max-w-5xl px-4 md:px-6 py-6 md:py-10">
          <div className="text-center space-y-4 sm:mt-4">
            <h1 className="text-4xl md:text-6xl font-bold tracking-widest">
              LT2MIND
            </h1>
            <p className="text-lg md:text-xl max-w-3xl mx-auto italic">
              <Typewriter
                words={[
                  "Transform your text and links into beautiful mind maps with ease.",
                ]}
                loop={1}
                cursor
                cursorStyle=""
                typeSpeed={20}
                deleteSpeed={50}
                delaySpeed={1000}
              />
            </p>
          </div>
        </section>
        <section className="py-12 md:py-20">
          <div className="container max-w-5xl px-4 md:px-6 grid grid-cols-1 md:grid-cols-2 gap-8">
            <div className="space-y-4">
              <h2 className="text-3xl font-bold text-purple-400">
                Convert to Mind Map
              </h2>
              <p className="text-muted-foreground">
                Enter your text or link and let LT2Mind do the rest. You may
                wait for one minute or more for the transition to complete.
              </p>
              <form className="flex gap-2" onSubmit={handleSubmit}>
                <div className="flex flex-col gap-2 h-[40vh] w-full">
                  <Textarea
                    name="textOrLink"
                    placeholder="Enter text or link..."
                    className="shadow-sm focus:border-none flex-1 resize-none bg"
                    style={{
                      outline: "none",
                      overflow: "auto",
                      scrollbarWidth: "none",
                      msOverflowStyle: "none",
                    }}
                  />

                  <style jsx>{`
                    textarea::-webkit-scrollbar {
                      display: none;
                    }
                  `}</style>
                  <TooltipProvider>
                    <Tooltip>
                      <TooltipTrigger asChild>
                        <div>
                          <Button
                            type="submit"
                            className="mt-2 w-full bg-pink-200 text-purple-500 hover:bg-pink-100"
                            disabled={!isSignedIn}
                          >
                            Convert
                          </Button>
                        </div>
                      </TooltipTrigger>
                      {!isSignedIn && (
                        <TooltipContent>
                          You need to sign in to convert
                        </TooltipContent>
                      )}
                    </Tooltip>
                  </TooltipProvider>
                </div>
              </form>
            </div>
            {loading ? (
              <div className="flex flex-col items-center justify-center gap-2">
                <div className="animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-purple-500"></div>
                <p className="text-lg text-purple-400">converting...</p>
              </div>
            ) : imgUrl ? (
              <div className="flex flex-col items-center justify-center gap-2">
                <img
                  src={imgUrl}
                  alt="Image 1"
                  className="w-full h-full object-contain shadow-sm"
                />
                <div className="flex gap-x-4 w-full justify-center">
                  <Link href={editUrl} target="_blank" className="w-full">
                    <Button className="bg-pink-200 text-purple-500 w-full hover:bg-pink-100">
                      Edit in TreeMind
                    </Button>
                  </Link>
                  <a
                    href={imgUrl}
                    download="mindmap.jpeg"
                    target="_blank"
                    className="w-full"
                  >
                    <Button className="bg-pink-200 text-purple-500 w-full hover:bg-pink-100">
                      Download
                    </Button>
                  </a>
                </div>
              </div>
            ) : (
              <div className="flex flex-col items-center justify-center gap-2">
                <p className="text-lg text-purple-400">
                  Waiting For Conversion
                  <Typewriter
                    words={["..."]}
                    loop={true}
                    cursor
                    cursorStyle=""
                    typeSpeed={200}
                    deleteSpeed={50}
                    delaySpeed={2000}
                  />
                </p>
              </div>
            )}
          </div>
        </section>
      </header>
    </div>
  );
}

这时,你应该能得到这样一个页面,并且有了打字机的动画效果:
在这里插入图片描述

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

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

相关文章

【AI大模型RAG】深入探索检索增强生成(RAG)技术

目录 1. 引言2. RAG技术概述2.1 RAG技术的定义2.2 RAG技术的工作原理2.3 RAG技术的优势2.4 RAG技术的应用场景 3. RAG的工作流程3.1 输入处理3.2 索引建立3.3 信息检索3.4 文档生成3.5 融合与优化 4. RAG范式的演变4.1 初级 RAG 模型4.2 高级 RAG 模型4.3 模块化 RAG 模型优化技…

生命在于学习——Python人工智能原理(2.5.1)

五、Python的类与继承 5.1 Python面向对象编程 在现实世界中存在各种不同形态的事物&#xff0c;这些事物之间存在各种各样的联系。在程序中使用对象来映射现实中的事物&#xff0c;使用对象之间的关系描述事物之间的联系&#xff0c;这种思想用在编程中就是面向对象编程。 …

nodejs国内源下载

nodejs的官网下载太慢了 可以尝试网盘下载快一点 夸克网盘分享夸克网盘是夸克推出的一款云服务产品&#xff0c;功能包括云存储、高清看剧、文件在线解压、PDF一键转换等。通过夸克网盘可随时随地管理和使用照片、文档、手机资料&#xff0c;目前支持Android、iOS、PC、iPad。…

2024年公司加密软件排行榜(企业加密软件推荐)

在信息时代&#xff0c;企业数据安全至关重要&#xff0c;防止数据泄露和未授权访问是首要任务之一。以下是2024年备受好评的企业加密软件排行榜&#xff1a; 固信加密软件https://www.gooxion.com/ 1.固信加密软件 固信加密软件是新一代企业级加密解决方案&#xff0c;采用先…

【网络架构】lvs集群

目录 一、集群与分布式 1.1 集群介绍 1.2 分布式系统 1.3 集群设计原则 二、LVS 2.1 lvs工作原理 2.2 lvs集群体系架构 ​编辑 2.3 lvs功能及组织架构 2.4 lvs集群类型中术语 三、LVS工作模式和命令 3.1 lvs集群的工作模式 3.1.1 lvs的nat模式 3.1.2 lvs的dr模式 …

胶质瘤的发病原因及诊断方式有哪些?

胶质瘤&#xff0c;这个听起来有些陌生的名词&#xff0c;实际上是一种起源于神经胶质细胞的常见脑肿瘤。它的发病原因复杂&#xff0c;涉及遗传、环境、年龄及感染等多种因素。 首先&#xff0c;遗传因素在胶质瘤的发病中占据一席之地。某些遗传性疾病&#xff0c;如结节性硬化…

3Dmax模型渲染时的常见问题与解决方法

3Dmax是一个广为人知的三维建模工具&#xff0c;它在建筑、电影制作和游戏开发等多个领域都有着广泛的应用。尽管如此&#xff0c;在进行3Dmax模型渲染的过程中&#xff0c;用户可能会遇到一些常见问题。本文将提供这些常见问题的解决方案&#xff0c;以帮助用户提高渲染效率和…

BIO、NIO编程深入理解与直接内存、零拷贝

网路编程基本常识 一. Socket 什么是Socket Socket是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。它提供了应用层进程利用网络协议交换数据的机制&#xff0c;是应用程序与网络协议栈进行交互的接口。 说白了&#xff0c;Socket就是把TCP/IP协议族进行封装…

JOSEF约瑟 ESRW-322打滑开关 智能运算,工作稳定

产品特点 非接触式检测&#xff1a;ESRW-322打滑开关采用非接触式检测方式&#xff0c;不会对输送带造成磨损&#xff0c;提高了设备的使用寿命。 高精度测量&#xff1a;该开关具有高精度测量能力&#xff0c;可检测到的打滑率范围广泛&#xff08;0∽100%&#xff09;&#x…

LangCell:用于细胞注释的语言-细胞预训练模型

细胞身份包括细胞的各种语义&#xff0c;包括细胞类型、pathway信息、疾病信息等。从转录组数据中了解细胞身份&#xff0c;例如注释细胞类型&#xff0c;是一项基础任务。由于语义是由人类赋予的&#xff0c;如果没有cell-label pair提供监督信号&#xff0c;AI模型很难有效地…

文献解读-基因编辑-第十二期|《CRISPR-detector:快速、准确地检测、可视化和注释基因组编辑事件引起的全基因组范围突变》

关键词&#xff1a;基因组变异检测&#xff1b;全基因组测序&#xff1b;基因编辑&#xff1b; 文献简介 标题&#xff08;英文&#xff09;&#xff1a;CRISPR-detector: fast and accurate detection, visualization, and annotation of genome-wide mutations induced by g…

IDEA 安装与激活详细教程最新(附最新激活码)2099年亲测有效!

我们先从 IDEA 官网下载 IDEA 2024.1 版本的安装包&#xff0c;下载链接如下&#xff1a; https://www.jetbrains.com/idea/download/ 点击下载(下载Ultimate版)&#xff0c;静心等待其下载完毕即可。 激活方式&#xff1a; 正版专属激活码领取

自定义APT插件导致IDEA调试时StreamTrace(跟踪当前流链)报internal error(内部错误)

IDEA里面debug的时候&#xff0c;针对stream流提供了流追踪调试功能&#xff0c;方便大家调试stream流代码。 最近改其他人代码&#xff0c;需要用到这个&#xff0c;发现提示内部错误。 然后百度一圈发现没啥解决方案&#xff0c;就自己看IDEA的日志&#xff0c;看看是什么引…

css控制整个div下的所有元素中的文字放大缩小

css控制文字放大缩小 话不多说,直接上代码,我用了最简单粗暴的方法,找个下面所有的元素,然后遍历放大所有文字 add() {var div this.$refs[myDiv];var elements div.querySelectorAll("*");for (var i 0; i < elements.length; i) {var fontSize parseInt(win…

FineReport填报列权限控制

近期换东家啦&#xff0c;又回归使用帆软啦&#xff0c;对于填报报表列权限的控制我这边顺带记录一下 首先讲解下场景&#xff1a;填报报表需要不同角色决定对不同列是否有填写或者查看权限 以填写权限为例&#xff0c;首先考虑用到的是 帆软自带的权限编辑&#xff0c;其次考虑…

如何不改变 PostgreSQL 列类型#PG培训

开发应用程序并在其背后操作数据库集群时&#xff0c;会遇到一个意想不到的问题是实践与理论、开发环境与生产之间的差异。这种不匹配的一个完美例子就是更改列类型。 #PG考试#postgresql培训#postgresql考试#postgresql认证 关于如何在 PostgreSQL&#xff08;以及其他符合 SQ…

使用API有效率地管理Dynadot域名,为文件夹中的域名设置域名转发

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

鸿蒙开发系统基础能力:【@ohos.wallpaper (壁纸)】

壁纸 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import wallpaper from ohos.wallpaper;WallpaperType 定义壁纸类型。 系统能力: 以下各项对应的系统能力均为SystemCapability…

悬浮翻译工具有哪些?来看看这几款悬浮翻译工具吧

沉浸式观影时&#xff0c;却被那些叽里呱啦的外文台词搞得头大如斗&#xff1f; 别焦虑&#xff0c;就算没有现成的字幕&#xff0c;我们也能自己生成&#xff01;如何做到&#xff1f;交给悬浮翻译器&#xff0c;这些软件能实时捕获那些耳边飘过的异国语言&#xff0c;巧妙地…

#### 广告投放 ####

以巨量引擎为例&#xff1a; 计费模式 eCPM&#xff08;expected Cost Per Mile&#xff0c;估计千次展示收入&#xff09; 概括&#xff1a; ecpm为千次展示的预估收益&#xff0c;是广告平台用来给广告排序的指标。 注意是展示而不是千次点击收益&#xff0c;展示了可能不…