Gallery Editor Child SDK
概述
本 Skill 描述了 Gallery 静态网页(子页面)如何通过 Penpal 接收 ModelScope 主站 Gallery Editor(父页面)注入的编辑能力。
子页面被嵌入 /tools/gallery-editor?galleryId=xx/xx 的 iframe 中时,父页面通过 Penpal 向其注入方法:
getConfig()— 获取 gallery 域名下 /config.json 的完整内容saveGallery(files)— 全量更新 gallery 所有文件并发布saveConfig(json)— ⚠️ 暂不支持,请使用 saveGalleryuploadAsset(fileBase64, filename)— ⚠️ 暂不支持,请使用 saveGallery
前提条件
- 子页面需引入 Penpal v6.x
- 子页面需被
g-{gid}.ms.show域名托管(即存储在 Gallery 中的静态 HTML)
接口协议
| 方法 | 方向 | 签名 | 说明 |
|------|------|------|------|
| getConfig | 子 → 父 | () => Promise<object \| null> | 从 gallery 域名下读取 /config.json,不存在则返回 null |
| saveGallery | 子 → 父 | (files: {filename, contentBase64}[]) => Promise<{success}> | 全量更新 gallery 所有文件并发布 |
| saveConfig | 子 → 父 | (json: object) => Promise<{success}> | ⚠️ 暂不支持,会抛出错误 |
| uploadAsset | 子 → 父 | (fileBase64, filename) => Promise<string> | ⚠️ 暂不支持,会抛出错误 |
最小集成代码(CDN 方式)
<!-- 引入 Penpal CDN -->
<script src="https://resources.modelscope.cn/third-part/js/penpal/6.2.2/dist/penpal.min.js"></script>
<script>
(function() {
// 检测是否在 iframe 中
if (window.self === window.top) {
console.log('[GallerySDK] Not in iframe, editor disabled');
return;
}
var connection = Penpal.connectToParent({
// 子页面可暴露方法给父页面(可选)
methods: {
onConfigUpdated: function(config) {
console.log('[GallerySDK] Config updated from parent:', config);
}
}
});
connection.promise.then(function(parent) {
console.log('[GallerySDK] Connected to editor');
// 将 parent API 挂载到全局
window.__galleryEditor = {
ready: true,
getConfig: parent.getConfig,
saveGallery: parent.saveGallery,
};
// 派发自定义事件,通知业务代码编辑器已就绪
window.dispatchEvent(new CustomEvent('gallery-editor-ready', {
detail: { parent: parent }
}));
});
})();
</script>
TypeScript 类型声明
如果子页面是 TypeScript 项目,可创建如下类型声明文件:
// gallery-editor-sdk.d.ts
interface GalleryEditorAPI {
ready: boolean;
getConfig(): Promise<Record<string, any> | null>;
saveGallery(files: { filename: string; contentBase64: string }[]): Promise<{ success: boolean }>;
}
declare global {
interface Window {
__galleryEditor?: GalleryEditorAPI;
}
interface WindowEventMap {
'gallery-editor-ready': CustomEvent<{ parent: GalleryEditorAPI }>;
}
}
export {};
使用示例
1. 读取配置
window.addEventListener('gallery-editor-ready', async function() {
var editor = window.__galleryEditor;
// 读取当前配置(从 gallery 域名的 /config.json 读取)
var config = await editor.getConfig();
if (config === null) {
console.log('config.json 不存在,使用默认配置');
config = { title: '默认标题' };
}
console.log('当前配置:', config);
});
2. 全量更新 Gallery 文件
window.addEventListener('gallery-editor-ready', async function() {
var editor = window.__galleryEditor;
// 准备所有要提交的文件(内容需为 Base64)
var files = [
{
filename: 'config.json',
contentBase64: btoa(JSON.stringify({ title: '新标题', theme: 'dark' }, null, 2)),
},
{
filename: 'index.html',
contentBase64: btoa('<html><body>Hello</body></html>'),
}
];
var result = await editor.saveGallery(files);
console.log('全量更新结果:', result); // { success: true }
});
3. 上传文件并全量提交
window.addEventListener('gallery-editor-ready', function() {
var editor = window.__galleryEditor;
document.getElementById('file-input').addEventListener('change', async function(e) {
var selectedFiles = e.target.files;
if (!selectedFiles.length) return;
var fileList = [];
for (var i = 0; i < selectedFiles.length; i++) {
var file = selectedFiles[i];
var base64 = await fileToBase64(file);
fileList.push({ filename: file.name, contentBase64: base64 });
}
var result = await editor.saveGallery(fileList);
console.log('提交成功:', result);
});
});
function fileToBase64(file) {
return new Promise(function(resolve) {
var reader = new FileReader();
reader.onload = function() {
resolve(reader.result.split(',')[1]);
};
reader.readAsDataURL(file);
});
}
3. 检测编辑模式并切换 UI
// 方式一:监听事件
window.addEventListener('gallery-editor-ready', function() {
document.getElementById('edit-toolbar').style.display = 'block';
document.body.classList.add('editor-mode');
});
// 方式二:轮询检查(用于懒加载场景)
function isInEditorMode() {
return !!(window.__galleryEditor && window.__galleryEditor.ready);
}
注意事项
- 全量更新: gallery 当前只支持全量更新(saveGallery),saveConfig 和 uploadAsset 暂不支持
- 文件大小限制: saveGallery 使用 Base64 编码传输,建议单文件不超过 10MB
- 仅在 iframe 中生效: 直接访问 Gallery URL 时
connectToParent不会触发,编辑能力不会开启 - 异步操作: 所有方法均为 Promise,需 await 或 .then() 处理
- getConfig 读取方式: 直接从 gallery 域名下的 /config.json 读取,返回 null 表示文件不存在
- 发布延迟: saveGallery 包含发布步骤,更新后可能需要几秒才能在域名上看到新内容
微信扫一扫