# 数据范围全选/取消全选优化 - 页面改动说明

## 文档信息

- 文档名称：数据范围全选/取消全选优化 - 页面改动说明
- 所属模块：全知平台 / 风控模块 / 风险场景
- 编写目的：说明数据范围多选下拉框增加全选/取消全选功能的改动内容，为前端开发提供指引
- 优化背景：数据范围下拉选项有几十个公司，全选或取消全选需逐个点击，效率低。在下拉选项列表顶部增加全选复选框和已选计数

---

## 涉及页面清单

| 序号 | 页面文件 | 选择器类型 | 说明 |
|------|----------|-----------|------|
| 1 | `风险场景详情和编辑页面.html` | 静态 | 场景编辑页，HTML硬编码选项 |
| 2 | `新建风险场景页面.html` | 静态 | 场景新建页，HTML硬编码选项 |
| 3 | `疑点派发-疑点详情.html` | 静态 | 疑点详情页，HTML硬编码选项 |
| 4 | `疑点派发-场景疑点.html` | 动态 | 场景疑点筛选器，JS动态生成选项 |
| 5 | `疑点处置-场景疑点.html` | 动态 | 场景疑点筛选器，JS动态生成选项 |

---

## 通用改动：CSS样式

所有5个页面均需在 `<style>` 中新增以下样式（可抽取为公共样式）：

```css
.multi-select-header {
    padding: 8px 12px;
    border-bottom: 1px solid #e4e7ed;
    background: #fafafa;
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: sticky;
    top: 0;
    z-index: 1;
}
.multi-select-header label {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    margin: 0;
    font-size: 13px;
    color: #606266;
}
.multi-select-count {
    font-size: 12px;
    color: #909399;
}
```

**要点**：
- `position: sticky; top: 0` 使全选头部在下拉列表滚动时始终可见
- `z-index: 1` 确保头部不被选项遮挡

---

## 1. 风险场景详情和编辑页面

### 对应文件

`风险场景详情和编辑页面.html`

### 选择器类型

静态（HTML硬编码19个公司选项，`id="dataScopeOptions"`）

### 改动内容

#### 1.1 HTML

在 `#dataScopeOptions` 内部、第一个 `.multi-select-option` 之前插入全选头部：

```html
<div class="multi-select-options" id="dataScopeOptions">
    <!-- 新增：全选头部 -->
    <div class="multi-select-header">
        <label><input type="checkbox" id="selectAllDataScope"> 全选</label>
        <span class="multi-select-count" id="dataScopeCount">已选 2/19</span>
    </div>
    <!-- 原有选项 -->
    <div class="multi-select-option checked" data-value="示例单位A">示例单位A</div>
    ...
</div>
```

#### 1.2 JavaScript

**新增 `updateDataScopeUI()` 函数**：

```javascript
function updateDataScopeUI() {
    const total = $('#dataScopeOptions .multi-select-option').length;
    const checked = $('#dataScopeOptions .multi-select-option.checked').length;
    $('#dataScopeCount').text(`已选 ${checked}/${total}`);
    $('#selectAllDataScope').prop('checked', checked === total && total > 0);
}
```

**新增全选点击事件**：

```javascript
$('#selectAllDataScope').on('click', function(e) {
    e.stopPropagation(); // 阻止下拉关闭
    const isChecked = $(this).prop('checked');
    $('#dataScopeOptions .multi-select-option').toggleClass('checked', isChecked);
    updateDataScope();   // 已有的更新函数
    updateDataScopeUI(); // 新增：更新计数
});
```

**在已有的选项点击和标签移除事件末尾追加 `updateDataScopeUI()` 调用**：

```javascript
// 选项点击
$('#dataScopeOptions .multi-select-option').on('click', function() {
    // ...原有逻辑...
    updateDataScope();
    updateDataScopeUI(); // 新增
});

// 标签移除
$(document).on('click', '#dataScopeTags .fa-times', function() {
    // ...原有逻辑...
    updateDataScope();
    updateDataScopeUI(); // 新增
});
```

**页面初始化时调用**：

```javascript
updateDataScopeUI();
```

> 该页面默认勾选了2个单位，初始化计数显示为"已选 2/19"。

---

## 2. 新建风险场景页面

### 对应文件

`新建风险场景页面.html`

### 选择器类型

静态（HTML硬编码19个公司选项，`id="dataScopeOptions"`，默认无选中）

### 改动内容

#### 2.1 HTML

同页面1，在 `#dataScopeOptions` 内部插入全选头部：

```html
<div class="multi-select-header">
    <label><input type="checkbox" id="selectAllDataScope"> 全选</label>
    <span class="multi-select-count" id="dataScopeCount">已选 0/19</span>
</div>
```

> 新建页面默认无选中，计数初始为"已选 0/19"。

#### 2.2 JavaScript

与页面1逻辑一致，额外注意：

- 全选事件中需同步调用 `updateCompanyHandlerArea()`（分公司处置人区域联动）
- 全选事件中需调用 `updateSubmitButtonStatus()`（提交按钮状态更新）
- 选项点击和标签移除事件末尾同样追加 `updateDataScopeUI()` 调用

---

## 3. 疑点派发-疑点详情

### 对应文件

`疑点派发-疑点详情.html`

### 选择器类型

静态（HTML硬编码19个公司选项，`id="dataScopeOptions"`，默认勾选2个）

### 改动内容

#### 3.1 HTML

同页面1，在 `#dataScopeOptions` 内部插入全选头部，初始显示"已选 2/19"。

#### 3.2 JavaScript

与页面1逻辑一致，额外注意：

- 全选事件中需调用 `getSelectedDataScopes()` 重建筛选标签
- 全选事件末尾需调用 `applyAllFilters()` 应用筛选
- 选项点击和标签移除事件末尾同样追加 `updateDataScopeUI()` 调用

---

## 4. 疑点派发-场景疑点

### 对应文件

`疑点派发-场景疑点.html`

### 选择器类型

动态（JS从 `sceneData.dataScopes` 数组生成选项，`id` 前缀为 `rule`/`biz`，两个下拉共用状态 `sharedFilterState.dataScopes`）

### 改动内容

#### 4.1 修改 `renderDataScopeDropdown(prefix)` 函数

在生成选项HTML前，拼接全选头部：

```javascript
function renderDataScopeDropdown(prefix) {
    const tagsContainer = document.getElementById(`${prefix}DataScopeTags`);
    const optionsContainer = document.getElementById(`${prefix}DataScopeOptions`);
    if (!tagsContainer || !optionsContainer) return;

    const selectedScopes = sharedFilterState.dataScopes;
    const isAllSelected = isAllDataScopesSelected();

    // ...标签渲染逻辑保持不变...

    // 新增：全选头部
    const total = sceneData.dataScopes.length;
    const checked = selectedScopes.length;
    const headerHtml = `<div class="multi-select-header">
        <label><input type="checkbox" class="select-all-scope" data-prefix="${prefix}" ${checked === total && total > 0 ? 'checked' : ''}> 全选</label>
        <span class="multi-select-count">已选 ${checked}/${total}</span>
    </div>`;

    // 拼接头部 + 选项
    optionsContainer.innerHTML = headerHtml + sceneData.dataScopes.map(scope => `
        <div class="multi-select-option ${selectedScopes.includes(scope) ? 'checked' : ''}" data-value="${scope}">${scope}</div>
    `).join('');
}
```

> 使用 `class="select-all-scope"` 和 `data-prefix="${prefix}"` 区分 rule/biz 两个下拉的全选复选框。

#### 4.2 修改 `bindSharedFilterEvents()` 中的 options 点击事件

在原有的选项点击逻辑之前，增加全选复选框的处理：

```javascript
options.addEventListener('click', function(event) {
    // 新增：全选复选框处理
    const selectAll = event.target.closest('.select-all-scope');
    if (selectAll) {
        event.stopPropagation();
        if (selectAll.checked) {
            sharedFilterState.dataScopes = [...sceneData.dataScopes];
        } else {
            sharedFilterState.dataScopes = [];
        }
        syncSharedFilterControls(); // 已有函数，同步两个下拉的状态和标签
        return;
    }

    // 原有的单选逻辑保持不变
    const option = event.target.closest('.multi-select-option');
    if (!option) return;
    // ...
});
```

> `syncSharedFilterControls()` 会自动调用 `renderDataScopeDropdown()` 刷新两个下拉的标签和选项状态（含全选头部），无需额外处理。

---

## 5. 疑点处置-场景疑点

### 对应文件

`疑点处置-场景疑点.html`

### 选择器类型

动态（与页面4结构完全相同）

### 改动内容

与页面4完全一致：

1. 修改 `renderDataScopeDropdown(prefix)` — 增加全选头部HTML拼接
2. 修改 `bindSharedFilterEvents()` — 增加 `.select-all-scope` 点击处理

---

## 交互行为说明

### 全选复选框行为

| 操作 | 结果 |
|------|------|
| 勾选全选 | 所有选项变为 `checked`，标签全部显示 |
| 取消全选 | 所有选项取消 `checked`，标签清空 |
| 手动选择部分选项 | 全选复选框为未勾选状态，计数显示"已选 N/M" |
| 手动选满全部 | 全选复选框自动变为勾选状态 |
| 点击选项后 | 计数实时更新 |

### 动态选择器额外行为

- rule 和 biz 两个下拉的全选操作独立生效
- `syncSharedFilterControls()` 确保两个下拉的状态同步

### 关键技术点

- `e.stopPropagation()` 阻止点击全选复选框时下拉菜单关闭
- `position: sticky` 使全选头部在下拉列表滚动时固定在顶部
- 静态选择器使用 jQuery 事件委托，动态选择器使用原生 `addEventListener`

---

## 验证清单

### 静态选择器（页面1-3）

- [ ] 全选框勾选后，所有选项变为 `checked`，标签全部显示
- [ ] 全选框取消后，所有选项取消 `checked`，标签清空
- [ ] 手动选择部分选项后，全选框为未勾选状态，计数正确
- [ ] 手动选满全部后，全选框自动变为勾选状态
- [ ] 移除标签后，对应选项取消 `checked`，计数更新，全选框状态同步
- [ ] 全选头部在下拉列表滚动时始终可见（sticky 定位）

### 动态选择器（页面4-5）

- [ ] rule 和 biz 两个下拉均可独立全选/取消全选
- [ ] 全选后标签正确显示"全部数据范围（N）"
- [ ] 取消全选后标签显示"请选择数据范围"
- [ ] 手动选满后全选框自动勾选
- [ ] 两个下拉的全选操作互不影响

### 页面特殊逻辑

- [ ] 新建场景页面（页面2）：全选/取消全选后分公司处置人区域正确联动，提交按钮状态正确
- [ ] 疑点详情页面（页面3）：全选/取消全选后筛选标签重建，疑点列表正确筛选
