我发现我公司的一些人做了类似的功能,我和他们一起找到了一个令人满意的解决方案。如果将来还有其他人想做与此相同的事情,尽管我会分享我是如何做到的。
问题 1:Add In Part 是共享的还是个人的
如果 AddInPart 是由用户共享或创建的,我找不到任何属性,所以我通过简单地加载所有共享的 AddInPart 并将它们的 GUID 存储在一个数组中来解决这个问题。通过这样做,我可以检查我想要删除的 AddInPart 是否在该数组中,并在这种情况下采取正确的措施。我是这样做的:
var sharedWebPartGuids = new Array(); // An array containing guids from all shared webparts
function fetchSharedWebparts() {
//get the client context
var clientContext = new SP.ClientContext(_spPageContextInfo.webServerRelativeUrl);
//get the current page as a file
var oFile = clientContext.get_web().getFileByServerRelativeUrl(_spPageContextInfo.serverRequestPath);
// Fetch all webparts that are shared
var limitedWebPartManagerShared = oFile.getLimitedWebPartManager(SP.WebParts.PersonalizationScope.shared);
//get the web parts on the current page
var collWebPart = limitedWebPartManagerUser.get_webParts();
//request the web part collection and load it from the server
clientContext.load(collWebPart);
clientContext.executeQueryAsync(Function.createDelegate(this, function() {
// Go through all webparts
for (var x = 0; x < collWebPart.get_count(); x++) {
var webPartDef = collWebPart.get_item(x);
sharedWebPartGuids.push(webPartDef.get_id().toString());
}
}), Function.createDelegate(this, function() {
alert("failed to fetch shared webparts from page")
}));
}
问题2:获取ClientWebPart(AppPart)xml
不幸的是,如果不为每个具有应该能够添加的 AppPart 的应用程序手动提供 ProductID(GUID),我就无法做到这一点。为此,我部署了一个名为AvailableAppParts的列表,其中包含两列;标题和ProductId。然后,我通过比较Title将列表中的项目与已安装的应用程序匹配。GUID 可以在 App 中的 AppManifest.xml 中找到,或者将 AppPart 添加到页面然后导出。我还必须在我的代码中包含一个 xml 模板并替换唯一值。由于一切都是异步完成的,我有一个名为initMethods的计数器,我为每个异步方法添加了它,然后在它们结束时调用initMethodDone()在我向用户显示任何内容之前检查是否所有异步方法都已完成。我是这样做的:
var webpartsFromGallery = new Array(); // An array where I store an object for each AppPart
// The xml template:
var appPartXml = '<webParts><webPart xmlns="http://schemas.microsoft.com/WebPart/v3"><metaData><type name="Microsoft.SharePoint.WebPartPages.ClientWebPart, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" /><importErrorMessage>Cannot import this Web Part.</importErrorMessage> </metaData><data><properties><property name="TitleIconImageUrl" type="string" /><property name="Direction" type="direction">NotSet</property><property name="ExportMode" type="exportmode">NonSensitiveData</property><property name="HelpUrl" type="string" /><property name="Hidden" type="bool">False</property><property name="Description" type="string">AppPart Description</property><property name="FeatureId" type="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">{FeatureId}</property><property name="Title" type="string">{Title}</property><property name="AllowHide" type="bool">True</property><property name="ProductWebId" type="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">{ProductWebId}</property><property name="AllowZoneChange" type="bool">True</property><property name="TitleUrl" type="string" /><property name="ChromeType" type="chrometype">Default</property><property name="AllowConnect" type="bool">True</property><property name="Width" type="unit" /><property name="Height" type="unit" /><property name="WebPartName" type="string">AppPart</property><property name="HelpMode" type="helpmode">Navigate</property><property name="AllowEdit" type="bool">True</property><property name="AllowMinimize" type="bool">True</property><property name="ProductId" type="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">{ProductId}</property><property name="AllowClose" type="bool">True</property><property name="ChromeState" type="chromestate">Normal</property></properties></data></webPart></webParts>';
function fetchAppPartsFromGallery() {
initMethods++;
var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
// Fetch all installed Apps on this site (SPWeb)
var appInstances = SP.AppCatalog.getAppInstances(ctx, web);
ctx.load(appInstances);
ctx.executeQueryAsync(
function() {
if (appInstances.get_count() == 0) {
// No apps found, stop here
return;
}
// Iterate through the app instances and store them in a map
// Also create a filter string
var map = new Object();
var filterString = "";
for (var i = 0; i < appInstances.get_count(); i++) {
var instance = appInstances.getItemAtIndex(i);
var title = instance.get_title();
map[title] = instance;
// Append filter
if (filterString.length > 0) {
filterString += "or";
}
filterString += "(Title+eq+'" + title + "')";
}
if (filterString.length > 0) {
filterString = "?$filter=" + filterString;
}
// Fetch available apps from my list
$.ajax({
url: siteApiUrl + "/web/lists/getbytitle('AvailableAppParts')/items" + filterString,
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
},
success: function(data) {
// Go through all returned apps and build the xml for each one
var results = data.d.results;
for (var i = 0; i < results.length; i++) {
var listItem = results[i];
var title = listItem.Title;
var productId = listItem.ProductId;
var appInstance = map[title];
if (!appInstance) {
console.log("Could not find app with title '" + title + "'");
continue;
}
var instanceId = appInstance.get_id();
var webId = appInstance.get_webId();
var featureId = calculateFeatureIdFromProductId(productId);
// This is the values we have to replace with our unique ones
var xml = appPartXml.replace(/{Title}/g, title);
xml = xml.replace(/{ProductId}/g, productId);
xml = xml.replace(/{ProductWebId}/g, webId);
xml = xml.replace(/{FeatureId}/g, featureId);
webpartsFromGallery.push({
id: instanceId,
title: title,
xml: xml
});
}
function calculateFeatureIdFromProductId(productID) {
// Calculate featureId since it is always one hexadecimal value higher than productId
var lastIndex = productID.lastIndexOf('-');
var lastNumber = productID.substring(lastIndex + 12);
// We are using hexadecimal numbers therefor using parseInt(..., 16) and toString(16)
var increment = parseInt(lastNumber, 16) + 1;
var incrementHex = increment.toString(16);
var featureID = productID.substring(0, lastIndex + 12) + incrementHex;
return featureID;
}
initMethodDone();
},
error: function(error) {
alert(JSON.stringify(error));
initMethodDone();
}
});
},
function(sender, args) {
console.log(JSON.stringify(args));
initMethodDone();
});
}