我正在尝试启动并运行 Kirby 3.6 的前端搜索。但我现在陷入困境。我几乎不知道如何在 Kirby 中使用插件。由于我们在 Algolia 中搜索了一个 Kirby 3.5 项目,所以我想只是采用它,并可能在需要的地方对其进行调整。事实证明,这比我想象的要严重得多,尤其是对于我没有经验的自己。
所以,现在的问题是搜索插件似乎试图取代 Kirby 的内部“k-search”,它绝对不应该这样做。我希望它在后端做的是在保存页面时更新页面的索引,并在后端提供一个按钮来更新整个索引。
我应该添加到搜索中的一件事是 pdf/doc 文件及其在 Algolia 中的内容的索引。我还没有弄清楚那个。
我正在使用以下插件的修改版本(由前同事修改,无法联系他 atm): https ://github.com/distantnative/search-for-kirby
每当我打开具有索引所有页面的按钮的页面时,我都会收到一条错误消息,指出 this.load 不是函数。单击按钮时,获取失败“POST http://localhost:8888/MySite/api/search 400 (Bad Request)”我的猜测是这来自替换 kirby 面板搜索的插件......
这是插件文件夹中我的 index.js 的全部内容:
(function () {
var a = {
extends: "k-search",
data: () => ({ hasIndex: !0, isProcessing: !1 }),
computed: {
rebuild() {
let i = this.$t("search.index.missing");
return this.isProcessing && (i += "\u2026"), i;
},
},
methods: {
async index() {
this.isProcessing = !0;
try {
await this.$api.post("search"), this.$store.dispatch("notification/success", this.$t("search.index.built"));
} catch (i) {
console.error(e);
} finally {
await this.search(this.q), (this.isProcessing = !1), (this.hasIndex = !0);
}
},
async search(i) {
this.isLoading = !0;
try {
if ("" === i) throw new Error();
const t = await this.$api.get("search", { q: i, select: ["id", "title", "email", "name", "filename", "parent", "panelIcon", "panelImage"] });
this.items = t.data.map((i) => {
let e = { id: i.id, icon: { ...i.panelImage, back: "black", color: "#fff" }, image: { ...i.panelImage, back: "pattern", cover: !0 } };
return (
i.hasOwnProperty("email")
? ((e.title = i.name || i.email), (e.link = this.$api.users.link(i.id)), (e.info = i.email), (e.icon = { back: "black", type: "user" }))
: i.hasOwnProperty("filename")
? ((e.title = i.filename), (e.link = this.$api.files.link(this.$api.pages.url(i.parent.id), i.filename)), (e.info = i.id))
: ((e.title = i.title), (e.link = this.$api.pages.link(i.id)), (e.info = i.id)),
e
);
});
} catch (e) {
"error.notFound" === e.key && (this.hasIndex = !1), (this.items = []);
} finally {
(this.selected = -1), (this.isLoading = !1), (this.hasResults = this.items.length > 0);
}
},
},
};
if (typeof a === "function") {
a = a.options;
}
Object.assign(
a,
(function () {
var render = function () {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c("k-overlay", { ref: "overlay" }, [
_c("div", { staticClass: "k-search", attrs: { role: "search" } }, [
_c(
"div",
{ staticClass: "k-search-input" },
[
_c("input", {
directives: [{ name: "model", rawName: "v-model", value: _vm.q, expression: "q" }],
ref: "input",
attrs: { placeholder: _vm.$t("search") + " \u2026", "aria-label": _vm.$t("search"), autofocus: true, type: "text" },
domProps: { value: _vm.q },
on: {
input: [
function ($event) {
if ($event.target.composing) {
return;
}
_vm.q = $event.target.value;
},
function ($event) {
_vm.hasResults = true;
},
],
keydown: [
function ($event) {
if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "down", 40, $event.key, ["Down", "ArrowDown"])) {
return null;
}
$event.preventDefault();
return _vm.onDown($event);
},
function ($event) {
if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "up", 38, $event.key, ["Up", "ArrowUp"])) {
return null;
}
$event.preventDefault();
return _vm.onUp($event);
},
function ($event) {
if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "tab", 9, $event.key, "Tab")) {
return null;
}
$event.preventDefault();
return _vm.onTab($event);
},
function ($event) {
if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "enter", 13, $event.key, "Enter")) {
return null;
}
return _vm.onEnter($event);
},
function ($event) {
if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "esc", 27, $event.key, ["Esc", "Escape"])) {
return null;
}
return _vm.close($event);
},
],
},
}),
_vm._v(" "),
_c("k-button", { staticClass: "k-search-close", attrs: { tooltip: _vm.$t("close"), icon: _vm.isLoading ? "loader" : "cancel" }, on: { click: _vm.close } }),
],
1
),
_vm._v(" "),
_vm.q && (!_vm.hasResults || _vm.items.length)
? _c("div", { staticClass: "k-search-results" }, [
_vm.items.length
? _c(
"ul",
{
on: {
mouseout: function ($event) {
_vm.selected = -1;
},
},
},
_vm._l(_vm.items, function (item, itemIndex) {
return _c(
"li",
{
key: item.id,
attrs: { "data-selected": _vm.selected === itemIndex },
on: {
mouseover: function ($event) {
_vm.selected = itemIndex;
},
},
},
[
_c("k-link", { attrs: { to: item.link }, on: { click: _vm.close } }, [
_c(
"span",
{ staticClass: "k-search-item-image" },
[_vm.imageOptions(item.image) ? _c("k-image", _vm._b({}, "k-image", _vm.imageOptions(item.image), false)) : _c("k-icon", _vm._b({}, "k-icon", item.icon, false))],
1
),
_vm._v(" "),
_c("span", { staticClass: "k-search-item-info" }, [_c("strong", [_vm._v(_vm._s(item.title))]), _vm._v(" "), _c("small", [_vm._v(_vm._s(item.info))])]),
]),
],
1
);
}),
0
)
: !_vm.hasIndex
? _c("p", { staticClass: "k-search-empty k-search-index", on: { click: _vm.index } }, [_vm._v(" " + _vm._s(_vm.rebuild) + " ")])
: !_vm.hasResults
? _c("p", { staticClass: "k-search-empty" }, [_vm._v(" " + _vm._s(_vm.$t("search.results.none")) + " ")])
: _vm._e(),
])
: _vm._e(),
]),
]);
};
var staticRenderFns = [];
return { render: render, staticRenderFns: staticRenderFns, _compiled: true, _scopeId: null, functional: undefined };
})()
);
var b = {
data: () => ({ headline: "", isProcessing: !1 }),
computed: {
text() {
let s = this.$t("search.index.build");
return this.isProcessing && (s += "\u2026"), s;
},
},
async created() {
console.log(this)
const s = await this.load();
this.headline = s.headline;
},
methods: {
async build() {
this.isProcessing = !0;
try {
await this.$api.post("search"), this.$store.dispatch("notification/success", this.$t("search.index.built"));
} catch (s) {
console.error(e);
} finally {
this.isProcessing = !1;
}
},
},
};
if (typeof b === "function") {
b = b.options;
}
Object.assign(
b,
(function () {
var render = function () {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c(
"div",
[
_c("div", { staticClass: "k-section-header" }, [_c("k-headline", [_vm._v(_vm._s(_vm.headline))])], 1),
_vm._v(" "),
_c("k-button", { attrs: { icon: "refresh", disabled: _vm.isProcessing }, on: { click: _vm.build } }, [_vm._v(" " + _vm._s(_vm.text) + " ")]),
],
1
);
};
var staticRenderFns = [];
return { render: render, staticRenderFns: staticRenderFns, _compiled: true, _scopeId: null, functional: undefined };
})()
);
panel.plugin("distantnative/search-for-kirby", { sections: { search: b }, components: { "k-search": a } });})();
这也是我为 Kirby 准备的 config.php:
<?php
return [
'debug' => true,
'languages' => false,
'hashandsalt.chopper.keep' => '',
'panel' => [
'language' => 'de',
'css' => 'assets/css/panel.css',
'favicon' => [
'shortcut_icon' => [
'type' => 'image/svg+xml',
'url' => 'assets/images/site/panel/favicon.svg'
],
'alternate icon' => [
'type' => 'image/png',
'url' => 'assets/images/site/panel/favicon.png'
]
]
],
'auth' => [
'trials' => 10
],
'routes' => [
[
'pattern' => 'logout',
'action' => function() {
if ($user = kirby()->user()) {
$user->logout();
}
go('login');
}
]
],
"search" => [
// "provider" => "sqlite",
'provider' => 'algolia',
'algolia' => [
'app' => "[MYAPP]",
'key' => "[MYAPIKEY]",
'index' => 'kirby',
'options' => []
],
"entries" => [
"files" => 'page.files',
"users" => false
],
"fields" => [
"pages" => [
"url" => function($model) {
return $model->url();
},
"title" => function($model) {
return $model->title();
},
"headline" => function($model) {
switch ($model->intendedTemplate()) {
case "default":
case "seminars":
case "intern":
case "seminarpage":
return $model->title();
case "newspage":
return $model->headline();
}
},
"image" => function($model) {
switch ($model->intendedTemplate()) {
case "newspage":
$img = $model->posterimage()->toFile();
if ($img) {
return $img->resize(200, 200)->url();
}
break;
case "seminarpage":
$img = $model->posterimage()->toFile();
if ($img) {
return $img->resize(200, 200)->url();
}
break;
}
},
"content" => function($model) {
switch ($model->intendedTemplate()) {
case "intern":
case "seminars":
case "default":
$res = [];
$len = 0;
foreach ($model->content()->contentbuilder()->toBlocks() as $section) {
if ($section->draft()->value() != true) {
switch ($section->type()) {
case "text":
array_push($res, $section->headline(), $section->text()->excerpt());
case "separator":
array_push($res, $section->headline(), $section->subheadline(), $section->sepTextLarge()->excerpt(), $section->sepTextMedium()->excerpt(), $section->sepTextSmall()->excerpt());
case "downloads":
case "karte":
case "newslist":
case "video":
array_push($res, $section->headline());
}
}
}
foreach ($res as $i => $v) {
if ($len < 15000) {
$len += strlen($v);
$res[$i] = mb_convert_encoding($v, 'UTF-8', 'UTF-8');
}
else {
$res[$i] = "";
}
}
return $res;
case "newspage":
return $model->text();
}
},
"template" => function($model) {
return $model->intendedTemplate()->name();
}
],
"files" => [
"url" => function($model) {
return $model->url();
},
"title" => function($model) {
return $model->filetitle();
},
"extension" => function($model) {
return $model->extension();
}
]
],
"templates" => [
"pages" => ["default", "intern", "newspage", "seminarpage", "seminars"],
"files" => [],
"users" => false
]
]
];
我现在完全不知道该怎么做。有人有这方面的经验吗?如果您需要有关代码的更多文件或信息,我很乐意提供一些东西。