根据您要实现的功能,可能需要在 Limyee 电商平台的系统管理 UI 中公开一些管理选项。管理 UI 完全使用插件定义,因此易于添加。
系统管理 UI 扩展的类型
管理员使用 Limyee 电商平台中的系统管理 UI 来配置全局选项并启用特定功能。
它使用三种类型的插件构建:
管理类别
要将顶级类别添加到管理 UI,必须定义并启用实现 IAdministrationPanelCategory 接口的插件。IAdministrationPanelCategory 接口在 Limyee.Core.dll 的 Limyee.Extensibility.Administration.Version1 命名空间中定义。下面的示例创建一个名为“类别示例”的类别:
using System;
using Limyee.Extensibility.Administration.Version1;
namespace Samples
{
public class SampleAdministrationCategory : IAdministrationPanelCategory
{
private readonly Guid _id = new Guid("07108CA8-9D4E-4D98-BE87-69F19742E0D2");
#region IPlugin
// ...
#endregion
#region IAdministrationPanelCategory
public Guid AdministrationPanelCategoryId { get { return _id; } }
public string AvatarUrl { get { return null; } }
public string CategoryName { get { return "类别示例"; } }
public int? DisplayOrder { get { return null; } }
#endregion
}
}
AdministrationPanelCategoryId 应该是用于唯一引用此类别的唯一标识符。请注意,没有任何面板的管理类别不会在站点中呈现。当它有用户可访问的面板时,该面板将显示在管理 UI 中:
要将新的管理面板添加到管理 UI,必须定义并启用实现 IAdministrationPanel 接口的插件。IAdministrationPanel 接口在 Limyee.Core.dll 中定义。面板的一个非常基本的示例(添加到上面创建的类别,使用相同的 AdministrationPanelCategoryId)如下所示:
using System;
using Limyee.Extensibility.Administration.Version1;
namespace Samples
{
public class SampleAdministrationPanel : IAdministrationPanel
{
private readonly Guid _id = new Guid("8C41AD4F-EBBF-4B03-8CAD-F7A50A66C90D");
#region IPlugin
// ...
#endregion
#region IAdministrationPanel
public Guid PanelId { get { return _id; } }
public string PanelName { get { return "面板示例 1"; } }
public string PanelDescription { get { return "面板示例描述 1。"; } }
public bool VaryCacheByUser { get { return false; } }
public string GetViewHtml() { return "<p>面板内容 1</p>"; }
public bool HasAccess(int userId) { return true; }
public Guid AdministrationPanelCategoryId { get { return new Guid("07108CA8-9D4E-4D98-BE87-69F19742E0D2"); } }
public string CssClass { get { return string.Empty; } }
public int? DisplayOrder { get { return null; } }
public bool IsCacheable { get { return true; } }
#endregion
}
}
PanelId 应该是此面板的唯一标识符。AdministrationPanelCategoryId 应引用管理类别的标识符(示例引用我们上面创建的类别)。PanelName 和 PanelDescription 属性标识 UI 中的面板,当此面板处于活动状态时,GetViewHtml() 方法返回填充管理 UI 的大内容区域的 HTML。
面板的完整内容可以在代码中定义,也可以使用插件定义的小组件定义管理面板。
当一个类别中只有一个面板可用时,将删除插件类型面板,导航到该类别或面板将呈现单个可用面板。当某个类别中的用户可以使用多个面板时,将显示第插件类型面板,并在导航到类别中时选择第一个面板。当多个面板可用且选择了类别时,此示例面板将呈现为:
要按类型将插件列表添加到管理类别,应定义并启用实现 IPluginTypesAdministrationPanel 接口的插件。IPluginTypesAdministrationPanel 接口在 Limyee.Core.dll 的 Limyee.Extensibility.Administration.Version1 命名空间中定义。下面是一个实现示例,其中包括“插件类型”的内容类型插件列表:
using System;
using System.Collections.Generic;
using Limyee.Extensibility.Administration.Version1;
namespace Samples
{
public class SamplePluginTypesAdministrationPanel : IPluginTypesAdministrationPanel
{
#region IPlugin
// ...
#endregion
public Guid AdministrationPanelCategoryId { get { return new Guid("07108CA8-9D4E-4D98-BE87-69F19742E0D2"); } }
public string PluginTypesName { get { return "Plugin Types"; } }
public IEnumerable<Type> PluginTypes { get { return new Type[] { typeof(Limyee.Extensibility.Content.Version1.IContentType) }; } }
public int? DisplayOrder { get { return null; } }
}
}
AdministrationPanelCategoryId 属性引用会将此插件列表添加到其中的类别。PluginTypesName是插件列表上方显示的标签。PluginTypes 属性列出了应列出的插件类型,这些插件可以是接口、基类或实质类。平台呈现匹配插件的列表,这些插件链接到平台定义的插件编辑器。
该平台包括优化过滤选项,以便在列表中有一定数量插件时能提供匹配插件,并且当只有一个匹配的插件时,还会折叠列表使它像其他面板一样显示。
该示例呈现为:
该平台定义了用于在管理 UI 中编辑插件的 UI。插件管理体验可以通过实现 IPluginTypesEditor 接口插件来扩展特定类型。IPluginTypesEditor 接口是在 Limyee.Components.dll 的 Limyee.Extensibility.Version1 命名空间中定义的。下面的示例实现将“示例类型编辑器”添加到用于编辑内容类型的 UI 中:
using System;
using Limyee.Extensibility.Version1;
namespace Samples
{
public class SamplePluginTypesEditor : IPluginTypesEditor
{
#region IPlugin
// ...
#endregion
#region IPluginTypesEditor
public IEnumerable<Type> PluginTypes { get { return new Type[] { typeof(Limyee.Extensibility.Content.Version1.IContentType) }; } }
public string GetViewHtml(IPlugin plugin, string apiJson)
{
return string.Format(@"
<div id=""sample-plugin-type-editor"">
'{0}'的插件类型编辑器内容
</div>
<script type=""text/javascript"">
(function() {{
var api = {1};
api.registerContent({{
name: '类型编辑器示例',
orderNumber: 0,
selected: function() {{ $('#sample-plugin-type-editor').show(); }},
unselected: function() {{ $('#sample-plugin-type-editor').hide(); }}
}});
}})();
</script>
",
plugin.Name,
apiJson);
}
#endregion
}
}
PluginTypes 属性标识应应用此编辑器的插件类型,并且可以是接口或实体类的列表。当在管理 UI 中呈现与定义类型匹配的插件时,将调用插件类型编辑器的 GetViewHtml() 方法,并提供正在编辑的插件的当前实例以及用于与平台定义的插件编辑 UI 交互的 JSON API。GetViewHtml() 方法应返回实现编辑器行为所需的 HTML 和脚本。在上面的示例中,它添加了一组命名的内容“类型编辑器示例”,内容包含文本“正在编辑的插件的名称”和“插件类型编辑器内容”。
该示例呈现为:
GetViewHtml() 呈现的标记和脚本应与提供的 JSON API 交互。API 是一个 JSON 对象,其中包含以下成员,用于定义编辑器的 UI 并与平台插件编辑器集成:
{
registerSave: function(saveFunction) { /* ... */ },
registerContent: function(contentDetails) { /* ... */ },
validate: function() { /* forces all validation on the plugin process, returns true (valid) or false (invalid) */ }
}
应调用 registerContent(contentDetails) 函数来注册条件的渲染内容(如:tabs)。contentDetails 参数是以下格式的对象:
{
name: 'Name of the tab',
orderNumber: 1, /* optional order for this UI compared to other UIs */
selected: function() { /* called when the tab is selected */ },
unselected: function() { /* called when the tab is unselected */ },
validate: function() { /* called when tab should be validated, should return true (valid) or false (invalid) */ },
actions: [
{
label: 'Label of the action',
messageName: 'name of the message to publish when this action is invoked',
messageData: 'data to provide when the message is published',
show: /* either 'always' or 'contextually', default: 'contextually' */
}
]
}
registerSave(saveFunction) 函数应通过引用自定义 UI 的函数来调用,该函数可以用于保存配置表单。当平台调用 saveFunction 参数时,会提供一个有以下属性的对象参数:
{
success: function() { ... },
error: function() { ... }
}
要强制验证所有插件类型编辑器,可以调用 validate() 方法。
要创建可从多个其他面板引用的管理面板,可以定义显式管理面板。显式管理面板不存在于管理 UI 的可浏览层次结构中,而是通过 URL 从任何面板打开。要添加显式管理面板,可以定义并启用实现 IAdministrationExplicitPanel 接口的插件。IAdministrationExplicitPanel 接口是在 Limyee.Core.dll 的 Limyee.Extensibility.Administration.Version1 命名空间中定义。示例实现如下:
using System;
using Limyee.Extensibility.Administration.Version1;
using System.Collections.Specialized;
using System.Linq;
namespace Samples
{
public class SampleExplicitAdministrationPanel : IAdministrationExplicitPanel
{
private readonly Guid _id = new Guid("cb7864ca-395e-49e0-b7b3-4bfece0f9db9");
private IAdministrationExplicitPanelController _explicitPanelController;
#region IPlugin
// ...
#endregion
public void SetController(IAdministrationExplicitPanelController controller)
{
_explicitPanelController = controller;
}
public bool HasAccess(int userId, NameValueCollection parameters)
{
return true;
}
public string CssClass { get { return string.Empty; } }
public int? DisplayOrder { get { return null; } }
public bool IsCacheable { get { return true; } }
public Guid PanelId { get { return _id; } }
public bool VaryCacheByUser { get { return false; } }
public string GetPanelName(NameValueCollection parameters)
{
return "Sample Explicit Panel";
}
public string GetPanelDescription(NameValueCollection parameters)
{
return "This is a sample explicit panel.";
}
public string GetViewHtml(NameValueCollection parameters)
{
if (parameters != null && parameters.Count > 0)
return "<p>Sample explicit panel. Parameters: " + string.Join(", ", parameters.AllKeys.Select(k => k + " = " + parameters[k])) + "</p>";
else
return "<p>Sample explicit panel.</p>";
}
}
}
显式面板通过 SetController() 方法随控制器一起提供。此控制器提供了一种方法来生成此面板的 URL(带或不带参数)。然后,可以将此 URL 提供给其他面板,以使它们能够生成指向此显式面板的链接并共享其功能。大多数成员与上面的面板示例类似,但有一些例外:
如果我们从之前创建的示例面板 1(以及名为“示例面板 2”)添加了指向此示例显式面板的链接,
using System;
using Limyee.Extensibility.Administration.Version1;
namespace Samples
{
public class SampleAdministrationPanel : IAdministrationPanel
{
private readonly Guid _id = new Guid("8C41AD4F-EBBF-4B03-8CAD-F7A50A66C90D");
#region IPlugin
// ...
#endregion
#region IAdministrationPanel
public Guid PanelId { get { return _id; } }
public string PanelName { get { return "面板示例 1"; } }
public string GetViewHtml() { return string.Format("<p>面板内容 1</p><div><a href=\"{0}\">显式面板</a></div>", SiteUrls.Instance().AdministrationExplicitPanel(new Guid("cb7864ca-395e-49e0-b7b3-4bfece0f9db9"))); }
public bool VaryCacheByUser { get { return false; } }
public string GetViewHtml() { return "<p>面板内容 1</p>"; }
public bool HasAccess(int userId) { return true; }
public Guid AdministrationPanelCategoryId { get { return new Guid("07108CA8-9D4E-4D98-BE87-69F19742E0D2"); } }
public string CssClass { get { return string.Empty; } }
public int? DisplayOrder { get { return null; } }
public bool IsCacheable { get { return true; } }
#endregion
}
}
则单击面板中的链接将呈现:
请注意,示例类别和面板仍突出显示,我们可以从显式面板导航回示例面板。
如果我们从“示例面板 2”面板链接到同一显式面板,它将如下所示:
如果我们在生成URL时传递参数,
using System;
using Limyee.Extensibility.Administration.Version1;
namespace Samples
{
public class SampleAdministrationPanel : IAdministrationPanel
{
private readonly Guid _id = new Guid("8C41AD4F-EBBF-4B03-8CAD-F7A50A66C90D");
#region IPlugin
// ...
#endregion
#region IAdministrationPanel
public Guid PanelId { get { return _id; } }
public string PanelName { get { return "面板示例 1"; } }
public string GetViewHtml()
{
return string.Format("<p>面板内容 1</p><div><a href=\"{0}\">显式面板</a></div>", SiteUrls.Instance().AdministrationExplicitPanel(new Guid("cb7864ca-395e-49e0-b7b3-4bfece0f9db9"), new NameValueCollection
{
{ "Key1", "Value1" },
{ "Key2", "Value2" }
}));
}
public bool VaryCacheByUser { get { return false; } }
public string GetViewHtml() { return "<p>面板内容 1</p>"; }
public bool HasAccess(int userId) { return true; }
public Guid AdministrationPanelCategoryId { get { return new Guid("07108CA8-9D4E-4D98-BE87-69F19742E0D2"); } }
public string CssClass { get { return string.Empty; } }
public int? DisplayOrder { get { return null; } }
public bool IsCacheable { get { return true; } }
#endregion
}
}
显式面板可以检索并使用这些值: