如果您曾经在Bitrix24中使用过通用列表,那么您可能知道元素的详细信息页面与编辑页面完全相同。唯一的区别是,如果用户具有只读权限,则该页面将没有“保存”和“应用”按钮。同意,而不是最愉快的界面。
因此,在工作中有必要使用通用列表时,我决定更改详细视图页面,因为我们使用的是框,并且自定义的可能性是无限的。
重要警告
Bitrix24的创建者强烈不鼓励更改公司门户界面,因为包装盒中的公共部分等同于内核,并且在更新系统时,存在删除所有修改内容的风险。
如果您决定将所需的模板复制到本地文件夹并根据需要模拟它们,那么它们将不受更新的影响。但是新功能也不会应用到它们。
因此,在这种情况下,唯一正确的方法是通过Javascript修改DOM树。
实际上,我们只需要更改列表表中详细页面的链接即可:
但是,实际上,这并不是那么容易实现,因为 您需要进入负责显示通用列表的组件,然后在其中编辑链接。
因此,我们将采取不同的途径-通过Javascript,我们将使用SidePanel bitrix库在滑块中打开页面。
有两种方法可以执行此操作-在init.php和您自己的模块中。您还需要注册您的JS库。
而且虽然第二种方法更方便,但我将向您展示第一种,在本文的结尾,我将提供指向我的模块的链接。
所以走吧 所有操作必须在本地文件夹中执行。
首先,您需要创建一个单独的文件夹,用于存储我们的库。让我们称它为查看器,它将具有以下结构:
/viewer
-/js
--viewer.js // js-
-include.php // , init.php
让我们在这里停一下。对于php代码,我创建了一个单独的文件,然后将其包含在init.php中,以免乱扔后者。
现在让我们使用旧的核心CJSCore :: RegisterExt方法注册我们的库:
// include.php
// .. js- viewer,
CJSCore::RegisterExt('elementviewer', [
'js' => '/local/viewer/js/viewer.js', //
'rel' => ['SidePanel'] //
]);
它仍然仅是使用CJSCore :: Init方法将通用列表页面上的该库连接起来的,而且似乎已经放在袋子里了-您可以开始编写该库本身。
但是,并非所有事情都那么简单,因为 连接之前,您需要检查我们在正确的页面上。最好使用正则表达式执行此操作,因为 地址中列表的ID可以更改
// include.php
$pattern = '/\/lists\/(\d+)\/view\//'; // , (\d+) = id
$server = Bitrix\Main\Context::getCurrent()->getServer(); // Server,
if(preg_match($pattern, $server->getRequestUri())) {
CJSCore::Init(['elementviewer']); //
}
因此,库已连接,仍需编写。为此,请创建一个viewer.js文件(如果您之前尚未创建过),首先我们使用BX.namespace函数声明一个名称空间:
const ElementViewer = BX.namespace('Viewer');
现在,可以通过以下方式声明所有变量和函数:
ElementViewer.init = function() {
}
为了不将所有代码写在一个函数中,为方便起见,我们将其分解为较小的代码。
首先,我们需要在页面上找到包含详细信息页面链接的节点。为此,我们将使用BX.findChildren函数,该函数应向我们返回包含包含详细信息页面链接的所有对象的列表:
ElementViewer.findCell = function () {
return BX.findChildren(document, {
class: 'main-grid-cell-content' // css-
}, true);
}
同时,我们将编写一个函数,该函数将从链接中提取列表的ID和元素,以进行进一步的工作:
ElementViewer.pattern = '/lists/(\\d+)/element/0/(\\d+)'; // , = id , = id .
ElementViewer.extractListData = function (url) {
let match = url.match(this.pattern); //
if(match) {
return {
list_id: Number(match[1]),
element_id: Number(match[2])
};
}
}
让我们回到BX.findChildren。该函数的独特之处在于它返回具有指定css类的所有对象的列表,并且这不是链接是事实。因此,我们需要检查,只有在那之后,取消链接打开事件并打开滑块:
ElementViewer.init = function (sliderUrl) {
const cell = this.findCell();
cell.forEach(item => {
let itemChild = item.children;
let child = itemChild[0];
if(child && child.tagName === 'A') {
const listData = this.extractListData(child.toString()); // id
if(listData !== undefined) {
child.addEventListener('click', (e) => {
e.preventDefault(); //
this.openSlider(sliderUrl, listData.list_id, listData.element_id); //
})
}
}
});
}
我们仍然需要编写最后一个将打开滑块的函数。为此,我们使用SidePanel库:
ElementViewer.openSlider = function (sliderUri, listId, elementId) {
// POST, id
let sliderParams = {
list_id: listId,
element_id: elementId
}
return BX.SidePanel.Instance.open(sliderUri, {
allowChangeHistory: false,
cacheable: false,
requestMethod: 'POST',
requestParams: sliderParams
});
}
好吧,库已编写,连接后仍然可以调用init函数。为此,让我们返回include.php,在其中检查页面地址:
if(preg_match($pattern, $server->getRequestUri())) {
CJSCore::Init(['elementviewer']); //
$asset = Bitrix\Main\Page\Asset::getInstance();
$script = '<script>BX.ready(function() {
ElementViewer.init();
})</script>';
$asset->addString($script);
}
最后的接触仍然是-将我们的代码包含在init.php中:
// init.php
$file = $_SERVER['DOCUMENT_ROOT'] . '/local/path/to/viewer/include.php';
if(file_exists($file)) {
require $file;
}
如果一切都正确完成,那么当您单击通用列表的元素时,将打开一个滑块:
最后,如所承诺的,将链接到实现相同功能的模块。
感谢您的关注。