ruoyi-vue-pro 开发指南 ruoyi-vue-pro 开发指南
  • 萌新必读
  • 后端手册
  • 中间件手册
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 会员手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • HRM 手册
  • FMS 手册
  • PMS 手册
  • OA 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
  • 运维手册
  • 前端手册 Vue 3.x
  • 前端手册 Vben 5.x
  • 前端手册 Vue 2.x
  • 前端手册 Admin Uniapp
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 会员手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • HRM 手册
  • FMS 手册
  • PMS 手册
  • OA 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
视频教程
  • Vue3 + element-plus (opens new window)
  • Vue3 + vben5(ant-design-vue、element-plus) (opens new window)
  • Vue2 + element-ui (opens new window)
微服务版 (opens new window)
作者博客 (opens new window)
GitHub (opens new window)
  • 萌新必读
  • 后端手册
  • 中间件手册
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 会员手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • HRM 手册
  • FMS 手册
  • PMS 手册
  • OA 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
  • 运维手册
  • 前端手册 Vue 3.x
  • 前端手册 Vben 5.x
  • 前端手册 Vue 2.x
  • 前端手册 Admin Uniapp
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 会员手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • HRM 手册
  • FMS 手册
  • PMS 手册
  • OA 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
视频教程
  • Vue3 + element-plus (opens new window)
  • Vue3 + vben5(ant-design-vue、element-plus) (opens new window)
  • Vue2 + element-ui (opens new window)
微服务版 (opens new window)
作者博客 (opens new window)
GitHub (opens new window)
  • 萌新必读

    • 简介
    • 交流群
    • 视频教程
    • 功能列表
    • 快速启动(后端项目)
    • 快速启动(前端项目)
    • 接口文档
    • 技术选型
    • 项目结构
    • 代码热加载
    • 一键改包
    • 迁移模块(适合新项目)
    • 删除功能(以租户为例)
    • 表结构变更(版本升级)
    • 国产信创数据库(DM 达梦、大金、OpenGauss、瀚高)
    • 如何去除 Redis 缓存
    • 内网穿透
    • 面试题、简历模版、简历优化
    • 项目外包
  • 后端手册

    • 新建模块
    • 代码生成【单表】(新增功能)
    • 代码生成【主子表】
    • 代码生成(树表)
    • 代码生成(移动端)
    • 功能权限
    • 数据权限
    • 用户体系
    • 三方登录
    • OAuth 2.0(SSO 单点登录)
    • SaaS 多租户【字段隔离】
    • SaaS 多租户【数据库隔离】
    • WebSocket 实时通信
    • 异常处理(错误码)
    • 参数校验、时间传参
    • 分页实现
    • VO 对象转换、数据翻译
    • 文件存储(上传下载)
    • Excel 导入导出
    • 操作日志、访问日志、异常日志
    • MyBatis 数据库
    • MyBatis 联表&分页查询
    • 多数据源(读写分离)、事务
    • Redis 缓存
    • 本地缓存
    • 异步任务
    • 分布式锁
    • 幂等性(防重复提交)
    • 请求限流(RateLimiter)
    • HTTP 接口签名(防篡改)
    • HTTP 接口加解密
    • 单元测试
    • 验证码
    • 工具类 Util
    • 配置管理
    • 数据库文档
  • 中间件手册

    • 定时任务
    • 消息队列(内存)
    • 消息队列(Redis)
    • 消息队列(RocketMQ)
    • 消息队列(RabbitMQ)
    • 消息队列(Kafka)
    • 限流熔断
  • 工作流手册

    • 工作流演示
    • 功能开启
    • 工作流(达梦适配)
    • 审批接入(流程表单)
    • 审批接入(业务表单)
    • 流程设计器(BPMN)
    • 流程设计器(钉钉、飞书)
    • 选择审批人、发起人自选
    • 会签、或签、依次审批
    • 流程发起、取消、重新发起
    • 审批通过、不通过、驳回
    • 审批加签、减签
    • 审批转办、委派、抄送
    • 执行监听器、任务监听器
    • 流程表达式
    • 流程审批通知
    • 移动端审批
  • 大屏手册

    • 报表设计器
    • 大屏设计器
  • 支付手册

    • 功能开启
    • 支付宝支付接入
    • 微信公众号支付接入
    • 微信小程序支付接入
    • 支付宝、微信退款接入
    • 支付宝转账接入
    • 微信转账接入
    • 钱包充值、支付、退款
    • 模拟支付、退款
    • 移动端支付管理
  • 会员手册

    • 功能开启
    • 微信公众号登录
    • 微信小程序登录
    • 微信小程序订阅消息
    • 微信小程序码
    • 会员用户、标签、分组
    • 会员等级、积分、签到
    • 移动端会员管理
  • 商城手册

    • 商城演示
    • 功能开启
    • 商城装修
    • 在线客服
    • 【商品】商品分类
    • 【商品】商品属性
    • 【商品】商品 SPU 与 SKU
    • 【商品】商品评价
    • 【交易】购物车
    • 【交易】交易订单
    • 【交易】售后退款
    • 【交易】快递发货
    • 【交易】门店自提
    • 【交易】分销返佣
    • 【营销】优惠劵
    • 【营销】积分商城
    • 【营销】拼团活动
    • 【营销】秒杀活动
    • 【营销】砍价活动
    • 【营销】满减送活动
    • 【营销】限时折扣
    • 【营销】内容管理
    • 【统计】会员、商品、交易统计
    • 移动端商城管理
  • ERP手册

    • ERP 演示
    • 功能开启
    • 【产品】产品信息、分类、单位
    • 【库存】产品库存、库存明细
    • 【库存】其它入库、其它出库
    • 【库存】库存调拨、库存盘点
    • 【采购】采购订单、入库、退货
    • 【销售】销售订单、出库、退货
    • 【财务】采购付款、销售收款
    • 移动端 ERP
  • CRM手册

    • CRM 演示
    • 功能开启
    • 【线索】线索管理
    • 【客户】客户管理、公海客户
    • 【商机】商机管理、商机状态
    • 【合同】合同管理、合同提醒
    • 【回款】回款管理、回款计划
    • 【产品】产品管理、产品分类
    • 【通用】数据权限
    • 【通用】跟进记录、待办事项
    • 移动端 CRM
  • AI大模型手册

    • AI 大模型演示
    • 功能开启
    • AI 聊天对话
    • AI 绘画创作
    • AI 知识库(RAG)
    • AI 音乐创作
    • AI 写作助手
    • AI 思维导图
    • AI 工具(function calling)
    • AI 工作流
    • Dify 工作流
    • FastGPT 工作流
    • Coze 智能体
    • 推理模式(thinking)
    • 联网搜索
    • MCP Client 客户端
    • MCP Server 服务端
    • 【模型接入】Claude
    • 【模型接入】OpenAI
    • 【模型接入】通义千问
    • 【模型接入】DeepSeek
    • 【模型接入】字节豆包
    • 【模型接入】腾讯混元
    • 【模型接入】硅基流动
    • 【模型接入】MiniMax
    • 【模型接入】月之暗面
    • 【模型接入】百川智能
    • 【模型接入】文心一言
    • 【模型接入】LLAMA
    • 【模型接入】智谱 GLM
    • 【模型接入】讯飞星火
    • 【模型接入】微软 OpenAI
    • 【模型接入】谷歌 Gemini
    • 【模型接入】Stable Diffusion
    • 【模型接入】Midjourney
    • 【模型接入】Suno
    • 【模型接入】Grok
    • 【模型接入】阶跃星辰
    • 移动端 AI 大模型
  • IoT物联网手册

    • 功能开启
    • 产品管理
    • 设备管理
    • 物模型配置
    • 设备网关与子设备
    • 设备动态注册
    • 设备接入(概述)
    • 设备接入(HTTP 协议)
    • 设备接入(MQTT 协议)
    • 设备接入(EMQX 协议)
    • 设备接入(TCP 协议)
    • 设备接入(UDP 协议)
    • 设备接入(WebSocket 协议)
    • 设备接入(CoAP 协议)
    • 设备接入(Modbus Client 模式)
    • 设备接入(Modbus Server 模式)
    • 设备接入(自定义协议)
    • 场景联动
    • 数据流转
    • 告警配置
    • OTA 固件升级
    • 移动端 IoT 物联网
  • MES手册

    • MES 演示
    • 功能开启
    • 【基础】物料产品、分类、计量单位
    • 【基础】客户管理、供应商管理
    • 【基础】车间设置、工作站设置
    • 【基础】编码规则
    • 【生产】工序设置、工艺流程
    • 【生产】生产工单
    • 【生产】生产排产、工序流转卡
    • 【生产】生产报工
    • 【生产】安灯配置、安灯呼叫
    • 【生产】工作记录
    • 【仓库】仓库与库区库位、条码赋码、SN码
    • 【仓库】批次管理、库存现有量、库存事务
    • 【仓库】到货通知、采购入库、采购退货
    • 【仓库】生产领料、生产退料、物料消耗
    • 【仓库】产品产出、产品入库
    • 【仓库】发货通知、销售出库、销售退货
    • 【仓库】外协发料、外协入库
    • 【仓库】其他入库、其他出库
    • 【仓库】调拨单、装箱管理
    • 【仓库】库存盘点
    • 【质量】检测项设置、常见缺陷
    • 【质量】质检方案
    • 【质量】来料检验(IQC)
    • 【质量】过程检验(IPQC)
    • 【质量】出货检验(OQC)
    • 【质量】退货检验(RQC)
    • 【质量】待检任务、检验结果、缺陷记录
    • 【设备】设备类型、设备台账
    • 【设备】点检保养项目、点检保养方案
    • 【设备】点检记录、保养记录、维修单
    • 【工具】工具类型、工装夹具台账
    • 【排班】班组设置、节假日设置
    • 【排班】排班计划、排班日历
    • 移动端 MES
  • WMS手册

    • WMS 演示
    • 功能开启
    • 【基础】仓库
    • 【基础】商品、SKU、分类、品牌
    • 【基础】往来企业(供应商、客户)
    • 【库存】库存记录、流水、统计
    • 【单据】入库
    • 【单据】出库
    • 【单据】移库
    • 【单据】盘库
    • 【其它】WMS、MES、ERP 对比
    • 移动端 WMS
  • HRM人力资源

    • HRM 演示
    • 功能开启
    • 【组织】工作台、组织架构
    • 【员工】员工管理
    • 【招聘】招聘管理
    • 【考勤】考勤管理
    • 【社保】社保管理
    • 【薪资】计薪设置、薪资档案
    • 【薪资】月度工资、工资条
    • 【绩效】绩效模板、绩效计划
    • 【绩效】绩效考核、绩效档案
    • 移动端 HRM
  • FMS财务管理

    • FMS 演示
    • 功能开启
    • 【设置】账套管理、财务参数、财务指标
    • 【设置】币别、科目、辅助核算、初始余额
    • 【设置】凭证字、常用摘要、凭证模板
    • 【凭证】凭证管理
    • 【账簿】账簿管理
    • 【报表】财务报表
    • 【结账】期末结账
    • 移动端 FMS
  • PMS项目管理

    • PMS 演示
    • 功能开启
    • 【项目中心】工作台与项目管理
    • 【项目中心】项目详情与迭代
    • 【项目中心】工作项与协作
    • 【知识中心】知识库管理
    • 【知识中心】文档与协作
    • 移动端 PMS
  • OA协同办公

    • OA 演示
    • 功能开启
    • 【协作】日程、任务、计划与汇报
    • 【协作】公告、讨论、通讯录与笔记
      • 1. 公告管理
        • 1.1 主表表结构
        • 1.2 子表结构
        • 1.3 发布、阅读与转发
        • 1.4 管理后台
      • 2. 讨论区
        • 2.1 主表表结构
        • 2.2 子表结构
        • 2.3 投票规则
        • 2.4 管理后台
      • 3. 通讯录
        • 3.1 表结构
        • 3.2 共享与持有
        • 3.3 管理后台
      • 4. 笔记管理
        • 4.1 表结构
        • 4.2 共享与收藏
        • 4.3 管理后台
    • 【办公】企业邮箱
    • 【办公】企业云盘
    • 【行政】办公用品、用印管理
    • 【行政】会议室、车辆管理
    • 【流程】公文管理
    • 【流程】出差、费用报销
    • 【流程】考勤、请假、加班、转正与离职
    • 移动端 OA
  • IM即时通讯手册

    • IM 演示
    • 功能开启
    • 【好友】好友关系、好友申请
    • 【群聊】群组、群成员、入群申请
    • 【消息】私聊、群聊、频道消息
    • 【频道】频道、频道素材
    • 【内容】表情、敏感词
    • 【通话】语音通话、视频通话、共享屏幕
    • 【WebSocket】实时推送与离线消息
    • 移动端 IM 即时通讯
  • 公众号手册

    • 功能开启
    • 公众号接入
    • 公众号粉丝
    • 公众号标签
    • 公众号消息
    • 模版消息
    • 自动回复
    • 公众号菜单
    • 公众号素材
    • 公众号图文
    • 公众号统计
    • 移动端公众号管理
  • 系统手册

    • 短信配置
    • 邮件配置
    • 站内信配置
    • Webhook(钉钉、飞书、企微)
    • 数据脱敏、字段权限
    • 敏感词
    • 地区 & IP 库
  • 运维手册

    • 开发环境
    • Linux 部署
    • Docker 部署
    • Jenkins 部署
    • 宝塔部署
    • 1Panel 部署
    • HTTPS 证书
    • 服务监控
    • Tomcat WAR 部署
  • 前端手册 Vue 3.x

    • 开发规范
    • 菜单路由
    • Icon 图标
    • 字典数据
    • 系统组件
    • 通用方法
    • 配置读取
    • CRUD 组件
    • 国际化
    • IDE 调试
    • 代码格式化
  • 前端手册 Vben 5.x

    • 开发规范
    • 菜单路由
    • 图标、主题、国际化
    • 字典数据
    • 系统组件
    • 通用方法
    • 配置读取
    • IDE 调试
    • 代码格式化
  • 前端手册 Vue 2.x

    • 开发规范
    • 菜单路由
    • Icon 图标
    • 字典数据
    • 系统组件
    • 通用方法
    • 配置读取
  • 前端手册 Admin Uniapp

    • 开发规范
    • 菜单路由
    • 图标、主题、国际化
    • 字典数据
    • 系统组件
    • 通用方法
    • IDE 调试
    • 代码格式化
    • 运行发布
  • 更新日志

    • 【v2026-09】
    • 【v2026-08】
    • 【v2026-07】
    • 【v2026-06】
    • 【v2026-05】
    • 【v2026-04】
    • 【v2026-03】
    • 【v2026-01】
    • 【v2025-12】
    • 【v2025-11】
    • 【v2025-10】
    • 【v2025-09】
    • 【v2025-08】
  • 开发指南
  • OA协同办公
芋道源码
2026-09-17
目录

【协作】公告、讨论、通讯录与笔记

公告、讨论、通讯录与笔记,由 yudao-module-oa 后端模块的 announcement、discussion、contact、note 包实现,前端实现在 @/views/oa/announcement/list、@/views/oa/discussion/manage、@/views/oa/contact、@/views/oa/note 目录。

公告用于发布和接收通知,讨论区用于回复和投票,通讯录与笔记支持个人维护及共享。四类数据分别保存;阅读、共享和回复各自落在关系表上,删除自己的接收记录不会直接删除其他人的记录。本文四个功能均不涉及 BPM 流程。

本文涉及表如下图所示:

信息协作表关系

# 1. 公告管理

公告管理,由 OaAnnouncementController 提供接口(/oa/announcement)。

# 1.1 主表表结构

省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段

公告表 oa_announcement,保存公告的类型、优先级、正文和置顶设置:

CREATE TABLE `oa_announcement` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `type` tinyint NOT NULL COMMENT '公告类型',
  `priority` tinyint NOT NULL COMMENT '优先级',

  `title` varchar(255) NOT NULL COMMENT '公告标题',
  `content` text COMMENT '公告内容',
  `url` varchar(512) DEFAULT NULL COMMENT '公告链接',

  `top` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否置顶',
  PRIMARY KEY (`id`),
  KEY `idx_creator_top_create_time` (`creator`, `top`, `create_time`)
) ENGINE=InnoDB COMMENT='OA 公告';

① 公告没有独立的发布人字段,通用字段 creator 即发布人,create_time 即发布时间。idx_creator_top_create_time 索引支撑【我发布的】按发布人 + 置顶 + 时间的查询。修改和删除由 OaAnnouncementServiceImpl 的 validateAnnouncementPublisher 校验只能发布人操作。

② 枚举 type 公告类型(OaAnnouncementTypeEnum),对应字典 oa_announcement_type:

值 枚举 说明
1 ANNOUNCEMENT 公告
2 NOTICE 通知
3 VOTE 投票

公告类型里的「投票」≠ 讨论区投票

这里的 VOTE 只是公告的分类标签,不会创建投票选项和投票记录。真正的投票互动在讨论区(oa_discussion.type = VOTE)完成。

③ 枚举 priority 优先级(OaPriorityEnum),对应字典 oa_priority,与日程、笔记复用同一套:

值 枚举 说明
1 NORMAL 一般
2 IMPORTANT 重要
3 URGENT 紧急

④ top 置顶只影响列表排序;url 是可选的外链,正文 content 为富文本。


该表包含一个子表:

  • oa_announcement_receiver(公告接收人):创建公告时按发布人的管理范围自动写入,转发时追加下属。

# 1.2 子表结构

接收人表 oa_announcement_receiver,保存公告发给了谁以及各自的阅读状态:

CREATE TABLE `oa_announcement_receiver` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `announcement_id` bigint NOT NULL COMMENT '公告编号',
  `receiver_user_id` bigint NOT NULL COMMENT '接收人用户编号',

  `read_status` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否已读',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_announcement_id_receiver_user_id` (`announcement_id`, `receiver_user_id`, `deleted`),
  KEY `idx_receiver_user_id_read_status` (`receiver_user_id`, `read_status`)
) ENGINE=InnoDB COMMENT='OA 公告接收人';

① announcement_id 关联 oa_announcement 表的 id 字段,receiver_user_id 关联 system_users 表的 id 字段。uk_announcement_id_receiver_user_id 唯一索引保证同一公告不会重复发给同一个人。

② idx_receiver_user_id_read_status 索引支撑【我收到的】按接收人 + 已读状态过滤。查看权限由 getAnnouncement 校验:要么是发布人,要么在接收人表中,否则抛出 ANNOUNCEMENT_ACCESS_DENIED。

# 1.3 发布、阅读与转发

公告没有独立的 status 字段,生命周期由接收关系驱动:

发布 / 阅读 / 转发说明

创建公告 ──→ 写入下属接收关系(read_status=0)
              │
              ├── 打开详情 ──→ updateAnnouncementReadStatus → 已读(1)
              │
              └── 转发 ──→ 向下属追加接收关系(不重复)
  • 创建公告(createAnnouncement):接收人取自 adminUserApi.getUserListBySubordinate(userId),即发布人负责部门及其子部门下的用户。不额外发站内信,接收人在【我收到的】列表查看。
  • 阅读(updateAnnouncementReadStatus):已读时直接返回,不重复更新;公告本身没有 read_time 字段(与日程参与人不同)。
  • 转发(forwardAnnouncement):先用 selectByIdForUpdate 对公告行加锁,串行处理同一公告的并发转发;再由 validateAnnouncementReceiver 校验当前用户本人必须是该公告的接收人,然后查其下属。无下属时直接返回 0,不报错。只要任一下属已经是接收人,就视为已转发,抛出 ANNOUNCEMENT_ALREADY_FORWARDED,不允许再次转发;否则批量追加下属的接收关系,并返回新增人数。
  • 移除收到的公告(deleteReceivedAnnouncement):只有已读才允许移除,未读抛出 ANNOUNCEMENT_UNREAD_DELETE_DENIED;仅物理删除本人的接收关系,不影响公告和其他人。
  • 发布人删除(deleteAnnouncement):同时删除全部接收关系。

# 1.4 管理后台

对应 [OA 办公协同 -> 公告管理 -> 我发布的 / 我收到的] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/oa/announcement/list、@/views/oa/announcement/my 目录。

# 列表

管理后台 - 公告管理

# 新增与修改

点击【新增】打开 OaAnnouncementForm.vue,填写公告类型、优先级、置顶、标题、相关链接和正文。修改时仅发布人可以维护本人公告。

管理后台 - 公告表单

# 阅读与转发

对应 [OA 办公协同 -> 公告管理 -> 我收到的] 菜单,页面在 @/views/oa/announcement/my。点击标题打开详情并标记已读;点击【转发】调用 POST /oa/announcement/forward,已经转发的公告显示【已转发】。

管理后台 - 我收到的公告

# 删除

发布人删除公告时,同时删除接收关系。在【我收到的】中,只有已读公告可以移除,调用 /oa/announcement/delete-received,仅移除本人的接收关系。

# 2. 讨论区

讨论区,由 OaDiscussionController 提供接口(/oa/discussion)。回复、点赞、投票分别由 OaDiscussionReplyController(/oa/discussion-reply)、OaDiscussionLikeController(/oa/discussion-like)、OaDiscussionVoteController(/oa/discussion-vote)提供。

# 2.1 主表表结构

省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段

讨论表 oa_discussion,保存讨论或投票主题,投票主题额外记录单选多选和起止时间:

CREATE TABLE `oa_discussion` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `user_id` bigint NOT NULL COMMENT '发布人用户编号',
  `type` tinyint NOT NULL COMMENT '类型',

  `title` varchar(200) NOT NULL COMMENT '标题',
  `content` longtext COMMENT '正文',
  `file_urls` json DEFAULT NULL COMMENT '附件地址列表',

  `visit_count` int NOT NULL DEFAULT 0 COMMENT '访问次数',

  `vote_multiple` bit(1) DEFAULT NULL COMMENT '投票是否多选',
  `vote_start_time` datetime DEFAULT NULL COMMENT '投票开始时间',
  `vote_end_time` datetime DEFAULT NULL COMMENT '投票结束时间',
  PRIMARY KEY (`id`),
  KEY `idx_type_create_time` (`type`, `create_time`),
  KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB COMMENT='OA 讨论';

① 与公告不同,讨论有独立的 user_id 发布人字段(不复用 creator 做业务判断),关联 system_users 表的 id 字段。创建时强制写入当前登录用户,更新时 setUserId(null) 禁止被前端篡改。

② 枚举 type 讨论类型(OaDiscussionTypeEnum),对应字典 oa_discussion_type:

值 枚举 说明
1 ANNOUNCEMENT 公告
2 DISCUSSION 讨论
3 VOTE 投票

③ 发布后不允许修改 type。非投票类型会在保存时清空三个 vote_* 字段;投票类型在更新时只允许改结束时间(必须晚于原开始时间),vote_multiple 和 vote_start_time 以及投票选项在发布后都不能改。

④ visit_count 由 increaseDiscussionVisitCount 在打开详情时累加。file_urls 是 JSON 数组,形如 ["http://xxx/a.pdf"]。


该表包含四个子表:

  • oa_discussion_reply(讨论回复):楼层回复,parent_id 形成楼中楼。
  • oa_discussion_like(讨论点赞):对主题或主回复的点赞。
  • oa_vote_option(投票选项):仅投票主题使用。
  • oa_vote_record(投票记录):谁投了哪个选项。

# 2.2 子表结构

回复表 oa_discussion_reply,保存楼层回复:

CREATE TABLE `oa_discussion_reply` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `discussion_id` bigint NOT NULL COMMENT '讨论编号',
  `user_id` bigint NOT NULL COMMENT '回复人用户编号',

  `parent_id` bigint NOT NULL DEFAULT 0 COMMENT '父回复编号',
  `reply_user_id` bigint DEFAULT NULL COMMENT '被回复人用户编号',

  `content` varchar(2000) NOT NULL COMMENT '回复内容',
  PRIMARY KEY (`id`),
  KEY `idx_discussion_id_create_time` (`discussion_id`, `create_time`)
) ENGINE=InnoDB COMMENT='OA 讨论回复';

① discussion_id 关联 oa_discussion 表的 id 字段。parent_id = 0 表示回复主贴;非 0 时必须属于同一讨论,否则非法。创建楼中楼时,reply_user_id 自动取父回复的作者,不接受前端指定。

② 删除回复(deleteDiscussionReply)校验当前用户是讨论发布人或超级管理员(不是回复作者本人),否则抛出 DISCUSSION_REPLY_ACCESS_DENIED。删除某条回复时,会连同其全部子孙回复及对应点赞一起清理。

点赞表 oa_discussion_like,保存对讨论主题或某条回复的点赞关系:

CREATE TABLE `oa_discussion_like` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `discussion_id` bigint DEFAULT NULL COMMENT '讨论编号',
  `reply_id` bigint DEFAULT NULL COMMENT '回复编号',

  `user_id` bigint NOT NULL COMMENT '用户编号',
  PRIMARY KEY (`id`),
  KEY `idx_discussion_id_user_id` (`discussion_id`, `user_id`, `deleted`),
  KEY `idx_reply_id_user_id` (`reply_id`, `user_id`, `deleted`)
) ENGINE=InnoDB COMMENT='OA 讨论点赞';

① discussion_id 与 reply_id 二选一:赞主题时写 discussion_id,赞回复时写 reply_id。createDiscussionLike 已点赞则直接返回,取消点赞找不到记录也直接返回,保证幂等。

投票选项表 oa_vote_option,保存投票主题下的候选项:

CREATE TABLE `oa_vote_option` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `discussion_id` bigint NOT NULL COMMENT '讨论编号',

  `title` varchar(200) NOT NULL COMMENT '选项标题',
  `color` varchar(20) DEFAULT NULL COMMENT '展示颜色',
  `sort` int NOT NULL DEFAULT 0 COMMENT '显示顺序',
  PRIMARY KEY (`id`),
  KEY `idx_discussion_id_sort` (`discussion_id`, `sort`)
) ENGINE=InnoDB COMMENT='OA 投票选项';

① discussion_id 关联 oa_discussion 表的 id 字段。选项只在创建主题时一次性写入(createVoteOptionList),发布后不能增删改。

投票记录表 oa_vote_record,保存「谁投了哪个选项」:

CREATE TABLE `oa_vote_record` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `discussion_id` bigint NOT NULL COMMENT '讨论编号',
  `option_id` bigint NOT NULL COMMENT '投票选项编号',
  `user_id` bigint NOT NULL COMMENT '投票人用户编号',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_option_id_user_id` (`option_id`, `user_id`, `deleted`),
  KEY `idx_discussion_id_user_id` (`discussion_id`, `user_id`)
) ENGINE=InnoDB COMMENT='OA 投票记录';

① option_id 关联 oa_vote_option 表的 id 字段,uk_option_id_user_id 唯一索引保证同一选项不能被同一个人投两次。

# 2.3 投票规则

投票由 OaDiscussionVoteServiceImpl 的 voteDiscussion 控制:

投票说明

投票主题(type=VOTE) ──在 [vote_start_time, vote_end_time] 内──→ 提交选项
                         │
          ┌──────────────┴──────────────┐
          ▼                             ▼
     单选(vote_multiple=0)         多选(vote_multiple=1)
     只能提交一次、选一个          可分次追加,同一选项不重复
  • 非投票类型调用投票接口 → DISCUSSION_VOTE_INVALID。
  • 当前时间不在投票窗口内 → DISCUSSION_VOTE_EXPIRED。
  • 单选却传了多个选项,或多选时选项不属于本主题 → DISCUSSION_VOTE_INVALID / DISCUSSION_VOTE_OPTION_NOT_EXISTS。
  • 单选已投过,或多选重复投同一选项 → DISCUSSION_VOTE_DUPLICATE。

删除讨论主题(deleteDiscussion)时,依次清理回复(含回复点赞)、主题点赞、投票记录和选项,最后删主题。发布人或超级管理员可删。

# 2.4 管理后台

对应 [OA 办公协同 -> 讨论区 -> 讨论管理 / 讨论区列表] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/oa/discussion/manage、@/views/oa/discussion/list 目录。

# 列表

管理后台 - 讨论区

# 发布与管理

点击【发布】打开 OaDiscussionForm.vue,选择讨论类型,填写标题、正文和附件。投票类型还需配置单选或多选、起止时间和投票选项。

管理后台 - 讨论发布表单

# 查看与回复

在 [讨论区 -> 讨论区列表] 点击标题进入 @/views/oa/discussion/detail/index.vue。OaDiscussionReply.vue 展示回复楼层,支持回复主贴或楼层,并按全部、楼主、本人筛选。

管理后台 - 讨论详情

# 点赞与投票

讨论和主回复可点赞、取消点赞。投票在 OaDiscussionVote.vue 中选择选项后点击【提交投票】,调用 POST /oa/discussion-vote/create。

管理后台 - 讨论投票

# 删除

讨论管理中删除主题时会删除关联互动记录。回复删除由后端校验讨论发布人或超级管理员身份,删除某条回复时连同其子回复一起清理。

# 3. 通讯录

通讯录,由 OaContactController 提供接口(/oa/contact)。分类由 OaContactCategoryController 提供接口(/oa/contact-category)。

# 3.1 表结构

省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段

联系人分类表 oa_contact_category,保存每个用户自己的联系人分类:

CREATE TABLE `oa_contact_category` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `user_id` bigint NOT NULL COMMENT '用户编号',

  `name` varchar(50) NOT NULL COMMENT '分类名称',
  `sort` int NOT NULL DEFAULT 0 COMMENT '显示排序',
  PRIMARY KEY (`id`),
  KEY `idx_user_id_sort` (`user_id`, `sort`)
) ENGINE=InnoDB COMMENT='OA 联系人分类';

① user_id 关联 system_users 表的 id 字段。分类是个人维度的,用户 A 的分类编号不能被用户 B 使用。删除分类时只清空联系人上的 category_id,不删除联系人。

外部联系人表 oa_contact,保存联系人的姓名、电话、邮箱和公司等资料:

CREATE TABLE `oa_contact` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `category_id` bigint DEFAULT NULL COMMENT '分类编号',

  `name` varchar(50) NOT NULL COMMENT '姓名',
  `pinyin` varchar(100) DEFAULT NULL COMMENT '姓名拼音',
  `sex` tinyint DEFAULT NULL COMMENT '性别',

  `mobile` varchar(20) DEFAULT NULL COMMENT '手机号码',
  `email` varchar(100) DEFAULT NULL COMMENT '邮箱',
  `address` varchar(255) DEFAULT NULL COMMENT '地址',

  `company_name` varchar(100) DEFAULT NULL COMMENT '公司名称',
  `company_phone` varchar(30) DEFAULT NULL COMMENT '公司电话',

  `avatar` varchar(512) DEFAULT NULL COMMENT '头像地址',
  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`),
  KEY `idx_creator_category_id` (`creator`, `category_id`),
  KEY `idx_name_mobile` (`name`, `mobile`)
) ENGINE=InnoDB COMMENT='OA 外部联系人';

① category_id 关联 oa_contact_category 表的 id 字段,表示创建人自己的分类。共享给别人之后,接收人的分类存在共享关系表里,不改这里的值。

② pinyin 由后端用 StrUtils.toPinyin(name) 在创建/修改时自动生成,不接受前端传入,用于列表按拼音检索。

③ sex 复用 System 模块的 SexEnum(不是 OA 自有枚举)。

联系人共享表 oa_contact_share,保存「谁持有这个联系人」:

CREATE TABLE `oa_contact_share` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `contact_id` bigint NOT NULL COMMENT '联系人编号',
  `user_id` bigint NOT NULL COMMENT '共享接收人用户编号',

  `category_id` bigint DEFAULT NULL COMMENT '接收人的分类编号',
  `handle_status` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否已处理',
  PRIMARY KEY (`id`),
  KEY `idx_contact_id_user_id` (`contact_id`, `user_id`, `deleted`),
  KEY `idx_user_id_handle_status` (`user_id`, `handle_status`)
) ENGINE=InnoDB COMMENT='OA 联系人共享';

① contact_id 关联 oa_contact 表的 id 字段,user_id 关联 system_users 表的 id 字段。创建人在创建联系人时也会写入一条 handle_status = 1 的持有关系。

② category_id 是接收人自己的分类,与主表 oa_contact.category_id 彼此独立。

# 3.2 共享与持有

共享 / 处理 / 移除说明

创建联系人 ──→ 写入本人持有关系(handle_status=1)
                │
                ├── 共享 ──→ 为接收人写入 handle_status=0
                │               │
                │               └── 处理 ──→ handle_status=1 + 写入本人分类
                │
                └── 移除 ──→ 删除本人持有关系
                              │
                              └── 若已无任何持有人 ──→ 删除联系人正文
  • 共享(shareContact):已持有且有权限的人可继续共享;新接收人初始 handle_status = 0。
  • 处理(handleContactShare):接收人选择自己的分类后,标记已处理,联系人进入【我的联系人】。
  • 移除(deleteReceivedContact / deleteContact):只删当前用户的持有关系;最后一个持有人离开时才删除 oa_contact 正文。

# 3.3 管理后台

对应 [OA 办公协同 -> 通讯录] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/oa/contact 目录。

# 分类与新增

点击【管理分类】维护个人分类。点击【新增】打开 OaContactForm.vue,填写姓名、分类、性别、手机、邮箱、公司和地址等资料。

管理后台 - 通讯录

# 共享

选择联系人后点击【共享】,选择共享接收人,调用 POST /oa/contact/share。已持有联系人且有相应操作权限的接收人也可继续共享。

# 接收与归类

切换到共享给本人的联系人,点击【处理】选择自己的分类,调用 PUT /oa/contact/handle-share。处理后联系人进入【我的联系人】;分类属于当前用户,不使用共享人的分类编号。

# 修改与移除

联系人资料修改由后端校验归属。删除或移除时仅清理当前用户的持有关系;删除分类会清空对应分类关联,不删除联系人。

# 4. 笔记管理

笔记管理,由 OaNoteController 提供接口(/oa/note)。目录由 OaNoteCategoryController 提供接口(/oa/note-category)。

# 4.1 表结构

省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段

笔记目录表 oa_note_category,保存每个用户自己的笔记目录:

CREATE TABLE `oa_note_category` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `user_id` bigint NOT NULL COMMENT '用户编号',

  `name` varchar(50) NOT NULL COMMENT '目录名称',
  `sort` int NOT NULL DEFAULT 0 COMMENT '显示顺序',
  PRIMARY KEY (`id`),
  KEY `idx_user_id_sort` (`user_id`, `sort`)
) ENGINE=InnoDB COMMENT='OA 笔记目录';

① 与通讯录分类一样,目录是个人维度的。删除目录时(deleteNotesByCategoryId)会删除该目录下本人的笔记及其接收关系,行为比通讯录分类更激进,使用时需注意。

笔记表 oa_note,保存笔记的正文、附件和收藏状态:

CREATE TABLE `oa_note` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `category_id` bigint DEFAULT NULL COMMENT '目录编号',
  `type` tinyint NOT NULL COMMENT '笔记类型',
  `priority` tinyint NOT NULL COMMENT '优先级',

  `title` varchar(100) NOT NULL COMMENT '标题',
  `content` longtext COMMENT '内容',

  `favorite` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否收藏',
  `file_urls` json DEFAULT NULL COMMENT '附件地址列表',
  PRIMARY KEY (`id`),
  KEY `idx_creator_category_id` (`creator`, `category_id`),
  KEY `idx_type` (`type`)
) ENGINE=InnoDB COMMENT='OA 笔记';

① category_id 关联 oa_note_category 表的 id 字段。通用字段 creator 即笔记所属人,修改、删除、共享由 OaNoteServiceImpl 校验归属。

② 枚举 type 笔记类型(OaNoteTypeEnum),对应字典 oa_note_type:

值 枚举 说明
1 PRIVATE 我的笔记
2 COMPANY 公司笔记
3 SHARED 共享笔记

③ 枚举 priority 优先级(OaPriorityEnum),对应字典 oa_priority,与公告、日程复用。

④ favorite 由 updateNoteFavorite 单独维护,只对本人笔记生效。file_urls 是 JSON 附件地址列表。

笔记接收人表 oa_note_receiver,保存笔记共享给了哪些用户:

CREATE TABLE `oa_note_receiver` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `note_id` bigint NOT NULL COMMENT '笔记编号',
  `user_id` bigint NOT NULL COMMENT '接收人用户编号',
  PRIMARY KEY (`id`),
  KEY `idx_note_id_user_id` (`note_id`, `user_id`, `deleted`),
  KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB COMMENT='OA 笔记接收人';

① note_id 关联 oa_note 表的 id 字段,user_id 关联 system_users 表的 id 字段。共享范围由创建人通过 updateNoteShare 全量覆盖维护(与日程参与人的差量更新不同):本次列表之外的接收关系会被删除,新的会被插入。

# 4.2 共享与收藏

共享 / 收藏 / 移除说明

创建笔记 ──→ 本人可收藏、可共享
              │
              ├── updateNoteFavorite ──→ favorite 0↔1(仅本人)
              │
              ├── updateNoteShare ──→ 全量覆盖接收人列表
              │
              └── 接收人 deleteReceivedNote ──→ 只删本人接收关系
  • 创建人维护笔记正文和共享范围;接收人只能查看共享给自己的笔记,不能改正文。
  • 取消某人的共享只移除接收关系,笔记正文仍由创建人持有。
  • 创建人删除笔记时,会一并清理全部接收关系。

# 4.3 管理后台

对应 [OA 办公协同 -> 笔记管理] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/oa/note 目录。

# 列表

管理后台 - 笔记管理

# 目录与新增

点击【管理分类】维护笔记目录。点击【新增】打开 OaNoteForm.vue,填写类型、优先级、目录、标题、正文和附件。

管理后台 - 笔记表单

# 收藏与共享

本人笔记可点击【收藏】,调用 PUT /oa/note/update-favorite。点击【共享】打开 OaNoteShareForm.vue,选择共享接收人后保存,调用 PUT /oa/note/update-share。

# 查看与删除

切换本人笔记和共享笔记查看详情。创建人可修改、删除本人笔记;接收人点击【移除】,只调用 /oa/note/delete-received 删除本人的接收关系。

【协作】日程、任务、计划与汇报
【办公】企业邮箱

← 【协作】日程、任务、计划与汇报 【办公】企业邮箱→

Theme by Vdoing | Copyright © 2019-2026 芋道源码 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×