8.7 KiB
8.7 KiB
混合架构快速开发模板
🚀 5 分钟添加新功能
模板代码
复制下面的模板,替换 YOUR_FEATURE 为你的功能名称。
📝 Step 1: 后端 API(3 层)
文件: Server/app/api/v1/jsx_demo.py
# ==================== 请求/响应模型 ====================
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
/**
* 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
<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>
🔄 开发流程
本地测试
# Terminal 1: 启动后端
cd Server
python -m uvicorn app.main:app --reload
# Terminal 2: 启动前端
cd Designer
npm run dev
发布新版本
# 自动构建、打包、发布
python auto_deploy_core.py
📋 检查清单
开发新功能时,确保:
- 后端添加了 API Key 验证
- 后端添加了详细日志
- 后端添加了输入验证
- 前端使用了正确的 API Key
- 前端添加了错误处理
- UI 有加载提示和错误提示
- 测试了成功和失败的情况
- 更新了版本号
🎯 三种常见模式
模式 1:纯服务器计算
前端输入 → 服务器计算 → 前端显示结果
(不涉及 PS 操作)
模式 2:服务器计算 + PS 应用
前端获取 PS 数据 → 服务器计算 → 前端应用到 PS
(当前示例)
模式 3:本地执行 + 服务器验证
前端执行操作 → 服务器验证权限 → 前端继续
(需要权限控制的操作)
💡 快速参考
后端日志模板
logger.info("="*60)
logger.info("📥 收到请求")
logger.info("✅ 验证通过")
logger.info("🔒 开始计算")
logger.info("✅ 计算完成")
logger.info("="*60)
前端错误处理模板
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 模板
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);
🎉 完成!
现在你可以:
- 复制模板代码
- 替换功能名称
- 填写核心逻辑
- 测试
- 发布
预计开发时间:5-15 分钟/功能 ⚡