mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 07:03:53 +08:00
Merge branch 'main' of https://github.com/xinnan-tech/xiaozhi-esp32-server
This commit is contained in:
+36
-10
@@ -1,12 +1,31 @@
|
||||
# 第一阶段:构建依赖
|
||||
# 第一阶段:前端构建
|
||||
FROM node:18 as frontend-builder
|
||||
|
||||
WORKDIR /app/ZhiKongTaiWeb
|
||||
|
||||
COPY ZhiKongTaiWeb/package*.json ./
|
||||
|
||||
RUN npm install
|
||||
|
||||
COPY ZhiKongTaiWeb .
|
||||
|
||||
RUN npm run build
|
||||
|
||||
# 第二阶段:构建Python依赖
|
||||
FROM python:3.10-slim as builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY requirements.txt .
|
||||
|
||||
# 安装构建依赖
|
||||
RUN apt-get update && \
|
||||
# 使用清华源加速apt安装
|
||||
RUN rm -rf /etc/apt/sources.list.d/* && \
|
||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-backports main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
apt-get clean && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
libopus-dev \
|
||||
@@ -16,24 +35,31 @@ RUN apt-get update && \
|
||||
# 安装Python依赖到虚拟环境
|
||||
RUN python -m venv /opt/venv
|
||||
ENV PATH="/opt/venv/bin:$PATH"
|
||||
RUN pip install --no-cache-dir -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
|
||||
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
|
||||
# 第二阶段:生产镜像
|
||||
# 第三阶段:生产镜像
|
||||
FROM python:3.10-slim
|
||||
|
||||
WORKDIR /opt/xiaozhi-esp32-server
|
||||
|
||||
# 从构建阶段复制虚拟环境
|
||||
COPY --from=builder /opt/venv /opt/venv
|
||||
|
||||
# 安装运行时依赖
|
||||
RUN apt-get update && \
|
||||
# 使用清华源加速apt安装
|
||||
RUN rm -rf /etc/apt/sources.list.d/* && \
|
||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-backports main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
apt-get clean && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
libopus0 \
|
||||
ffmpeg && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 从构建阶段复制虚拟环境和前端构建产物
|
||||
COPY --from=builder /opt/venv /opt/venv
|
||||
COPY --from=frontend-builder /app/ZhiKongTaiWeb/dist /opt/xiaozhi-esp32-server/manager/static
|
||||
|
||||
# 设置虚拟环境路径
|
||||
ENV PATH="/opt/venv/bin:$PATH"
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
VITE_API_BASE_URL=http://localhost:8002
|
||||
VITE_API_BASE_URL=''
|
||||
|
||||
@@ -1 +1 @@
|
||||
VITE_API_BASE_URL=http://localhost:8002
|
||||
VITE_API_BASE_URL='' # 空字符串表示使用当前域名和端口
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
import Login from './components/Login.vue';
|
||||
import Registration from './components/Registration.vue';
|
||||
import panel from './components/panel.vue';
|
||||
import MainPage from './components/main.vue';
|
||||
import MainPage from './components/Main.vue';
|
||||
import RoleSetting from './components/RoleSetting.vue';
|
||||
import Footer from './components/Footer.vue';
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { API_BASE_URL } from '../config/api';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -34,7 +36,7 @@
|
||||
|
||||
this.isLoading = true;
|
||||
try {
|
||||
const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/login`, {
|
||||
const response = await fetch(`${API_BASE_URL}/api/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { API_BASE_URL } from '../config/api';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -47,7 +49,7 @@ export default {
|
||||
|
||||
this.isLoading = true;
|
||||
try {
|
||||
const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/register`, {
|
||||
const response = await fetch(`${API_BASE_URL}/api/register`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
</option>
|
||||
</select>
|
||||
<div class="model-description">
|
||||
除了“qwen-turbo”,其他模型通常会增加约 1 秒的延迟。改变模型后,建议清空记忆体,以免影响体验。
|
||||
除了"qwen-turbo",其他模型通常会增加约 1 秒的延迟。改变模型后,建议清空记忆体,以免影响体验。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -109,6 +109,7 @@
|
||||
import { ref, onMounted } from 'vue';
|
||||
import NavBar from './NavBar.vue';
|
||||
import RoleTemplates from '../utils/RoleTemplates';
|
||||
import { API_BASE_URL } from '../config/api';
|
||||
|
||||
const roleTemplates = RoleTemplates.getTemplates();
|
||||
|
||||
@@ -120,7 +121,7 @@ const activeMemoryTab = ref('recent');
|
||||
const memoryContent = ref('');
|
||||
const selectedModel = ref('qianwen');
|
||||
|
||||
const baseUrl = import.meta.env.VITE_API_BASE_URL;
|
||||
const baseUrl = API_BASE_URL;
|
||||
const moduleOptions = ref({
|
||||
LLM: [],
|
||||
TTS: [],
|
||||
|
||||
@@ -41,10 +41,11 @@
|
||||
import { ref, onMounted } from 'vue';
|
||||
import NavBar from './NavBar.vue';
|
||||
import DeviceCard from './DeviceCard.vue';
|
||||
import { API_BASE_URL } from '../config/api';
|
||||
|
||||
const emit = defineEmits(['show-role', 'go-home']);
|
||||
|
||||
const baseUrl = import.meta.env.VITE_API_BASE_URL;
|
||||
const baseUrl = API_BASE_URL;
|
||||
const devices = ref([]);
|
||||
|
||||
const formatLastActivity = (timestamp) => {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// 获取当前运行环境的基础 URL
|
||||
const getBaseUrl = () => {
|
||||
// 如果是开发环境,使用环境变量中的地址
|
||||
if (import.meta.env.DEV) {
|
||||
return import.meta.env.VITE_API_BASE_URL;
|
||||
}
|
||||
|
||||
// 生产环境使用当前域名和端口
|
||||
const protocol = window.location.protocol;
|
||||
const hostname = window.location.hostname;
|
||||
const port = window.location.port;
|
||||
|
||||
return `${protocol}//${hostname}${port ? `:${port}` : ''}`;
|
||||
};
|
||||
|
||||
export const API_BASE_URL = getBaseUrl();
|
||||
@@ -3,6 +3,9 @@ from config.logger import setup_logging
|
||||
from config.settings import load_config
|
||||
from core.websocket_server import WebSocketServer
|
||||
from manager.http_server import ConfigServer
|
||||
from core.webui import WebUI
|
||||
from aiohttp import web
|
||||
from core.utils.util import get_local_ip
|
||||
|
||||
async def main():
|
||||
setup_logging() # 最先初始化日志
|
||||
@@ -21,6 +24,20 @@ async def main():
|
||||
except Exception as e:
|
||||
print(f"Failed to start HTTP server: {e}")
|
||||
|
||||
# 启动 WebUI 服务器
|
||||
webui_runner = None
|
||||
try:
|
||||
webui = WebUI()
|
||||
runner = web.AppRunner(webui.app)
|
||||
await runner.setup()
|
||||
site = web.TCPSite(runner, '0.0.0.0', 8002)
|
||||
await site.start()
|
||||
webui_runner = runner
|
||||
local_ip = get_local_ip()
|
||||
print(f"WebUI server is running at http://{local_ip}:8002")
|
||||
except Exception as e:
|
||||
print(f"Failed to start WebUI server: {e}")
|
||||
|
||||
try:
|
||||
# 等待 WebSocket 服务器运行
|
||||
await ws_task
|
||||
@@ -28,6 +45,9 @@ async def main():
|
||||
# 清理 HTTP 服务器
|
||||
if http_runner:
|
||||
await http_runner.cleanup()
|
||||
# 清理 WebUI 服务器
|
||||
if webui_runner:
|
||||
await webui_runner.cleanup()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
@@ -3,6 +3,7 @@ import sys
|
||||
import logging
|
||||
from aiohttp import web
|
||||
from aiohttp_cors import setup as cors_setup, ResourceOptions
|
||||
from core.utils.util import get_local_ip
|
||||
|
||||
# 添加项目根目录到Python路径
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
@@ -68,6 +69,7 @@ class WebUI:
|
||||
|
||||
# 添加静态文件服务
|
||||
self.app.router.add_static('/assets/', path=os.path.join(self.static_path, 'assets'))
|
||||
# 所有未匹配的路由都返回 index.html
|
||||
self.app.router.add_get('/{tail:.*}', self.handle_static_files)
|
||||
|
||||
async def handle_static_files(self, request):
|
||||
@@ -79,6 +81,8 @@ class WebUI:
|
||||
|
||||
def run(self, host='0.0.0.0', port=8002):
|
||||
"""运行服务器"""
|
||||
local_ip = get_local_ip()
|
||||
logger.info(f"WebUI server is running at http://{local_ip}:{port}")
|
||||
web.run_app(self.app, host=host, port=port)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,12 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
# 添加项目根目录到Python路径
|
||||
project_root = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.append(project_root)
|
||||
|
||||
from core.webui import WebUI
|
||||
|
||||
if __name__ == '__main__':
|
||||
webui = WebUI()
|
||||
webui.run()
|
||||
Reference in New Issue
Block a user