diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index c1d70e8..6c4928f 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -1,9 +1,4 @@ -# 公共工作流仓库:platform/workflow -# Gitea 要求 uses 格式:{owner}/{repo}/.gitea/workflows/{文件名}@{ref} -# 公共仓内请将工作流放在:.gitea/workflows/web-spa-deploy.yml(若当前仅在 ci/ 下,请复制或移动到该路径) -# -# 本仓库「工作流 → 变量」:DEPLOY_PATH、DEPLOY_HOST、DEPLOY_USER -# 本仓库「工作流 → 密钥」:SSH_PRIVATE_KEY(secrets: inherit) +# 业务 CI:触发公共工作流; name: CI @@ -21,7 +16,7 @@ jobs: build: uses: platform/workflow/.gitea/workflows/web-spa-deploy.yml@main with: - node_version: "22.14.0" - yarn_version: "1.22.22" - project_dir: "chat-one-web" - secrets: inherit + node_version: "22.14.0" # Node 完整 semver + yarn_version: "1.22.22" # Yarn 1 + project_dir: "chat-one-web" # 远端目录 = $DEPLOY_PATH/本字段 + secrets: inherit # 传入 SSH_PRIVATE_KEY diff --git a/src/index.css b/src/index.css index ba0b7be..203df11 100644 --- a/src/index.css +++ b/src/index.css @@ -6,3 +6,16 @@ body, margin: 0; min-height: 100%; } + +/* DeepSeek 风格近似色 */ +:root { + --ds-bg-main: #ffffff; + --ds-bg-sider: #f7f7f8; + --ds-border: #ececec; + --ds-text-secondary: #8b8b8b; + --ds-user-bubble: #e8f3ff; + --ds-user-border: #cce7ff; + --ds-active-item: #e3f2fd; + --ds-send: #4dabf7; + --ds-send-hover: #339af0; +} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 4d669d6..34e6e12 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,62 +1,62 @@ import { useEffect, useMemo, useState } from "react"; -import { Button, Drawer, Input, Layout, Space, Typography } from "antd"; import { + ArrowUpOutlined, MenuFoldOutlined, MenuUnfoldOutlined, MessageOutlined, + PaperClipOutlined, + PlusOutlined, + SearchOutlined, SettingOutlined, + ThunderboltOutlined, UserOutlined, } from "@ant-design/icons"; +import { Button, Collapse, Drawer, Input, Layout, Typography } from "antd"; const { Header, Sider, Content } = Layout; const MOBILE_WIDTH = 750; const mockMessages = [ - { role: "assistant", content: "你好,我是 ChatOne 助手,有什么可以帮你?" }, - { role: "user", content: "请帮我总结今天的工作内容。" }, - { role: "assistant", content: "当然可以,请先告诉我今天完成了哪些任务。" }, + { role: "assistant" as const, content: "你好,我是 ChatOne 助手,有什么可以帮你?" }, + { role: "user" as const, content: "请帮我总结今天的工作内容。" }, + { + role: "assistant" as const, + content: "当然可以,请先告诉我今天完成了哪些任务。", + thinking: "正在理解用户意图并检索相关知识…", + }, ]; export default function HomePage() { - // 桌面端侧边栏折叠状态(移动端不使用该状态) const [collapsed, setCollapsed] = useState(false); - // 移动端抽屉侧边栏显示状态 const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false); - // 当前视口宽度(用于调试响应式是否生效) const [viewportWidth, setViewportWidth] = useState(0); - // 是否为移动端(小于 750px) const [isMobile, setIsMobile] = useState(false); const [inputValue, setInputValue] = useState(""); + const [deepThink, setDeepThink] = useState(false); + const [smartSearch, setSmartSearch] = useState(false); - const menuItems = useMemo( + const historyGroups = useMemo( () => [ - { icon: , label: "新建会话" }, - { icon: , label: "我的对话" }, - { icon: , label: "设置" }, + { title: "30 天内", keys: ["前端 CI 工具对比", "Nginx SPA 配置"] }, + { title: "2025-12", keys: ["Gitea Actions 入门"] }, ], [], ); useEffect(() => { const updateIsMobile = () => { - // 兼容不同浏览器/缩放场景下的视口宽度读取 - const viewportWidth = Math.min( + const w = Math.min( window.innerWidth, document.documentElement.clientWidth || window.innerWidth, ); - setViewportWidth(viewportWidth); - const mobile = viewportWidth < MOBILE_WIDTH; + setViewportWidth(w); + const mobile = w < MOBILE_WIDTH; setIsMobile(mobile); - if (!mobile) { - // 切回桌面端时关闭移动抽屉,避免状态残留 - setMobileSidebarOpen(false); - } + if (!mobile) setMobileSidebarOpen(false); }; - updateIsMobile(); window.addEventListener("resize", updateIsMobile); window.addEventListener("orientationchange", updateIsMobile); - return () => { window.removeEventListener("resize", updateIsMobile); window.removeEventListener("orientationchange", updateIsMobile); @@ -64,106 +64,241 @@ export default function HomePage() { }, []); const sidebarContent = ( - <> - {/* 侧边栏头部:桌面折叠时显示缩写,其他情况显示完整标题 */} -
- - {collapsed && !isMobile ? "CO" : "ChatOne"} - +
+
+
-
- - {menuItems.map((item) => ( - - ))} - + +
+ {historyGroups.map((group) => ( +
+ + {group.title} + + {group.keys.map((key) => ( + + ))} +
+ ))}
- + +
+ +
+
+ +
+ {(!collapsed || isMobile) && ( + 用户 + )} +
+
+
); return ( - - {/* 桌面端固定侧边栏;移动端改为 Drawer 抽屉 */} + {!isMobile && ( - + +
+ + {collapsed ? "CO" : "ChatOne"} + +
{sidebarContent}
)} - -
-
+ + 快速模式 + - - {/* 聊天窗口:消息列表 + 底部输入区 */} -
-
- - 聊天窗口 - + +
+
+
+ {mockMessages.map((item, index) => ( +
+
+ {item.role === "assistant" && item.thinking && ( + + + 已思考(用时约 2 秒) + + ), + children: ( + + {item.thinking} + + ), + }, + ]} + /> + )} + {item.role === "assistant" && ( +
+ {item.content} +
+ )} + {item.role === "user" && item.content} +
+
+ ))} +
-
- {mockMessages.map((item, index) => ( -
-
- {item.content} +
+
+
+ setInputValue(e.target.value)} + placeholder="给 ChatOne 发送消息" + variant="borderless" + autoSize={{ minRows: 1, maxRows: 6 }} + className="!px-1 !text-[15px] placeholder:text-neutral-400" + /> +
+
+ + +
+
+
- ))} -
- -
- - setInputValue(e.target.value)} - placeholder="输入消息..." - /> - - + {import.meta.env.DEV && ( + + W:{viewportWidth}px · {isMobile ? "mobile" : "desktop"} + + )} +
@@ -175,7 +310,8 @@ export default function HomePage() { closable onClose={() => setMobileSidebarOpen(false)} open={isMobile && mobileSidebarOpen} - size={260} + width={280} + styles={{ body: { padding: 0, background: "var(--ds-bg-sider)" } }} > {sidebarContent}