schema([
//
Tabs::make("")->tabs([
Tab::make('基本資訊')->schema([
TextInput::make('keyword')->label("關聯字詞")->required()
->validationMessages([
'required' => '請填寫關聯字詞',
]),
Translate::make()->schema(fn (string $locale) => [
TextInput::make('title')
->label("標題")
->columnSpan(1)
->required($locale == "zh_TW")
->validationMessages([
'required' => '請填寫標題',
])
])->locales(["zh_TW", "en"])
->columnSpanFull()->columns(3),
]),
Tab::make('Banner 設定')->schema([
FileUpload::make('banner_pc')->label("Banner (PC)")
->disk("public")
->helperText('檔案大小限制為1MB以下')
// ->helperText('建議寬高限制為:1280*720px,檔案大小限制為1M以下')->maxSize('1024')
->directory("esg")->required()
->validationMessages([
'required' => '請上傳圖片',
]),
FileUpload::make('banner_mobile')->label("Banner (Mobile)")
->disk("public")
->helperText('檔案大小限制為1MB以下')
// ->helperText('建議寬高限制為:600*896px,檔案大小限制為1M以下')->maxSize('1024')
->directory("esg")->required()
->validationMessages([
'required' => '請上傳圖片',
]),
Translate::make()->schema(fn (string $locale) => [
TextInput::make('banner_alt')
->label("Banner 圖片註釋")
->required($locale == "zh_TW")
->validationMessages([
'required' => '請填寫圖片註釋',
]),
Textarea::make("description")->rows(5)->columnSpanFull()->label("短文"),
])->locales(["zh_TW", "en"])
->columnSpanFull(),
]),
Tab::make("段落設計")->schema([
//1: 純文字 2:區塊文字 3:表格 4:影片 or 圖片 5:左右圖文
Repeater::make("paragraphs")->label("")->schema([
TextInput::make('item_key')
->default(fn () => Str::random())
->hidden()
->afterStateHydrated(function (TextInput $component, $state) {
if (empty($state)) {
$component->state(Str::random());
}
}),
Radio::make("type")->options([
1 => "純文字",
2 => "區塊文字",
3 => "表格",
4 => "圖片",
5 => "影片",
])->label("")->default(1)->Live(),
Group::make()->schema([
Section::make('純文字設定')->schema([
FilamentLexicalEditor::make('content.text_content_tw')
->label('中文')
->label(new \Illuminate\Support\HtmlString('中文 工具列說明'))
->id(fn ($get) => "text_content_tw_" . $get('item_key') . "_" . uniqid())
->enabledToolbars($editor_toolbar)
->required()
->columnSpanFull(),
FilamentLexicalEditor::make('content.text_content_en')
->label('English')
->id(fn ($get) => "text_content_en_" . $get('item_key') . "_" . uniqid())
->enabledToolbars($editor_toolbar)
->columnSpanFull(),
]),
])->visible(fn (Get $get):bool => $get("type") == 1),
Group::make()->schema([
Section::make('區塊文字設定')->schema([
// 文字區塊重複器
Repeater::make("content.text_blocks")->schema([
TextInput::make('block_item_key')
->default(fn () => Str::random())
->hidden()
->afterStateHydrated(function (TextInput $component, $state) {
if (empty($state)) {
$component->state(Str::random());
}
}),
FilamentLexicalEditor::make('block_content_tw')
// ->label('繁體中文內容')
->label(new \Illuminate\Support\HtmlString('繁體中文內容 工具列說明'))
->id(fn ($get) => "block_content_tw_" . $get('block_item_key') . "_" . uniqid())
->enabledToolbars($editor_toolbar)
->required()
->live(onBlur: true)
->columnSpanFull(),
FilamentLexicalEditor::make('block_content_en')
->label('English Content')
->id(fn ($get) => "block_content_en_" . $get('block_item_key') . "_" . uniqid())
->enabledToolbars($editor_toolbar)
->columnSpanFull(),
])
->label("")
->addActionLabel('增加區塊')
->orderColumn('order')
->reorderableWithButtons()
->cloneable()
->minItems(1)
->maxItems(20)
->defaultItems(1),
]),
])->visible(fn (Get $get):bool => $get('type') == 2),
Group::make()->schema([
Section::make('表格設定')->schema([
Radio::make('content.is_card')
->label('手機板卡片顯示')
->options([
'1' => '是', // 改為數字鍵值
'0' => '否'
])
->default('0')
->inline(),
// 表格資料
Placeholder::make('table_builder_info')->label("")->content('請先設定表格欄數,然後填入表格資料'),
Grid::make(3)->schema([
Radio::make('content.column_count')
->label('欄數')
->options([
2 => '2欄', // 改為數字鍵值
3 => '3欄',
4 => '4欄'
])
->default(2)
->inline()
->live()
->reactive(), // ✅ 添加 reactive()
]),
Translate::make()->schema(fn (string $locale) => [
Grid::make(2) // 改用 Grid 來支援動態 columns
->schema([
TextInput::make('content.head1')->label('標題第1欄')->required()
->validationMessages([
'required' => '請填寫',
]),
Radio::make('content.head_align1')
->label('對齊')
->options([
1 => '置左', // 改為數字鍵值
2 => '置中',
3 => '置右'
])
->default(1),
TextInput::make('content.head2')->label('標題第2欄')->required()
->validationMessages([
'required' => '請填寫',
]),
Radio::make('content.head_align2')
->label('對齊')
->options([
1 => '置左', // 改為數字鍵值
2 => '置中',
3 => '置右'
])
->default(1),
TextInput::make('content.head3')->label('標題第3欄')
->visible(fn (Get $get) => intval($get('content.column_count')) >= 3)->columnSpan(1),
Radio::make('content.head_align3')
->label('對齊')
->options([
1 => '置左', // 改為數字鍵值
2 => '置中',
3 => '置右'
])
->default(1)
->visible(fn (Get $get) => intval($get('content.column_count')) >= 3)->columnSpan(1),
TextInput::make('content.head4')->label('標題第4欄')
->visible(fn (Get $get) => intval($get('content.column_count')) >= 4)->columnSpan(1),
Radio::make('content.head_align4')
->label('對齊')
->options([
1 => '置左', // 改為數字鍵值
2 => '置中',
3 => '置右'
])
->default(1)
->visible(fn (Get $get) => intval($get('content.column_count')) >= 4)->columnSpan(1),
])
->reactive() // 加入響應式
])->locales(["zh_TW", "en"]),
Repeater::make('content.simple_table_rows')
->label('表格資料')
->schema([
TextInput::make('simple_table_rows_key')
->default(fn () => Str::random())
->hidden()
->afterStateHydrated(function (TextInput $component, $state) {
if (empty($state)) {
$component->state(Str::random());
}
}),
Grid::make(1) // 改用 Grid 來支援動態 columns
->schema([
Section::make("第一欄")->schema([
Fieldset::make('中文')->schema([
Radio::make('align1_tw')
->label('對齊')
->options([
1 => '置左', // 改為數字鍵值
2 => '置中',
3 => '置右'
])
->default(1)->inline(),
FilamentLexicalEditor::make('col1_tw')
->id(fn ($get) => "col1_tw_" . $get('simple_table_rows_key') . "_" . uniqid())
->label(new \Illuminate\Support\HtmlString('工具列說明'))
->enabledToolbars($editor_toolbar)
->required()
->columnSpanFull(),
]),
Fieldset::make('英文')->schema([
Radio::make('align1_en')
->label('對齊')
->options([
1 => '置左', // 改為數字鍵值
2 => '置中',
3 => '置右'
])
->default(1)->inline(),
FilamentLexicalEditor::make('col1_en')
->id(fn ($get) => "col1_en_" . $get('simple_table_rows_key') . "_" . uniqid())
->enabledToolbars($editor_toolbar)
->columnSpanFull(),
]),
]),
Section::make("第二欄")->schema([
Fieldset::make('中文')->schema([
Radio::make('align2_tw')
->label('對齊')
->options([
1 => '置左', // 改為數字鍵值
2 => '置中',
3 => '置右'
])
->default(1)->inline(),
FilamentLexicalEditor::make('col2_tw')
->id(fn ($get) => "col2_tw_" . $get('simple_table_rows_key') . "_" . uniqid())
->label(new \Illuminate\Support\HtmlString('工具列說明'))
->enabledToolbars($editor_toolbar)
->required()
->columnSpanFull(),
]),
Fieldset::make('英文')->schema([
Radio::make('align2_en')
->label('對齊')
->options([
1 => '置左', // 改為數字鍵值
2 => '置中',
3 => '置右'
])
->default(1)->inline(),
FilamentLexicalEditor::make('col2_en')
->id(fn ($get) => "col2_en_" . $get('simple_table_rows_key') . "_" . uniqid())
->enabledToolbars($editor_toolbar)
->columnSpanFull(),
]),
]),
Section::make("第三欄")->schema([
Fieldset::make('中文')->schema([
Radio::make('align3_tw')
->label('對齊')
->options([
1 => '置左', // 改為數字鍵值
2 => '置中',
3 => '置右'
])
->default(1),
FilamentLexicalEditor::make('col3_tw')
->id(fn ($get) => "col3_tw_" . $get('simple_table_rows_key') . "_" . uniqid())
->label(new \Illuminate\Support\HtmlString('工具列說明'))
->enabledToolbars($editor_toolbar)
->required()
->columnSpanFull(),
]),
Fieldset::make('英文')->schema([
Radio::make('align3_en')
->label('對齊')
->options([
1 => '置左', // 改為數字鍵值
2 => '置中',
3 => '置右'
])
->default(1)->inline(),
FilamentLexicalEditor::make('col3_en')
->id(fn ($get) => "col3_en_" . $get('simple_table_rows_key') . "_" . uniqid())
->enabledToolbars($editor_toolbar)
->columnSpanFull(),
]),
])->visible(fn (Get $get) => intval($get('../../../content.column_count')) >= 3),
Section::make("第四欄")->schema([
Fieldset::make('中文')->schema([
Radio::make('align4_tw')
->label('對齊')
->options([
1 => '置左', // 改為數字鍵值
2 => '置中',
3 => '置右'
])
->default(1)->inline(),
FilamentLexicalEditor::make('col4_tw')
->id(fn ($get) => "col4_tw_" . $get('simple_table_rows_key') . "_" . uniqid())
->label(new \Illuminate\Support\HtmlString('工具列說明'))
->enabledToolbars($editor_toolbar)
->required()
->columnSpanFull(),
]),
Fieldset::make('英文')->schema([
Radio::make('align4_en')
->label('對齊')
->options([
1 => '置左', // 改為數字鍵值
2 => '置中',
3 => '置右'
])
->default(1)->inline(),
FilamentLexicalEditor::make('col4_en')
->id(fn ($get) => "col4_en_" . $get('simple_table_rows_key') . "_" . uniqid())
->enabledToolbars($editor_toolbar)
->columnSpanFull(),
]),
])->visible(fn (Get $get) => intval($get('../../../content.column_count')) >= 4),
])
->reactive() // 加入響應式
])
->id(fn ($get) => "simple_table_" . $get('simple_table_rows_key'))
->addActionLabel('新增列')
->reorderableWithButtons()
->minItems(1)
]),
])->visible(fn (Get $get):bool => $get('type') == 3),
Group::make()->schema([
Section::make('')->schema([
Repeater::make("content.multiple_images")->schema([
TextInput::make('para_img_item_key')
->default(fn () => Str::random())
->hidden()
->afterStateHydrated(function (TextInput $component, $state) {
if (empty($state)) {
$component->state(Str::random());
}
}),
Translate::make()->schema(fn (string $locale) => [
TextInput::make('image_alt')->label("圖片註文")
])->locales(["zh_TW", "en"])
->id(fn ($get) => "para_img_mul_" . $get('para_img_item_key')),
FileUpload::make('image_url')->label("")->disk("public")
->helperText('檔案大小限制為1MB以下')
// ->helperText('建議寬高限制為:1080*675px,檔案大小限制為1M以下')->maxSize('1024')
->directory("esg/paragraphPhoto")
->maxFiles(10)
->required()
->validationMessages([
'required' => '請上傳圖片',
]),
])
->addActionLabel('新增')
->label("")
->orderColumn('order')
])
])->visible(fn (Get $get):bool => $get("type") == 4),
Group::make()->schema([
Section::make("")->schema([
FileUpload::make('content.video_img')->label("影片底圖")
->disk("public")
->helperText('檔案大小限制為1MB以下')
->directory("esg/paragraphVideo"),
TextInput::make('content.link')->label("網址")->required()
->validationMessages([
'required' => '請附上連結',
]),
Translate::make()->schema(fn (string $locale) => [
TextInput::make('content.video_alt')->label("影片註文"),
])->locales(["zh_TW", "en"])
]),
])->visible(fn (Get $get):bool => $get("type") == 5),
])
->relationship("paragraphs")
->addActionLabel('新增段落')
->collapsible()
->reorderableWithButtons()
->orderColumn('order')
->cloneable()
->mutateRelationshipDataBeforeFillUsing(function (array $data): array {
switch($data["type"]){
case "1":
if (!empty($data["content"]['text_content'])) {
$content = is_string($data["content"]['text_content'])
? json_decode($data["content"]['text_content'], true)
: $data["content"]['text_content'];
if (is_array($content)) {
$data["content"]['text_content_tw'] = $content['zh_TW'] ?? '';
$data["content"]['text_content_en'] = $content['en'] ?? '';
}
}
break;
case "2":
if (!empty($data["content"]['text_blocks']) && count($data["content"]['text_blocks']) > 0) {
foreach ($data["content"]['text_blocks'] as $block_index => $block){
$content = is_string($block['block_content'])
? json_decode($block['block_content'], true)
: $block['block_content'];
if (is_array($content)) {
$data["content"]['text_blocks'][$block_index]["block_content_tw"] = $content['zh_TW'] ?? '';
$data["content"]['text_blocks'][$block_index]["block_content_en"] = $content['en'] ?? '';
}
}
}
break;
case "3":
if (!empty($data["content"]['simple_table_rows']) && count($data["content"]['simple_table_rows']) > 0) {
foreach ($data["content"]['simple_table_rows'] as $row_key => $row) {
$flatRow = [];
foreach ($row as $key => $value) {
if (is_array($value) && isset($value['zh_TW'], $value['en'])) {
// 多语言字段,分离为两个字段
$flatRow[$key . '_tw'] = $value['zh_TW'];
$flatRow[$key . '_en'] = $value['en'];
} else {
// 非多语言字段,保持原样
$flatRow[$key] = $value;
}
}
$data["content"]['simple_table_rows'][$row_key] = $flatRow;
}
}
break;
}
return $data;
})
->mutateRelationshipDataBeforeSaveUsing(function (array $data): array {
switch($data["type"]){
case "1":
$data["content"]["text_content"] = ["zh_TW" => $data["content"]["text_content_tw"] ?? "" , "en" => $data["content"]["text_content_en"] ?? ""];
// 移除臨時的分離欄位,只保留合併的 JSON 欄位
unset($data["content"]["text_content_tw"]);
unset($data["content"]["text_content_en"]);
// 清理 HTML 標籤(如果需要)
foreach ($data['content']['text_content'] as $locale => $content) {
$data['content']['text_content'][$locale] = stripslashes($content);
}
break;
case "2":
// 確保有 text_blocks
if (!isset($data['content']['text_blocks'])) {
$data['content']['text_blocks'] = [];
}
// 處理每個文字區塊
foreach ($data['content']['text_blocks'] as $index => &$block) {
// 確保區塊有必要的欄位
$block['block_item_key'] = $block['block_item_key'] ?? Str::random();
$block['order'] = $block['order'] ?? ($index + 1);
$block["block_content"] = ["zh_TW" => $block["block_content_tw"] ?? "" , "en" => $block["block_content_en"] ?? ""];
// 移除臨時的分離欄位,只保留合併的 JSON 欄位
unset($block["block_content_tw"]);
unset($block["block_content_en"]);
// 清理區塊內容
if (isset($block['block_content'])) {
foreach ($block['block_content'] as $locale => $content) {
$block['block_content'][$locale] = stripslashes($content);
}
}
}
break;
case "3":
// 確保欄數設定
$columnCount = $data['content']['column_count'] ?? 2;
// 確保表頭存在
if (!isset($data['content']['headers'])) {
$data['content']['headers'] = ['zh_TW' => [], 'en' => []];
}
// 確保表格資料存在
if (!isset($data['content']['simple_table_rows'])) {
$data['content']['simple_table_rows'] = [];
}
// 處理表格資料,確保欄數一致
foreach ($data['content']['simple_table_rows'] as $rowIndex => &$row) {
// 確保每行都有正確的欄數
for ($i = 1; $i <= $columnCount; $i++) {
$row["col{$i}"] = ["zh_TW" => $row["col{$i}_tw"] ?? "" , "en" => $row["col{$i}_en"] ?? ""];
foreach ($row["col{$i}"] as $locale => $content) {
$row["col{$i}"][$locale] = $content;
}
unset($row["col{$i}_tw"]);
unset($row["col{$i}_en"]);
$row["align{$i}"] = ["zh_TW" => $row["align{$i}_tw"] ?? "" , "en" => $row["align{$i}_en"] ?? ""];
foreach ($row["align{$i}"] as $locale => $content) {
$row["align{$i}"][$locale] = $content;
}
unset($row["align{$i}_tw"]);
unset($row["align{$i}_en"]);
}
// 移除多餘的欄位
for ($i = $columnCount + 1; $i <= 4; $i++) {
unset($row["col{$i}_tw"]);
unset($row["col{$i}_en"]);
unset($row["align{$i}_tw"]);
unset($row["align{$i}_en"]);
}
}
break;
}
return $data;
})
->mutateRelationshipDataBeforeCreateUsing(function (array $data): array {
switch($data["type"]){
case "1":
$data["content"]["text_content"] = ["zh_TW" => $data["content"]["text_content_tw"] ?? "" , "en" => $data["content"]["text_content_en"] ?? ""];
// 移除臨時的分離欄位,只保留合併的 JSON 欄位
unset($data["content"]["text_content_tw"]);
unset($data["content"]["text_content_en"]);
// 清理 HTML 標籤(如果需要)
foreach ($data['content']['text_content'] as $locale => $content) {
$data['content']['text_content'][$locale] = stripslashes($content);
}
break;
case "2":
// 確保有 text_blocks
if (!isset($data['content']['text_blocks'])) {
$data['content']['text_blocks'] = [];
}
// 處理每個文字區塊
foreach ($data['content']['text_blocks'] as $index => &$block) {
// 確保區塊有必要的欄位
$block['block_item_key'] = $block['block_item_key'] ?? Str::random();
$block['order'] = $block['order'] ?? ($index + 1);
$block["block_content"] = ["zh_TW" => $block["block_content_tw"] ?? "" , "en" => $block["block_content_en"] ?? ""];
// 移除臨時的分離欄位,只保留合併的 JSON 欄位
unset($block["block_content_tw"]);
unset($block["block_content_en"]);
// 清理區塊內容
if (isset($block['block_content'])) {
foreach ($block['block_content'] as $locale => $content) {
$block['block_content'][$locale] = stripslashes($content);
}
}
}
break;
case "3":
// 確保欄數設定
$columnCount = $data['content']['column_count'] ?? 2;
// 確保表頭存在
if (!isset($data['content']['headers'])) {
$data['content']['headers'] = ['zh_TW' => [], 'en' => []];
}
// 確保表格資料存在
if (!isset($data['content']['simple_table_rows'])) {
$data['content']['simple_table_rows'] = [];
}
// 處理表格資料,確保欄數一致
foreach ($data['content']['simple_table_rows'] as $rowIndex => &$row) {
// 確保每行都有正確的欄數
for ($i = 1; $i <= $columnCount; $i++) {
$row["col{$i}"] = ["zh_TW" => $row["col{$i}_tw"] ?? "" , "en" => $row["col{$i}_en"] ?? ""];
foreach ($row["col{$i}"] as $locale => $content) {
$row["col{$i}"][$locale] = $content;
}
unset($row["col{$i}_tw"]);
unset($row["col{$i}_en"]);
$row["align{$i}"] = ["zh_TW" => $row["align{$i}_tw"] ?? "" , "en" => $row["align{$i}_en"] ?? ""];
foreach ($row["align{$i}"] as $locale => $content) {
$row["align{$i}"][$locale] = $content;
}
unset($row["align{$i}_tw"]);
unset($row["align{$i}_en"]);
}
// 移除多餘的欄位
for ($i = $columnCount + 1; $i <= 4; $i++) {
unset($row["col{$i}_tw"]);
unset($row["col{$i}_en"]);
unset($row["align{$i}_tw"]);
unset($row["align{$i}_en"]);
}
}
break;
}
\Log::info($data);
return $data;
})
])->columnSpanFull(),
])
->columnSpanFull()
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
//
TextColumn::make("title")->label("標題"),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListEsg::route('/'),
'create' => Pages\CreateEsg::route('/create'),
'edit' => Pages\EditEsg::route('/{record}/edit'),
];
}
}