# 许可管理单位权限优化PRD ## 1. 需求背景 ### 1.1 当前问题 - 现有权限体系:市局账号 vs 区局子管理员(通过grade区分) - 现状:市局账号查看全部许可,区局子管理员仅能查看本区许可 - 局限: - 缺乏市级单位(局、委、办)和区级单位的层级管理 - 上传许可文件时无法指定绑定的具体单位 - 浏览方式低效(仅按行政区筛选) ### 1.2 优化目标 1. **单位层级管理**:引入市级单位和区级单位的概念 2. **权限细分**: - 市局账号:保留全部可见权限 - 市级单位:可见自身 + 下属区级单位 - 区局子管理员:可见下属所有单位 - 区级单位:仅可见自身 3. **文件绑定优化**:上传许可可绑定到具体单位 4. **浏览效率提升**:从单一"选择区域"改为多维度"过滤器筛选" ### 1.3 保留内容 - ✅ 一市五区的行政区划不变 - ✅ 现有账户保留(作为市局和区局子管理员) - ✅ 现有API保持兼容 ## 2. 功能需求 ### 2.1 单位管理功能 #### 2.1.1 单位级别定义 | 单位类型 | 说明 | 示例 | 可视范围 | |---------|------|------|----------| | admin | 市局管理员 | FSSJSJ(市级管理员) | 全部许可 | | municipal | 市级单位 | 市监局、卫健局、交通局等 | 自身 + 下属区级单位 | | district | 区局子管理员 | 禅城区、南海区等管理员 | 下属所有单位 | | unit | 区级单位 | 禅城区市场监督管理局等 | 仅自身 | #### 2.1.2 单位创建流程 1. **创建市级单位** - 指定单位名称、编码 - 设置单位级别为 `municipal` - 可绑定多个区级行政区 - 自动生成管理员账号 2. **创建区级单位** - 指定单位名称、编码 - 设置单位级别为 `unit` - 绑定到具体行政区(禅城区、南海区等) - 关联到市级单位作为上级 ### 2.2 权限控制功能 #### 2.2.1 可见性规则 ```python # 权限判断逻辑 def get_visible_permits(user, filters): dept = user.service_department unit_level = dept.unit_level if user.role == 'admin' or user.grade >= 90: # 市局:全部许可 return query_all_permits(filters) elif unit_level == 'municipal': # 市级单位:自身 + 下属区级单位 subordinate_ids = get_subordinate_departments(dept.id, level='unit') return query_permits_by_departments([dept.id] + subordinate_ids, filters) elif unit_level == 'district': # 区局子管理员:下属所有单位 return query_permits_by_region(dept.region_id, filters) elif unit_level == 'unit': # 区级单位:仅自身 return query_permits_by_departments([dept.id], filters) else: # 未知级别:无权限 return [] ``` #### 2.2.2 权限矩阵 | 用户类型 | 自身许可 | 下属单位许可 | 其他区许可 | 其他市级单位许可 | |---------|---------|-------------|----------|----------------| | 市局管理员 | ✅ | ✅ | ✅ | ✅ | | 市级单位用户 | ✅ | ✅ | ❌ | ❌ | | 区局子管理员 | ✅ | ✅ | ❌ | ❌ | | 区级单位用户 | ✅ | ❌ | ❌ | ❌ | ### 2.3 文件上传绑定功能 #### 2.3.1 绑定规则 | 上传者类型 | 默认绑定 | 可修改性 | 可见用户 | |----------|---------|---------|----------| | 市局管理员 | 市局自身 | 可选择任意单位 | 所有用户 | | 市级单位用户 | 市级单位自身 | 可选择下属区级单位 | 市局 + 相关单位 | | 区局子管理员 | 所属区 | 可修改 | 市局 + 相关区局 | | 区级单位用户 | 自身单位 | 不可修改 | 市局 + 上级区局 | #### 2.3.2 绑定流程 ```python def handle_permit_upload(file_data, uploader_user, bound_department_id=None): # 1. 确定绑定单位 if not bound_department_id: bound_department_id = get_default_binding(uploader_user) # 2. 保存文件 file_id = save_permit_file(file_data) # 3. 记录绑定关系 bind_permit_to_department( file_id=file_id, bound_department_id=bound_department_id, uploader_department_id=uploader_user.service_department_id, uploader_user_id=uploader_user.id ) # 4. 返回可见用户列表 return get_visible_users(bound_department_id, uploader_user) ``` ### 2.4 筛选浏览功能 #### 2.4.1 筛选维度 1. **市级单位**:下拉选择(全部/具体单位) 2. **区级单位**:下拉选择(全部/具体单位) 3. **行政区**:下拉选择(全部/禅城区/南海区/.../市级) 4. **许可名称**:文本搜索 #### 2.4.2 交互方式 - 市级单位和区级单位联动选择 - 支持搜索过滤 - 重置按钮清空所有筛选 - 显示已筛选结果数量 ## 3. 技术方案 ### 3.1 数据库设计 #### 3.1.1 现有表调整 **service_departments 表新增字段** ```sql ALTER TABLE service_departments ADD COLUMN unit_level VARCHAR(20) DEFAULT 'unit' CHECK (unit_level IN ('admin', 'municipal', 'district', 'unit')), ADD COLUMN allowed_regions TEXT; -- 市级单位可访问的行政区,多个用逗号分隔 ``` **permit_sources 表新增字段** ```sql ALTER TABLE permit_sources ADD COLUMN uploader_department_id UUID REFERENCES service_departments(id), ADD COLUMN bound_department_id UUID REFERENCES service_departments(id); ``` #### 3.1.2 新建索引 ```sql CREATE INDEX idx_service_dept_unit_level ON service_departments(unit_level); CREATE INDEX idx_service_dept_parent_level ON service_departments(parent_id, unit_level); CREATE INDEX idx_permit_sources_bound_dept ON permit_sources(bound_department_id); CREATE INDEX idx_permit_sources_uploader ON permit_sources(uploader_department_id); ``` #### 3.1.3 数据迁移脚本 ```sql -- 迁移现有数据 UPDATE service_departments SET unit_level = 'admin' WHERE grade >= 90; UPDATE service_departments SET unit_level = 'district' WHERE parent_id IS NULL AND grade < 90; -- 为现有表添加约束 ALTER TABLE service_departments ALTER COLUMN unit_level SET NOT NULL; ``` ### 3.2 后端API设计 #### 3.2.1 新增API **获取单位列表(支持层级)** ``` GET /admin/departments/tree Response: { "success": true, "data": { "municipal_units": [ { "id": "uuid-1", "name": "市监局", "code": "AMR_FS", "units": [ {"id": "uuid-2", "name": "禅城区市监局", "region": "禅城区"}, {"id": "uuid-3", "name": "南海区市监局", "region": "南海区"} ] } ] } } ``` **筛选查询许可** ``` POST /admin/permits/filter Request: { "municipal_dept_id": "uuid-1", "district_dept_id": "uuid-2", "region": "禅城区", "search_text": "电影院", "page": 1, "page_size": 20 } Response: { "success": true, "data": { "permits": [...], "pagination": { "total": 100, "page": 1, "page_size": 20 } } } ``` **上传许可文件(新增绑定参数)** ``` POST /admin/permit-import/upload Request: form-data - file: [Excel文件] - bound_department_id: "uuid-2" # 可选,不传则自动绑定 Response: { "success": true, "data": { "session_id": "uuid", "bound_to": { "department_id": "uuid-2", "department_name": "禅城区市监局", "visible_to": ["admin_users", "related_users"] } } } ``` #### 3.2.2 修改现有API **获取许可列表(向后兼容)** ``` GET /getPermits?region=禅城区 ``` - 保持现有参数不变 - 新增根据单位级别过滤的逻辑 ### 3.3 前端设计 #### 3.3.1 筛选器UI ```html