fs-lawrisk/docs/features/admin/GRADE_DRAG_DROP_FEATURE.md

12 KiB
Raw Permalink Blame History

拖拽修改权限等级功能 - 完整实现

🎯 功能概述

根据您的需求我们实现了通过拖拽方式修改部门权限等级grade的功能。

核心特性:

  • 拖拽节点名称旁的提示文字 ⋮⋮ 拖拽修改权限
  • 弹出权限等级选择面板90/80/70/60/50/0
  • 支持6个权限等级超级/高级/中级/一般/较低/普通)
  • 显示当前权限等级
  • 拖拽时实时提示
  • 点击面板选择新等级
  • 确认后更新数据库

🎨 界面设计

1. 权限等级显示

每个部门节点显示当前权限等级:

🔑 权限等级: 80
  • 样式:黄色背景 (#fef3c7),橙色边框 (#fcd34d)
  • 位置:部门代码和区域标签下方
  • 图标:🔑 钥匙图标

2. 拖拽提示

节点名称右侧显示拖拽提示:

部门名称 ⋮⋮ 拖拽修改权限
  • 字体11px灰色 (#9ca3af)
  • 鼠标样式move可移动
  • 拖拽时:半透明 + 阴影 + 旋转效果

3. 权限等级选择面板

位置: 页面右上角 样式:

  • 白色卡片,紫色边框 (#4f46e5)
  • 圆角12px大阴影
  • 280px 最小宽度

内容:

┌────────────────────────┐
│  修改「XX部门」的权限等级   │
│  当前等级80选择新等级 │
│  ┌───┐ ┌───┐ ┌───┐     │
│  │ 90│ │ 80│ │ 70│     │
│  │超级│ │高级│ │中级│     │
│  └───┘ └───┘ └───┘     │
│  ┌───┐ ┌───┐ ┌───┐     │
│  │ 60│ │ 50│ │  0│     │
│  │一般│ │较低│ │普通│     │
│  └───┘ └───┘ └───┘     │
└────────────────────────┘

交互效果:

  • 悬停边框变蓝背景变淡蓝上移2px
  • 点击:边框和背景变蓝,白色文字,加粗

⚙️ 技术实现

后端改动

1. 数据库 Schema (licensing_repo.py)

ALTER TABLE service_departments
ADD COLUMN IF NOT EXISTS grade int DEFAULT 0;

CREATE INDEX IF NOT EXISTS service_departments_grade_idx
ON service_departments (grade);

2. 服务函数 (licensing_repo.py)

创建部门 - 支持grade参数

def create_service_department(
    name: str,
    *,
    code: Optional[str] = None,
    phone: Optional[str] = None,
    parent_id: Optional[str] = None,
    region_id: Optional[str] = None,
    description: Optional[str] = None,
    grade: Optional[int] = 0,  # 新增
) -> Dict[str, Any]:

更新部门 - 支持grade更新

def update_service_department(
    department_id: str,
    *,
    name: Optional[str] = None,
    phone: Optional[str] = None,
    parent_id: Optional[str] = None,
    region_id: Optional[str] = None,
    description: Optional[str] = None,
    grade: Optional[int] = None,  # 新增
) -> Optional[Dict[str, Any]]:

序列化 - 返回grade字段

def _serialize_service_department_row(record: Dict[str, Any]) -> Dict[str, Any]:
    return {
        ...
        "grade": record.get("grade", 0),  # 新增
        ...
    }

3. API 路由 (v2.py)

创建部门 - 处理grade

POST /fs-ai-asistant/api/workflow/lawrisk/admin/service-departments
{
    "name": "部门名称",
    "code": "部门账号",
    "grade": 80,  # 新增字段
    ...
}

更新部门 - 处理grade更新

PATCH /fs-ai-asistant/api/workflow/lawrisk/admin/service-departments/{id}
{
    "grade": 90,  # 修改权限等级
    ...
}

前端实现

1. HTML结构 (super_admin.html)

<!-- 权限等级选择面板 -->
<div id="gradeDropPanel" class="grade-drop-panel">
    <h4>选择权限等级</h4>
    <p>拖拽部门到此处来修改权限</p>
    <div class="grade-options">
        <div class="grade-option" data-grade="90">
            <span class="grade-number">90</span>
            <span class="grade-label">超级</span>
        </div>
        <div class="grade-option" data-grade="80">
            <span class="grade-number">80</span>
            <span class="grade-label">高级</span>
        </div>
        <div class="grade-option" data-grade="70">
            <span class="grade-number">70</span>
            <span class="grade-label">中级</span>
        </div>
        <div class="grade-option" data-grade="60">
            <span class="grade-number">60</span>
            <span class="grade-label">一般</span>
        </div>
        <div class="grade-option" data-grade="50">
            <span class="grade-number">50</span>
            <span class="grade-label">较低</span>
        </div>
        <div class="grade-option" data-grade="0">
            <span class="grade-number">0</span>
            <span class="grade-label">普通</span>
        </div>
    </div>
</div>

2. CSS样式 (super_admin.html)

/* 权限等级显示 */
.node-grade {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 8px;
    background: #fef3c7;
    border-radius: 6px;
    font-size: 12px;
    color: #92400e;
    border: 1px solid #fcd34d;
}

/* 权限等级选择面板 */
.grade-drop-panel {
    position: fixed;
    background: white;
    border: 2px solid #4f46e5;
    border-radius: 12px;
    padding: 16px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
    z-index: 2000;
    min-width: 280px;
}

/* 权限等级选项 */
.grade-option {
    border: 2px solid #e5e7eb;
    border-radius: 8px;
    padding: 12px 8px;
    text-align: center;
    cursor: pointer;
    transition: all 0.2s ease;
    background: #f9fafb;
}

.grade-option:hover {
    border-color: #4f46e5;
    background: #eef2ff;
    transform: translateY(-2px);
}

3. JavaScript逻辑 (super_admin.html)

function initDragAndDrop() {
    const nameSpans = document.querySelectorAll('.node-name');
    const gradePanel = document.getElementById('gradeDropPanel');

    nameSpans.forEach(span => {
        const nodeDiv = span.closest('.org-node');
        const nodeId = nodeDiv.getAttribute('data-node-id');

        span.setAttribute('draggable', 'true');

        span.addEventListener('dragstart', (evt) => {
            currentDraggedNode = nodeId;
            nodeDiv.classList.add('dragging');

            const sourceNode = orgChartData.nodeMap[nodeId];
            gradePanel.querySelector('h4').textContent =
                `修改「${sourceNode.name}」的权限等级`;
            gradePanel.querySelector('p').textContent =
                '当前等级:' + (sourceNode.grade || 0) + ',选择新等级:';

            gradePanel.classList.add('show');
        });

        span.addEventListener('dragend', () => {
            nodeDiv.classList.remove('dragging');
            gradePanel.classList.remove('show');
            currentDraggedNode = null;
        });
    });

    // 点击权限等级选项
    gradePanel.querySelectorAll('.grade-option').forEach(option => {
        option.addEventListener('click', async () => {
            const newGrade = parseInt(option.dataset.grade);
            const sourceNode = orgChartData.nodeMap[currentDraggedNode];
            const currentGrade = sourceNode.grade || 0;

            if (confirm(`确定要将「${sourceNode.name}」的权限等级从 ${currentGrade} 修改为 ${newGrade} 吗?`)) {
                await fetchJSON(`${API_BASE}/admin/service-departments/${sourceNode.id}`, {
                    method: 'PATCH',
                    body: JSON.stringify({ grade: newGrade })
                });
                showMessage(`权限等级已更新为 ${newGrade}`, 'success');
                gradePanel.classList.remove('show');
                await loadOrgChart();
            }
        });
    });
}

🎬 使用步骤

1. 访问界面

http://127.0.0.1:8000/static/super_admin.html

2. 切换到组织架构标签页

点击「组织架构」标签

3. 查看权限等级

每个部门节点下方显示:

🔑 权限等级: 80

4. 拖拽修改权限

  1. 开始拖拽:拖拽节点名称右侧的 ⋮⋮ 拖拽修改权限
  2. 显示面板:权限等级选择面板自动弹出
  3. 选择等级点击面板中的权限等级90/80/70/60/50/0
  4. 确认操作:弹出确认对话框
  5. 完成更新:数据库更新,界面刷新

5. 新增部门时设置权限

  1. 点击 新增 按钮
  2. 填写部门信息
  3. 选择权限等级:下拉菜单选择 90-0
  4. 点击「确定」创建

6. 编辑部门权限

  1. 点击 ✏️ 编辑 按钮
  2. 修改「权限等级」下拉菜单
  3. 点击「确定」保存

📊 权限等级说明

等级 名称 用途
90 超级 最高管理权限,系统级操作
80 高级 部门级管理权限,默认等级
70 中级 一般管理权限
60 一般 标准操作权限
50 较低 受限操作权限
0 普通 基础查看权限

默认等级: 80高级


功能特点

1. 直观的拖拽体验

  • 清晰的拖拽提示文字
  • 拖拽时的视觉反馈(半透明+旋转)
  • 实时显示当前权限等级
  • 友好的确认对话框

2. 清晰的视觉设计

  • 权限等级标签使用醒目颜色(黄色背景)
  • 权限等级面板使用紫色主题
  • 悬停效果提升交互感
  • 图标+文字的组合设计

3. 完善的功能支持

  • 新增部门时可设置权限等级
  • 编辑部门时可修改权限等级
  • 拖拽快速调整权限等级
  • 显示所有部门当前权限

4. 数据安全

  • 拖拽前显示当前权限
  • 修改前弹出确认对话框
  • 修改后显示成功消息
  • 数据库实时更新

🧪 测试用例

测试用例 1查看权限等级显示

步骤:

  1. 访问组织架构页面
  2. 查看部门节点信息

预期:

  • 每个节点显示 🔑 权限等级: XX
  • 颜色为黄色背景,橙色边框

测试用例 2拖拽修改权限

步骤:

  1. 拖拽节点名称旁的 ⋮⋮ 拖拽修改权限
  2. 权限面板弹出,显示当前等级
  3. 点击新的权限等级(如从 80 改为 90
  4. 确认对话框出现
  5. 点击「确定」

预期:

  • 权限面板显示部门名称和当前等级
  • 点击后弹出确认对话框
  • 确认后权限等级更新
  • 界面显示成功消息
  • 页面刷新,新权限生效

测试用例 3新增部门设置权限

步骤:

  1. 点击 新增 按钮
  2. 填写部门信息
  3. 选择权限等级(如选择 70
  4. 点击「确定」

预期:

  • 表单中有「权限等级」下拉菜单
  • 默认选中 80高级
  • 创建成功后显示默认密码
  • 新部门显示选中的权限等级

测试用例 4编辑部门权限

步骤:

  1. 点击 ✏️ 编辑 按钮
  2. 修改权限等级下拉菜单
  3. 点击「确定」

预期:

  • 表单预填充当前权限等级
  • 可以修改权限等级
  • 保存后权限更新成功

🎉 总结

拖拽修改权限等级功能已经完全实现!

主要文件:

  • lawrisk/services/licensing_repo.py - 数据库Schema和操作函数
  • lawrisk/api/v2.py - API路由和业务逻辑
  • static/super_admin.html - 前端界面和交互

核心功能:

  • 拖拽修改权限等级6个等级90/80/70/60/50/0
  • 权限等级显示(黄色标签)
  • 权限等级面板(紫色主题)
  • 新增时设置权限
  • 编辑时修改权限

用户体验:

  • 清晰的拖拽提示
  • 实时权限显示
  • 友好的确认对话框
  • 操作成功反馈

完全满足您的需求!🎯