# 画面設計書 14-ユーザーロール割当

## 概要

本ドキュメントは、RuoYi後台管理システムにおけるユーザーロール割当画面の設計仕様を定義するものである。

### 本画面の処理概要

ユーザーロール割当画面は、特定のユーザーに対してロールを割り当て・解除するための画面である。ユーザー管理一覧から選択したユーザーに対して、どのロールを付与するかをテーブル形式のチェックボックスで管理する。

**業務上の目的・背景**：システムのアクセス制御はロールベースで行われる。ユーザーの役割や責任範囲が変更された場合、適切なロールを割り当て直す必要がある。本画面は、ユーザーと ロールの関連を一覧で確認しながら、直感的に割当・解除操作ができる機能を提供する。編集画面のロール選択とは異なり、ロール情報（権限字符、作成時間等）を確認しながら操作できる。

**画面へのアクセス方法**：ユーザー管理一覧画面から対象ユーザーの「更多操作」メニューから「分配角色（ロール割当）」を選択するか、専用ボタンをクリックすると、新しいタブ形式でこの画面が表示される。URLパターンは `/system/user/authRole/{userId}` で、userIdパスパラメータで対象のユーザーを特定する。

**主要な操作・処理内容**：
1. 画面表示時に対象ユーザーの基本情報と、全ロール一覧（現在の割当状態を含む）を取得・表示
2. ロールテーブルでチェックボックスにより割当・解除を選択
3. ロール情報（ロール名、権限字符、作成時間）を確認しながら操作
4. 「保存」ボタンで選択したロールをユーザーに割り当て
5. 「閉じる」ボタンでタブを閉じて一覧に戻る

**画面遷移**：
- 遷移元：ユーザー管理一覧画面（No.9）
- 遷移先：なし（タブを閉じて一覧に戻る）

**権限による表示制御**：本画面へのアクセスには `system:user:edit` 権限が必要。停用状態のロールはチェックボックスが無効化される。管理者（admin）ユーザーの場合は全ロールが表示されるが、非管理者には管理者ロールは非表示。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | ユーザー管理 | 主機能 | ユーザーへのロール割当・解除処理 |
| 2 | ロール管理 | API連携 | ロール一覧取得と割当状態確認 |

## 画面種別

編集（タブ形式・テーブル選択UI）

## URL/ルーティング

| メソッド | URL | 説明 |
|---------|-----|------|
| GET | /system/user/authRole/{userId} | ロール割当画面表示 |
| POST | /system/user/authRole/insertAuthRole | ロール割当保存 |

## 入出力項目

### 入力項目

| No | 項目名 | 物理名 | 型 | 桁数 | 必須 | 初期値 | バリデーション |
|----|--------|--------|----|----|------|--------|--------------|
| 1 | ユーザーID | userId | hidden | - | ○ | 対象ユーザーID | - |
| 2 | ロールID配列 | roleIds | checkbox | - | - | 現在割当済みのロール | - |

### 表示項目（テーブル形式）

| No | 項目名 | 物理名 | 説明 |
|----|--------|--------|------|
| 1 | 選択チェック | checkbox | ロール選択用チェックボックス |
| 2 | 角色編號 | roleId | ロールID |
| 3 | 角色名稱 | roleName | ロール名称 |
| 4 | 権限字符 | roleKey | 権限識別子（ソート可能） |
| 5 | 作成時間 | createTime | ロール作成日時（ソート可能） |

### ユーザー基本情報（読み取り専用）

| No | 項目名 | 物理名 | 説明 |
|----|--------|--------|------|
| 1 | ユーザー名称 | userName | 対象ユーザーの表示名 |
| 2 | 登録帳號 | loginName | 対象ユーザーのログインID |

## イベント仕様

### 1-画面初期表示

| 項目 | 内容 |
|------|------|
| トリガー | ユーザー管理一覧画面から「分配角色」メニュー選択時 |
| 処理内容 | 1. コントローラーがuserIdパラメータを受け取り、データ権限チェックを実行<br>2. 該当ユーザー情報を取得<br>3. ユーザーに紐づくロール一覧（全ロール+割当フラグ）を取得<br>4. 管理者以外の場合は管理者ロールを除外<br>5. タブ画面を表示し、Bootstrap Tableでロール一覧を描画 |
| 呼び出しAPI | GET /system/user/authRole/{userId} |
| 遷移先 | - |

### 2-テーブルロール選択

| 項目 | 内容 |
|------|------|
| トリガー | ロール行のチェックボックスクリック時 |
| 処理内容 | 1. clickToSelect: trueにより行クリックでも選択可能<br>2. maintainSelected: trueにより選択状態を維持<br>3. 停用ロール（status=1）はdisabledで選択不可 |
| 呼び出しAPI | - |
| 遷移先 | - |

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

| 項目 | 内容 |
|------|------|
| トリガー | 「保存」ボタン押下時 |
| 処理内容 | 1. Bootstrap Tableから全データを取得<br>2. チェックされたロールのroleIdを配列に収集<br>3. userIdとroleIds（カンマ区切り）をPOST送信<br>4. 既存のユーザーロール関連を削除後、新規関連を登録<br>5. 成功時はタブを閉じて一覧を更新 |
| 呼び出しAPI | POST /system/user/authRole/insertAuthRole |
| 遷移先 | ユーザー管理一覧画面（タブを閉じる） |

### 4-閉じるボタン押下

| 項目 | 内容 |
|------|------|
| トリガー | 「閉じる」ボタン押下時 |
| 処理内容 | 現在のタブを閉じる |
| 呼び出しAPI | - |
| 遷移先 | ユーザー管理一覧画面 |

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 保存ボタン押下 | sys_user_role | DELETE | 既存のユーザーロール関連を全削除 |
| 保存ボタン押下 | sys_user_role | INSERT | 選択されたロールとの関連を登録 |

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

#### sys_user_role

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | user_id = #{userId} | 既存関連の全削除 |
| INSERT | user_id | 対象ユーザーID | - |
| INSERT | role_id | 選択されたロールID | 選択数分繰り返し |

## メッセージ仕様

| No | 種別 | メッセージ | 表示条件 |
|----|------|----------|----------|
| 1 | 成功 | 操作成功 | ロール割当保存成功時 |
| 2 | エラー | 操作失敗 | ロール割当保存失敗時 |

## 例外処理

| 例外パターン | 対応処理 |
|------------|---------|
| データ権限不足 | 対象ユーザーへのデータ権限がない場合、アクセス拒否エラー |
| ロールデータ権限不足 | 割当しようとしたロールへの権限がない場合、エラー返却 |
| 対象ユーザー不存在 | 対象のユーザーIDが存在しない場合、エラー画面表示 |

## 備考

- Bootstrap Tableを使用したクライアントサイドテーブル（sidePagination: "client"）
- roleSort（表示順）でデフォルトソート
- 検索・リフレッシュ・トグル・カラム表示切替機能は非表示（showSearch/showRefresh/showToggle/showColumns: false）
- ロールのflagフィールドで現在の割当状態を判定

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SysRole.java | `ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java` | flagフィールドがユーザーとの割当状態を示す |
| 1-2 | SysUserRole.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java` | ユーザーロール関連テーブルのエンティティ |

**読解のコツ**: SysRoleのflagフィールドはDB項目ではなく、selectRolesByUserIdで動的に設定される割当状態フラグ。

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

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

**主要処理フロー**:
1. **244-258行目**: `authRole()` メソッド - 画面表示、ユーザー情報とロール一覧取得
2. **260-274行目**: `insertAuthRole()` メソッド - ロール割当保存処理

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ISysRoleService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java` | selectRolesByUserIdの定義 |
| 3-2 | ISysUserService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java` | insertUserAuthの定義 |

**主要処理フロー**:
- `selectRolesByUserId()`: ユーザーに紐づくロール一覧を取得（flagで割当状態を示す）
- `insertUserAuth()`: ユーザーロール関連の削除・登録

#### Step 4: 画面テンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | authRole.html | `ruoyi-admin/src/main/resources/templates/system/user/authRole.html` | Bootstrap Table初期化、チェックボックスフォーマッタ |

**主要処理フロー**:
- **9行目**: hidden項目でuserIdを保持
- **48-100行目**: Bootstrap Table初期化設定
- **65-72行目**: チェックボックスformatter（flag/statusでチェック状態・無効状態を制御）
- **102-112行目**: submitHandler()関数でroleIds収集と保存処理

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

```
ユーザー管理一覧画面 [分配角色]メニュー選択
    │
    ├─ SysUserController.authRole()           ← GET /system/user/authRole/{userId}
    │      ├─ userService.checkUserDataScope()    ← 権限チェック
    │      ├─ userService.selectUserById()        ← ユーザー情報取得
    │      └─ roleService.selectRolesByUserId()   ← ロール一覧取得（flag付き）
    │
    └─ authRole.html 表示（タブ形式）
           │
           └─ [保存]ボタン押下
                  │
                  ├─ submitHandler() → $.operate.saveTab()
                  │
                  └─ SysUserController.insertAuthRole()  ← POST /authRole/insertAuthRole
                         ├─ userService.checkUserDataScope()
                         ├─ roleService.checkRoleDataScope()
                         │
                         └─ userService.insertUserAuth()
                                ├─ userRoleMapper.deleteUserRoleByUserId()
                                └─ userRoleMapper.batchUserRole()
```

### データフロー図

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

userId (hidden)          SysUserController.insertAuthRole()  sys_user_role更新
roleIds (チェック選択) ───▶    │                               │
                              ├─ deleteUserRoleByUserId() ───▶ DELETE
                              │
                              └─ batchUserRole()         ───▶ INSERT (n件)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SysUserController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java` | コントローラー | authRole(), insertAuthRole()メソッド |
| authRole.html | `ruoyi-admin/src/main/resources/templates/system/user/authRole.html` | テンプレート | ロール割当画面UI（Bootstrap Table） |
| SysRole.java | `ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java` | エンティティ | ロールドメイン（flag付き） |
| SysUserRole.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java` | エンティティ | ユーザーロール関連 |
| ISysRoleService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java` | インターフェース | ロールサービス定義 |
| SysUserRoleMapper.xml | `ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml` | Mapper | ユーザーロール関連SQL |
