KI-Kennzeichnung: 2 Optionen im Submit-Modal + Labels auf Detailseite
Submit-Modal auf zwei Auswahloptionen reduziert (kein Label vs.
"Ganz oder ueberwiegend mit generativer KI erstellt"); alle vier
Enum-Werte bleiben fuer API/Bestand gueltig und mappen per formOption()
auf die zwei Gruppen. Oeffentliche Detailseite rendert jetzt Text-Label
("KI-generiert: Nach Angaben ...") und Bild-Badge (KI-generiert/
KI-bearbeitet, abgedunkelter Hintergrund) — fehlte dort bisher komplett.
Bildnachweis-Vorschlag ohne "Foto:"-Praefix (stand sonst doppelt).
Einreich-Toast + FAQ: automatische Pruefung in Minuten statt 24 h.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c8836564e9
commit
dc2a3443c1
13 changed files with 172 additions and 50 deletions
|
|
@ -126,14 +126,16 @@
|
|||
<p class="m-0 text-[12.5px] leading-[1.6] text-[color:var(--color-ink-2)]">
|
||||
{{ __('Wie wurde der Text dieser Pressemitteilung erstellt? Diese Angabe ist gesetzlich verpflichtend (Art. 50 KI-VO).') }}
|
||||
</p>
|
||||
{{-- Zwei Gruppen (Entscheidung 10.07.2026): Option 1 = kein
|
||||
Label, Option 2 = Hinweis „KI-generiert" am Pressetext. --}}
|
||||
<flux:radio.group wire:model="aiTextDeclaration">
|
||||
@foreach (\App\Enums\AiTextDeclaration::cases() as $aiOption)
|
||||
@foreach (\App\Enums\AiTextDeclaration::formCases() as $aiOption)
|
||||
<flux:radio :value="$aiOption->value" :label="$aiOption->label()" />
|
||||
@endforeach
|
||||
</flux:radio.group>
|
||||
<flux:error name="aiTextDeclaration" />
|
||||
<p class="m-0 pt-2 border-t border-[color:var(--color-bg-rule)] text-[11.5px] leading-[1.5] text-[color:var(--color-ink-3)]">
|
||||
{{ __('Bei überwiegend oder vollständig KI-generierten Texten erscheint an der Veröffentlichung ein neutraler Hinweis in Ihrer Stimme („Nach Angaben des einreichenden Unternehmens …"). KI-generierte oder KI-bearbeitete Bilder kennzeichnen Sie direkt beim Bild-Upload.') }}
|
||||
{{ __('Bei der ersten Option erscheint kein Label an der Veröffentlichung. Bei der zweiten Option wird der Pressetext mit dem Hinweis „KI-generiert" in Ihrer Stimme gekennzeichnet („Nach Angaben des einreichenden Unternehmens …"). KI-generierte oder KI-bearbeitete Bilder kennzeichnen Sie direkt beim Bild-Upload.') }}
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
|
|
|
|||
|
|
@ -198,13 +198,15 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends
|
|||
@php
|
||||
$adminTitleImage = $pr->images->sortByDesc('is_preview')->first();
|
||||
@endphp
|
||||
@if ($adminTitleImage && ($adminTitleImage->copyright || $adminTitleImage->is_ai_generated))
|
||||
@if ($adminTitleImage && ($adminTitleImage->copyright || $adminTitleImage->is_ai_generated || $adminTitleImage->ai_declaration?->publicLabel()))
|
||||
{{-- Bildnachweis + KI-Kennzeichnung (Art. 50 EU AI Act) --}}
|
||||
<div class="flex flex-wrap items-center gap-2 border-t border-[color:var(--color-bg-rule)] px-5 py-2.5 text-[12px] text-[color:var(--color-ink-3)]">
|
||||
@if ($adminTitleImage->is_ai_generated)
|
||||
<span class="badge hub">{{ __('KI-generiert') }}</span>
|
||||
@if ($aiImageBadge = $adminTitleImage->ai_declaration?->publicLabel() ?? ($adminTitleImage->is_ai_generated ? __('KI-generiert') : null))
|
||||
<span class="badge hub">{{ $aiImageBadge }}</span>
|
||||
@endif
|
||||
@if ($adminTitleImage->copyright)
|
||||
<span>{{ $adminTitleImage->copyright }}</span>
|
||||
@endif
|
||||
<span>{{ $adminTitleImage->copyright ?? __('Bild: KI-generiert') }}</span>
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ new class extends Component {
|
|||
$this->resetErrorBag('newLicenseDetail');
|
||||
|
||||
// Automatisch erzeugte Vorschläge weichen dem Vorschlag des neuen Typs.
|
||||
if ($this->newCopyright === $this->autoCopyright || str_starts_with($this->newCopyright, __('Bild: KI-generiert'))) {
|
||||
if ($this->newCopyright === $this->autoCopyright || str_starts_with($this->newCopyright, __('KI-generiert'))) {
|
||||
$this->newCopyright = '';
|
||||
$this->autoCopyright = '';
|
||||
}
|
||||
|
|
@ -135,7 +135,9 @@ new class extends Component {
|
|||
return;
|
||||
}
|
||||
|
||||
$this->autoCopyright = filled($this->newAuthor) ? __('Foto: :author', ['author' => trim($this->newAuthor)]) : '';
|
||||
// Ohne „Foto:"-Präfix — die Veröffentlichungsseite stellt es dem
|
||||
// Bildnachweis bereits selbst voran (sonst stünde dort „Foto: Foto: …").
|
||||
$this->autoCopyright = filled($this->newAuthor) ? trim($this->newAuthor) : '';
|
||||
$this->newCopyright = $this->autoCopyright;
|
||||
}
|
||||
|
||||
|
|
@ -154,11 +156,11 @@ new class extends Component {
|
|||
return;
|
||||
}
|
||||
|
||||
if (filled($this->newCopyright) && !str_starts_with($this->newCopyright, __('Bild: KI-generiert'))) {
|
||||
if (filled($this->newCopyright) && !str_starts_with($this->newCopyright, __('KI-generiert'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->newCopyright = filled($this->newLicenseDetail) ? __('Bild: KI-generiert (:tool)', ['tool' => trim($this->newLicenseDetail)]) : __('Bild: KI-generiert');
|
||||
$this->newCopyright = filled($this->newLicenseDetail) ? __('KI-generiert (:tool)', ['tool' => trim($this->newLicenseDetail)]) : __('KI-generiert');
|
||||
}
|
||||
|
||||
public function closeUploadForm(): void
|
||||
|
|
@ -214,7 +216,7 @@ new class extends Component {
|
|||
]),
|
||||
],
|
||||
[
|
||||
'newCopyright.required' => __('Bitte einen öffentlichen Bildnachweis angeben, z. B. Foto: Max Mustermann / Beispiel GmbH.'),
|
||||
'newCopyright.required' => __('Bitte einen öffentlichen Bildnachweis angeben, z. B. Max Mustermann / Beispiel GmbH.'),
|
||||
'newAuthor.required' => $isAiGenerated ? __('Bitte angeben, wer für die Erstellung verantwortlich ist (Person oder Firma).') : __('Bitte Urheber, Fotograf oder Rechteinhaber angeben.'),
|
||||
'newLicenseType.required' => __('Bitte einen Lizenztyp wählen.'),
|
||||
'newLicenseDetail.required' => $isAiGenerated ? __('Bitte das verwendete KI-Tool angeben, z. B. Midjourney, Gemini, ChatGPT, DALL·E, Adobe Firefly.') : __('Bitte die Lizenz genauer angeben.'),
|
||||
|
|
@ -624,8 +626,8 @@ new class extends Component {
|
|||
|
||||
<flux:input wire:model="newCopyright" :label="__('Öffentlicher Bildnachweis')"
|
||||
:badge="__('Pflicht')"
|
||||
:description="__('Wird öffentlich unter dem Bild angezeigt — Vorschlag anpassbar.')"
|
||||
:placeholder="__('z. B. Foto: Max Mustermann / Beispiel GmbH')" required />
|
||||
:description="__('Wird öffentlich unter dem Bild angezeigt („Foto: …") — Vorschlag anpassbar.')"
|
||||
:placeholder="__('z. B. Max Mustermann / Beispiel GmbH')" required />
|
||||
</section>
|
||||
|
||||
{{-- ===== Schritt 3 · Personen & Rechte Dritter ===== --}}
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ new #[Layout('components.layouts.app'), Title('Neue Pressemitteilung')] class ex
|
|||
|
||||
Flux::toast(
|
||||
heading: __('Eingereicht'),
|
||||
text: __('Die Inhaltsprüfung ist typischerweise innerhalb von 24 h abgeschlossen.'),
|
||||
text: __('Die automatische Inhaltsprüfung ist in der Regel innerhalb weniger Minuten abgeschlossen.'),
|
||||
variant: 'success',
|
||||
);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -125,9 +125,10 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl
|
|||
|
||||
$this->placeholderVariant = PressReleasePlaceholder::fromValueOrDefault($pr->placeholder_variant?->value)->value;
|
||||
|
||||
// KI-Grad vorbelegen (bereits deklariert); die verbindliche
|
||||
// Bestätigung muss bei jedem Submit erneut gesetzt werden.
|
||||
$this->aiTextDeclaration = $pr->ai_text_declaration?->value;
|
||||
// KI-Grad vorbelegen (bereits deklariert), gemappt auf die zwei
|
||||
// Formular-Optionen; die verbindliche Bestätigung muss bei jedem
|
||||
// Submit erneut gesetzt werden.
|
||||
$this->aiTextDeclaration = $pr->ai_text_declaration?->formOption()->value;
|
||||
}
|
||||
|
||||
#[On('placeholder-selected')]
|
||||
|
|
@ -337,7 +338,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl
|
|||
|
||||
Flux::toast(
|
||||
heading: __('Eingereicht'),
|
||||
text: __('Die Inhaltsprüfung ist typischerweise innerhalb von 24 h abgeschlossen.'),
|
||||
text: __('Die automatische Inhaltsprüfung ist in der Regel innerhalb weniger Minuten abgeschlossen.'),
|
||||
variant: 'success',
|
||||
);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@
|
|||
$imageUrl = $image?->variantUrl('detail') ?? $image?->variantUrl('card') ?? $image?->url();
|
||||
$imageCaption = $image?->description ?: $image?->title;
|
||||
$imageCredit = $image?->copyright ?: $image?->author;
|
||||
// KI-Bildkennzeichnung (Art. 50 KI-VO): Badge direkt am Bild
|
||||
// („KI-generiert" / „KI-bearbeitet"), null bei Originalfotos.
|
||||
$imageAiBadge = $image?->ai_declaration?->publicLabel();
|
||||
|
||||
// Ohne Pressefoto: die im User-Panel gewählte Platzhalter-Variante.
|
||||
// Null bei Altbeständen ohne Variante — dann generischer Hero-Fallback.
|
||||
|
|
@ -306,6 +309,13 @@
|
|||
<div class="relative flex items-end p-[18px] bg-bg-dark overflow-hidden" style="aspect-ratio:21/9;">
|
||||
<img src="{{ $imageUrl }}" alt="{{ $imageCaption ?: $release->title }}"
|
||||
class="absolute inset-0 h-full w-full object-cover" loading="eager">
|
||||
@if ($imageAiBadge)
|
||||
{{-- KI-Badge am Bild (Art. 50 KI-VO): kräftig abgedunkelter
|
||||
Hintergrund, damit es auch auf hellen Bildern lesbar bleibt. --}}
|
||||
<span class="relative text-[9.5px] font-bold tracking-[0.18em] uppercase text-white px-2.5 py-[3px] border border-white/60 font-mono bg-black/75 shadow-sm">
|
||||
{{ $imageAiBadge }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
@if ($imageCaption || $imageCredit)
|
||||
<div class="text-[11.5px] text-ink-3 mt-2.5 italic max-w-[720px]">
|
||||
|
|
@ -319,6 +329,19 @@
|
|||
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 pt-10 grid grid-cols-1 lg:grid-cols-[1fr_280px] gap-10 lg:gap-14">
|
||||
{{-- Body --}}
|
||||
<div>
|
||||
{{-- KI-Label (Art. 50 KI-VO) in Einreicher-Stimme am Anfang
|
||||
des Inhalts; neutrales ℹ-Icon, kein Flux auf Web-Domains. --}}
|
||||
@if ($aiTextLabel = $release->aiTextPublicLabel())
|
||||
<div class="flex items-start gap-2 border border-bg-rule-strong bg-bg-elev px-3 py-2.5 mb-6 max-w-[680px] text-[12px] leading-[1.5] text-ink-3">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true" class="shrink-0 mt-0.5">
|
||||
<circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="1.8" fill="none" />
|
||||
<path d="M12 11v5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
||||
<circle cx="12" cy="8" r="1.1" fill="currentColor" />
|
||||
</svg>
|
||||
<span>{{ $aiTextLabel }}</span>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="pm-body max-w-[680px]">
|
||||
{!! $bodyHtml !!}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue