# 画面設計書 49-通知公告編集

## 概要

本ドキュメントは、RuoYi後台管理システムの「通知公告編集」画面の設計仕様を定義するものである。

### 本画面の処理概要

既存の通知・公告を編集・更新するためのフォーム画面である。リッチテキストエディタ（Summernote）を使用して、書式付きのコンテンツや画像を含む通知・公告を修正できる。

**業務上の目的・背景**：作成済みの通知や公告の内容を修正する必要がある場合に使用する画面である。タイトルの誤字修正、内容の追記・訂正、状態の変更（正常→関閉）などに対応できる。Summernoteエディタにより、新規登録時と同様の編集機能が利用可能である。

**画面へのアクセス方法**：通知公告管理一覧画面のツールバーにある「修改」ボタン、または各行の「編集」ボタンを押下することでフルスクリーンモーダルとして表示される。

**主要な操作・処理内容**：
1. 既存データの確認（画面表示時に自動読み込み）
2. 公告標題（タイトル）の変更
3. 公告類型（通知/公告）の変更
4. 公告内容のリッチテキスト編集
5. 公告状態（正常/関閉）の変更
6. 確定ボタンで更新実行

**画面遷移**：
- 遷移元：通知公告管理一覧画面（フルスクリーンモーダルとして開く）
- 遷移先：通知公告管理一覧画面（更新成功後、モーダルを閉じて一覧を更新）

**権限による表示制御**：
- `system:notice:edit`権限がある場合のみ本画面にアクセス可能
- 権限がない場合、通知公告管理一覧画面の「修改」ボタンおよび行内「編集」ボタンが非表示

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | 通知公告 | 主機能 | 通知情報の更新保存処理 |

## 画面種別

編集

## URL/ルーティング

- 画面表示: `GET /system/notice/edit/{noticeId}`
- 更新実行: `POST /system/notice/edit`
- 画像アップロード: `POST /common/upload`

## 入出力項目

### 入力項目

| 項目名 | 項目ID | 型 | 必須 | 最大長 | 初期値 | 説明 |
|--------|--------|-----|------|--------|--------|------|
| 公告ID | noticeId | hidden | ○ | - | DBから取得 | 主キー（非表示） |
| 公告標題 | noticeTitle | text | ○ | 50 | DBから取得 | 通知・公告のタイトル |
| 公告類型 | noticeType | select | - | - | DBから取得 | 1:通知、2:公告 |
| 公告内容 | noticeContent | hidden+editor | - | - | DBから取得 | Summernoteエディタで編集 |
| 公告状態 | status | radio | - | - | DBから取得 | 0:正常、1:関閉 |

## 表示項目

なし（入力フォームのみ）

## イベント仕様

### 1-画面表示時

URLパラメータのnoticeIdを元にデータを取得し、フォームに初期表示する。

- エンドポイント: `GET /system/notice/edit/{noticeId}`
- レスポンス: editビュー + 通知・公告モデル
- Summernoteエディタに既存内容を設定

### 2-画像アップロード（Summernote内）

Summernoteエディタで画像を挿入する際に実行される。

- エンドポイント: `POST /common/upload`
- リクエスト: FormData（file）
- レスポンス: {code, url, fileName}
- 成功時: エディタに画像を挿入
- 失敗時: 「图片上传失败」警告表示

### 3-確定（保存）ボタン押下

入力内容をバリデーション後、データを更新する。

- バリデーション:
  - noticeTitle: 必須、50文字以内、XSSチェック
- 処理フロー:
  1. Summernoteの内容をhiddenフィールドに設定
  2. フォームをシリアライズして送信
- エンドポイント: `POST /system/notice/edit`
- リクエストパラメータ: フォーム全項目（noticeId含む）
- 成功時: モーダルを閉じ、親画面の一覧を更新
- 失敗時: エラーメッセージを表示

### 4-取消（キャンセル）ボタン押下

モーダルウィンドウを閉じ、変更内容を破棄する。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示時 | sys_notice | SELECT | noticeIdに該当するデータを取得 |
| 確定ボタン押下 | sys_notice | UPDATE | 通知・公告を更新 |

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

#### sys_notice

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | 全カラム | notice_id = パラメータ値 | 初期表示用 |
| UPDATE | notice_title | 入力値 | 公告標題 |
| UPDATE | notice_type | 入力値（1/2） | 公告類型 |
| UPDATE | notice_content | 入力値（HTML） | リッチテキスト内容 |
| UPDATE | status | 入力値（0/1） | 公告状態 |
| UPDATE | update_by | ログインユーザー名 | 更新者 |
| UPDATE | update_time | sysdate() | 更新日時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 発生条件 |
|-------------|------|---------------|---------|
| - | 成功 | 修改成功 | 更新完了時 |
| - | エラー | 公告标题不能为空 | noticeTitle未入力時 |
| - | エラー | 公告标题不能超过50个字符 | noticeTitle50文字超過時 |
| - | エラー | 公告标题不能包含脚本字符 | XSS検出時 |
| - | 警告 | 图片上传失败。 | 画像アップロード失敗時 |
| - | エラー | 操作失败 | 処理失敗時 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| データ取得エラー | エラーページを表示 |
| バリデーションエラー | 該当項目にエラーメッセージを表示 |
| 画像アップロードエラー | 警告メッセージ表示、エディタへの挿入は行わない |
| XSSコンテンツ検出 | エラーメッセージを表示、更新を中止 |
| 対象データなし | エラーメッセージを表示 |
| 通信エラー | エラーメッセージ表示 |
| 権限不足 | アクセス前に制御されるため基本的に発生しない |

## 備考

- Summernoteエディタの初期化後、既存の公告内容をエディタに設定する処理がある
- 公告内容の更新では、notice_contentがnullの場合も更新対象となる（空での更新可能）
- 画像アップロードは共通エンドポイント（/common/upload）を使用
- XSS対策として、noticeTitleには@Xss注釈が付与されている

---

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

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

### 推奨読解順序

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

まず、プログラム間で受け渡されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SysNotice.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java` | フィールド定義、バリデーション制約 |

**読解のコツ**: 編集画面ではth:field属性でエンティティのプロパティとバインドされる点に注目。

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SysNoticeController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java` | edit(), editSave()メソッド |

**主要処理フロー**:
1. **82-88行目**: `edit()`メソッド - 編集画面表示、noticeIdでデータ取得
2. **93-101行目**: `editSave()`メソッド - 更新処理実行、updateByを設定

#### Step 3: サービス層を理解する

ビジネスロジックの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SysNoticeServiceImpl.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java` | selectNoticeById(), updateNotice()メソッド |

**主要処理フロー**:
- **29-33行目**: `selectNoticeById()` - 主キー検索
- **64-68行目**: `updateNotice()` - Mapper呼び出し

#### Step 4: テンプレート（View）を理解する

フロントエンドの構造と動作を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | edit.html | `ruoyi-admin/src/main/resources/templates/system/notice/edit.html` | Thymeleafバインディング、Summernote初期化、既存内容設定 |

**主要処理フロー**:
- **9行目**: th:objectでエンティティバインド
- **10行目**: hiddenフィールドでnoticeId保持
- **28行目**: hiddenフィールドに既存noticeContentを設定
- **48-63行目**: Summernote初期化
- **61-62行目**: 既存内容をエディタに設定
- **94-100行目**: submitHandler - 内容取得してフォーム送信

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

```
edit.html (View)
    │
    ├─ 画面表示時 ← GET /system/notice/edit/{noticeId}
    │      │
    │      └─ SysNoticeController.edit()
    │             │
    │             └─ ISysNoticeService.selectNoticeById()
    │                    │
    │                    └─ SysNoticeMapper.selectNoticeById()
    │
    ├─ $(function) → summernote('code', content)
    │      │
    │      └─ hiddenフィールドの内容をエディタに設定
    │
    ├─ Summernote onImageUpload → POST /common/upload
    │      │
    │      └─ CommonController.uploadFile()
    │
    └─ submitHandler() → POST /system/notice/edit
           │
           ├─ summernote('code') → noticeContent設定
           │
           └─ SysNoticeController.editSave()
                  │
                  ├─ getLoginName() → updateBy設定
                  │
                  └─ ISysNoticeService.updateNotice()
                         │
                         └─ SysNoticeMapper.updateNotice()
                                │
                                └─ sys_notice UPDATE
```

### データフロー図

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

noticeId ─────────▶ Controller ──────────────▶ edit.html
(PathVariable)       │                         (初期値設定済フォーム)
                     ▼
                   Service
                     │
                     └─▶ Mapper (SELECT)
                            │
                            └─▶ Summernote初期化
                                  │
                                  └─▶ エディタに内容設定

フォーム入力 ───────▶ jQuery Validate ────────▶ バリデーションOK/NG
(noticeId,           │
 noticeTitle,        ▼ OK
 noticeType,       summernote('code')
 noticeContent,      │
 status)             ▼
                   hiddenフィールド設定
                     │
                     ▼
                   Controller
                     │
                     ├─ updateBy設定
                     │
                     ▼
                   Service
                     │
                     └─▶ Mapper (UPDATE)
                           │
                           └─▶ AjaxResult (成功/失敗)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SysNotice.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java` | ソース | 通知・公告エンティティ |
| SysNoticeController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java` | ソース | コントローラー |
| SysNoticeServiceImpl.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java` | ソース | サービス実装 |
| SysNoticeMapper.xml | `ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml` | 設定 | SELECT/UPDATE文定義 |
| edit.html | `ruoyi-admin/src/main/resources/templates/system/notice/edit.html` | テンプレート | 編集フォーム |
| CommonController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java` | ソース | 画像アップロード |
