qwe
This commit is contained in:
61
.gitea/workflows/docker-build-deploy.yml
Normal file
61
.gitea/workflows/docker-build-deploy.yml
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
name: Docker Build and Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "main" ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: crpi-fvhgrxlptowy5yb9.cn-hongkong.personal.cr.aliyuncs.com # 请替换为您的镜像仓库地址
|
||||||
|
IMAGE_NAME: agent
|
||||||
|
IMAGE_TAG: ${{ github.sha }}
|
||||||
|
NAMESPACE: aditorpublic
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: worker0
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: 声明环境变量
|
||||||
|
run: |
|
||||||
|
echo "REGISTRY=crpi-fvhgrxlptowy5yb9.cn-hongkong.personal.cr.aliyuncs.com" >> $GITHUB_ENV
|
||||||
|
echo "IMAGE_NAME=plug" >> $GITHUB_ENV
|
||||||
|
echo "IMAGE_TAG=${{ github.sha }}" >> $GITHUB_ENV
|
||||||
|
# echo "NAMESPACE=dianfen" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
run: |
|
||||||
|
docker login -u dianfenkeji -p 13324052902! ${{ env.REGISTRY }}
|
||||||
|
echo "docker build -t ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} ."
|
||||||
|
docker build -t ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} .
|
||||||
|
docker push ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
|
||||||
|
|
||||||
|
deploy-hk:
|
||||||
|
needs: build-and-push
|
||||||
|
runs-on: hs
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# - name: 声明环境变量
|
||||||
|
# run: |
|
||||||
|
# echo "REGISTRY=crpi-fvhgrxlptowy5yb9.cn-hongkong.personal.cr.aliyuncs.com" >> $GITHUB_ENV
|
||||||
|
# echo "IMAGE_NAME=plug" >> $GITHUB_ENV
|
||||||
|
# echo "IMAGE_TAG=${{ github.sha }}" >> $GITHUB_ENV
|
||||||
|
# echo "NAMESPACE=dianfen" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Create .env file
|
||||||
|
run: |
|
||||||
|
echo "IMAGE_TAG=${{ github.sha }}" > .env
|
||||||
|
echo "REGISTRY=${{ env.REGISTRY }}" >> .env
|
||||||
|
echo "IMAGE_NAME=${{ env.IMAGE_NAME }}" >> .env
|
||||||
|
|
||||||
|
- name: Deploy
|
||||||
|
run: |
|
||||||
|
# 登录到镜像仓库
|
||||||
|
docker pull ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
|
||||||
|
docker run -d -p 3000:3000 --restart=always --name=agent ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
|
||||||
32
Dockerfile
32
Dockerfile
@ -6,6 +6,11 @@ WORKDIR /app
|
|||||||
|
|
||||||
# 配置npm使用淘宝镜像源(解决国内网络问题)
|
# 配置npm使用淘宝镜像源(解决国内网络问题)
|
||||||
RUN npm config set registry https://registry.npmmirror.com
|
RUN npm config set registry https://registry.npmmirror.com
|
||||||
|
RUN npm config set disturl https://npm.taobao.org/dist
|
||||||
|
RUN npm config set electron_mirror https://npm.taobao.org/mirrors/electron/
|
||||||
|
RUN npm config set puppeteer_download_host https://npm.taobao.org/mirrors
|
||||||
|
RUN npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
|
||||||
|
RUN npm config set phantomjs_cdnurl https://npm.taobao.org/mirrors/phantomjs/
|
||||||
|
|
||||||
# 复制package.json和package-lock.json
|
# 复制package.json和package-lock.json
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
@ -16,28 +21,23 @@ RUN npm install
|
|||||||
# 复制项目文件
|
# 复制项目文件
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# 构建项目
|
# 构建应用
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# 生产阶段 - 使用Node镜像运行Next.js应用
|
# 生产阶段 - 使用阿里云Nginx镜像
|
||||||
FROM node:20-alpine
|
FROM nginx:alpine
|
||||||
|
|
||||||
# 设置工作目录
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# 配置Alpine使用国内镜像源
|
# 配置Alpine使用国内镜像源
|
||||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||||
|
|
||||||
# 复制构建产物
|
# 复制构建产物到nginx的html目录
|
||||||
COPY --from=builder /app/.next ./.next
|
COPY --from=builder /app/out /usr/share/nginx/html
|
||||||
COPY --from=builder /app/public ./public
|
|
||||||
COPY --from=builder /app/package*.json ./
|
|
||||||
|
|
||||||
# 安装生产依赖
|
# 复制自定义nginx配置(如果需要)
|
||||||
RUN npm install --production
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
# 暴露Next.js默认端口
|
# 暴露80端口
|
||||||
EXPOSE 3000
|
EXPOSE 80
|
||||||
|
|
||||||
# 启动Next.js生产服务器
|
# 启动nginx
|
||||||
CMD ["npm", "start"]
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
@ -1,9 +1,5 @@
|
|||||||
import * as React from 'react';
|
import React, { useRef } from 'react';
|
||||||
const { useRef } = React;
|
import { Box, Paper, Typography, Avatar, useMediaQuery, useTheme } from '@mui/material';
|
||||||
import { Box, Paper, Typography, Avatar, useMediaQuery, useTheme, Theme } from '@mui/material';
|
|
||||||
import ReactMarkdown from 'react-markdown';
|
|
||||||
import rehypeRaw from 'rehype-raw';
|
|
||||||
import remarkGfm from 'remark-gfm';
|
|
||||||
import type { Message as MessageType } from '../types/types';
|
import type { Message as MessageType } from '../types/types';
|
||||||
|
|
||||||
interface MessageProps {
|
interface MessageProps {
|
||||||
@ -24,6 +20,7 @@ const Message: React.FC<MessageProps> = ({ message, isLast = false }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
key={message.id}
|
||||||
display="flex"
|
display="flex"
|
||||||
marginBottom={2}
|
marginBottom={2}
|
||||||
justifyContent={isUser ? "flex-end" : "flex-start"}
|
justifyContent={isUser ? "flex-end" : "flex-start"}
|
||||||
@ -71,60 +68,12 @@ const Message: React.FC<MessageProps> = ({ message, isLast = false }) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ lineHeight: 1.6 }}>
|
<div style={{ lineHeight: 1.6 }}>
|
||||||
{isUser ? (
|
{message.content.split('\n').map((line, index) => (
|
||||||
// 用户消息仍然使用普通文本展示
|
<React.Fragment key={index}>
|
||||||
message.content.split('\n').map((line: string, index: number) => (
|
{line}
|
||||||
<React.Fragment key={index}>
|
{index < message.content.split('\n').length - 1 && <br />}
|
||||||
{line}
|
</React.Fragment>
|
||||||
{index < message.content.split('\n').length - 1 && <br />}
|
))}
|
||||||
</React.Fragment>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
// 大模型回复使用markdown格式展示
|
|
||||||
<ReactMarkdown
|
|
||||||
rehypePlugins={[rehypeRaw]}
|
|
||||||
remarkPlugins={[remarkGfm]}
|
|
||||||
components={{
|
|
||||||
// 自定义标题样式
|
|
||||||
h1: (props: React.ComponentProps<'h1'>) => (
|
|
||||||
<h1 style={{ fontSize: '1.4rem', fontWeight: 'bold', margin: '12px 0 8px 0' }} {...props} />
|
|
||||||
),
|
|
||||||
h2: (props: React.ComponentProps<'h2'>) => (
|
|
||||||
<h2 style={{ fontSize: '1.2rem', fontWeight: 'bold', margin: '10px 0 6px 0' }} {...props} />
|
|
||||||
),
|
|
||||||
h3: (props: React.ComponentProps<'h3'>) => (
|
|
||||||
<h3 style={{ fontSize: '1.1rem', fontWeight: 'bold', margin: '8px 0 4px 0' }} {...props} />
|
|
||||||
),
|
|
||||||
// 自定义列表样式
|
|
||||||
ul: (props: React.ComponentProps<'ul'>) => (
|
|
||||||
<ul style={{ paddingLeft: '20px', margin: '6px 0' }} {...props} />
|
|
||||||
),
|
|
||||||
ol: (props: React.ComponentProps<'ol'>) => (
|
|
||||||
<ol style={{ paddingLeft: '20px', margin: '6px 0' }} {...props} />
|
|
||||||
),
|
|
||||||
li: (props: React.ComponentProps<'li'>) => (
|
|
||||||
<li style={{ margin: '4px 0' }} {...props} />
|
|
||||||
),
|
|
||||||
// 自定义代码块样式
|
|
||||||
code: (props: React.ComponentProps<'code'>) => (
|
|
||||||
<code style={{ backgroundColor: '#f5f5f5', padding: '2px 4px', borderRadius: '3px', fontFamily: 'monospace' }} {...props} />
|
|
||||||
),
|
|
||||||
pre: (props: React.ComponentProps<'pre'>) => (
|
|
||||||
<pre style={{ backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '6px', overflowX: 'auto', fontFamily: 'monospace', fontSize: '0.9rem' }} {...props} />
|
|
||||||
),
|
|
||||||
// 自定义引用样式
|
|
||||||
blockquote: (props: React.ComponentProps<'blockquote'>) => (
|
|
||||||
<blockquote style={{ borderLeft: '4px solid #ccc', margin: '10px 0', paddingLeft: '12px', color: '#666' }} {...props} />
|
|
||||||
),
|
|
||||||
// 自定义链接样式
|
|
||||||
a: (props: React.ComponentProps<'a'>) => (
|
|
||||||
<a style={{ color: theme.palette.primary.main, textDecoration: 'underline' }} {...props} />
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{message.content}
|
|
||||||
</ReactMarkdown>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Typography
|
<Typography
|
||||||
|
|||||||
@ -32,7 +32,7 @@ const welcomeMessage: MessageType = {
|
|||||||
|
|
||||||
const ChatInterface: React.FC = () => {
|
const ChatInterface: React.FC = () => {
|
||||||
// 状态管理
|
// 状态管理
|
||||||
const [messages, setMessages] = useState<MessageType[]>([welcomeMessage]);
|
const [messages, setMessages] = useState<MessageType[]>([]);
|
||||||
const [input, setInput] = useState('');
|
const [input, setInput] = useState('');
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [isConfigured, setIsConfigured] = useState(false);
|
const [isConfigured, setIsConfigured] = useState(false);
|
||||||
|
|||||||
23
nginx.conf
23
nginx.conf
@ -2,37 +2,18 @@ server {
|
|||||||
listen 80;
|
listen 80;
|
||||||
server_name localhost;
|
server_name localhost;
|
||||||
|
|
||||||
# Next.js项目的根目录
|
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
# Next.js路由配置
|
# 支持Next.js的路由
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
# 处理Next.js静态资源
|
|
||||||
location /_next/ {
|
|
||||||
alias /usr/share/nginx/html/_next/;
|
|
||||||
expires 30d;
|
|
||||||
access_log off;
|
|
||||||
}
|
|
||||||
|
|
||||||
# 处理API路由
|
|
||||||
location /api/ {
|
|
||||||
proxy_pass http://localhost:3000;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection 'upgrade';
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_cache_bypass $http_upgrade;
|
|
||||||
}
|
|
||||||
|
|
||||||
# 静态文件缓存
|
# 静态文件缓存
|
||||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
|
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
|
||||||
expires 30d;
|
expires 30d;
|
||||||
add_header Cache-Control "public, no-transform";
|
add_header Cache-Control "public, no-transform";
|
||||||
access_log off;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# 错误页面
|
# 错误页面
|
||||||
|
|||||||
1660
package-lock.json
generated
1660
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -16,10 +16,7 @@
|
|||||||
"@mui/material": "^7.3.4",
|
"@mui/material": "^7.3.4",
|
||||||
"next": "15.5.5",
|
"next": "15.5.5",
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-dom": "19.1.0",
|
"react-dom": "19.1.0"
|
||||||
"react-markdown": "^10.1.0",
|
|
||||||
"rehype-raw": "^7.0.0",
|
|
||||||
"remark-gfm": "^4.0.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3",
|
"@eslint/eslintrc": "^3",
|
||||||
|
|||||||
Reference in New Issue
Block a user