# 画面設計書 14-ページブロック編集

## 概要

本ドキュメントは、QuickerSite CMSのバックサイト（管理画面）における「ページブロック編集」画面の設計仕様を定義するものである。

### 本画面の処理概要

ページブロック編集画面は、テンプレート内で定義された8つのデフォルトブロック（PAGE_BLOCK01〜PAGE_BLOCK08）に対して、ページごとのカスタムコンテンツを設定するための画面である。テンプレート内で使用される[PAGE_BLOCK01]〜[PAGE_BLOCK08]のプレースホルダに挿入されるHTMLコンテンツを編集できる。

**業務上の目的・背景**：
Webサイトのテンプレートには、ヘッダー、サイドバー、フッターなど共通のレイアウト要素が含まれる。しかし、特定のページでは共通要素の一部をカスタマイズしたい場合がある（例：特定ページのサイドバーに専用バナーを表示）。本画面は、テンプレートの共通ブロックをページ単位で上書きする機能を提供し、柔軟なページカスタマイズを実現する。

**画面へのアクセス方法**：
1. バックサイトにログイン後、対象ページの編集画面を開く
2. ページ要素設定へのリンクをクリック
3. URLパラメータとして暗号化されたページID（iPageID）が渡される

**主要な操作・処理内容**：
1. PAGE_BLOCK01〜PAGE_BLOCK08の8つのブロックに対するコンテンツ入力
2. 奇数番号ブロック（01,03,05,07）はテキストエリアで入力
3. 偶数番号ブロック（02,04,06,08）はWYSIWYGエディタ（FCKEditor）で入力
4. 各ブロックのデフォルト値（customer設定）を参照表示
5. 保存ボタンでデータベースに保存

**画面遷移**：
- 遷移元: 各ページ編集画面（bs_editItem.asp等）からのリンク
- 遷移先: 同一画面（保存後も同じ画面に留まる）

**権限による表示制御**：
secondAdmin.bSetupPageElementsがfalseの場合、画面へのアクセスが拒否される（logon.hasaccess関数による制御）。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 19 | ページブロック編集 | 主機能 | ページ内ブロック（コンテンツ領域）のレイアウト管理 |

## 画面種別

編集画面

## URL/ルーティング

```
asp/bs_editPageBlocks.asp?iPageID={暗号化されたページID}
```

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|---------|------|------|
| iPageID | 入力（hidden） | String | Yes | 暗号化されたページID |
| btnaction | 入力（hidden） | String | Yes | アクション種別（save） |
| sProp01 | 入力（textarea） | String | No | PAGE_BLOCK01のコンテンツ |
| sProp02 | 入力（WYSIWYG） | String | No | PAGE_BLOCK02のコンテンツ |
| sProp03 | 入力（textarea） | String | No | PAGE_BLOCK03のコンテンツ |
| sProp04 | 入力（WYSIWYG） | String | No | PAGE_BLOCK04のコンテンツ |
| sProp05 | 入力（textarea） | String | No | PAGE_BLOCK05のコンテンツ |
| sProp06 | 入力（WYSIWYG） | String | No | PAGE_BLOCK06のコンテンツ |
| sProp07 | 入力（textarea） | String | No | PAGE_BLOCK07のコンテンツ |
| sProp08 | 入力（WYSIWYG） | String | No | PAGE_BLOCK08のコンテンツ |
| QS_secCodeHidden | 入力（hidden） | String | Yes | CSRF対策トークン |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|---------|------|
| ページタイトル | テキスト | 編集対象のページ名 |
| [PAGE_BLOCK01]入力欄 | テキストエリア | ブロック1のコンテンツ入力 |
| [PAGE_BLOCK01]デフォルト値 | テキスト | customerのsProp01値 |
| [PAGE_BLOCK02]入力欄 | WYSIWYG | ブロック2のコンテンツ入力 |
| [PAGE_BLOCK02]デフォルト値 | テキスト | customerのsProp02値 |
| ...（03〜08も同様） | ... | ... |

## イベント仕様

### 1-保存ボタン押下

1. フォームをPOST送信
2. btnaction=l("save")の条件でサーバー処理開始
3. checkCSRF()でCSRFトークン検証
4. Request.Form()から各sPropXX値を取得
5. removeEmptyP()とconvertStr()で値をサニタイズ
6. page.save()でデータベースに保存
7. 保存成功時、message.Add("fb_saveOK")でメッセージ設定
8. 同一画面を再表示（アラートでメッセージ表示）

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 保存ボタン押下 | tblPage | UPDATE | ページブロックコンテンツを更新 |

### テーブル別更新項目詳細

#### tblPage

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sProp01 | フォームから取得（サニタイズ済み） | PAGE_BLOCK01のコンテンツ |
| UPDATE | sProp02 | フォームから取得（サニタイズ済み） | PAGE_BLOCK02のコンテンツ |
| UPDATE | sProp03 | フォームから取得（サニタイズ済み） | PAGE_BLOCK03のコンテンツ |
| UPDATE | sProp04 | フォームから取得（サニタイズ済み） | PAGE_BLOCK04のコンテンツ |
| UPDATE | sProp05 | フォームから取得（サニタイズ済み） | PAGE_BLOCK05のコンテンツ |
| UPDATE | sProp06 | フォームから取得（サニタイズ済み） | PAGE_BLOCK06のコンテンツ |
| UPDATE | sProp07 | フォームから取得（サニタイズ済み） | PAGE_BLOCK07のコンテンツ |
| UPDATE | sProp08 | フォームから取得（サニタイズ済み） | PAGE_BLOCK08のコンテンツ |
| UPDATE | updatedTS | now() | 更新日時 |

## メッセージ仕様

| メッセージID | 種別 | 表示条件 | メッセージ内容 |
|-------------|------|---------|--------------|
| fb_saveOK | 成功 | 保存成功時 | 保存が完了しました |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 未認証アクセス | bs_security.aspによりログイン画面にリダイレクト |
| 権限不足 | logon.hasaccess(secondAdmin.bSetupPageElements)でアクセス拒否 |
| 不正なページID | page.pick()で該当なしの場合、空のオブジェクトとなる |
| CSRFトークン不正 | checkCSRF()でエラー処理 |

## 備考

- 画面は白背景のシンプルなレイアウト（body style="background-color:#FFF"）
- 奇数ブロック：プレーンテキスト/HTML入力（480px幅のtextarea）
- 偶数ブロック：WYSIWYGエディタ（FCKEditor/siteBuilderMailSource設定）
- デフォルト値はcustomerオブジェクトから取得（サイト全体のデフォルトブロック設定）
- 空のp要素は removeEmptyP() 関数で除去される
- cPopup.dumpJS()でポップアップ関連のJavaScriptを出力

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

ページブロックがどのようにデータベースに格納されるかを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | page.asp | `asp/includes/page.asp` | cls_pageクラスのsProp01〜sProp08プロパティ（行11） |

**読解のコツ**: sProp01〜sProp08はtblPageテーブルの同名カラムに対応し、ページごとのカスタムブロックコンテンツを格納する。

#### Step 2: エントリーポイントを理解する

画面表示とフォーム処理の流れを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bs_editPageBlocks.asp | `asp/bs_editPageBlocks.asp` | メイン画面処理ファイル |

**主要処理フロー**:
1. **行4**: secondAdmin.bSetupPageElementsの権限チェック
2. **行4-6**: ページオブジェクトの初期化と既存データの取得
3. **行7-17**: POSTリクエスト時の保存処理
4. **行18**: WYSIWYGエディタ（createFCKInstance）の生成

#### Step 3: 権限制御を理解する

アクセス権限の仕組みを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | bs_security.asp | `asp/bs_security.asp` | 認証チェック処理 |

**主要処理フロー**:
- logon.hasaccess(secondAdmin.bSetupPageElements)で権限確認
- 権限がない場合はアクセスを拒否

#### Step 4: WYSIWYGエディタを理解する

FCKEditorの初期化と値の取得方法を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | commonheader.asp | `asp/includes/commonheader.asp` | FCKEditor関連のJS読み込み |

**読解のコツ**: createFCKInstance関数は、指定されたフィールド名でWYSIWYGエディタを生成する。第2引数はエディタの設定プロファイル名。

### プログラム呼び出し階層図

```
bs_editPageBlocks.asp
    │
    ├─ begin.asp（セッション・DB初期化）
    │
    ├─ bs_security.asp（認証チェック）
    │      └─ logon.hasaccess(secondAdmin.bSetupPageElements)
    │
    ├─ commonheader.asp（HTMLヘッダー、FCKEditor）
    │
    ├─ bs_initBack.asp（バックサイト初期化）
    │
    ├─ cls_page.pick()（ページデータ取得）
    │      └─ tblPageテーブルSELECT
    │
    ├─ [POST時] 保存処理
    │      ├─ checkCSRF()
    │      ├─ removeEmptyP() / convertStr()
    │      └─ cls_page.save()
    │
    ├─ createFCKInstance()（WYSIWYGエディタ生成）
    │      └─ sProp02, sProp04, sProp06, sProp08用
    │
    └─ bs_endBack.asp（バックサイトフッター）
```

### データフロー図

```
[入力]                        [処理]                      [出力]

URLパラメータ(iPageID) ───────▶ decrypt() ─────────────▶ ページID取得
                                    │
                                    ▼
                              cls_page.pick() ──────────▶ 現在のブロック値
                                    │
                                    ▼
customerオブジェクト ─────────────────────────────────▶ デフォルト値表示
                                    │
フォーム入力                         │
   │ sProp01（textarea）            │
   │ sProp02（WYSIWYG）             ▼
   │ ...                     request.form() ──────────▶ 入力値取得
   │ sProp08（WYSIWYG）             │
   │                                │
   │                          removeEmptyP()
   │                          convertStr() ────────────▶ サニタイズ
   │                                │
   │                                ▼
   └──────────────────────────▶ page.save() ────────────▶ tblPage UPDATE
                                    │
                                    ▼
                              message.showAlert() ────▶ 完了メッセージ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bs_editPageBlocks.asp | `asp/bs_editPageBlocks.asp` | ソース | メイン画面処理 |
| begin.asp | `asp/begin.asp` | インクルード | 初期化処理 |
| bs_security.asp | `asp/bs_security.asp` | インクルード | 認証チェック |
| commonheader.asp | `asp/includes/commonheader.asp` | インクルード | HTMLヘッダー |
| bs_initBack.asp | `asp/bs_initBack.asp` | インクルード | バックサイト初期化 |
| bs_endBack.asp | `asp/bs_endBack.asp` | インクルード | バックサイトフッター |
| page.asp | `asp/includes/page.asp` | インクルード | cls_pageクラス |
