穷鬼计划:react+tailwindcss+vercel

windows系统。

1.找一个目录:cmd

复制代码
Microsoft Windows [版本 10.0.26100.3775]
(c) Microsoft Corporation。保留所有权利。

D:\gitee>npm create vite@latest pe100_ghost -- --template react

> npx
> create-vite pe100_ghost --template react

|
o  Scaffolding project in D:\gitee\pe100_ghost...
|
---  Done. Now run:

  cd pe100_ghost
  npm install
  npm run dev


D:\gitee>cd pe100_ghost

D:\gitee\pe100_ghost>npm install

added 196 packages, and audited 197 packages in 1m

32 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

D:\gitee\pe100_ghost>npm install -D [email protected] postcss autoprefixer

added 95 packages, and audited 292 packages in 17s

60 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

D:\gitee\pe100_ghost>npx tailwindcss init -p

Created Tailwind CSS config file: tailwind.config.js
Created PostCSS config file: postcss.config.js

D:\gitee\pe100_ghost>

2.vscode打开文件夹,修改必要的内容

复制代码
/*
 * @Author: DuYicheng
 * @Date: 2025-04-27 13:57:40
 * @LastEditors: DuYicheng
 * @LastEditTime: 2025-04-27 13:59:40
 * @Description: 
 * @FilePath: \pe100_ghost\tailwind.config.js
 */
/** @type {import('tailwindcss').Config} */
export default {
  content: ["./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",],
  theme: {
    extend: {},
  },
  plugins: [],
}

3.试运行

复制代码
(base) PS D:\gitee\pe100_ghost> npm run dev

> [email protected] dev
> vite


  VITE v6.3.3  ready in 688 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

结果:

4. 因为大多数代码已经完成,所以,我直接复制

记录一下过程:

4.1丰富一下assets下的图片资源。

4.2建一个components目录,存放小型组件

4.3建一个layouts目录,存放中型组件。

4.4建一个pages目录,存放页面组件。

4.5建一个sections目录,存放切片组件。

目前结构如下:

5.根据文件链进行调整。

index.html->main.jsx->app.jsx

复制代码
<body class="antialiased"> <!-- 启用Tailwind抗锯齿 -->
  <div id="root"></div>
  <script type="module" src="/src/main.jsx"></script>

  <!-- 示例:Google Analytics集成 -->
  <!-- <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXX"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
    gtag('config', 'G-XXXXXX');
  </script> -->
</body>

/*
 * @Author: DuYicheng
 * @Date: 2025-04-25 13:36:04
 * @LastEditors: DuYicheng
 * @LastEditTime: 2025-04-27 14:36:51
 * @Description: 
 * @FilePath: \pe100net\src\main.jsx
 */
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';


const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

/*
 * @Author: DuYicheng
 * @Date: 2025-04-27 14:35:03
 * @LastEditors: DuYicheng
 * @LastEditTime: 2025-04-27 14:35:05
 * @Description: 
 * @FilePath: \pe100net\src\App.jsx
 */


// src/App.jsx (简化版)
import MainLayout from './layouts/MainLayout'
import HomePage from './pages/HomePage'

export default function App() {
  return (
    <MainLayout>
      <HomePage />
    </MainLayout>
  )
}

import Header from '../sections/Header'
import Footer from '../sections/Footer'

const MainLayout = ({ children }) => {
  return (
    <div className="min-h-screen flex flex-col">
      <Header />
      <main className="flex-1">{children}</main>
      <Footer />
    </div>
  )
}

export default MainLayout



import Hero from '../sections/Hero'
import Features from '../sections/Features'
import Pricing from '../sections/Pricing'

const HomePage = () => {
  return (
    <>
      <Hero />
      <Features />
      <Pricing />
    </>
  )
}

export default HomePage

/*
 * @Author: DuYicheng
 * @Date: 2025-04-25 13:50:53
 * @LastEditors: DuYicheng
 * @LastEditTime: 2025-04-27 14:38:25
 * @Description: 
 * @FilePath: \pe100net\src\sections\Hero.jsx
 */


const Hero = () => (
  <section className="bg-gradient-to-b from-blue-50 to-white py-20">
    <div className="container mx-auto px-4 text-center">
      <h1 className="text-5xl font-bold text-gray-900 mb-6">
        体育测试数据一键解决
      </h1>
      <p className="text-xl text-gray-600 mb-8 max-w-2xl mx-auto">
        通过智能分析和自动化流程,提升您的业务效率,节省99%人工操作时间。您只需专注于测试,剩下的交给我们。
      </p>
      {/* <Button variant="primary" className="text-lg px-8 py-4">
        免费开始
      </Button> */}

      {/* <img 
        src="/assets/images/hero-dashboard.png" 
        alt="产品预览" 
        className="mt-16 mx-auto shadow-xl rounded-lg"
      /> */}
    </div>
  </section>
)

export default Hero

import Card from '../components/Card'

const Features = () => {
  const features = [
    {
      title: "智能分析",
      description: "数据自动化分析,提升业务效率",
      icon: "📊"
    },
    {
      title: "自动化流程",
      description: "智能工作流引擎节省99%人工操作",
      icon: "⚡"
    },
    {
      title: "安全可靠",
      description: "勿需担心数据安全,隐私保护",
      icon: "🔒"
    }
  ]

  return (
    <section className="py-20 bg-white">
      <div className="container mx-auto px-4">
        <h2 className="text-3xl font-bold text-center mb-12">核心功能</h2>
        <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
          {features.map((feature, index) => (
            <Card key={index}>
              <div className="text-4xl mb-4">{feature.icon}</div>
              <h3 className="text-xl font-semibold mb-2">{feature.title}</h3>
              <p className="text-gray-600">{feature.description}</p>
            </Card>
          ))}
        </div>
      </div>
    </section>
  )
}

export default Features

/*
 * @Author: DuYicheng
 * @Date: 2025-04-25 14:03:54
 * @LastEditors: DuYicheng
 * @LastEditTime: 2025-04-27 10:04:39
 * @Description: 
 * @FilePath: \pe100net\src\sections\Pricing.jsx
 */
// src/sections/Pricing.jsx
import Card from '../components/Card'
import DownloadLink from '../components/OpenLink'

const Pricing = () => {
  const plans = [
    {
      name: "班级版",
      price: "¥0",
      features: ["基础功能,一键转换成百分数(含加分项目)", "60行数据,满足多数场景", "小学一年级到大学四年级", "本地操作,数据安全"],
      buttonText: "免费下载",
      href: "https://www.alipan.com/s/Ri8k2LLMzLZ",
      variant: "outline",
      recommended: false
    },
    {
      name: "专业版",
      price: "¥0",
      features: ["正在开发中...", "更多功能", "图文分析计算", "数据导出"],
      buttonText: "立即购买",
      href: "https://www.alipan.com/s/Ri8k2LLMzLZ",
      variant: "primary",
      recommended: true
    }
  ]

  return (
    <section className="py-20 bg-gray-50">
      <div className="container mx-auto px-4">
        <h2 className="text-3xl font-bold text-center mb-12">定价方案</h2>
        <div className="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-4xl mx-auto">
          {plans.map((plan, index) => (
            <Card
              key={index}
              className={`relative ${plan.recommended ? 'ring-2 ring-blue-600' : ''}`}
            >
              {plan.recommended && (
                <div className="absolute top-0 right-0 bg-blue-600 text-white px-3 py-1 text-sm rounded-bl-lg">
                  推荐
                </div>
              )}
              <h3 className="text-2xl font-bold mb-4">{plan.name}</h3>
              <div className="text-4xl font-bold mb-6">{plan.price}</div>
              <ul className="space-y-3">
                {plan.features.map((feature, i) => (
                  <li key={i} className="flex items-center">
                    <svg className="w-5 h-5 text-blue-600 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M5 13l4 4L19 7"></path>
                    </svg>
                    {feature}
                  </li>
                ))}
              </ul>
              <DownloadLink
                href={plan.href}
                variant={plan.variant}
                className="mt-6 w-full py-3 bg-blue-600 text-white rounded-lg transition-colors"
                message={`即将跳转到 ${plan.name} 下载页面`}
              >
                {plan.buttonText}
              </DownloadLink>
            </Card>
          ))}
        </div>
      </div>
    </section>
  )
}

export default Pricing

/*
 * @Author: DuYicheng
 * @Date: 2025-04-25 13:50:16
 * @LastEditors: DuYicheng
 * @LastEditTime: 2025-04-27 09:59:20
 * @Description: header
 * @FilePath: \pe100net\src\sections\Header.jsx
 */

import DownloadLink from '../components/OpenLink'
import logo from '../assets/icon.ico'

const Header = () => (
  <header className="sticky top-0 bg-white shadow-sm">
    <nav className="container mx-auto px-4 py-4 flex justify-between items-center">
      {/* <div className="text-2xl font-bold text-blue-600">Logo</div> */}
      {/* 修改后的 logo 部分 */}
      <div className="flex items-center space-x-2">
        <img
          src={logo}
          alt="PE100NET Logo"
          className="w-8 h-8" // 根据实际图标尺寸调整
        />
        <span className="text-2xl font-bold text-blue-600">PE100NET</span>
      </div>

      <div className="hidden md:flex space-x-6">
        {/* <a href="#features" className="text-gray-600 hover:text-blue-600">功能</a>
        <a href="#pricing" className="text-gray-600 hover:text-blue-600">帮助</a> */}
        {/* <a href="#contact" className="text-gray-600 hover:text-blue-600">About us</a> */}
      </div>

      <DownloadLink href={"https://www.alipan.com/s/Ri8k2LLMzLZ"} variant={"primary"}
        className={"hidden md:block top-0 right-0 bg-green-600 text-white px-16 py-2 text-lg rounded"}>基础版免费下载</DownloadLink>


    </nav>
  </header>
)

export default Header

5.其他未展示的代码

复制代码
const Button = ({ children, variant = 'primary', ...props }) => {
  const baseClasses = "px-6 py-3 rounded-lg font-medium transition-all"

  const variants = {
    primary: "bg-blue-600 text-white hover:bg-blue-700",
    secondary: "bg-gray-100 text-gray-900 hover:bg-gray-200",
    outline: "border-2 border-blue-600 text-blue-600 hover:bg-blue-50"
  }

  return (
    <button
      className={`${baseClasses} ${variants[variant]}`}
      {...props}
    >
      {children}
    </button>
  )
}

export default Button

/*
 * @Author: DuYicheng
 * @Date: 2025-04-25 14:00:32
 * @LastEditors: DuYicheng
 * @LastEditTime: 2025-04-27 14:43:15
 * @Description: 
 * @FilePath: \pe100net\src\components\Card.jsx
 */

const Card = ({ children, className }) => {
  return (
    <div className={`bg-white p-8 rounded-xl shadow-lg hover:shadow-xl transition-shadow ${className}`}>
      {children}
    </div>
  )
}

export default Card

/*
 * @Author: DuYicheng
 * @Date: 2025-04-27 08:24:01
 * @LastEditors: DuYicheng
 * @LastEditTime: 2025-04-27 14:26:42
 * @Description: 
 * @FilePath: \pe100net\src\components\OpenLink.jsx
 */
// components/DownloadLink.jsx
import React from 'react';
import PropTypes from 'prop-types';
import Button from './Button'; // 确保路径正确

const OpenLink = ({
    href,
    message = "请在新页面中点击下载按钮",
    children,
    variant,
    className,
    ...props
}) => {
    const handleDownload = (e) => {
        try {
            // 显示用户指引
            if (message) alert(message);
            e.preventDefault();

            // 基础验证
            if (!href) {
                throw new Error('缺少下载链接');
            }

            // 尝试打开新窗口
            const newWindow = window.open(href, '_blank', 'noopener,noreferrer');

            // // 处理弹窗拦截
            // if (!newWindow || newWindow.closed || newWindow.document === window.document) {
            //     // 备选方案:直接跳转
            //     window.location.href = href;
            //     return;
            // }


        } catch (error) {
            console.error('下载异常:', error);
            alert(`下载失败: ${error.message}`);
        }
    };

    return (
        <Button
            variant={variant}
            className={className}
            onClick={handleDownload}
            {...props}
        >
            {children}
        </Button>
    );
};

// 类型检查
OpenLink.propTypes = {
    href: PropTypes.string.isRequired,
    message: PropTypes.string,
    variant: PropTypes.string,
    className: PropTypes.string,
    children: PropTypes.node.isRequired
};

export default OpenLink;

/*
 * @Author: DuYicheng
 * @Date: 2025-04-27 10:12:03
 * @LastEditors: DuYicheng
 * @LastEditTime: 2025-04-27 10:12:05
 * @Description: 
 * @FilePath: \pe100net\src\components\QRCodeWithOverlay.jsx
 */
// src/components/QRCodeWithOverlay.jsx
import React from 'react';

const QRCodeWithOverlay = ({ src, alt, title, description, note }) => {
  return (
    <div className="md:col-span-2 flex flex-col items-center">
      <div className="mb-4 text-center">
        <h4 className="text-xl font-bold mb-2">{title}</h4>
        <p className="text-gray-400">{description}</p>
      </div>

      <div className="relative group">
        <img
          src={src}
          alt={alt}
          className="w-32 h-32 md:w-48 md:h-48 object-contain border-4 border-white rounded-lg transition-transform duration-300 group-hover:scale-105"
        />
        <div className="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-40 transition-all duration-300 rounded-lg flex items-center justify-center">
          <span className="opacity-0 group-hover:opacity-100 text-white font-medium">
            扫码添加
          </span>
        </div>
      </div>

      <p className="mt-4 text-gray-400 text-sm">
        <br />
        {note}
      </p>
    </div>
  );
};

export default QRCodeWithOverlay;

5.全部完成,示例如下:

6.上传到git

6.1初始化

(1)鼠标右键 --> Git Bash Here

复制代码
Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net
$ git config --global user.name "-----"

Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net
$ git config --global user.email "---------"

Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net
$ git init
Initialized empty Git repository in D:/gitee/pe100net/.git/

Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$

7.相关教程

基于 VScode 的 git 详细使用指南【保姆级!建议收藏!】_vscode使用git-CSDN博客

记得要填写提交备注。

然后。

Git命令详解、VScode中使用Git_vscode git工具-CSDN博客

【VSCode ☆ Git 】最佳代码管理 ➔ 高效且优雅_哔哩哔哩_bilibili

8.过程记录

复制代码
Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ git status
On branch master
nothing to commit, working tree clean

Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ 

一、是否需要先创建远程仓库?

1. 如果仅进行本地版本控制
  • 不需要远程仓库。Git 可以在本地独立管理代码历史,无需远程服务器。
2. 如果需要将代码推送到远程平台(如备份、协作)
  • 必须先在远程平台创建空仓库,否则 Git 不知道将代码推送到哪里。
复制代码
Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ git remote add origin https://github.com/18053923230/pe100net.git

Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ 

一定要先手工建个文件夹。否则会出错。

C:\Users\Administrator\.ssh

将该文件夹下的pub文件打开,复制到。

发布

复制代码
Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ git push -u origin master
fatal: unable to access 'https://github.com/18053923230/pe100net.git/': SSL certificate problem: unable to get local issuer certificate

Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ git status
On branch master
nothing to commit, working tree clean

Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ git remote -v
origin  https://github.com/18053923230/pe100net.git (fetch)
origin  https://github.com/18053923230/pe100net.git (push)

Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ git remote set-url origin [email protected]:18053923230/pe100net.git

Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ ssh -T [email protected]
ssh: connect to host github.com port 22: Connection refused

Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ ssh -T [email protected]
The authenticity of host '[ssh.github.com]:443 ([20.205.243.160]:443)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? y
Please type 'yes', 'no' or the fingerprint: yes
Warning: Permanently added '[ssh.github.com]:443' (ED25519) to the list of known hosts.
Enter passphrase for key '/c/Users/Administrator/.ssh/id_ed25519': 
Enter passphrase for key '/c/Users/Administrator/.ssh/id_ed25519': 
Hi 18053923230! You've successfully authenticated, but GitHub does not provide shell access.

效果:

7,打开 vercel,登录。

根据实际,修改下面的。

失败了文件夹不存在。

重来。

复制代码
Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ git remote -v
origin  [email protected]:18053923230/pe100net.git (fetch)
origin  [email protected]:18053923230/pe100net.git (push)

Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ git push origin master
Enter passphrase for key '/c/Users/Administrator/.ssh/id_ed25519': 
Enumerating objects: 16, done.
Counting objects: 100% (16/16), done.
Delta compression using up to 8 threads
Compressing objects: 100% (14/14), done.
Writing objects: 100% (14/14), 439.06 KiB | 1.69 MiB/s, done.
Total 14 (delta 3), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (3/3), completed with 2 local objects.
To github.com:18053923230/pe100net.git
   062a60f..3e75067  master -> master

好了,有了一个 dist目录

再试。

成功

查看

结果测试

8.添加域名

我在cloudflare上买了一个域名

如下错误提示。需要修正

进入域名注册

com后面有一个.别忘了。

回到vercel,

输入网址100fei.com调试一下。

到目前为止,已经可以正常访问 了。几分钟就好。

9.用户数据分析,

https://clarity.microsoft.com/

回到layouts/MainLayout.jsx 里定义一段脚本:

复制代码
<script id='clarity-script' strategy='afterInteractive'>
        {

          
        }
      </script>

回到clarity

复制代码
Administrator@User-2025SOLYHK MINGW64 /d/gitee/pe100net (master)
$ git push origin master
Enter passphrase for key '/c/Users/Administrator/.ssh/id_ed25519': 
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 772 bytes | 772.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0)

更新一下。

本地打开网址,测试一下。

看来还有一很多的设置。一个个的来。

按顺序完成即可。

图片不再补充了。以上为全过程 。然后就可以。

相关推荐
JarvanMo24 分钟前
借助FlutterFire CLI实现Flutter与Firebase的多环境配置
前端·flutter
Jedi Hongbin37 分钟前
echarts自定义图表--仪表盘
前端·javascript·echarts
凯哥197042 分钟前
Sciter.js指南 - 桌面GUI开发时使用第三方模块
前端
边洛洛42 分钟前
对Electron打包的exe文件进行反解析
前端·javascript·electron
财神爷亲闺女42 分钟前
js 实现pc端鼠标横向拖动滚动
前端
用户20311966009643 分钟前
sheet在SwiftUI中的基本用法
前端
晴殇i44 分钟前
一行代码搞定防抖节流:JavaScript新特性解析
前端·javascript
啊花是条龙1 小时前
使用 Axios 和 AbortController 实现请求控制和取消
react.js·typescript