Files
DP/tempdocs/混合架构快速开发模板.md

356 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 混合架构快速开发模板
## 🚀 5 分钟添加新功能
### 模板代码
复制下面的模板,替换 `YOUR_FEATURE` 为你的功能名称。
---
## 📝 Step 1: 后端 API3 层)
**文件:** `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: 前端 API2 层)
**文件:** `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 分钟/功能**