Qwen3 网页开发:类似微博!

初始提示词:

参考新浪微博开发一个微博网站

改进提示词:

这个页面设计的挺好的。但是好像少一些东西。比如热榜啊,关注推荐啊等。请完善一下,保持风格,重构布局和内容

右上方 “首页” 前面添加一个 home 的图标,”热门“前面添加一个火热的图片,“我的”改成用户头像,这些图标和文字要对齐。点击用户头像之后,还有相关的下拉菜单。比如设置,我的微博,我的收藏,我的点赞。热门话题添加编号。1,2,3 名编号颜色火热一些,其他淡一些。

热门前面的图标改成火焰相关的图标。 用户 1 发布的内容,加一些表情包。发布按钮前面添加一个表情包选择图标。

右上方 首页,热门,我的应该是一个整体,一个选中的状态下,其他就都是没选中的状态。另外我的的弹出菜单。当点击其他所以空白区域的时候应该收起来。

最终效果:

在线预览:

打开链接

最终代码:

import React, { useState, useEffect, useRef } from "react";

export default function App() {
  const [activeTab, setActiveTab] = useState("home");
  const [posts, setPosts] = useState([
    {
      id: 1,
      user: "用户1",
      avatar: "https://picsum.photos/200/300?random=1 ",
      content: "这是我的第一条微博!今天心情很好🙂。",
      likes: 24,
      comments: 8,
      retweets: 5,
      time: "2小时前",
    },
    {
      id: 2,
      user: "用户2",
      avatar: "https://picsum.photos/200/300?random=2 ",
      content: "分享一个好看的风景图~",
      image: "https://picsum.photos/600/400?random=3 ",
      likes: 17,
      comments: 3,
      retweets: 2,
      time: "3小时前",
    },
    {
      id: 3,
      user: "用户3",
      avatar: "https://picsum.photos/200/300?random=3 ",
      content: "今天学习了React,感觉很有趣!",
      likes: 9,
      comments: 1,
      retweets: 0,
      time: "5小时前",
    },
  ]);
  const [newPost, setNewPost] = useState("");
  const [showScrollTop, setShowScrollTop] = useState(false);
  const [userMenuOpen, setUserMenuOpen] = useState(false);

  // 用户信息
  const currentUser = {
    name: "当前用户",
    avatar: "https://picsum.photos/200/300?random=4 ",
  };

  const menuRef = useRef(null); // 用于检测点击是否发生在菜单之外

  // 模拟滚动事件检测
  useEffect(() => {
    const handleScroll = () => {
      if (window.scrollY > 300) {
        setShowScrollTop(true);
      } else {
        setShowScrollTop(false);
      }
    };

    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  }, []);

  // 点击外部区域关闭下拉菜单
  useEffect(() => {
    const handleClickOutside = (event) => {
      if (menuRef.current && !menuRef.current.contains(event.target)) {
        setUserMenuOpen(false);
      }
    };

    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  const handlePost = () => {
    if (newPost.trim()) {
      const post = {
        id: Date.now(),
        user: currentUser.name,
        avatar: currentUser.avatar,
        content: newPost,
        likes: 0,
        comments: 0,
        retweets: 0,
        time: "刚刚",
      };
      setPosts([post, ...posts]);
      setNewPost("");
    }
  };

  const toggleLike = (id) => {
    setPosts(
      posts.map((post) =>
        post.id === id ? { ...post, likes: post.likes + 1 } : post
      )
    );
  };

  // 热门话题数据
  const hotTopics = [
    { title: "#春天来了#", views: "1.2亿" },
    { title: "#AI改变生活#", views: "9800万" },
    { title: "#健康饮食指南#", views: "6700万" },
    { title: "#明星穿搭趋势#", views: "5400万" },
    { title: "#世界杯预选赛#", views: "4300万" },
  ];

  // 推荐关注用户
  const suggestedUsers = [
    { name: "科技达人", avatar: "https://picsum.photos/200/300?random=5 " },
    { name: "旅行日记", avatar: "https://picsum.photos/200/300?random=6 " },
    { name: "美食博主", avatar: "https://picsum.photos/200/300?random=7 " },
  ];

  return (
    <div className="min-h-screen bg-gray-100 text-gray-800">
      {/* 头部导航 */}
      <header className="bg-white shadow-md fixed w-full z-10">
        <div className="container mx-auto px-4 py-3 flex justify-between items-center">
          <h1 className="text-2xl font-bold text-red-600">Weibo</h1>
          <nav className="hidden md:flex space-x-6 items-center">
            <button
              onClick={() => {
                setActiveTab("home");
                setUserMenuOpen(false);
              }}
              className={`flex items-center gap-1 pb-1 border-b-2 ${
                activeTab === "home"
                  ? "border-red-500 text-red-500"
                  : "border-transparent hover:border-gray-300"
              }`}
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                width="18"
                height="18"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              >
                <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V9z"></path>
                <polyline points="9 22 9 12 15 12 15 22"></polyline>
              </svg>
              <span>首页</span>
            </button>

            <button
              onClick={() => {
                setActiveTab("hot");
                setUserMenuOpen(false);
              }}
              className={`flex items-center gap-1 pb-1 border-b-2 ${
                activeTab === "hot"
                  ? "border-red-500 text-red-500"
                  : "border-transparent hover:border-gray-300"
              }`}
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                width="18"
                height="18"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              >
                <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"></path>
              </svg>
              <span>热门</span>
            </button>

            <div className="relative" ref={menuRef}>
              <button
                onClick={() => {
                  setActiveTab("profile");
                  setUserMenuOpen(!userMenuOpen);
                }}
                className={`flex items-center gap-1 pb-1 border-b-2 ${
                  activeTab === "profile"
                    ? "border-red-500 text-red-500"
                    : "border-transparent hover:border-gray-300"
                }`}
              >
                <img
                  src={currentUser.avatar}
                  alt="头像"
                  className="w-6 h-6 rounded-full object-cover"
                />
                <span>我的</span>
              </button>

              {/* 下拉菜单 */}
              {userMenuOpen && (
                <div className="absolute right-0 mt-2 w-40 bg-white rounded shadow-lg z-20">
                  <ul className="py-1 text-sm text-gray-700">
                    <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer">
                      设置
                    </li>
                    <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer">
                      我的微博
                    </li>
                    <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer">
                      我的收藏
                    </li>
                    <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer">
                      我的点赞
                    </li>
                  </ul>
                </div>
              )}
            </div>
          </nav>
        </div>
      </header>

      <main className="container mx-auto px-4 pt-20 pb-24 flex flex-col lg:flex-row gap-6">
        {/* 主内容区 */}
        <section className="lg:w-2/3">
          {/* 发布微博表单 */}
          <div className="bg-white rounded-lg shadow p-4 mb-6">
            <textarea
              value={newPost}
              onChange={(e) => setNewPost(e.target.value)}
              placeholder="有什么新鲜事想告诉大家?"
              className="w-full p-3 border border-gray-300 rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-red-300"
              rows="3"
            />
            <div className="flex justify-between items-center mt-2">
              <button
                className="p-1 text-gray-500 hover:text-red-500 transition-colors"
                title="选择表情"
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  width="20"
                  height="20"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="2"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                >
                  <circle cx="12" cy="12" r="10"></circle>
                  <path d="M8 14s1.5 2 4 2 4-2 4-2"></path>
                  <line x1="9" y1="9" x2="9.01" y2="9"></line>
                  <line x1="15" y1="9" x2="15.01" y2="9"></line>
                </svg>
              </button>
              <button
                onClick={handlePost}
                disabled={!newPost.trim()}
                className={`flex items-center gap-1 px-4 py-2 rounded-lg font-medium transition-colors ${
                  newPost.trim()
                    ? "bg-red-500 text-white hover:bg-red-600"
                    : "bg-gray-200 text-gray-500 cursor-not-allowed"
                }`}
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  width="16"
                  height="16"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="2"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                >
                  <circle cx="12" cy="12" r="10"></circle>
                  <path d="M8 14s1.5 2 4 2 4-2 4-2"></path>
                  <line x1="9" y1="9" x2="9.01" y2="9"></line>
                  <line x1="15" y1="9" x2="15.01" y2="9"></line>
                </svg>
                <span>发布</span>
              </button>
            </div>
          </div>

          {/* 动态列表 */}
          <div className="space-y-6">
            {posts.map((post) => (
              <div
                key={post.id}
                className="bg-white rounded-lg shadow overflow-hidden transition-transform hover:scale-[1.01]"
              >
                <div className="p-4 flex">
                  <img
                    src={post.avatar}
                    alt={post.user}
                    className="w-12 h-12 rounded-full object-cover mr-3"
                  />
                  <div className="flex-1">
                    <div className="flex justify-between items-start">
                      <div>
                        <h3 className="font-semibold">{post.user}</h3>
                        <span className="text-sm text-gray-500">{post.time}</span>
                      </div>
                      <button className="text-gray-400 hover:text-gray-600">
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          width="20"
                          height="20"
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke="currentColor"
                          strokeWidth="2"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        >
                          <circle cx="12" cy="12" r="1"></circle>
                          <circle cx="19" cy="12" r="1"></circle>
                          <circle cx="5" cy="12" r="1"></circle>
                        </svg>
                      </button>
                    </div>
                    <p className="mt-2 whitespace-pre-line">{post.content}</p>
                    {post.image && (
                      <img
                        src={post.image}
                        alt="动态图片"
                        className="mt-3 rounded-lg max-h-96 w-full object-cover"
                      />
                    )}
                    <div className="mt-3 flex justify-between text-gray-500 text-sm">
                      <button
                        onClick={() => toggleLike(post.id)}
                        className="hover:text-red-500 flex items-center gap-1"
                      >
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          width="18"
                          height="18"
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke="currentColor"
                          strokeWidth="2"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        >
                          <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path>
                        </svg>
                        <span>{post.likes}</span>
                      </button>
                      <button className="hover:text-blue-500 flex items-center gap-1">
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          width="18"
                          height="18"
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke="currentColor"
                          strokeWidth="2"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        >
                          <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
                        </svg>
                        <span>{post.comments}</span>
                      </button>
                      <button className="hover:text-green-500 flex items-center gap-1">
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          width="18"
                          height="18"
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke="currentColor"
                          strokeWidth="2"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        >
                          <path d="M17 1l4 4-4 4"></path>
                          <path d="M3 11V9a4 4 0 0 1 4-4h14"></path>
                          <path d="M7 23l-4-4 4-4"></path>
                          <path d="M21 13v2a4 4 0 0 1-4 4H3"></path>
                        </svg>
                        <span>{post.retweets}</span>
                      </button>
                    </div>
                  </div>
                </div>
              </div>
            ))}
          </div>
        </section>

        {/* 右侧边栏:热榜 + 推荐关注 */}
        <aside className="lg:w-1/3 space-y-6">
          {/* 热榜模块 */}
          <div className="bg-white rounded-lg shadow p-4">
            <h2 className="text-lg font-bold mb-3">热门话题</h2>
            <ul className="space-y-2">
              {hotTopics.map((topic, index) => (
                <li
                  key={index}
                  className="flex justify-between items-center p-2 hover:bg-gray-100 rounded cursor-pointer"
                >
                  <div className="flex items-center gap-2">
                    <span
                      className={`text-xs font-bold w-5 text-center ${
                        index < 3 ? "text-red-500" : "text-gray-400"
                      }`}
                    >
                      {index + 1}
                    </span>
                    <span className="font-medium">{topic.title}</span>
                  </div>
                  <span className="text-sm text-gray-500">{topic.views}</span>
                </li>
              ))}
            </ul>
          </div>

          {/* 推荐关注 */}
          <div className="bg-white rounded-lg shadow p-4">
            <h2 className="text-lg font-bold mb-3">推荐关注</h2>
            <ul className="space-y-3">
              {suggestedUsers.map((user, index) => (
                <li key={index} className="flex items-center gap-3">
                  <img
                    src={user.avatar}
                    alt={user.name}
                    className="w-10 h-10 rounded-full object-cover"
                  />
                  <div>
                    <h4 className="font-medium">{user.name}</h4>
                    <button className="text-xs bg-red-100 text-red-600 px-2 py-1 rounded hover:bg-red-200">
                      关注
                    </button>
                  </div>
                </li>
              ))}
            </ul>
          </div>
        </aside>
      </main>

      {/* 底部导航(移动端) */}
      <nav className="md:hidden fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 flex justify-around py-3">
        <button
          onClick={() => {
            setActiveTab("home");
            setUserMenuOpen(false);
          }}
          className={`flex flex-col items-center ${
            activeTab === "home" ? "text-red-500" : "text-gray-500"
          }`}
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="20"
            height="20"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
          >
            <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V9z"></path>
            <polyline points="9 22 9 12 15 12 15 22"></polyline>
          </svg>
          <span className="text-xs mt-1">首页</span>
        </button>
        <button
          onClick={() => {
            setActiveTab("hot");
            setUserMenuOpen(false);
          }}
          className={`flex flex-col items-center ${
            activeTab === "hot" ? "text-red-500" : "text-gray-500"
          }`}
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="18"
            height="18"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
          >
            <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"></path>
          </svg>
          <span className="text-xs mt-1">热门</span>
        </button>
        <button
          onClick={() => {
            setActiveTab("profile");
            setUserMenuOpen(!userMenuOpen);
          }}
          className={`flex flex-col items-center ${
            activeTab === "profile" ? "text-red-500" : "text-gray-500"
          }`}
        >
          <img
            src={currentUser.avatar}
            alt="头像"
            className="w-6 h-6 rounded-full object-cover"
          />
          <span className="text-xs mt-1">我的</span>
        </button>
      </nav>

      {/* 返回顶部按钮 */}
      {showScrollTop && (
        <button
          onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })}
          className="fixed bottom-20 right-4 bg-red-500 text-white p-3 rounded-full shadow-lg hover:bg-red-600 transition-colors"
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="20"
            height="20"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
          >
            <polyline points="18 15 12 9 6 15"></polyline>
          </svg>
        </button>
      )}
    </div>
  );
}

 

小尾巴==========================
公众号:托尼不是塔克
交流群
知识星球
==============================

 



发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注