use anyhow::{Context, Result};
use colored::*;
use std::fs;
use std::path::{Path, PathBuf};
use crate::template;
pub fn generate_project(name: &str, template_name: &str, output_dir: &Path) -> Result<()> {
// 验证模板存在
let template = template::get_template(template_name)
.ok_or_else(|| anyhow::anyhow!("模板 '{}' 不存在", template_name))?;
println!("📝 使用模板: {}", template.name.bright_green());
println!("📂 创建目录: {}", output_dir.display().to_string().bright_yellow());
// 创建项目目录
fs::create_dir_all(output_dir)
.context("创建项目目录失败")?;
// 根据模板类型生成不同的项目结构
match template_name {
"wallet" => generate_wallet_project(name, output_dir)?,
"exchange" => generate_exchange_project(name, output_dir)?,
_ => generate_standard_project(name, template_name, output_dir)?,
}
Ok(())
}
fn generate_wallet_project(name: &str, output_dir: &Path) -> Result<()> {
println!("💼 生成NAC钱包项目...");
// 创建目录结构
create_dir_structure(output_dir, &[
"src",
"src/components",
"src/hooks",
"src/utils",
"src/services",
"src/stores",
"public",
])?;
// 生成package.json
let package_json = format!(r#"{{
"name": "{}",
"version": "1.0.0",
"type": "module",
"scripts": {{
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}},
"dependencies": {{
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.20.0",
"@tanstack/react-query": "^5.0.0",
"zustand": "^4.4.0",
"axios": "^1.6.0"
}},
"devDependencies": {{
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@vitejs/plugin-react": "^4.2.0",
"vite": "^5.0.0",
"typescript": "^5.3.0"
}}
}}
"#, name);
fs::write(output_dir.join("package.json"), package_json)?;
// 生成vite.config.js
let vite_config = r#"import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
server: {
port: 3000
}
})
"#;
fs::write(output_dir.join("vite.config.js"), vite_config)?;
// 生成index.html
let index_html = format!(r#"
{} - NAC钱包
"#, name);
fs::write(output_dir.join("index.html"), index_html)?;
// 生成src/main.jsx
let main_jsx = r#"import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')).render(
,
)
"#;
fs::write(output_dir.join("src/main.jsx"), main_jsx)?;
// 生成src/App.jsx
let app_jsx = r#"import { useState } from 'react'
import WalletConnector from './components/WalletConnector'
import './App.css'
function App() {
const [account, setAccount] = useState(null)
return (
{account && (
账户信息
地址: {account.address}
余额: {account.balance} XTZH
)}
)
}
export default App
"#;
fs::write(output_dir.join("src/App.jsx"), app_jsx)?;
// 生成WalletConnector组件
let wallet_connector = r#"import { useState } from 'react'
export default function WalletConnector({ onConnect }) {
const [loading, setLoading] = useState(false)
const handleConnect = async () => {
setLoading(true)
try {
// TODO: 实现NAC钱包连接逻辑
const account = {
address: 'nac1...',
balance: '1000.00'
}
onConnect(account)
} catch (error) {
console.error('连接失败:', error)
} finally {
setLoading(false)
}
}
return (
)
}
"#;
fs::write(output_dir.join("src/components/WalletConnector.jsx"), wallet_connector)?;
// 生成CSS
let app_css = r#".app {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
}
.account-info {
background: #f5f5f5;
padding: 1.5rem;
border-radius: 8px;
}
"#;
fs::write(output_dir.join("src/App.css"), app_css)?;
fs::write(output_dir.join("src/index.css"), "* { margin: 0; padding: 0; box-sizing: border-box; }")?;
// 生成README
let readme = format!(r#"# {} - NAC钱包
NAC原生公链钱包应用
## 功能特性
- 钱包连接与管理
- 资产查看与转账
- 交易历史记录
- 宪法收据验证
## 开发
```bash
npm install
npm run dev
```
## 构建
```bash
npm run build
```
"#, name);
fs::write(output_dir.join("README.md"), readme)?;
Ok(())
}
fn generate_exchange_project(name: &str, output_dir: &Path) -> Result<()> {
println!("🏦 生成RWA交易所项目...");
// 创建目录结构
create_dir_structure(output_dir, &[
"src",
"src/components",
"src/pages",
"src/hooks",
"src/utils",
"src/services",
"src/stores",
"public",
])?;
// 生成package.json
let package_json = format!(r#"{{
"name": "{}",
"version": "1.0.0",
"type": "module",
"scripts": {{
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}},
"dependencies": {{
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.20.0",
"@tanstack/react-query": "^5.0.0",
"zustand": "^4.4.0",
"axios": "^1.6.0",
"recharts": "^2.10.0"
}},
"devDependencies": {{
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@vitejs/plugin-react": "^4.2.0",
"vite": "^5.0.0",
"typescript": "^5.3.0"
}}
}}
"#, name);
fs::write(output_dir.join("package.json"), package_json)?;
// 生成vite.config.js
let vite_config = r#"import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
})
"#;
fs::write(output_dir.join("vite.config.js"), vite_config)?;
// 生成index.html
let index_html = format!(r#"
{} - NAC RWA交易所
"#, name);
fs::write(output_dir.join("index.html"), index_html)?;
// 生成src/main.jsx
let main_jsx = r#"import React from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import App from './App'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')).render(
,
)
"#;
fs::write(output_dir.join("src/main.jsx"), main_jsx)?;
// 生成src/App.jsx
let app_jsx = r#"import { Routes, Route } from 'react-router-dom'
import HomePage from './pages/HomePage'
import TradePage from './pages/TradePage'
import './App.css'
function App() {
return (
)
}
export default App
"#;
fs::write(output_dir.join("src/App.jsx"), app_jsx)?;
// 生成HomePage
let home_page = r#"export default function HomePage() {
return (
欢迎来到NAC RWA交易所
全球首个RWA原生公链交易平台
)
}
"#;
fs::write(output_dir.join("src/pages/HomePage.jsx"), home_page)?;
// 生成TradePage
let trade_page = r#"import { useState } from 'react'
export default function TradePage() {
const [orderType, setOrderType] = useState('buy')
const [amount, setAmount] = useState('')
const [price, setPrice] = useState('')
const handleSubmit = (e) => {
e.preventDefault()
console.log('提交订单:', { orderType, amount, price })
}
return (
)
}
"#;
fs::write(output_dir.join("src/pages/TradePage.jsx"), trade_page)?;
// 生成CSS
let app_css = r#".app {
min-height: 100vh;
}
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
background: #1a1a1a;
color: white;
}
.nav-links a {
margin-left: 1.5rem;
color: white;
text-decoration: none;
}
.home-page {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
.features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
margin-top: 2rem;
}
.feature-card {
padding: 1.5rem;
background: #f5f5f5;
border-radius: 8px;
}
.trade-page {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 1.5rem;
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
.trade-form form {
display: flex;
flex-direction: column;
gap: 1rem;
}
.order-type {
display: flex;
gap: 0.5rem;
}
.order-type button {
flex: 1;
padding: 0.75rem;
border: none;
background: #e0e0e0;
cursor: pointer;
}
.order-type button.active {
background: #4CAF50;
color: white;
}
"#;
fs::write(output_dir.join("src/App.css"), app_css)?;
fs::write(output_dir.join("src/index.css"), "* { margin: 0; padding: 0; box-sizing: border-box; }")?;
// 生成README
let readme = format!(r#"# {} - NAC RWA交易所
NAC原生公链RWA资产交易平台
## 功能特性
- 资产上架与交易
- 订单簿与撮合引擎
- 碎片化交易支持
- 跨链资产桥接
- 实时行情数据
## 开发
```bash
npm install
npm run dev
```
## 构建
```bash
npm run build
```
## API接口
后端API运行在 `http://localhost:8080`
主要接口:
- GET /api/assets - 获取资产列表
- GET /api/orderbook/:asset - 获取订单簿
- POST /api/orders - 创建订单
- GET /api/trades - 获取交易历史
"#, name);
fs::write(output_dir.join("README.md"), readme)?;
Ok(())
}
fn generate_standard_project(_name: &str, _template_name: &str, _output_dir: &Path) -> Result<()> {
// TODO: 实现标准模板生成
Ok(())
}
fn create_dir_structure(base: &Path, dirs: &[&str]) -> Result<()> {
for dir in dirs {
fs::create_dir_all(base.join(dir))?;
}
Ok(())
}