# 画面設計書 22-ロールデータ権限設定

## 概要

本ドキュメントは、RuoYi後台管理システムにおける「ロールデータ権限設定」画面の設計仕様を定義するものである。ロールに対してデータアクセス範囲（データスコープ）を設定するための画面で、部門単位でのアクセス制御を実現する。

### 本画面の処理概要

この画面では、ロールに対してデータアクセス権限の範囲を設定する。データスコープは、ユーザーがアクセス可能なデータの範囲を部門単位で制御する機能であり、組織階層に基づいたきめ細かなアクセス制御を可能にする。

**業務上の目的・背景**：企業の組織構造に応じて、各ロールがアクセスできるデータ範囲を制限する必要がある。例えば、部門長は自部門のデータのみ閲覧可能、管理者は全社データを閲覧可能といった制御を実現する。この機能により、機密情報の漏洩防止と業務効率の両立を図る。

**画面へのアクセス方法**：ロール管理一覧画面から対象ロールの「データ権限」ボタンをクリック、またはロールを選択して「その他」メニューから「データ権限」を選択することで、モーダルダイアログとして表示される。

**主要な操作・処理内容**：
1. データ範囲の選択（全部数据権限/自定義数据権限/本部門数据権限/本部門及以下数据権限/仅本人数据権限）
2. 「自定義数据権限」選択時の部門ツリー選択
3. ツリー操作（展開/折叠、全選択/全解除、親子連動）
4. データ権限設定の保存

**画面遷移**：ロール管理一覧画面から遷移し、保存完了後は一覧画面に戻る。キャンセル時も一覧画面に戻る。

**権限による表示制御**：`system:role:edit`権限を持つユーザーのみアクセス可能。管理者ロール（roleId=1）は操作が制限される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | ロール管理 | 主機能 | ロールのデータアクセス権限設定処理 |
| 4 | 部門管理 | 補助機能 | 部門データ権限ツリーの取得処理 |

## 画面種別

編集（モーダルダイアログ）

## URL/ルーティング

- 画面表示: `GET /system/role/authDataScope/{roleId}`
- データ保存: `POST /system/role/authDataScope`
- 部門ツリーデータ: `GET /system/role/deptTreeData?roleId={roleId}`

## 入出力項目

### 入力項目

| 項目名 | 物理名 | 型 | 必須 | 最大長 | バリデーション | 説明 |
|--------|--------|-----|------|--------|----------------|------|
| ロールID | roleId | Long | - | - | 自動（hidden） | 設定対象のロールID |
| ロール名称 | roleName | String | - | - | 読み取り専用 | ロールの表示名（変更不可） |
| 権限字符 | roleKey | String | - | - | 読み取り専用 | 権限識別子（変更不可） |
| データ範囲 | dataScope | String | 必須 | 1 | 1-5の値 | データアクセス範囲の種別 |
| 部門ID配列 | deptIds | Long[] | - | - | dataScope=2の場合のみ有効 | アクセス許可する部門のID配列 |

### 出力項目（初期表示）

| 項目名 | 物理名 | 型 | 説明 |
|--------|--------|-----|------|
| ロール情報 | role | SysRole | 設定対象のロール情報 |
| 部門ツリー | deptTrees | List<Ztree> | 選択済み部門を含むツリーデータ |

## 表示項目

| 表示項目 | 説明 | 初期値 |
|----------|------|--------|
| ロール名称（読取専用） | テキスト表示 | DBから取得した値 |
| 権限字符（読取専用） | テキスト表示 | DBから取得した値 |
| データ範囲セレクト | ドロップダウン選択 | DBの現在設定値 |
| 展開/折叠チェックボックス | ツリー展開制御 | チェック済み |
| 全選択/全解除チェックボックス | 一括選択制御 | 未チェック |
| 親子連動チェックボックス | 連動選択制御 | チェック済み |
| データ権限ツリー | zTreeによるチェックボックスツリー | 既存設定が選択された状態（dataScope=2の場合のみ表示） |

### データ範囲の選択肢

| 値 | 表示ラベル | 説明 |
|----|----------|------|
| 1 | 全部数据権限 | システム全体のデータにアクセス可能 |
| 2 | 自定義数据権限 | 選択した部門のデータのみアクセス可能 |
| 3 | 本部門数据権限 | 自身が所属する部門のデータのみアクセス可能 |
| 4 | 本部門及以下数据権限 | 自身の部門と配下部門のデータにアクセス可能 |
| 5 | 仅本人数据権限 | 自身が作成したデータのみアクセス可能 |

## イベント仕様

### 1-画面表示

モーダルダイアログとしてデータ権限設定画面を表示する。

**処理フロー**：
1. `SysRoleController.authDataScope()`がroleIdを受け取る
2. `roleService.checkRoleDataScope()`でデータスコープ権限を検証
3. `roleService.selectRoleById()`でロール情報を取得
4. ModelMapにロール情報を設定
5. Thymeleafテンプレートを描画
6. JavaScript初期化処理で部門ツリーをAjax取得
7. dataScope=2の場合、部門選択エリアを表示

### 2-データ範囲変更

データ範囲のセレクトボックス変更時の処理。

**処理フロー**：
1. `$("#dataScope").change()`イベントが発火
2. `dataScopeVisible()`関数が呼び出される
3. dataScope=2の場合: `$("#authDataScope").show()`で部門ツリーを表示
4. dataScope!=2の場合: `$._tree.checkAllNodes(false)`で全解除し、`$("#authDataScope").hide()`で非表示

### 3-ツリー展開/折叠

部門ツリーの展開/折叠を切り替える。

**処理フロー**：
1. チェックボックスの変更イベントを検知
2. チェック時: `$._tree.expandAll(true)`で全展開
3. 未チェック時: `$._tree.expandAll(false)`で全折叠

### 4-全選択/全解除

部門ツリーの全選択/全解除を切り替える。

**処理フロー**：
1. チェックボックスの変更イベントを検知
2. チェック時: `$._tree.checkAllNodes(true)`で全選択
3. 未チェック時: `$._tree.checkAllNodes(false)`で全解除

### 5-親子連動切替

親子ノードの連動選択を切り替える。

**処理フロー**：
1. チェックボックスの変更イベントを検知
2. チェック時: `chkboxType = { "Y": "ps", "N": "ps" }`で連動有効
3. 未チェック時: `chkboxType = { "Y": "", "N": "" }`で連動無効

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

設定内容をサーバーに送信して保存する。

**処理フロー**：
1. `submitHandler()`関数が呼び出される
2. `$.validate.form()`でクライアントバリデーション実行
3. バリデーション成功時、`edit()`関数を呼び出し
4. 選択された部門IDを`$.tree.getCheckedNodes()`で取得
5. Ajax POSTでサーバーに送信
6. サーバー側で`checkRoleAllowed()`、`checkRoleDataScope()`を実行
7. `roleService.authDataScope()`でDB更新
8. 成功時はモーダルを閉じて一覧を更新

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 保存ボタン押下 | sys_role | UPDATE | data_scopeの更新 |
| 保存ボタン押下 | sys_role_dept | DELETE | 既存のロール-部門関連を全削除 |
| 保存ボタン押下 | sys_role_dept | INSERT | 新規のロール-部門関連を登録（dataScope=2の場合のみ） |

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

#### sys_role

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | data_scope | 入力値（1-5） | データ範囲 |
| UPDATE | update_by | ログインユーザー名 | 更新者 |
| UPDATE | update_time | sysdate() | 更新日時 |

#### sys_role_dept

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | role_id = 対象ロールID | 既存関連を削除 |
| INSERT | role_id | 対象ロールID | ロールID |
| INSERT | dept_id | 選択された部門ID | 部門ID |

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|----------|----------|
| エラー | 系统错误 | 通信エラー発生時 |
| 成功 | 操作成功 | 保存成功時 |

## 例外処理

| 例外状況 | 処理内容 |
|----------|----------|
| データスコープ外のロール | ServiceExceptionをスローし、アクセス拒否 |
| 管理者ロール(roleId=1)の編集 | ServiceExceptionをスローし、操作拒否 |
| 通信エラー | 「系统错误」メッセージを表示 |
| セッションタイムアウト | ログイン画面へリダイレクト |

## 備考

- 管理者ロール（roleId=1）は特別な保護対象であり、データ権限設定が制限される
- データ範囲が「自定義数据権限」以外の場合、部門ツリーの選択状態は保存されない
- データ権限はSQLレベルで動的に適用され、ユーザーは設定されたスコープ外のデータにアクセスできない
- 部門ツリーは2階層まで初期展開される（expandLevel: 2）
- nocheckInherit: trueにより、親ノードのチェック状態が子に継承される

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SysRole.java | `ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java` | dataScopeフィールド（36-38行目）とdeptIds配列の用途を理解する |
| 1-2 | Ztree.java | `ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Ztree.java` | 部門ツリー表示用のデータ構造を理解する |

**読解のコツ**: dataScopeの値（1-5）の意味を把握することが重要。ExcelアノテーションのreadConverterExpに定義されている。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SysRoleController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java` | authDataScope()メソッドとauthDataScopeSave()メソッドの処理フローを理解する |

**主要処理フロー**:
1. **149-155行目**: authDataScope()メソッド - 画面表示処理
2. **160-175行目**: authDataScopeSave()メソッド - 保存処理
3. **317-325行目**: deptTreeData()メソッド - 部門ツリーデータ取得

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ISysRoleService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java` | authDataScope()メソッドの定義（88-93行目） |
| 3-2 | SysRoleServiceImpl.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java` | authDataScope()メソッドの実装詳細 |
| 3-3 | ISysDeptService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java` | roleDeptTreeData()メソッドの定義 |

**主要処理フロー**:
- authDataScope(): ロールのdataScope更新 -> 既存部門関連の削除 -> 新規部門関連の登録

#### Step 4: データアクセス層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SysRoleMapper.xml | `ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml` | updateRole SQLでdata_scopeの更新を確認 |
| 4-2 | SysRoleDeptMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java` | ロール-部門関連のCRUD操作 |
| 4-3 | SysDeptMapper.xml | `ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml` | selectRoleDeptTree（30-36行目）で部門ツリーデータ取得 |

#### Step 5: フロントエンド処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | dataScope.html | `ruoyi-admin/src/main/resources/templates/system/role/dataScope.html` | 画面構造とJavaScript処理を理解する |

**主要処理フロー**:
- **54-63行目**: 部門ツリーの初期化処理
- **65-87行目**: ツリー操作のイベントハンドラ
- **95-120行目**: edit()関数 - 保存処理のAjax呼び出し
- **122-134行目**: dataScopeVisible()関数 - 部門ツリーの表示制御

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

```
[画面表示] dataScope.html
    │
    ├─ SysRoleController.authDataScope()
    │      ├─ roleService.checkRoleDataScope()
    │      └─ roleService.selectRoleById()
    │
    ├─ [Ajax] deptTreeData
    │      └─ SysRoleController.deptTreeData()
    │             └─ deptService.roleDeptTreeData()
    │                    └─ SysDeptMapper.selectRoleDeptTree()
    │
    └─ [保存] edit()関数
           └─ SysRoleController.authDataScopeSave()
                  ├─ roleService.checkRoleAllowed()
                  ├─ roleService.checkRoleDataScope()
                  └─ roleService.authDataScope()
                         ├─ SysRoleMapper.updateRole()
                         ├─ SysRoleDeptMapper.deleteRoleDeptByRoleId()
                         └─ SysRoleDeptMapper.batchRoleDept()
```

### データフロー図

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

roleId(hidden) ─────┐
roleName(readonly) ─┤     SysRoleController.authDataScopeSave()
roleKey(readonly) ──┼───▶ SysRoleServiceImpl.authDataScope() ───▶ sys_role (UPDATE data_scope)
dataScope ──────────┤           │                                  sys_role_dept (DELETE/INSERT)
deptIds[] ──────────┘           ▼
                         userService.selectUserById(getUserId())
                         (現在ユーザー情報のリロード)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dataScope.html | `ruoyi-admin/src/main/resources/templates/system/role/dataScope.html` | テンプレート | データ権限設定画面のHTML/JavaScript |
| SysRoleController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java` | コントローラー | HTTPリクエストの処理 |
| ISysRoleService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java` | インターフェース | ロールサービスの定義 |
| SysRoleServiceImpl.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java` | サービス実装 | ビジネスロジック |
| ISysDeptService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java` | インターフェース | 部門サービスの定義 |
| SysDeptServiceImpl.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java` | サービス実装 | 部門ツリー取得ロジック |
| SysRoleMapper.xml | `ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml` | SQL定義 | ロールSQL |
| SysDeptMapper.xml | `ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml` | SQL定義 | 部門ツリーSQL |
| SysRole.java | `ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java` | エンティティ | ロールデータモデル |
