chore(branding): 更新登录与首页标题资源及部署配置
引入新的 logo-title 资源并替换登录页与首页左上角标题展示,统一相关样式细节;同时补充 Docker 与 Gitea 部署配置,便于服务器端自动化构建发布。 Made-with: Cursor
This commit is contained in:
10
.dockerignore
Normal file
10
.dockerignore
Normal file
@@ -0,0 +1,10 @@
|
||||
.git
|
||||
.gitignore
|
||||
node_modules
|
||||
dist
|
||||
.idea
|
||||
.vscode
|
||||
.cursor
|
||||
*.log
|
||||
Dockerfile*
|
||||
docker-compose*.yml
|
||||
43
.gitea/workflows/deploy.yml
Normal file
43
.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
name: Deploy To Server
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, master]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: deploy-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Deploy over SSH
|
||||
env:
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
|
||||
DEPLOY_SSH_KNOWN_HOSTS: ${{ secrets.DEPLOY_SSH_KNOWN_HOSTS }}
|
||||
DEPLOY_WORKDIR: ${{ secrets.DEPLOY_WORKDIR }}
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
printf '%s\n' "$DEPLOY_SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
printf '%s\n' "$DEPLOY_SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
|
||||
chmod 644 ~/.ssh/known_hosts
|
||||
|
||||
SSH_PORT="${DEPLOY_PORT:-22}"
|
||||
REMOTE_DIR="${DEPLOY_WORKDIR:-/opt/chat-one-web}"
|
||||
|
||||
ssh -p "$SSH_PORT" "$DEPLOY_USER@$DEPLOY_HOST" <<EOF
|
||||
set -eu
|
||||
cd "$REMOTE_DIR"
|
||||
git pull --ff-only
|
||||
docker compose up -d --build
|
||||
docker image prune -f
|
||||
EOF
|
||||
24
Dockerfile
Normal file
24
Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
|
||||
# 先复制依赖清单,利用 Docker layer cache
|
||||
COPY package.json yarn.lock ./
|
||||
RUN yarn install --frozen-lockfile
|
||||
|
||||
# 再复制源码并构建
|
||||
COPY . .
|
||||
RUN yarn build
|
||||
|
||||
FROM nginx:1.27-alpine AS runner
|
||||
WORKDIR /usr/share/nginx/html
|
||||
|
||||
# 覆盖默认站点配置,启用 SPA 回退与缓存策略
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# 仅拷贝构建产物,减小镜像体积
|
||||
COPY --from=builder /app/dist ./
|
||||
|
||||
EXPOSE 80
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
12
docker-compose.yml
Normal file
12
docker-compose.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
chat-one-web:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: chat-one-web:latest
|
||||
container_name: chat-one-web
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
BIN
src/assets/logo-title.png
Normal file
BIN
src/assets/logo-title.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
@@ -12,7 +12,6 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
theme={{
|
||||
algorithm: theme.defaultAlgorithm,
|
||||
token: {
|
||||
colorPrimary: "#4A90E2",
|
||||
colorBgBase: "#F7F7F8",
|
||||
colorBgContainer: "#FFFFFF",
|
||||
colorBorder: "#E9E9EB",
|
||||
|
||||
@@ -39,6 +39,7 @@ import {
|
||||
import type { MenuProps } from "antd";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import logoSrc from "../assets/logo.png";
|
||||
import logoTitleSrc from "../assets/logo-title.png";
|
||||
import { ACCESS_TOKEN_KEY, SessionExpiredError, USER_KEY, logout } from "../api/auth";
|
||||
import {
|
||||
createChatSession,
|
||||
@@ -99,6 +100,7 @@ const DEEP_THINK_STORAGE_KEY = "chatone-deep-think-enabled";
|
||||
const SMART_SEARCH_STORAGE_KEY = "chatone-smart-search-enabled";
|
||||
const SELECTED_MODEL_STORAGE_KEY = "chatone-selected-model";
|
||||
const LOGO_SRC = logoSrc;
|
||||
const TITLE_SRC = logoTitleSrc;
|
||||
|
||||
/** 展示名与请求 model 字段;需与后端实际支持的模型 id 一致 */
|
||||
const DEFAULT_QWEN_MODEL = "qwen3.6-plus";
|
||||
@@ -745,9 +747,12 @@ export default function HomePage() {
|
||||
decoding="async"
|
||||
/>
|
||||
{!collapsed && (
|
||||
<Typography.Title level={5} className="!m-0 !truncate !text-[15px] !font-semibold">
|
||||
ChatOne
|
||||
</Typography.Title>
|
||||
<img
|
||||
src={TITLE_SRC}
|
||||
alt="chatone"
|
||||
className="h-7 w-auto max-w-[170px] object-contain object-left"
|
||||
decoding="async"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{sidebarContent}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Button, Input, Typography, message } from "antd";
|
||||
import { Button, Input, message } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import logoSrc from "../assets/logo.png";
|
||||
import logoTitleSrc from "../assets/logo-title.png";
|
||||
import {
|
||||
ACCESS_TOKEN_KEY,
|
||||
persistTokens,
|
||||
@@ -14,6 +15,7 @@ import { tw } from "../utils/tw";
|
||||
/** 发送验证码成功后,按钮冷却秒数 */
|
||||
const SMS_RESEND_COOLDOWN_SEC = 60;
|
||||
const LOGO_SRC = logoSrc;
|
||||
const LOGIN_TITLE_SRC = logoTitleSrc;
|
||||
|
||||
/** 短信验证码登录页:校验本地 token、发送验证码、提交登录 */
|
||||
export default function LoginPage() {
|
||||
@@ -127,18 +129,19 @@ export default function LoginPage() {
|
||||
>
|
||||
{contextHolder}
|
||||
<section className="w-[325px] -translate-y-6">
|
||||
<div className="mb-7 flex items-center justify-center gap-2">
|
||||
<div className="mb-7 flex items-center justify-center">
|
||||
<img
|
||||
src={LOGO_SRC}
|
||||
alt="ChatOne Logo"
|
||||
width={28}
|
||||
height={28}
|
||||
className="h-7 w-7 object-contain"
|
||||
className="h-10 w-10 shrink-0 object-contain"
|
||||
decoding="async"
|
||||
/>
|
||||
<img
|
||||
src={LOGIN_TITLE_SRC}
|
||||
alt="chatone"
|
||||
className="h-auto w-[150px] object-contain object-left"
|
||||
decoding="async"
|
||||
/>
|
||||
<Typography.Title level={3} className="mb-0! leading-none text-[#355ad9]">
|
||||
ChatOne
|
||||
</Typography.Title>
|
||||
</div>
|
||||
|
||||
<div className="space-y-5">
|
||||
@@ -201,7 +204,7 @@ export default function LoginPage() {
|
||||
onClick={() => {
|
||||
void onLogin();
|
||||
}}
|
||||
className="mt-1 h-[42px] rounded-full border-0 bg-[#3b5ff7]"
|
||||
className="mt-1 h-[42px] rounded-full border-0"
|
||||
>
|
||||
登录
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user