801 lines
17 KiB
Markdown
801 lines
17 KiB
Markdown
# Funstat MCP 工具 - 替代部署方案
|
||
|
||
## 🎯 方案概览
|
||
|
||
除了让每个用户独立部署,还有以下几种完美的永久替代方案:
|
||
|
||
---
|
||
|
||
## 🌟 方案 1:Docker 容器化部署(最推荐)
|
||
|
||
### 概述
|
||
|
||
将 MCP 服务器打包成 Docker 镜像,用户只需一个命令即可启动。
|
||
|
||
### 架构
|
||
|
||
```
|
||
用户 → Docker 容器 → Telegram Session → @openaiw_bot
|
||
```
|
||
|
||
### 优势
|
||
|
||
- ✅ **一键启动**:`docker run` 即可
|
||
- ✅ **环境隔离**:不用担心依赖冲突
|
||
- ✅ **跨平台**:Windows/macOS/Linux 统一
|
||
- ✅ **易更新**:`docker pull` 拉取新版本
|
||
- ✅ **配置简单**:环境变量配置
|
||
- ✅ **易分发**:推送到 Docker Hub
|
||
|
||
### 实现步骤
|
||
|
||
#### 1. 创建 Dockerfile
|
||
|
||
```dockerfile
|
||
# Dockerfile
|
||
FROM python:3.11-slim
|
||
|
||
WORKDIR /app
|
||
|
||
# 安装依赖
|
||
COPY requirements.txt .
|
||
RUN pip install --no-cache-dir -r requirements.txt
|
||
|
||
# 复制应用代码
|
||
COPY funstat_mcp/ /app/
|
||
COPY create_session_safe.py /app/
|
||
|
||
# 创建 session 目录
|
||
RUN mkdir -p /app/sessions
|
||
|
||
# 设置环境变量
|
||
ENV TELEGRAM_API_ID=""
|
||
ENV TELEGRAM_API_HASH=""
|
||
ENV SESSION_DIR="/app/sessions"
|
||
|
||
# 暴露端口(如果需要)
|
||
# EXPOSE 8080
|
||
|
||
# 启动命令
|
||
CMD ["python3", "server.py"]
|
||
```
|
||
|
||
#### 2. 创建 docker-compose.yml
|
||
|
||
```yaml
|
||
version: '3.8'
|
||
|
||
services:
|
||
funstat-mcp:
|
||
build: .
|
||
container_name: funstat-mcp
|
||
environment:
|
||
- TELEGRAM_API_ID=${TELEGRAM_API_ID}
|
||
- TELEGRAM_API_HASH=${TELEGRAM_API_HASH}
|
||
volumes:
|
||
# 持久化 session 文件
|
||
- ./sessions:/app/sessions
|
||
restart: unless-stopped
|
||
stdin_open: true
|
||
tty: true
|
||
```
|
||
|
||
#### 3. 创建 .env.example
|
||
|
||
```bash
|
||
# .env.example
|
||
TELEGRAM_API_ID=你的_api_id
|
||
TELEGRAM_API_HASH=你的_api_hash
|
||
```
|
||
|
||
### 用户使用步骤
|
||
|
||
```bash
|
||
# 1. 克隆仓库
|
||
git clone https://github.com/your-repo/funstat-mcp-docker.git
|
||
cd funstat-mcp-docker
|
||
|
||
# 2. 配置环境变量
|
||
cp .env.example .env
|
||
nano .env # 填入自己的 API 凭证
|
||
|
||
# 3. 首次创建 session
|
||
docker-compose run --rm funstat-mcp python3 create_session_safe.py
|
||
|
||
# 4. 启动服务
|
||
docker-compose up -d
|
||
|
||
# 5. 查看日志
|
||
docker-compose logs -f
|
||
```
|
||
|
||
### 配置 Claude Code
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"funstat": {
|
||
"command": "docker",
|
||
"args": [
|
||
"exec",
|
||
"-i",
|
||
"funstat-mcp",
|
||
"python3",
|
||
"server.py"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🌐 方案 2:WebSocket 远程服务(推荐用于团队)
|
||
|
||
### 概述
|
||
|
||
部署一个中心化的 MCP 服务器,用户通过 WebSocket 连接使用。
|
||
|
||
### 架构
|
||
|
||
```
|
||
多个用户 → WebSocket → 中心 MCP 服务器 → Session 池 → @openaiw_bot
|
||
↓
|
||
认证 & 计费
|
||
```
|
||
|
||
### 优势
|
||
|
||
- ✅ **零配置**:用户不需要任何本地配置
|
||
- ✅ **统一管理**:集中维护和更新
|
||
- ✅ **权限控制**:可以设置用户权限
|
||
- ✅ **使用统计**:追踪使用量
|
||
- ✅ **成本分摊**:可以收费或限额
|
||
|
||
### 实现步骤
|
||
|
||
#### 1. 创建 WebSocket 服务器
|
||
|
||
```python
|
||
# ws_server.py
|
||
import asyncio
|
||
import json
|
||
from aiohttp import web
|
||
from server import FunstatMCPServer
|
||
|
||
class WebSocketMCPServer:
|
||
def __init__(self):
|
||
self.clients = {}
|
||
self.mcp_server = FunstatMCPServer()
|
||
|
||
async def handle_websocket(self, request):
|
||
ws = web.WebSocketResponse()
|
||
await ws.prepare(request)
|
||
|
||
# 认证
|
||
auth_msg = await ws.receive_json()
|
||
token = auth_msg.get('token')
|
||
|
||
if not self.verify_token(token):
|
||
await ws.send_json({'error': 'Invalid token'})
|
||
await ws.close()
|
||
return ws
|
||
|
||
client_id = auth_msg.get('client_id')
|
||
self.clients[client_id] = ws
|
||
|
||
try:
|
||
async for msg in ws:
|
||
if msg.type == web.WSMsgType.TEXT:
|
||
data = json.loads(msg.data)
|
||
|
||
# 调用 MCP 工具
|
||
result = await self.mcp_server.call_tool(
|
||
data['tool'],
|
||
data['arguments']
|
||
)
|
||
|
||
# 返回结果
|
||
await ws.send_json({
|
||
'id': data['id'],
|
||
'result': result
|
||
})
|
||
|
||
finally:
|
||
del self.clients[client_id]
|
||
|
||
return ws
|
||
|
||
def verify_token(self, token):
|
||
# 实现你的认证逻辑
|
||
return token in self.valid_tokens
|
||
|
||
async def start(self):
|
||
await self.mcp_server.initialize()
|
||
|
||
app = web.Application()
|
||
app.router.add_get('/ws', self.handle_websocket)
|
||
|
||
runner = web.AppRunner(app)
|
||
await runner.setup()
|
||
site = web.TCPSite(runner, '0.0.0.0', 8080)
|
||
await site.start()
|
||
|
||
if __name__ == '__main__':
|
||
server = WebSocketMCPServer()
|
||
asyncio.run(server.start())
|
||
```
|
||
|
||
#### 2. 创建客户端库
|
||
|
||
```python
|
||
# client.py
|
||
import asyncio
|
||
import json
|
||
import websockets
|
||
|
||
class FunstatMCPClient:
|
||
def __init__(self, url, token):
|
||
self.url = url
|
||
self.token = token
|
||
self.ws = None
|
||
|
||
async def connect(self):
|
||
self.ws = await websockets.connect(self.url)
|
||
|
||
# 认证
|
||
await self.ws.send(json.dumps({
|
||
'token': self.token,
|
||
'client_id': 'user-123'
|
||
}))
|
||
|
||
async def call_tool(self, tool, arguments):
|
||
msg = {
|
||
'id': str(uuid.uuid4()),
|
||
'tool': tool,
|
||
'arguments': arguments
|
||
}
|
||
|
||
await self.ws.send(json.dumps(msg))
|
||
response = await self.ws.recv()
|
||
|
||
return json.loads(response)
|
||
|
||
async def close(self):
|
||
await self.ws.close()
|
||
```
|
||
|
||
### 用户使用
|
||
|
||
```python
|
||
# 用户端代码
|
||
import asyncio
|
||
from client import FunstatMCPClient
|
||
|
||
async def main():
|
||
client = FunstatMCPClient(
|
||
url='ws://your-server.com:8080/ws',
|
||
token='user-token-here'
|
||
)
|
||
|
||
await client.connect()
|
||
|
||
result = await client.call_tool(
|
||
'funstat_search',
|
||
{'query': 'python'}
|
||
)
|
||
|
||
print(result)
|
||
|
||
await client.close()
|
||
|
||
asyncio.run(main())
|
||
```
|
||
|
||
### 部署到云服务器
|
||
|
||
```bash
|
||
# 使用 Docker + Nginx
|
||
docker-compose -f docker-compose.prod.yml up -d
|
||
```
|
||
|
||
---
|
||
|
||
## 📦 方案 3:NPM 包发布(适合开发者)
|
||
|
||
### 概述
|
||
|
||
将 MCP 服务器打包成 NPM 包,通过 `npx` 一键运行。
|
||
|
||
### 架构
|
||
|
||
```
|
||
用户 → npx funstat-mcp → 本地 MCP 服务器 → @openaiw_bot
|
||
```
|
||
|
||
### 优势
|
||
|
||
- ✅ **一键安装**:`npx funstat-mcp`
|
||
- ✅ **自动更新**:npx 自动使用最新版本
|
||
- ✅ **开发者友好**:熟悉的工具链
|
||
- ✅ **易维护**:集中发布更新
|
||
|
||
### 实现步骤
|
||
|
||
#### 1. 创建 Node.js 包装器
|
||
|
||
```javascript
|
||
// index.js
|
||
#!/usr/bin/env node
|
||
|
||
const { spawn } = require('child_process');
|
||
const path = require('path');
|
||
const fs = require('fs');
|
||
const os = require('os');
|
||
|
||
// 配置目录
|
||
const configDir = path.join(os.homedir(), '.funstat-mcp');
|
||
const sessionPath = path.join(configDir, 'session');
|
||
|
||
// 确保配置目录存在
|
||
if (!fs.existsSync(configDir)) {
|
||
fs.mkdirSync(configDir, { recursive: true });
|
||
}
|
||
|
||
// 检查是否首次运行
|
||
if (!fs.existsSync(path.join(configDir, '.env'))) {
|
||
console.log('首次运行,开始配置...');
|
||
|
||
const readline = require('readline').createInterface({
|
||
input: process.stdin,
|
||
output: process.stdout
|
||
});
|
||
|
||
readline.question('请输入 API ID: ', (apiId) => {
|
||
readline.question('请输入 API Hash: ', (apiHash) => {
|
||
// 保存配置
|
||
const config = `TELEGRAM_API_ID=${apiId}\nTELEGRAM_API_HASH=${apiHash}\n`;
|
||
fs.writeFileSync(path.join(configDir, '.env'), config);
|
||
|
||
console.log('配置已保存!');
|
||
readline.close();
|
||
|
||
// 创建 session
|
||
createSession();
|
||
});
|
||
});
|
||
} else {
|
||
// 启动服务器
|
||
startServer();
|
||
}
|
||
|
||
function startServer() {
|
||
const serverPath = path.join(__dirname, 'python', 'server.py');
|
||
const server = spawn('python3', [serverPath], {
|
||
env: {
|
||
...process.env,
|
||
SESSION_PATH: sessionPath
|
||
},
|
||
stdio: 'inherit'
|
||
});
|
||
|
||
server.on('exit', (code) => {
|
||
console.log(`服务器退出,代码: ${code}`);
|
||
});
|
||
}
|
||
|
||
function createSession() {
|
||
const scriptPath = path.join(__dirname, 'python', 'create_session_safe.py');
|
||
const proc = spawn('python3', [scriptPath], {
|
||
env: {
|
||
...process.env,
|
||
SESSION_PATH: sessionPath
|
||
},
|
||
stdio: 'inherit'
|
||
});
|
||
|
||
proc.on('exit', () => {
|
||
console.log('Session 创建完成!');
|
||
startServer();
|
||
});
|
||
}
|
||
```
|
||
|
||
#### 2. 创建 package.json
|
||
|
||
```json
|
||
{
|
||
"name": "@yourname/funstat-mcp",
|
||
"version": "1.0.0",
|
||
"description": "Funstat MCP Server - One-command deployment",
|
||
"bin": {
|
||
"funstat-mcp": "./index.js"
|
||
},
|
||
"scripts": {
|
||
"postinstall": "python3 -m pip install -r python/requirements.txt"
|
||
},
|
||
"keywords": ["mcp", "telegram", "funstat"],
|
||
"author": "Your Name",
|
||
"license": "MIT",
|
||
"files": [
|
||
"index.js",
|
||
"python/"
|
||
],
|
||
"engines": {
|
||
"node": ">=14.0.0"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 用户使用
|
||
|
||
```bash
|
||
# 首次运行(自动配置)
|
||
npx @yourname/funstat-mcp
|
||
|
||
# 之后直接运行
|
||
npx @yourname/funstat-mcp
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 方案 4:Electron 桌面应用(最用户友好)
|
||
|
||
### 概述
|
||
|
||
打包成独立的桌面应用,带图形界面配置。
|
||
|
||
### 架构
|
||
|
||
```
|
||
用户 → Electron GUI → 本地 MCP 服务器 → @openaiw_bot
|
||
```
|
||
|
||
### 优势
|
||
|
||
- ✅ **图形界面**:无需命令行
|
||
- ✅ **一键安装**:下载 .dmg/.exe 即可
|
||
- ✅ **自动更新**:electron-updater
|
||
- ✅ **状态显示**:可视化连接状态
|
||
- ✅ **配置管理**:GUI 配置界面
|
||
|
||
### 实现步骤
|
||
|
||
#### 1. 创建 Electron 主进程
|
||
|
||
```javascript
|
||
// main.js
|
||
const { app, BrowserWindow, ipcMain } = require('electron');
|
||
const { spawn } = require('child_process');
|
||
const path = require('path');
|
||
|
||
let mainWindow;
|
||
let mcpProcess;
|
||
|
||
function createWindow() {
|
||
mainWindow = new BrowserWindow({
|
||
width: 800,
|
||
height: 600,
|
||
webPreferences: {
|
||
nodeIntegration: true,
|
||
contextIsolation: false
|
||
}
|
||
});
|
||
|
||
mainWindow.loadFile('index.html');
|
||
}
|
||
|
||
app.whenReady().then(createWindow);
|
||
|
||
// 启动 MCP 服务器
|
||
ipcMain.on('start-server', (event, config) => {
|
||
const serverPath = path.join(__dirname, 'python', 'server.py');
|
||
|
||
mcpProcess = spawn('python3', [serverPath], {
|
||
env: {
|
||
...process.env,
|
||
TELEGRAM_API_ID: config.apiId,
|
||
TELEGRAM_API_HASH: config.apiHash
|
||
}
|
||
});
|
||
|
||
mcpProcess.stdout.on('data', (data) => {
|
||
event.reply('server-log', data.toString());
|
||
});
|
||
|
||
mcpProcess.on('exit', (code) => {
|
||
event.reply('server-stopped', code);
|
||
});
|
||
});
|
||
|
||
// 停止服务器
|
||
ipcMain.on('stop-server', () => {
|
||
if (mcpProcess) {
|
||
mcpProcess.kill();
|
||
}
|
||
});
|
||
```
|
||
|
||
#### 2. 创建前端界面
|
||
|
||
```html
|
||
<!-- index.html -->
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>Funstat MCP</title>
|
||
<style>
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||
padding: 20px;
|
||
}
|
||
.config-form {
|
||
max-width: 500px;
|
||
margin: 0 auto;
|
||
}
|
||
input {
|
||
width: 100%;
|
||
padding: 10px;
|
||
margin: 10px 0;
|
||
border: 1px solid #ccc;
|
||
border-radius: 4px;
|
||
}
|
||
button {
|
||
background: #007bff;
|
||
color: white;
|
||
padding: 10px 20px;
|
||
border: none;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
}
|
||
.status {
|
||
margin-top: 20px;
|
||
padding: 10px;
|
||
border-radius: 4px;
|
||
}
|
||
.status.running {
|
||
background: #d4edda;
|
||
color: #155724;
|
||
}
|
||
.status.stopped {
|
||
background: #f8d7da;
|
||
color: #721c24;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1>🚀 Funstat MCP Server</h1>
|
||
|
||
<div class="config-form">
|
||
<h2>配置</h2>
|
||
|
||
<label>API ID:</label>
|
||
<input type="text" id="apiId" placeholder="输入你的 API ID">
|
||
|
||
<label>API Hash:</label>
|
||
<input type="text" id="apiHash" placeholder="输入你的 API Hash">
|
||
|
||
<button onclick="startServer()">启动服务器</button>
|
||
<button onclick="stopServer()">停止服务器</button>
|
||
|
||
<div id="status" class="status stopped">
|
||
服务器状态:已停止
|
||
</div>
|
||
|
||
<div id="logs" style="margin-top: 20px; height: 300px; overflow-y: auto; background: #f5f5f5; padding: 10px; border-radius: 4px;">
|
||
<h3>日志</h3>
|
||
<pre id="logContent"></pre>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="renderer.js"></script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
#### 3. 创建渲染进程脚本
|
||
|
||
```javascript
|
||
// renderer.js
|
||
const { ipcRenderer } = require('electron');
|
||
|
||
function startServer() {
|
||
const config = {
|
||
apiId: document.getElementById('apiId').value,
|
||
apiHash: document.getElementById('apiHash').value
|
||
};
|
||
|
||
if (!config.apiId || !config.apiHash) {
|
||
alert('请填写 API 凭证');
|
||
return;
|
||
}
|
||
|
||
// 保存配置
|
||
localStorage.setItem('config', JSON.stringify(config));
|
||
|
||
// 启动服务器
|
||
ipcRenderer.send('start-server', config);
|
||
|
||
document.getElementById('status').className = 'status running';
|
||
document.getElementById('status').textContent = '服务器状态:运行中';
|
||
}
|
||
|
||
function stopServer() {
|
||
ipcRenderer.send('stop-server');
|
||
|
||
document.getElementById('status').className = 'status stopped';
|
||
document.getElementById('status').textContent = '服务器状态:已停止';
|
||
}
|
||
|
||
// 监听日志
|
||
ipcRenderer.on('server-log', (event, log) => {
|
||
const logContent = document.getElementById('logContent');
|
||
logContent.textContent += log;
|
||
logContent.scrollTop = logContent.scrollHeight;
|
||
});
|
||
|
||
// 恢复配置
|
||
window.addEventListener('DOMContentLoaded', () => {
|
||
const savedConfig = localStorage.getItem('config');
|
||
if (savedConfig) {
|
||
const config = JSON.parse(savedConfig);
|
||
document.getElementById('apiId').value = config.apiId;
|
||
document.getElementById('apiHash').value = config.apiHash;
|
||
}
|
||
});
|
||
```
|
||
|
||
### 打包和分发
|
||
|
||
```bash
|
||
# 安装依赖
|
||
npm install electron electron-builder --save-dev
|
||
|
||
# 打包
|
||
npm run build
|
||
|
||
# 生成安装包
|
||
# macOS: Funstat-MCP-1.0.0.dmg
|
||
# Windows: Funstat-MCP-Setup-1.0.0.exe
|
||
# Linux: Funstat-MCP-1.0.0.AppImage
|
||
```
|
||
|
||
### 用户使用
|
||
|
||
1. 下载安装包
|
||
2. 双击安装
|
||
3. 打开应用
|
||
4. 输入 API 凭证
|
||
5. 点击"启动服务器"
|
||
6. 完成!
|
||
|
||
---
|
||
|
||
## 🌍 方案 5:SaaS 服务(商业化)
|
||
|
||
### 概述
|
||
|
||
提供完全托管的云服务,用户注册账号即可使用。
|
||
|
||
### 架构
|
||
|
||
```
|
||
用户浏览器 → Web 界面 → API Gateway → MCP Server Pool → @openaiw_bot
|
||
↓
|
||
认证、计费、监控
|
||
```
|
||
|
||
### 优势
|
||
|
||
- ✅ **零配置**:注册即用
|
||
- ✅ **跨设备**:任何设备访问
|
||
- ✅ **托管服务**:无需维护
|
||
- ✅ **付费模式**:可以商业化
|
||
- ✅ **企业功能**:团队管理、审计日志
|
||
|
||
### 技术栈
|
||
|
||
```yaml
|
||
前端: React + TypeScript
|
||
后端: FastAPI + Python
|
||
数据库: PostgreSQL
|
||
缓存: Redis
|
||
消息队列: RabbitMQ
|
||
部署: Kubernetes + Docker
|
||
```
|
||
|
||
### 功能模块
|
||
|
||
1. **用户管理**
|
||
- 注册/登录
|
||
- OAuth 集成
|
||
- 团队管理
|
||
|
||
2. **计费系统**
|
||
- 按使用量计费
|
||
- 订阅套餐
|
||
- 积分系统
|
||
|
||
3. **API 网关**
|
||
- 速率限制
|
||
- 请求认证
|
||
- 负载均衡
|
||
|
||
4. **监控系统**
|
||
- 使用统计
|
||
- 性能监控
|
||
- 错误追踪
|
||
|
||
5. **管理后台**
|
||
- 用户管理
|
||
- 使用分析
|
||
- 配置管理
|
||
|
||
---
|
||
|
||
## 📊 方案对比
|
||
|
||
| 方案 | 难度 | 用户体验 | 维护成本 | 扩展性 | 推荐度 |
|
||
|------|------|----------|---------|--------|--------|
|
||
| **Docker** | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||
| **WebSocket** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
|
||
| **NPM 包** | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
|
||
| **Electron** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
|
||
| **SaaS** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||
|
||
---
|
||
|
||
## 🎯 推荐选择
|
||
|
||
### 个人/小团队(< 10人)
|
||
**推荐**:Docker 容器化
|
||
- 简单易用
|
||
- 成本低
|
||
- 易维护
|
||
|
||
### 中型团队(10-50人)
|
||
**推荐**:WebSocket 远程服务
|
||
- 集中管理
|
||
- 统一维护
|
||
- 权限控制
|
||
|
||
### 大型组织(> 50人)
|
||
**推荐**:SaaS 服务
|
||
- 完全托管
|
||
- 企业功能
|
||
- 可商业化
|
||
|
||
### 非技术用户
|
||
**推荐**:Electron 桌面应用
|
||
- 图形界面
|
||
- 一键安装
|
||
- 零配置
|
||
|
||
---
|
||
|
||
## 🚀 快速实施建议
|
||
|
||
### 阶段 1:立即可用(本周)
|
||
- ✅ 创建 Docker 镜像
|
||
- ✅ 发布到 Docker Hub
|
||
- ✅ 更新文档
|
||
|
||
### 阶段 2:团队版本(1个月)
|
||
- ✅ 开发 WebSocket 服务器
|
||
- ✅ 部署到云服务器
|
||
- ✅ 添加认证系统
|
||
|
||
### 阶段 3:桌面应用(2个月)
|
||
- ✅ 开发 Electron 应用
|
||
- ✅ 打包分发
|
||
- ✅ 自动更新
|
||
|
||
### 阶段 4:SaaS 化(3-6个月)
|
||
- ✅ 完整的 Web 平台
|
||
- ✅ 计费系统
|
||
- ✅ 企业功能
|
||
|
||
---
|
||
|
||
**每种方案都有完整的实现路径,可以根据需求选择!** 🎊
|