使用 Python + Flask 构建钉钉部门和人员管理系统
使用 Python Flask 构建钉钉部门和人员管理系统摘要: 本文详细介绍如何使用 Python 和 Flask 框架开发一个完整的钉钉组织架构管理系统,包括从钉钉API同步数据、构建Web管理界面、实现部门人员查看和编辑等功能。一、项目背景在企业日常管理中,钉钉的组织架构数据是非常重要的信息。为了方便管理和查看钉钉的部门和人员信息,我开发了一个基于 Python Flask 的Web管理系统。该系统可以实现:✅ 自动从钉钉API同步部门和人员数据✅ 可视化展示组织架构✅ 按部门筛选查看人员✅ 搜索和编辑人员信息✅ 实时统计部门人数二、技术栈后端框架: Flask 3.x前端技术: HTML5 CSS3 JavaScript (原生)数据存储: JSON文件钉钉API: 钉钉开放平台API v2开发语言: Python 3.x三、系统架构钉钉部门和人员管理系统 ── dingtalk_sync.py # 钉钉数据同步脚本 ├── app.py # Flask Web应用 ├── templates/ │ └── index.html # 前端管理界面 ├── departments.json # 部门数据 ├── users.json # 人员数据 └── requirements.txt # 依赖包四、核心功能实现4.1 钉钉数据同步模块首先,我们需要从钉钉API获取组织架构数据。钉钉提供了完善的API接口,我们可以通过以下步骤获取数据:1. 获取 Access Tokendefget_access_token(self)-str:获取访问令牌urlf{self.base_url}/gettokenparams{appkey:self.app_key,appsecret:self.app_secret}responserequests.get(url,paramsparams)resultresponse.json()ifresult.get(errcode)0:self.access_tokenresult.get(access_token)returnself.access_token关键点:Access Token 有效期为 2 小时需要缓存 Token,避免频繁请求使用 AppKey 和 AppSecret 进行认证2. 获取部门列表defget_all_departments(self)-List[Dict]:获取所有部门列表access_tokenself.get_access_token()urlf{self.base_url}/topapi/v2/department/listsub# 获取根部门dept_id1下的所有子部门data{dept_id:1}responserequests.post(url,paramsparams,jsondata)resultresponse.json()ifresult.get(errcode)0:returnresult.get(result,[])钉钉API说明:接口地址:/topapi/v2/department/listsub根部门 ID 固定为 1返回所有子部门列表3. 获取部门用户 (支持分页)钉钉的用户列表接口支持分页查询,需要处理分页逻辑:defget_department_users(self,dept_id:int)-List[Dict]:获取指定部门下的用户列表all_users[]cursor0size100# 每页最多100条whileTrue:data{dept_id:dept_id,cursor:cursor,size:size}responserequests.post(url,paramsparams,jsondata)resultresponse.json()ifresult.get(errcode)0:result_dataresult.get(result,{})usersresult_data.get(list,[])all_users.extend(users)# 检查是否有更多数据ifnotresult_data.get(has_more,False):breakcursorresult_data.get(next_cursor,0)returnall_users分页处理要点:使用cursor进行分页每页最多获取 100 条数据通过has_more判断是否还有下一页使用next_cursor获取下一页的游标4. 完整同步流程defget_all_users(self)-List[Dict]:获取所有用户信息departmentsself.get_all_departments()all_users[]# 获取根部门用户root_usersself.get_department_users(1)all_users.extend(root_users)# 获取所有子部门的用户fordeptindepartments:dept_iddept.get(dept_id)usersself.get_department_users(dept_id)all_users.extend(users)returnall_users4.2 Flask Web 后端使用 Flask 框架构建 RESTful API,提供数据查询和更新接口。1. 基础配置fromflaskimportFlask,render_template,jsonify,requestimportjsonimportos appFlask(__name__)# 数据文件路径DATA_DIRos.path.dirname(os.path.abspath(__file__))DEPARTMENTS_FILEos.path.join(DATA_DIR,departments.json)USERS_FILEos.path.join(DATA_DIR,users.json)2. 部门列表 API (带人数统计)app.route(/api/departments)defget_departments():API - 获取所有部门departmentsload_json(DEPARTMENTS_FILE)usersload_json(USERS_FILE)# 计算每个部门的人数dept_user_count{}foruserinusers:dept_idsuser.get(dept_id_list,[])fordept_idindept_ids:dept_user_count[dept_id]dept_user_count.get(dept_id,0)1# 为每个部门添加人数统计fordeptindepartments:dept_iddept.get(dept_id)dept[user_count]dept_user_count.get(dept_id,0)returnjsonify({success:True,data:departments,total:len(departments)})设计思路:同时加载部门和用户数据统计每个部门的用户数量将人数信息附加到部门对象中3. 按部门查询用户app.route(/api/users/by-department/int:dept_id)defget_users_by_department(dept_id):API - 获取指定部门的用户usersload_json(USERS_FILE)dept_users[uforuinusersifdept_idinu.get(dept_id_list,[])]returnjsonify({success:True,data:dept_users,total:len(dept_users)})4. 更新用户信息app.route(/api/user/string:user_id,methods[PUT])defupdate_user(user_id):API - 更新用户信息usersload_json(USERS_FILE)foruserinusers:ifuser.get(userid)user_id:datarequest.json# 更新允许的字段ifnameindata:user[name]data[name]ifmobileindata:user[mobile]data[mobile]ifemailindata:user[email]data[email]ifjob_numberindata:user[job_number]data[job_number]iftitleindata:user[title]data[title]save_json(USERS_FILE,users)returnjsonify({success:True,message:用户更新成功})returnjsonify({success:False,message:用户不存在}),4045. 触发数据同步app.route(/api/sync,methods[POST])defsync_data():API - 触发数据同步try:importsubprocess resultsubprocess.run([python3,dingtalk_sync.py],capture_outputTrue,textTrue,cwdDATA_DIR)ifresult.returncode0:returnjsonify({success:True,message:同步成功,output:result.stdout})else:returnjsonify({success:False,message:同步失败,error:result.stderr}),500exceptExceptionase:returnjsonify({success:False,message:f同步异常:{str(e)}}),500实现原理:通过subprocess调用同步脚本捕获标准输出和错误输出返回执行结果给前端4.3 前端界面实现前端使用原生 HTML CSS JavaScript,无需额外的前端框架,轻量且高效。1. 页面布局divclasscontainerheaderh1钉钉部门和人员管理系统/h1divclassheader-actionsbuttonclassbtn btn-successonclicksyncData()同步数据/buttonbuttonclassbtn btn-primaryonclickrefreshData()刷新/button/div/headerdivclassstats-grid!-- 统计卡片 --/divdivclassmain-contentdivclasspanel!-- 部门列表 --/divdivclasspanel!-- 人员列表 --/div/div/div2. 加载统计数据asyncfunctionloadStatistics(){constresponseawaitfetch(/api/statistics);constresultawaitresponse.json();if(result.success){conststatsresult.data;document.getElementById(statsGrid).innerHTMLdiv classstat-card h3部门总数/h3 div classvalue${stats.total_departments}/div /div div classstat-card h3人员总数/h3 div classvalue${stats.total_users}/div /div div classstat-card h3平均部门人数/h3 div classvalue${Math.round(stats.total_users/stats.total_departments)}/div /div;}}3. 加载所有用户 (默认显示)asyncfunctionloadAllUsers(){constresponseawaitfetch(/api/users);constresultawaitresponse.json();if(result.success){allUsersresult.data;filteredUsers[...allUsers];renderUsers(filteredUsers);}}4. 按部门筛选用户asyncfunctionselectDepartment(deptId){currentDeptIddeptId;constresponseawaitfetch(/api/users/by-department/${deptId});constresultawaitresponse.json();if(result.success){allUsersresult.data;filteredUsers[...allUsers];renderUsers(filteredUsers);}}5. 搜索功能functionfilterUsers(){constkeyworddocument.getElementById(userSearch).value.toLowerCase();filteredUsersallUsers.filter(user{return(user.nameuser.name.toLowerCase().includes(keyword))||(user.job_numberuser.job_number.toLowerCase().includes(keyword))||(user.mobileuser.mobile.includes(keyword));});renderUsers(filteredUsers);}搜索逻辑:支持按姓名搜索支持按工号搜索支持按手机号搜索实时过滤,无需刷新页面6. 编辑用户functioneditUser(userId){constuserallUsers.find(uu.useriduserId);document.getElementById(editUserId).valueuser.userid;document.getElementById(editName).valueuser.name||;document.getElementById(editJobNumber).valueuser.job_number||;document.getElementById(editTitle).valueuser.title||;document.getElementById(editMobile).valueuser.mobile||;document.getElementById(editEmail).valueuser.email||;document.getElementById(editModal).classList.add(show);}// 保存用户document.getElementById(editForm).addEventListener(submit,asyncfunction(e){e.preventDefault();constuserIddocument.getElementById(editUserId).value;constdata{name:document.getElementById(editName).value,job_number:document.getElementById(editJobNumber).value,title:document.getElementById(editTitle).value,mobile:document.getElementById(editMobile).value,email:document.getElementById(editEmail).value};constresponseawaitfetch(/api/user/${userId},{method:PUT,headers:{Content-Type:application/json},body:JSON.stringify(data)});constresultawaitresponse.json();if(result.success){showToast(保存成功,success);}});五、项目部署5.1 安装依赖# 创建虚拟环境python3-mvenv venvsourcevenv/bin/activate# 安装依赖包pipinstallrequests flask5.2 配置钉钉应用登录 钉钉开放平台创建应用,获取以下信息:CorpId: 企业 IDAppKey: 应用唯一标识AppSecret: 应用密钥配置应用权限:通讯录只读权限部门管理权限员工信息权限5.3 修改配置文件编辑dingtalk_sync.py,填入你的钉钉应用信息:CORP_IDyour_corp_idAPP_KEYyour_app_keyAPP_SECRETyour_app_secret5.4 运行项目# 首次同步数据python3 dingtalk_sync.py# 启动 Web 服务python3 app.py访问 http://localhost:5001 即可使用管理系统。六、功能展示6.1 首页概览顶部统计卡片: 显示部门总数、人员总数、平均部门人数左侧部门列表: 展示所有部门及人数,支持搜索右侧人员列表: 默认显示所有人员,支持筛选和搜索6.2 部门筛选点击左侧部门,右侧自动显示该部门的所有人员。6.3 人员编辑点击编辑按钮,弹出模态框修改人员信息:姓名工号职位手机号邮箱6.4 数据同步点击同步数据按钮,自动从钉钉API获取最新组织架构数据。七、技术亮点7.1 分页处理钉钉用户列表接口采用游标分页,系统自动处理所有分页数据,确保获取完整信息。7.2 数据缓存Access Token 自动缓存,避免重复请求部门人数统计在服务端计算,减轻前端压力7.3 响应式设计使用 CSS Grid 和 Flexbox 布局,适配不同屏幕尺寸。7.4 实时搜索前端搜索无需刷新页面,通过 JavaScript 实时过滤数据。7.5 错误处理API 请求失败时显示友好提示数据加载异常时显示加载状态表单提交失败时回滚数据八、扩展功能建议基于当前系统,还可以扩展以下功能:定时同步: 使用 cron 或 celery 实现定时自动同步权限管理: 添加用户登录和权限控制数据导出: 支持导出 Excel 或 CSV 格式组织架构树: 以树形结构展示部门层级关系数据统计图表: 使用 ECharts 展示部门人员分布操作日志: 记录所有编辑操作批量导入: 支持批量导入人员信息消息通知: 人员变动时发送通知九、常见问题Q1: 获取 Access Token 失败?A: 检查 AppKey 和 AppSecret 是否正确,确保应用有足够的权限。Q2: 部门人数显示为 0?A: 确保已执行同步脚本,生成了departments.json和users.json文件。Q3: 端口被占用?A: 修改app.py中的端口号,例如改为 5001:app.run(host0.0.0.0,port5001,debugTrue)Q4: 如何部署到生产环境?A: 建议使用 Gunicorn Nginx:pipinstallgunicorn gunicorn-w4-b0.0.0.0:5000 app:app十、总结本文详细介绍了一个完整的钉钉部门和人员管理系统的开发过程。系统采用 Python Flask 技术栈,实现了数据同步、Web管理、人员编辑等核心功能。项目优势:代码简洁,易于理解和维护功能完整,满足日常管理需求扩展性强,可根据需求添加新功能部署简单,无需复杂配置适用场景:企业组织架构管理人员信息统计和分析钉钉数据本地化存储自动化办公流程集成希望本文对你有所帮助!如果觉得不错,欢迎点赞和收藏。有任何问题或建议,欢迎在评论区留言交流。完整源码: 项目所有代码已开源,可根据实际需求进行修改和扩展。相关链接:钉钉开放平台Flask 官方文档Python requests 文档