# 混合架构快速开发模板

## 🚀 5 分钟添加新功能

### 模板代码

复制下面的模板，替换 `YOUR_FEATURE` 为你的功能名称。

---

## 📝 Step 1: 后端 API（3 层）

**文件：** `Server/app/api/v1/jsx_demo.py`

```python
# ==================== 请求/响应模型 ====================
class YourFeatureRequest(BaseModel):
    """你的功能请求"""
    param1: str
    param2: int

class YourFeatureResult(BaseModel):
    """你的功能结果"""
    success: bool
    result_data: dict
    message: str

# ==================== API 端点 ====================
@router.post("/your-feature", response_model=YourFeatureResult)
async def your_feature_endpoint(
    request: YourFeatureRequest,
    x_api_key: Optional[str] = Header(None)
):
    """
    🔒 服务器端核心计算
    客户端只能拿到结果，看不到算法
    """
    
    # 📝 日志：记录请求
    logger.info("="*60)
    logger.info("📥 收到请求: YOUR_FEATURE")
    logger.info(f"   参数1: {request.param1}")
    logger.info(f"   参数2: {request.param2}")
    logger.info(f"   API Key: {x_api_key}")
    logger.info("="*60)
    
    # 🔐 API Key 验证
    if not validate_api_key(x_api_key):
        logger.warning(f"❌ API Key 验证失败")
        raise HTTPException(status_code=403, detail="无效的 API Key")
    
    key_info = get_key_info(x_api_key)
    logger.info(f"✅ API Key 验证通过 | 名称: {key_info['name']}")
    
    try:
        # 🛡️ 输入验证
        logger.info("🛡️ 验证输入参数...")
        if not request.param1 or request.param2 < 0:
            logger.warning("❌ 参数验证失败")
            return YourFeatureResult(
                success=False,
                result_data={},
                message="参数无效"
            )
        logger.info("✅ 参数验证通过")
        
        # 🔒 核心算法（客户端看不到）
        logger.info("🔒 开始执行核心算法...")
        
        # ===== 在这里写你的核心逻辑 =====
        result = {
            "output1": f"处理结果: {request.param1}",
            "output2": request.param2 * 2
        }
        # ================================
        
        logger.info(f"✅ 计算完成: {result}")
        
        # 📤 返回结果
        logger.info("="*60)
        return YourFeatureResult(
            success=True,
            result_data=result,
            message="处理成功"
        )
        
    except Exception as e:
        logger.error(f"❌ 处理失败: {str(e)}")
        return YourFeatureResult(
            success=False,
            result_data={},
            message=f"处理失败: {str(e)}"
        )
```

---

## 📝 Step 2: 前端 API（2 层）

**文件：** `Designer/src/api/jsxApi/inline/your-feature.ts`

```typescript
/**
 * YOUR_FEATURE 功能
 * 混合方案：本地执行 + 服务器计算
 */

import { evalInlineJSX, JSXResponse } from './utils';
import { config } from '@/config';

export async function yourFeatureFunction(
    param1: string,
    param2: number
): Promise<JSXResponse> {
    try {
        // 1. 💻 【可选】本地获取 PS 数据
        const getDataJsx = `
            try {
                if (!$.global.JSXUtils.hasDocument()) {
                    return $.global.JSXUtils.stringify({ error: '没有打开的文档' });
                }
                
                var doc = $.global.JSXUtils.getDocument();
                
                // 获取你需要的数据
                var layerName = doc.activeLayer ? doc.activeLayer.name : '';
                
                return $.global.JSXUtils.stringify({ 
                    success: true,
                    layerName: layerName
                });
            } catch (error) {
                return $.global.JSXUtils.stringify({ error: error.toString() });
            }
        `;
        
        const psData = await evalInlineJSX(getDataJsx);
        
        if (psData.error) {
            return psData;
        }
        
        // 2. 🌐 发送到服务器计算（核心算法）
        const response = await fetch(`${config.apiBaseUrl}/jsx_demo/your-feature`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-API-Key': 'demo_key_123'  // 🔐 API Key
            },
            body: JSON.stringify({
                param1: param1,
                param2: param2
            })
        });
        
        if (!response.ok) {
            return { error: '服务器错误' };
        }
        
        const serverResult = await response.json();
        
        if (!serverResult.success) {
            return { error: serverResult.message };
        }
        
        // 3. 💻 【可选】使用服务器结果执行 PS 操作
        const { output1, output2 } = serverResult.result_data;
        
        const applyJsx = `
            try {
                var doc = $.global.JSXUtils.getDocument();
                
                // 使用服务器计算的结果
                // 示例：创建文本图层显示结果
                var textLayer = doc.artLayers.add();
                textLayer.kind = LayerKind.TEXT;
                textLayer.name = "${output1}";
                
                return $.global.JSXUtils.stringify({ 
                    success: true,
                    message: '操作完成'
                });
            } catch (error) {
                return $.global.JSXUtils.stringify({ error: error.toString() });
            }
        `;
        
        return evalInlineJSX(applyJsx);
        
    } catch (error) {
        return { error: String(error) };
    }
}
```

---

## 📝 Step 3: UI 界面（2 层）

**文件：** `Designer/src/view/Home.vue`

```vue
<template>
  <a-button type="primary" @click="handleYourFeature">
    你的功能
  </a-button>
</template>

<script setup lang="ts">
import { yourFeatureFunction } from '@/api/jsxApi/inline/your-feature';
import { Message } from '@arco-design/web-vue';

const handleYourFeature = async () => {
  try {
    Message.loading('处理中...');
    
    // 调用混合 API
    const res = await yourFeatureFunction('测试参数', 100);
    
    if (res && res.success) {
      Message.success(res.message || '操作成功');
    } else {
      Message.error(res?.error || '执行失败');
    }
  } catch (e: any) {
    Message.error('调用失败: ' + e.message);
  }
};
</script>
```

---

## 🔄 开发流程

### 本地测试
```bash
# Terminal 1: 启动后端
cd Server
python -m uvicorn app.main:app --reload

# Terminal 2: 启动前端
cd Designer
npm run dev
```

### 发布新版本
```bash
# 自动构建、打包、发布
python auto_deploy_core.py
```

---

## 📋 检查清单

开发新功能时，确保：

- [ ] 后端添加了 API Key 验证
- [ ] 后端添加了详细日志
- [ ] 后端添加了输入验证
- [ ] 前端使用了正确的 API Key
- [ ] 前端添加了错误处理
- [ ] UI 有加载提示和错误提示
- [ ] 测试了成功和失败的情况
- [ ] 更新了版本号

---

## 🎯 三种常见模式

### 模式 1：纯服务器计算
```
前端输入 → 服务器计算 → 前端显示结果
（不涉及 PS 操作）
```

### 模式 2：服务器计算 + PS 应用
```
前端获取 PS 数据 → 服务器计算 → 前端应用到 PS
（当前示例）
```

### 模式 3：本地执行 + 服务器验证
```
前端执行操作 → 服务器验证权限 → 前端继续
（需要权限控制的操作）
```

---

## 💡 快速参考

### 后端日志模板
```python
logger.info("="*60)
logger.info("📥 收到请求")
logger.info("✅ 验证通过")
logger.info("🔒 开始计算")
logger.info("✅ 计算完成")
logger.info("="*60)
```

### 前端错误处理模板
```typescript
try {
    Message.loading('处理中...');
    const res = await yourFunction();
    if (res?.success) {
        Message.success(res.message);
    } else {
        Message.error(res?.error || '失败');
    }
} catch (e: any) {
    Message.error('调用失败: ' + e.message);
}
```

### JSX 模板
```typescript
const jsx = `
    try {
        if (!$.global.JSXUtils.hasDocument()) {
            return $.global.JSXUtils.stringify({ error: '没有打开的文档' });
        }
        
        var doc = $.global.JSXUtils.getDocument();
        
        // 你的 PS 操作代码
        
        return $.global.JSXUtils.stringify({ 
            success: true,
            message: '成功'
        });
    } catch (error) {
        return $.global.JSXUtils.stringify({ error: error.toString() });
    }
`;

return evalInlineJSX(jsx);
```

---

## 🎉 完成！

现在你可以：
1. 复制模板代码
2. 替换功能名称
3. 填写核心逻辑
4. 测试
5. 发布

**预计开发时间：5-15 分钟/功能** ⚡

