Frontend Geliştirme
Bu sayfa size ne verir: her eklenti frontend'inin paylaştığı tek giriş noktası — src/main.js — artı arayüzün kendisini oluşturan iki konu sayfasına bir harita.
Eklentinizin iki yarımı vardır: bir Kotlin backend ve bir Svelte frontend (kullanıcıların gördüğü ve tıkladığı görsel kısım). Eklentinizi derlediğinizde, derlenmiş Kotlin backend'i ve derlenmiş Svelte dosyalarınız tek bir .jar dosyasına birlikte ziplenir — o dosyanın tamamı eklentinizin kendisidir. Bunun için özel bir şey yapmazsınız; derleme halleder.
Pano iki ayrı web sitesi çalıştırır: tema (ziyaretçilerin siteniz.com'da gördüğü) ve panel (siteniz.com/panel'deki yönetici panosu). Tek eklentiniz her ikisine de arayüz ekler. Tek bir dosya — src/main.js — her ikisi için de giriş noktasıdır.
Bu sayfalar boyunca kullanacağımız örnek Shoutbox'tır: ana sayfanın üstünde son "shout"lardan oluşan küçük bir bileşen, artı yöneticilerin onları yönettiği bir panel. Bu sayfa main.js'i bağlar; iki konu sayfası — Tema Arayüzü ve Panel Arayüzü — gerçek ekranları oluşturur (Sonraki adım'a bakın).
Bir yapay zeka asistanı veya eski bir eğitim size bu sayfalarda veya Arayüz API Referansı'nda olmayan bir API verirse, o var değildir. Yaygın sahte veya kaldırılmış çağrılar bu sayfanın altında listelenmiştir.
Svelte'te yeni misiniz?
Eklenti arayüzleri, Pano temalarıyla aynı şekilde Svelte'te yazılır. Onu hiç kullanmadıysanız, etkileşimli Svelte eğitimi bir eklenti arayüzünün ihtiyaç duyduğu her şeyi kapsar.
Başlamadan önce
Eklentinizi pano-boilerplate-plugin şablonundan iskele olarak oluşturmuş ve Backend Geliştirme'yi tamamlamış olmalısınız. src/main.js dosyası boilerplate'te zaten var — onu oluşturmayacak, düzenleyeceksiniz. Dev döngüsünü bun run dev ile başlatın ve tüm süre boyunca çalışır bırakın; bu sayfalardaki her değişiklik sıcak yeniden yüklenir, böylece onu hemen görebilirsiniz. (Bitmiş eklentiyi bir yayına dönüştürmek Derleme ve Yayınlama'da kapsanır.)
Eklentinizin dosyaları
İşte bu sayfaların atıfta bulunduğu düzen. theme/ ve panel/ klasörleri yalnızca ziyaretçi bileşenleri ile yönetici bileşenlerini ayrı tutmak için düzenli bir gelenektir — Pano adları zorlamaz, dosyaları istediğiniz gibi düzenleyebilirsiniz.
src/
├─ main.js ← entry point; Pano loads this first
├─ theme/ ← components shown to visitors (the public site)
│ └─ ShoutboxWidget.svelte
└─ panel/ ← components shown to admins (the dashboard)
├─ ShoutboxSettings.svelte
└─ ShoutboxPage.svelteGiriş noktası: src/main.js
Her şey main.js'te başlar. PanoPlugin'i genişleten varsayılan bir sınıf dışa aktarır. Pano sınıfınızın bir örneğini oluşturur, üzerine sizin için this.pano'yu ayarlar (onu asla kendiniz ayarlamazsınız), sonra onLoad() metodunuzu çağırır.
onLoad()'ı iki kez çağırır — bir kez panelde ve bir kez temada. Tema ve panel iki ayrı çalışan programdır ve her biri eklentinizi bağımsız olarak yükler, bu yüzden onLoad() gerçekten iki kez, her birinde bir kez, çalışır. Bu normaldir, bir hata değildir. pano.isPanel kontrolü, her tarafa farklı arayüz vermenizin yoludur: panelde true, temada false'tur.
İşte tüm eklentinin üzerine inşa edildiği iskelet. İçindeki bir satır — export const _ = ... — korkutucu görünüyor; şimdilik olduğu gibi kopyalayın, o aşağıdaki Metni çevirme bölümünde tam olarak açıklanan bir çeviri yardımcısıdır ve iskeleti kullanmak için onu anlamanıza gerek yok.
// src/main.js
import { PanoPlugin, viewComponent } from '@panomc/sdk';
import ApiUtil from '@panomc/sdk/utils/api';
import { derived } from 'svelte/store';
import { _ as i18n } from '@panomc/sdk/utils/language';
export const pluginId = 'pano-plugin-shoutbox';
// A translate function scoped to your addon's keys — see the i18n section below.
export const _ = derived(i18n, ($t) => (key, options) => $t(`plugins.${pluginId}.${key}`, options));
export default class ShoutboxUiPlugin extends PanoPlugin {
onLoad() {
const { pano } = this;
if (pano.isPanel) {
// panel registrations go here
} else {
// theme registrations go here
}
}
onUnload() {}
}Önemli olan birkaç kural, hepsine yerleşik eklentiler (PanoMC GitHub org'daki çalışan referans eklentileri) uyar:
- Sınıf
defaultdışa aktarım olmalıdır. Pano tam olarak bir tane arar. this.panotüm API'nizdir. Pano onuonLoad()çalışmadan önce sizin için ayarlar —onLoad()içinde yalnızcapano.isPanel'i okur vepano.ui.*'ı kullanırsınız.pluginId, eklentinizin ID'siyle tam olarak eşleşmelidir — Backend Geliştirme'den / plugin manifestonuzdan. Çeviriler ve panel detay-sayfası kancası ona göre anahtarlanır, bu yüzden bir uyumsuzluk onları sessizce bozar.- Her bileşeni
viewComponent(() => import('./File.svelte'))içine sarın. Bu isteğe bağlı değildir. Birregisterçağrısına verdiğiniz her bileşen — kancalar, sayfalar, view slotları — bu şekilde sarılmalıdır. Sade sözlerle: bu, Pano'ya dosyanın kendisi yerine dosyanızı yüklemek için bir tarif verir, böylece Pano onu sayfanın kendi Svelte kopyasıyla doğru anda yükleyebilir. Ayrıntılara ihtiyacınız yok — meraklıysanız Mimari'ye bakın. - Paylaşılan durumu
main.js'te tutun.main.js'in üst düzeyinde bildirdiğiniz değişkenler (yukarıdaki_deposu gibi) tam olarak bir kez var olur ve tüm bileşenleriniz tarafından paylaşılır. Derleme bunu yalnızcamain.jsiçin garanti eder, bu yüzden paylaşılan durum için başka dosyalara güvenmeyin. (Mekaniği Mimari'dedir.) onUnload()eklentiniz devre dışı bırakıldığında çalışır. Şimdilik boş bırakın; çoğu eklentinin ona hiç ihtiyacı olmaz.
package.json'da asla svelte bildirmeyin
Paketiniz Svelte, svelte-i18n veya @panomc/sdk göndermez — host bunları sağlar, böylece tüm sayfa tek bir Svelte örneği paylaşır. Derlemeniz siz (veya bun add ile kurduğunuz bir kütüphane) package.json'a svelte ekledikten hemen sonra başarısız olmaya başlarsa, neden budur: svelte'i package.json'dan kaldırın. Sade sözlerle, sayfa yalnızca bir Svelte kopyası çalıştırabilir ve host onu zaten sağlar; kendinizinkini eklemek ikinci bir kopyayı sabitler ve hydration'ı (sunucu-render'lı HTML'in tarayıcıda etkileşimli hale gelmek için bağlandığı adım) bozar. Nedenini Mimari'de görün.
İlerlemenizi kontrol edin
Bu iskelet tek başına ekranda henüz hiçbir şey çizmez — yalnızca eklentinizi kurar. bun run dev çalışırken, hem siteniz.com'u (tema) hem de siteniz.com/panel'i (panel) yeniden yükleyin ve tarayıcı konsolunu açın (F12). Eklentinizden kırmızı hata görmemelisiniz. Eksik bir default dışa aktarımı veya kötü bir pluginId hakkında bir tane görürseniz, daha ileri gitmeden önce onu düzeltin — aşağıdaki her şey bu çalışan iskeletin üzerine yığılır.
Şimdi iki dalı doldurun. Her birine ne gireceğinin kendi sayfası var: else (tema) dalı için Tema Arayüzü, if (pano.isPanel) dalı için Panel Arayüzü. Bu sayfanın geri kalanı her iki dalın da kullandığı iki şeyi kapsar.
Bileşenlerinizde metni çevirme
Tema geliştirmenin aksine, eklenti bileşenlerinize otomatik olarak bir çeviri yardımcısı enjekte edilmez — _'yi kendi main.js'inizden içe aktarmalısınız. O _, iskeletten korkutucu satırdır:
export const _ = derived(i18n, ($t) => (key, options) => $t(`plugins.${pluginId}.${key}`, options));İşte tüm yaptığı: Pano'nun çeviri fonksiyonunu saran bir Svelte derived deposudur (kaynağı değiştiğinde yeniden hesaplayan bir değer) ve geçtiğiniz her anahtarın önüne otomatik olarak plugins.<pluginId>. ekler. Yani bir bileşende $_('widget.title') yazarsınız ve o plugins.pano-plugin-shoutbox.widget.title'ı arar. Onu kullanmak için içeride nasıl inşa edildiğini anlamanıza gerek yok — yalnızca içe aktarın ve $ önekiyle okuyun:
<script>
import { _ } from '../main.js';
</script>
<h2>{$_('widget.title')}</h2>{$_('widget.title')} dil dosyalarınızdaki plugins.pano-plugin-shoutbox.widget.title anahtarına çözümlenir. O anahtarların nerede yaşadığı ve nasıl ad-alanlandığı için Çeviriler'e bakın.
İlerlemenizi kontrol edin
O anahtarı Çeviriler'de gerçekten ekleyene kadar, ekran güzel bir etiket yerine ham anahtar dizesini (plugins.pano-plugin-shoutbox.widget.title) gösterir. Bu, bu aşamada beklenendir — yardımcının doğru bağlandığının ve yalnızca dil dosyasını beklediğinin işaretidir.
Var olmayan, AI tarafından uydurulan API'ler
Bir AI aracı, eski bir eğitim veya iskele bunlardan herhangi birini önerirse, onu görmezden gelin — hiçbiri var değil. Yalnızca bu sayfalarda ve Arayüz API Referansı'nda olanı kullanın.
pano.ui.page.register({ name, view, scopes })— gerçekpage.register,{ path, component, permission, ... }alır (bkz. Panel Arayüzü).name/view/scopesbiçimi yoktur.import { Button, Card } from '@panomc/sdk/components/panel'— SDK'da böyle bir bileşen kütüphanesi yoktur.onContextUpdate— eski boilerplate bu metodu tanımlar, ama hiçbir host onu çağırmaz. İskele oluşturulanmain.js'inizonContextUpdateiçeriyorsa, onu silin.- Düz bir dizeyle
ApiUtil.get('/api/...')— herApiUtilçağrısı bir seçenekler nesnesi alır, örn.ApiUtil.get({ path: '/api/...' }). pano.utils.toast— böyle bir şey yoktur; toast'lar yalnızca@panomc/sdk/toasts'tan gelir.
Sonraki adım
main.js kuruldu. Şimdi arayüzü oluşturun:
- Sitede bir şeyler gösterin → Tema Arayüzü — tema kancaları, ana sayfa bileşeni, sunucu-render'lı veri ve API'nizi çağırma.
- Yönetici ekranları ekleyin → Panel Arayüzü — ayarlar bölümleri, gezinme bağlantılı tam panel sayfaları ve toast'lar.
- Tam arama → Arayüz API Referansı — her kanca adı, view slotu, yaşam döngüsü olayı ve
@panomc/sdkdışa aktarımı tek yerde. - Çeviriler —
plugins.<pluginId>.<key>dizelerinizin nerede yaşadığı ve panelin yöneticilerin bunları geçersiz kılmasına nasıl izin verdiği. - Backend Geliştirme — bu sayfaların çağırdığı endpoint'lerin ve izinlerin Kotlin tarafı.
- Derleme ve Yayınlama — bitmiş eklentiyi bir yayın jar'ına dönüştürün. Bir yayın derlemesi arayüzü içermek zorundadır, bu yüzden onun için asla
-Pnouikullanmayın (-Pnoui, yalnızca-backend yinelemesi sırasında arayüz derlemesini atlayan Gradle bayrağıdır — bkz. Derleme ve Yayınlama). - Referans eklentiler — PanoMC GitHub org'daki yerleşik eklentiler, bu sayfalardaki her desen için çalışan referanstır.