东莞市连易网络科技有限公司
东莞市连易网络科技有限公司
  • 网站
  • 用户
  • 购物车
  • 购物车
  • 搜索
  • 网站
  • 用户
帮助
帮助
开发文档 创建自定义应用程序和内容
  • 用户文档
  • 开发文档
  • API文档
  • 提及
  • 标签
  • 更多
  • 取消
  • 新建
  • +开始
  • +UI 自定义
  • +外部集成
  • -插件/框架扩展
    • -插件
      • 异常和日志记录
      • 插件生命周期
      • -插件示例
        • 使用小组件从插件渲染内容
        • 公开数据给外部源
        • 公开配置选项
        • 创建动态
        • -创建自定义应用程序和内容
          • +向内容添加核心服务支持
        • 基于模板的电子邮件
        • 处理事件
        • 处理内容中的嵌入文件
        • 定义权限
        • 扩展规则支持
        • 文件交互
        • 文件查看器
        • 注册模板令牌
        • 管理依赖关系
        • 管理物理文件存储
        • 翻译插件文本
        • 通知
    • +设置开发环境
    • +进程 API

创建自定义应用程序和内容

Limyee 电商平台允许您创建自己的内容和应用程序类型。

为什么要创建自定义应用程序和内容?

如果您正在编写新的应用程序或有要与 Limyee 电商平台的核心服务进行交互的内容(内部或外部),则在平台内创建自定义内容和应用程序可能会有所帮助。平台内的内容类型可以与核心服务交互。点赞,评级,评论,审核,提及和主题标签是您的内容在平台注册后可以访问的一些服务。

在内容模型文章中,有关于内容和应用程序如何适应平台的更深入讨论。

内容和内容类型

平台中提供了两个接口,用于标识内容类型和单个内容实体。IContentType 接口用于标识内容类型,IContent 接口用于表示各个内容实体。这两个接口都可以在 Limyee.Core.dll 中找到。

应用程序和应用程序类型

与内容类似,该平台提供 IApplicationType 来标识应用程序的类型,而 IApplication 是表示单个应用程序实体。这些接口也可以在 Limyee.Core.dll 中找到。

创建应用程序和内容

对于我们的应用程序示例,我们将创建一个链接应用程序。链接应用程序将是指向网站链接的集合。

首先,让我们概述一下我们的实体。

 LinksApplication 实体

我们的 LinksApplication 实体将实现 IApplication 接口,并表示链接应用程序的一个实例。

ApplicationTypeId 是一个唯一的 ID,它表示平台中的一种应用程序类型,您可以自行定义此值。在这个例子中,我们有一个静态类,我们在其中定义了我们的 Id,因此可以从多个位置引用它。ApplicationId 是平台中单个应用程序的唯一 ID。我们也将向平台提供此功能。

public Guid ApplicationId { get; set; }

public Guid ApplicationTypeId
{
    get { return ContentTypes.LinksApplicationId; }
}

IApplication 界面不需要“名称”和“描述”字段,我们使用它来存储基本数据。然后,HtmlName 和 HtmlDescription 方法用于根据目标提供输出。这些允许针对这些目标定制输出,例如,如果您的目标是电子邮件,您可能不希望在内容中内联显示图像。我们的示例数据仅使用文本作为名称和描述,无需针对不同的目标定制输出,而是仅返回所有目标的文本。

public string Name { get; set; }
public string Description { get; set; }

public string HtmlName(string target)
{
    return Name;
}

public string HtmlDescription(string target)
{
    return Description;
}

对于此示例,我们不允许禁用应用程序,因此 IsEnabled 属性将始终返回 true。我们不会将应用程序存储在不同的组中,而是将它们全部存储在站点根组中,因此我们将始终返回应用程序容器的站点组。我们的应用程序没有用于查看它的 URL或与之关联的头像,因此,AvatarUrl 和 Url 都只会返回 null。

public bool IsEnabled
{
    get { return true; }
}

public IContainer Container
{
    get { return Apis.Get<IGroups>().Root; }
}

string IApplication.AvatarUrl
{
    get { return null; }
}

string IApplication.Url
{
    get { return null; }
}

以下是已完成的链接应用程序源代码:

using System;
using Limyee.Extensibility;
using Limyee.Extensibility.Api.Entities.Version1;
using Limyee.Extensibility.Api.Version1;
using Limyee.Extensibility.Content.Version1;

namespace Samples.Links
{
    public class LinksApplication : ApiEntity, IApplication
    {
        public string Name { get; set; }
        public string Description { get; set; }

        #region IApplication Members
        public Guid ApplicationId { get; set; }

        public Guid ApplicationTypeId
        {
            get { return ContentTypes.LinksApplicationId; }
        }

        public string HtmlName(string target)
        {
            return Name;
        }

        public string HtmlDescription(string target)
        {
            return Description;
        }

        public bool IsEnabled
        {
            get { return true; }
        }

        public IContainer Container
        {
            get { return Apis.Get<IGroups>().Root; }
        }

        string IApplication.AvatarUrl
        {
            get { return null; }
        }

        string IApplication.Url
        {
            get { return null; }
        }
        #endregion
    }
}

LinkItem 实体

我们的 LinkItem 实体将实现 IContent 接口,并在链接应用程序中表示单个链接项。

ContentTypeId 是一个唯一的 ID,表示平台中的一种内容类型,您可以在创建内容类型时自行定义此值。该示例使用定义 ApplicationTypeId 的同一静态类来定义此 Id。ContentId 是平台中单个内容项的唯一 Id。我们也将向平台提供此功能。

public Guid ContentId { get; set; }

public Guid ContentTypeId
{
    get { return ContentTypes.LinksItemId; }
}

每条内容都与平台中的一个应用程序相关,我们已经定义了一个属性来存储我们内容的应用程序 ApplicationId。当我们在 IContent 接口上实现 Application 属性时,使用此值返回应用程序的实例。

public Guid ApplicationId { get; set; }

public IApplication Application
{
    get { return LinksData.GetApplication(ApplicationId); }
}

IContent 接口不需要“名称”和“描述”字段,我们使用它来存储基本数据。然后,HtmlName 和 HtmlDescription 方法用于根据目标提供输出。这些允许针对这些目标定制输出,例如,如果您的目标是电子邮件,您可能不希望在内容中内联显示图像。

public string Name { get; set; }
public string Description { get; set; }

public string HtmlName(string target)
{
    return Name;
}

public string HtmlDescription(string target)
{
    return Description;
}

每个链接项都有一个 Url,IContent 接口需要一个 Url,因此我们将使用该属性来存储 Url 并满足接口要求。

public string Url { get; set; }

CreateDate、IsEnabled、AvatarUrl 和 CreatedByUserId 属性是接口所必需的,但在此示例中将是静态的或不需要的,因此我们将实现这些属性,但它们不提供任何值。如果这是一个实现平台核心服务或其他功能的全功能示例,则这些值对于正确填充将变得非常重要。

public DateTime CreatedDate { get; set; }

public bool IsEnabled
{
    get { return true; }
}

string IContent.AvatarUrl
{
    get { return null; }
}

int? IContent.CreatedByUserId
{
    get { return null; }
}

以下是已完成的 LinkItem 实体源代码:

using System;
using Limyee.Extensibility.Api.Entities.Version1;
using Limyee.Extensibility.Content.Version1;

namespace Samples.Links
{
    public class LinkItem : ApiEntity, IContent
    {
        public Guid ApplicationId { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }

        #region IContent Members
        public Guid ContentId { get; set; }

        public Guid ContentTypeId
        {
            get { return ContentTypes.LinksItemId; }
        }

        public IApplication Application
        {
            get { return LinksData.GetApplication(ApplicationId); }
        }

        public string HtmlName(string target)
        {
            return Name;
        }

        public string HtmlDescription(string target)
        {
            return Description;
        }

        public string Url { get; set; }

        public DateTime CreatedDate { get; set; }

        public bool IsEnabled
        {
            get { return true; }
        }

        string IContent.AvatarUrl
        {
            get { return null; }
        }

        int? IContent.CreatedByUserId
        {
            get { return null; }
        }

        #endregion
    }
}

LinksApplicationType 实体

IPlugin 和 ITranslatablePlugin 接口在其他文章中讨论过,我们将跳过这些接口的实现解释,而专注于 IApplicationType 实现。

ApplicationTypeId 与定义 IApplication 实体时使用的 ID 相同。应用程序名称是将在平台中显示的应用程序的名称。该示例使用翻译,以便可以为平台支持的每种语言翻译应用程序名称。

Guid IApplicationType.ApplicationTypeId
{
    get { return ContentTypes.LinksApplicationId; ; }
}

string IApplicationType.ApplicationTypeName
{
    get { return _translations.GetLanguageResourceValue("ApplicationTypeName"); }
}

AttachChangeEvents 方法提供了 IApplicationStateChanges 对象。应用程序类型使用此对象来通知平台对应用程序的更改。例如,当您的应用程序被删除时,通知平台删除与该应用程序关联的数据。

void IApplicationType.AttachChangeEvents(IApplicationStateChanges stateChanges)
{
    _applicationState = stateChanges;
}

ContainerTypes 属性应返回可以保存此应用程序的所有容器类型。在这种情况下,唯一的容器是组,因此返回 Id。

Guid[] IApplicationType.ContainerTypes
{
    get { return new Guid[] { Apis.Get<IGroups>().ContentTypeId }; }
}

最后,Get 方法应返回 LinksApplication 实体的实例。

IApplication IApplicationType.Get(Guid applicationId)
{
    return LinksData.GetApplication(applicationId);
}

以下是已完成的链接应用程序类型源代码:

using System;
using Limyee.Extensibility;
using Limyee.Extensibility.Api.Version1;
using Limyee.Extensibility.Content.Version1;
using Limyee.Extensibility.Version1;

namespace Samples.Links
{
    public class LinksApplicationType : IApplicationType, ITranslatablePlugin
    {
        IApplicationStateChanges _applicationState = null;
        ITranslatablePluginController _translations = null;

        #region IPlugin Members
        string IPlugin.Name
        {
            get { return "Links"; }
        }
        string IPlugin.Description
        {
            get { return "Collections of Links"; }
        }

        void IPlugin.Initialize()
        {

        }
        #endregion

        #region IApplicationType Members
        Guid IApplicationType.ApplicationTypeId
        {
            get { return ContentTypes.LinksApplicationId; ; }
        }

        string IApplicationType.ApplicationTypeName
        {
            get { return _translations.GetLanguageResourceValue("ApplicationTypeName"); }
        }

        void IApplicationType.AttachChangeEvents(IApplicationStateChanges stateChanges)
        {
            _applicationState = stateChanges;
        }

        Guid[] IApplicationType.ContainerTypes
        {
            get { return new Guid[] { Apis.Get<IGroups>().ContentTypeId }; }
        }

        IApplication IApplicationType.Get(Guid applicationId)
        {
            return LinksData.GetApplication(applicationId);
        }
        #endregion

        #region ITranslatablePlugin Members
        Translation[] ITranslatablePlugin.DefaultTranslations
        {
            get
            {
                var t = new Translation("en-US");
                t.Set("ApplicationTypeName", "Links Application");
                return new Translation[] { t };
            }
        }

        void ITranslatablePlugin.SetController(ITranslatablePluginController controller)
        {
            _translations = controller;
        }
        #endregion
    }
}

LinkItemContentType 实体

同样,IPlugin 和 ITranslatablePlugin 接口在其他文章中讨论过,我们将跳过对这些实现的解释,并专注于IContentType实现。

ContentTypeId 与定义 IContent 实体时使用的 ID 相同。内容名称是将在平台中显示的内容名称。该示例使用翻译,以便可以为平台支持的每种语言翻译内容名称。

Guid IContentType.ContentTypeId
{
    get { return ContentTypes.LinksItemId; }
}

string IContentType.ContentTypeName
{
    get { return _translations.GetLanguageResourceValue("ContentTypeName"); }
}

AttachChangeEvents 方法提供了 IContentStateChanges 对象。您的内容类型使用此对象来通知平台您的内容所做的更改。例如,当您的内容被删除时,通知平台删除与该内容关联的数据。

void IContentType.AttachChangeEvents(IContentStateChanges stateChanges)
{
    _contentState = stateChanges;
}

ApplicationTypes 属性应返回可以保存此内容的所有应用程序类型。在这种情况下,唯一的应用程序是我们的 LinksApplication,因此返回 Id。

Guid[] IContentType.ApplicationTypes
{
    get { return new Guid[] { ContentTypes.LinksApplicationId }; }
}

最后,Get 方法应返回 LinkItem 实体的实例。

IContent IContentType.Get(Guid contentId)
{
    return LinksData.GetLink(contentId);
}

以下是已完成的 LinkItemContentType 实体源代码:

using System;
using Limyee.Extensibility.Content.Version1;
using Limyee.Extensibility.Version1;
using IContent = Limyee.Extensibility.Content.Version1.IContent;

namespace Samples.Links
{
    public class LinkItemContentType : IContentType, ITranslatablePlugin
    {
        IContentStateChanges _contentState = null;
        ITranslatablePluginController _translations = null;

        #region IPlugin Members
        string IPlugin.Name
        {
            get { return "Link Items"; }
        }
        string IPlugin.Description
        {
            get { return "Items in a Links collection"; }
        }

        void IPlugin.Initialize()
        {

        }
        #endregion

        #region IContentType Members
        Guid[] IContentType.ApplicationTypes
        {
            get { return new Guid[] { ContentTypes.LinksApplicationId }; }
        }

        void IContentType.AttachChangeEvents(IContentStateChanges stateChanges)
        {
            _contentState = stateChanges;
        }

        Guid IContentType.ContentTypeId
        {
            get { return ContentTypes.LinksItemId; }
        }

        string IContentType.ContentTypeName
        {
            get { return _translations.GetLanguageResourceValue("ContentTypeName"); }
        }

        IContent IContentType.Get(Guid contentId)
        {
            return LinksData.GetLink(contentId);
        }
        #endregion

        #region ITranslatablePlugin Members
        Translation[] ITranslatablePlugin.DefaultTranslations
        {
            get
            {
                var t = new Translation("en-US");
                t.Set("ContentTypeName", "Link Item");
                return new Translation[] { t };
            }
        }

        void ITranslatablePlugin.SetController(ITranslatablePluginController controller)
        {
            _translations = controller;
        }
        #endregion
    }
}

自定义内容和应用程序插件现已完成,但我们可以添加一些附加功能,使其更易于在平台站点中使用。

小组件扩展

到目前为止,我们将无法使用 velocity 小组件与我们的新应用程序或内容进行交互,当您实现了 IScriptedContentWidgetExtensionsionsions, 就可以公开我们的数据方法,以便可以使用 velocity 调用它们。我们将添加一个名为 custom_v1_links 的实现来扩展 LinksApplication,以及一个名为 custom_v1_linkitem 的实现来扩展 LinkItem。

我们的 custom_v1_links 实现扩展了 LinksApplicationMethods 类,并公开该类的方法。$custom_v1_links.List() 将返回所有链接应用程序的列表,$custom_v1_links.Get(Guid applicationId) 将返回一个链接应用程序。

custom_v1_links 扩展的源代码:

using System;
using Limyee.Extensibility.Api.Entities.Version1;
using Limyee.Extensibility.UI.Version1;

namespace Samples.Links.WidgetApi
{
    public class LinksApplicationWidgetExtension : IScriptedContentWidgetExtension
    {
        #region IScriptedContentWidgetExtension Members

        public string ExtensionName
        {
            get { return "custom_v1_links"; }
        }

        public object Extension
        {
            get { return new LinksApplicationMethods(); }
        }

        #endregion

        #region IPlugin Members

        public string Name
        {
            get { return "Links Extension (custom_v1_links)"; }
        }

        public string Description
        {
            get { return "Enables widgets to work with Links Applications."; }
        }

        public void Initialize()
        {
        }
        #endregion
    }

    public class LinksApplicationMethods
    {
        public ApiList<LinksApplication> List()
        {
            return new ApiList<LinksApplication>(LinksData.ListApplications());
        }

        public LinksApplication Get(Guid applicationId)
        {
            return LinksData.GetApplication(applicationId);
        }
    }
}

我们的 custom_v1_linkitem 实现扩展了 LinkItemMethods 类,并公开该类的方法。$custom_v1_linkitem.List(Guid applicationId) 将返回列表,$custom_v1_linkitem.Get(Guid contentId) 将返回 LinkItem 的单个实例。

custom_v1_linkitem 扩展的源代码:

using System;
using Limyee.Extensibility.Api.Entities.Version1;
using Limyee.Extensibility.UI.Version1;

namespace Samples.Links.WidgetApi
{
    public class LinkItemWidgetExtension : IScriptedContentWidgetExtension
    {
        #region IScriptedContentWidgetExtension Members

        public string ExtensionName
        {
            get { return "custom_v1_linkitem"; }
        }

        public object Extension
        {
            get { return new LinkItemMethods(); }
        }

        #endregion

        #region IPlugin Members

        public string Name
        {
            get { return "LinkItem Extension (custom_v1_linkitem)"; }
        }

        public string Description
        {
            get { return "Enables widgets to work with Link Items."; }
        }

        public void Initialize()
        {
        }

        #endregion
    }

    public class LinkItemMethods
    {
        public ApiList<LinkItem> List(Guid applicationId)
        {
            return new ApiList<LinkItem>(LinksData.ListLinks(applicationId));
        }

        public LinkItem Get(Guid contentId)
        {
            return LinksData.GetLink(contentId);
        }
    }
}

插件组

我们可以按原样部署它,但是您需要在管理面板中搜索以启用这4个插件,更不用说这些插件彼此依赖,并且不应彼此独立使用。我们可以使用 IPluginGroup 创建一个入口来同时启用或禁用所有相关插件,以解决这些问题。

以下是我们插件组的完整源代码:

using System;
using System.Collections.Generic;
using Samples.Links.WidgetApi;
using Limyee.Extensibility.Version1;

namespace Samples.Links.Plugins
{
    public class LinksPluginGroup : IPluginGroup
    {
        #region IPlugin Members
        string IPlugin.Name
        {
            get { return "Links Application"; }
        }
        string IPlugin.Description
        {
            get { return "Defines the plugins required by the links application"; }
        }

        void IPlugin.Initialize()
        {

        }
        #endregion

        #region IPluginGroup Members
        IEnumerable<Type> IPluginGroup.Plugins
        {
            get
            {
                return new[]
                {
                    typeof (LinksApplicationType),
                    typeof (LinkItemContentType),
                    typeof (LinkItemWidgetExtension),
                    typeof (LinksApplicationWidgetExtension)
                };
            }
        }
        #endregion
    }
}

示例小组件

现在,我们可以将包含链接应用程序的 dll 部署到平台,并启用链接应用程序插件组。我们可以使用小组件来测试我们的应用程序是否正常工作,并且我们的内容是否可以使用核心服务,在本例中为“点赞”的服务。

该小组件将列出所有链接应用程序。对于每个应用程序,它将列出所有链接项,并且这些项将分别显示一个“点赞”按钮。

该小组件的源代码如下所示:

#set($linkapps = $custom_v1_links.List())

#foreach ($linkapp in $linkapps)
#beforeall
    <ul class="content-list simple">
#each
        <li class="content-item simple">
            <h4 style="margin-bottom: 5px;">$linkapp.Name</h4>
            <div class="description" style="margin: 5px 0;">$linkapp.Description</div>
            
            #set($links = $custom_v1_linkitem.List($linkapp.ApplicationId))
            
            #foreach ($link in $links)
		    #beforeall
		    	<ul class="links">
		    #each
    				<li class="link-item" style="margin-bottom: 5px;">
        				#if ($limyee_v1_user.IsRegistered($limyee_v1_user.Accessing.Id))
        					#set ($likeFormat = '{toggle} <span class="count"><span class="icon"></span>{count}</span>')
        				#else
        					#set ($likeFormat = '<span class="count"><span class="icon"></span>{count}</span>')
        				#end    				

    				    <a href="$link.Url">$link.Name</a> - $limyee_v1_ui.Like($link.ContentId, $link.ContentTypeId, "%{ Format = $likeFormat, IncludeTip = 'true' }")

    				    <div class="description">$link.Description</div>
    				</li>
		    #afterall
                </ul>		    
		    #end
        </li>
#afterall
    </ul>
#end

将小组件添加到页面后,您应该会看到以下内容:

可下载源

 Samples.Links.zip

现在,我们已经有了基本级别的应用程序和内容类型,我们可以开始向应用程序添加对核心服务的支持。有关向内容添加核心服务支持,请查阅其他文章。

  • 分享
  • 历史
  • 更多
  • 取消
相关
推荐
Copyright © 2021 东莞市连易网络科技有限公司. All rights reserved.
Powered by Limyee Commerce System(3.0.0). © 2014 - 2025 Limyee Inc.