OA 办公用品管理 —— 功能设计与开发计划
生成日期:2026-03-19
用途:面向中小企业的 OA 办公用品全生命周期管理功能设计,覆盖台账、领用、发放、归还的完整业务闭环。
一、产品定位与设计目标
| 维度 | 说明 |
|---|---|
| 目标用户 | 中小企业行政/后勤管理人员、普通员工 |
| 产品定位 | 80% 核心功能覆盖,简单易用,零学习成本 |
| 核心价值 | 规范办公用品从入库→领用→归还的全流程管理,杜绝重复采购和闲置浪费 |
| 设计原则 | ① 操作简单,减少配置 ② 流程闭环,数据可追溯 ③ 复用现有架构,降低开发成本 |
二、功能模块总览
办公用品管理
├── 1. 办公用品台账 ← 物品信息 + 库存管理 + 入库操作(左侧类别筛选 + 右侧列表)
├── 2. 领用申请管理 ← BPM 流程审批,支持多物品明细
└── 3. 领用发放管理 ← 管理员发放/确认归还,库存自动增减2.1 各模块核心能力
| 模块 | 核心功能 | 使用角色 |
|---|---|---|
| 办公用品台账 | 类别筛选、物品 CRUD、库存显示、入库操作、库存预警 | 管理员 |
| 领用申请管理 | 发起领用申请、选择多个物品、填写数量、BPM 审批 | 全员 |
| 领用发放管理 | 查看待发放/待归还明细、确认发放、确认归还 | 管理员 |
三、办公用品分类体系设计
3.1 双维度分类模型
办公用品管理需要从两个维度进行分类,类别维度决定展示归属,管理类型维度决定业务流程:
┌─────────────────────────────────────────────────────────┐
│ 办公用品分类体系 │
├─────────────────────┬───────────────────────────────────┤
│ 类别(Category) │ 管理类型(Management Type) │
│ ——展示归属—— │ ——业务流程—— │
├─────────────────────┼───────────────────────────────────┤
│ • 文具类 │ 1 = 消耗品(领用即消耗,无需归还) │
│ • 打印耗材 │ 2 = 借用品(需归还,低值耐用品) │
│ • 生活用品 │ 3 = 资产品(需归还,关联资产模块) │
│ • 电脑办公 │ │
│ • 办公设备/电器 │ │
│ • 财务用品 │ │
└─────────────────────┴───────────────────────────────────┘3.2 管理类型详细说明
| 管理类型 | 代码 | 典型物品 | 领用后是否归还 | 是否关联资产 | 库存变化 |
|---|---|---|---|---|---|
| 消耗品 | 1 | 打印纸、墨盒、笔芯、抽纸、垃圾袋、一次性纸杯 | ❌ 否 | ❌ 否 | 发放后 -N |
| 借用品 | 2 | 订书机、计算器、鼠标、键盘、U盘、剪刀、工具 | ✅ 是 | ❌ 否 | 发放后 -N,归还后 +N |
| 资产品 | 3 | 笔记本电脑、台式机、投影仪、打印机、显示器 | ✅ 是 | ✅ 预留 | 发放后 -N,归还后 +N |
设计说明:
- 消耗品:发放后状态直接变为"已领用",为终态,不产生归还流程
- 借用品:发放后状态变为"已领用待归还",员工使用完毕后需归还,管理员确认后库存恢复
- 资产品:流程与借用品一致,额外预留
asset_id字段,未来对接资产管理模块(资产登记、折旧、盘点等)
3.3 类别管理方案
采用系统字典方式管理类别(与车辆分类 oa_car_cls 保持一致),使用字典类型 oa_supply_category:
| 字典值 | 字典标签 | 说明 |
|---|---|---|
| 1 | 文具类 | 笔、本子、文件夹、胶带、订书钉等 |
| 2 | 打印耗材 | 打印纸、墨盒、碳粉、硒鼓等 |
| 3 | 生活用品 | 抽纸、垃圾袋、纸杯、洗手液等 |
| 4 | 电脑办公 | 鼠标、键盘、U盘、鼠标垫、数据线等 |
| 5 | 办公设备/电器 | 碎纸机、饮水机、咖啡机、电风扇等 |
| 6 | 财务用品 | 印泥、票据、凭证、计算器、保险柜等 |
管理员通过系统管理 → 字典管理维护类别,无需额外开发类别管理页面,保持简单。
四、核心业务流程
4.1 全流程闭环图
┌──────────────┐
│ 管理员录入 │
│ 办公用品信息 │
└──────┬───────┘
│
▼
┌────────────────────────┐
│ 办公用品台账(库存管理) │◄─────────────────┐
│ 管理员可手动入库/调整 │ │
└────────────┬───────────┘ │
│ │
员工查看库存 │
发起领用申请 │
│ │
▼ │
┌────────────────────────┐ │
│ 领用申请单(BPM审批) │ │
│ 选择多个物品+填写数量 │ │
└────────────┬───────────┘ │
│ │
审批通过后 │
系统自动生成待领用明细 │
│ │
▼ │
┌────────────────────────┐ │
│ 领用发放管理 │ │
│ 管理员查看待发放明细 │ │
└────────────┬───────────┘ │
│ │
┌────────────┼────────────┐ │
│ │ │ │
▼ ▼ ▼ │
┌─────────┐ ┌──────────┐ ┌──────────┐ │
│ 消耗品 │ │ 借用品 │ │ 资产品 │ │
│ 直接发放 │ │ 发放 │ │ 发放 │ │
│ 库存-N │ │ 库存-N │ │ 库存-N │ │
│→已领用 │ │→待归还 │ │→待归还 │ │
│ (终态) │ │ │ │ │ │
└─────────┘ └────┬─────┘ └────┬─────┘ │
│ │ │
员工归还 员工归还 │
│ │ │
▼ ▼ │
┌──────────────────────┐ │
│ 管理员确认归还 │ │
│ 库存+N → 状态:已归还 │─────────────┘
└──────────────────────┘
库存自动恢复4.2 领用明细状态机
┌─────────┐
审批通过自动 │ 待领用 │
生成 ────────► │ (0) │
└────┬────┘
│ 管理员发放
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌───────────┐ ┌───────────┐
│ 已领用 │ │已领用待归还│ │已领用待归还│
│ (1) │ │ (2) │ │ (2) │
│ 消耗品 │ │ 借用品 │ │ 资产品 │
│ 终态 ✓ │ └─────┬─────┘ └─────┬─────┘
└──────────┘ │ │
│ 确认归还 │ 确认归还
▼ ▼
┌──────────┐ ┌──────────┐
│ 已归还 │ │ 已归还 │
│ (3) │ │ (3) │
│ 终态 ✓ │ │ 终态 ✓ │
└──────────┘ └──────────┘4.3 库存变动规则
| 操作 | 库存变化 | 触发条件 |
|---|---|---|
| 手动入库 | +N | 管理员在台账页面点击"入库",输入入库数量 |
| 手动调整 | ±N | 管理员编辑物品时直接修改库存数量(盘点场景) |
| 发放 | -N | 管理员在领用发放管理页面确认发放 |
| 归还 | +N | 管理员确认归还(仅借用品/资产品) |
五、数据库表设计
5.1 表清单
| 表名 | 说明 | 备注 |
|---|---|---|
oa_supply | 办公用品表(台账主表) | 含库存字段 |
oa_supply_apply_bill | 办公用品领用申请单 | BPM 流程单据 |
oa_supply_apply_item | 领用申请明细表 | 一对多,贯穿领用→发放→归还全生命周期 |
设计思路:三张表即可覆盖完整业务闭环。类别通过字典管理(
oa_supply_category),不额外建表。
5.2 oa_supply(办公用品表)
sql
CREATE TABLE `oa_supply` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` VARCHAR(200) NOT NULL COMMENT '物品名称',
`code` VARCHAR(50) DEFAULT NULL COMMENT '物品编码',
`category` BIGINT NOT NULL COMMENT '类别(字典 oa_supply_category)',
`management_type` TINYINT NOT NULL COMMENT '管理类型(1消耗品 2借用品 3资产品)',
`spec` VARCHAR(200) DEFAULT NULL COMMENT '规格型号',
`unit` VARCHAR(20) DEFAULT NULL COMMENT '计量单位',
`unit_price` DECIMAL(10,2) DEFAULT NULL COMMENT '参考单价(元)',
`stock_quantity` INT NOT NULL DEFAULT 0 COMMENT '库存数量',
`min_stock` INT DEFAULT 0 COMMENT '最低库存预警值',
`pic_url` VARCHAR(500) DEFAULT NULL COMMENT '物品图片',
`company_id` BIGINT DEFAULT NULL COMMENT '公司ID',
`company_name` VARCHAR(100) DEFAULT NULL COMMENT '公司名称',
`sort` INT DEFAULT 0 COMMENT '排序',
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)',
`remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
-- BaseDO 公共字段
`creator` VARCHAR(64) DEFAULT '' COMMENT '创建者',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` VARCHAR(64) DEFAULT '' COMMENT '更新者',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='办公用品表';字段说明:
| 字段 | 说明 |
|---|---|
category | 关联字典 oa_supply_category,用于左侧类别筛选 |
management_type | 决定业务流程:1=消耗品(无需归还)、2=借用品(需归还)、3=资产品(需归还+预留资产关联) |
stock_quantity | 实时库存数量,入库时增加,发放时减少,归还时恢复 |
min_stock | 库存预警阈值,低于此值在台账中红色标记提醒 |
company_id/company_name | 多租户下的公司归属 |
5.3 oa_supply_apply_bill(领用申请单)
sql
CREATE TABLE `oa_supply_apply_bill` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`bill_code` VARCHAR(50) NOT NULL COMMENT '单据编号',
`process_instance_id` VARCHAR(64) DEFAULT NULL COMMENT '流程实例ID',
`process_status` TINYINT DEFAULT 0 COMMENT '单据状态',
`applyer` VARCHAR(100) DEFAULT NULL COMMENT '申请人',
`apply_reason` VARCHAR(500) DEFAULT NULL COMMENT '申请事由',
`parent_id` BIGINT DEFAULT NULL COMMENT '父级ID',
`dept_id` BIGINT DEFAULT NULL COMMENT '部门ID',
`dept_name` VARCHAR(100) DEFAULT NULL COMMENT '部门名称',
`company_id` BIGINT DEFAULT NULL COMMENT '公司ID',
`company_name` VARCHAR(100) DEFAULT NULL COMMENT '公司名称',
`creator_name` VARCHAR(100) DEFAULT NULL COMMENT '创建者姓名',
`remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
-- BaseDO 公共字段
`creator` VARCHAR(64) DEFAULT '' COMMENT '创建者',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` VARCHAR(64) DEFAULT '' COMMENT '更新者',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='办公用品领用申请单';5.4 oa_supply_apply_item(领用申请明细)
sql
CREATE TABLE `oa_supply_apply_item` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`apply_bill_id` BIGINT NOT NULL COMMENT '申请单ID',
`supply_id` BIGINT NOT NULL COMMENT '办公用品ID',
`supply_name` VARCHAR(200) DEFAULT NULL COMMENT '物品名称(冗余)',
`supply_spec` VARCHAR(200) DEFAULT NULL COMMENT '规格型号(冗余)',
`supply_unit` VARCHAR(20) DEFAULT NULL COMMENT '计量单位(冗余)',
`management_type` TINYINT DEFAULT NULL COMMENT '管理类型(冗余,1消耗品 2借用品 3资产品)',
`apply_quantity` INT NOT NULL COMMENT '申请数量',
`issue_quantity` INT DEFAULT 0 COMMENT '实发数量',
`return_quantity` INT DEFAULT 0 COMMENT '已归还数量',
`item_status` TINYINT NOT NULL DEFAULT 0 COMMENT '明细状态(0待领用 1已领用 2已领用待归还 3已归还)',
`issue_time` DATETIME DEFAULT NULL COMMENT '发放时间',
`issue_by` VARCHAR(64) DEFAULT NULL COMMENT '发放人',
`issue_remark` VARCHAR(500) DEFAULT NULL COMMENT '发放备注',
`return_time` DATETIME DEFAULT NULL COMMENT '归还时间',
`return_by` VARCHAR(64) DEFAULT NULL COMMENT '归还确认人',
`return_remark` VARCHAR(500) DEFAULT NULL COMMENT '归还备注',
-- BaseDO 公共字段
`creator` VARCHAR(64) DEFAULT '' COMMENT '创建者',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` VARCHAR(64) DEFAULT '' COMMENT '更新者',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`),
INDEX `idx_apply_bill_id` (`apply_bill_id`),
INDEX `idx_supply_id` (`supply_id`),
INDEX `idx_item_status` (`item_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='办公用品领用申请明细';核心设计:oa_supply_apply_item 贯穿物品的完整生命周期:
申请提交 → 审批通过(待领用) → 发放(已领用/已领用待归还) → 归还(已归还)所有关键操作(发放人、发放时间、归还人、归还时间)均记录在此表中,实现全程可追溯。
5.5 字典数据
sql
-- 办公用品类别字典类型
INSERT INTO `system_dict_type` (`name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`)
VALUES ('办公用品类别', 'oa_supply_category', 0, '办公用品类别', '1', NOW(), '1', NOW(), b'0', NULL);
-- 办公用品类别字典数据
INSERT INTO `system_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`)
VALUES
(1, '文具类', '1', 'oa_supply_category', 0, '', '', '笔、本子、文件夹、胶带、订书钉等', '1', NOW(), '1', NOW(), b'0'),
(2, '打印耗材', '2', 'oa_supply_category', 0, '', '', '打印纸、墨盒、碳粉、硒鼓等', '1', NOW(), '1', NOW(), b'0'),
(3, '生活用品', '3', 'oa_supply_category', 0, '', '', '抽纸、垃圾袋、纸杯、洗手液等', '1', NOW(), '1', NOW(), b'0'),
(4, '电脑办公', '4', 'oa_supply_category', 0, '', '', '鼠标、键盘、U盘、鼠标垫、数据线等', '1', NOW(), '1', NOW(), b'0'),
(5, '办公设备/电器', '5', 'oa_supply_category', 0, '', '', '碎纸机、饮水机、咖啡机、电风扇等', '1', NOW(), '1', NOW(), b'0'),
(6, '财务用品', '6', 'oa_supply_category', 0, '', '', '印泥、票据、凭证等', '1', NOW(), '1', NOW(), b'0');
-- 办公用品管理类型字典类型
INSERT INTO `system_dict_type` (`name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`)
VALUES ('办公用品管理类型', 'oa_supply_management_type', 0, '办公用品管理类型', '1', NOW(), '1', NOW(), b'0', NULL);
-- 办公用品管理类型字典数据
INSERT INTO `system_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`)
VALUES
(1, '消耗品', '1', 'oa_supply_management_type', 0, 'default', '', '领用后无需归还', '1', NOW(), '1', NOW(), b'0'),
(2, '借用品', '2', 'oa_supply_management_type', 0, 'warning', '', '需归还,低值耐用品', '1', NOW(), '1', NOW(), b'0'),
(3, '资产品', '3', 'oa_supply_management_type', 0, 'danger', '', '需归还,关联资产管理', '1', NOW(), '1', NOW(), b'0');
-- 领用明细状态字典类型
INSERT INTO `system_dict_type` (`name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`)
VALUES ('办公用品领用状态', 'oa_supply_item_status', 0, '办公用品领用明细状态', '1', NOW(), '1', NOW(), b'0', NULL);
-- 领用明细状态字典数据
INSERT INTO `system_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`)
VALUES
(0, '待领用', '0', 'oa_supply_item_status', 0, 'info', '', '审批通过后自动生成', '1', NOW(), '1', NOW(), b'0'),
(1, '已领用', '1', 'oa_supply_item_status', 0, 'success', '', '消耗品终态', '1', NOW(), '1', NOW(), b'0'),
(2, '已领用待归还', '2', 'oa_supply_item_status', 0, 'warning', '', '借用品/资产品等待归还', '1', NOW(), '1', NOW(), b'0'),
(3, '已归还', '3', 'oa_supply_item_status', 0, 'success', '', '借用品/资产品归还终态', '1', NOW(), '1', NOW(), b'0');六、后端接口设计
6.1 模块结构
yudao-module-oa/yudao-module-oa-server/
└── src/main/java/cn/iocoder/yudao/module/oa/
├── controller/admin/supply/
│ ├── SupplyController.java # 办公用品台账
│ ├── SupplyApplyBillController.java # 领用申请单
│ ├── SupplyApplyItemController.java # 领用明细(发放/归还)
│ └── vo/
│ ├── SupplyPageReqVO.java
│ ├── SupplySaveReqVO.java
│ ├── SupplyRespVO.java
│ ├── SupplyApplyBillPageReqVO.java
│ ├── SupplyApplyBillSaveReqVO.java
│ ├── SupplyApplyBillRespVO.java
│ ├── SupplyApplyItemPageReqVO.java
│ ├── SupplyApplyItemRespVO.java
│ └── SupplyApplyItemIssueReqVO.java
├── service/supply/
│ ├── SupplyService.java
│ ├── SupplyServiceImpl.java
│ ├── SupplyApplyBillService.java
│ ├── SupplyApplyBillServiceImpl.java # 实现 FlowBillService
│ ├── SupplyApplyItemService.java
│ └── SupplyApplyItemServiceImpl.java
└── dal/
├── dataobject/supply/
│ ├── SupplyDO.java
│ ├── SupplyApplyBillDO.java
│ └── SupplyApplyItemDO.java
└── mysql/supply/
├── SupplyMapper.java
├── SupplyApplyBillMapper.java
└── SupplyApplyItemMapper.java6.2 OaBillTypeEnum 新增枚举
java
/**
* 办公用品领用申请单
*/
OA_SUPPLY_APPLY_BILL("108", "办公用品领用申请单", "oa_supply_apply_bill"),6.3 接口清单
6.3.1 办公用品台账 /admin-api/oa/supply
| 方法 | 路径 | 说明 | 权限标识 |
|---|---|---|---|
| POST | /create | 新增办公用品 | oa:supply:create |
| PUT | /update | 修改办公用品 | oa:supply:update |
| DELETE | /delete | 删除办公用品 | oa:supply:delete |
| DELETE | /delete-list | 批量删除 | oa:supply:delete |
| GET | /get | 获取详情 | oa:supply:query |
| GET | /page | 分页查询 | oa:supply:query |
| GET | /export-excel | 导出 | oa:supply:export |
| PUT | /instock | 入库(增加库存) | oa:supply:instock |
入库接口参数:
json
{
"id": 1, // 办公用品ID
"quantity": 100, // 入库数量
"remark": "采购入库" // 备注
}6.3.2 领用申请单 /admin-api/oa/supply-apply-bill
| 方法 | 路径 | 说明 | 权限标识 |
|---|---|---|---|
| POST | /save | 保存(草稿) | oa:supply-apply-bill:create |
| POST | /submit | 保存并提交审批 | oa:supply-apply-bill:create |
| PUT | /update | 修改 | oa:supply-apply-bill:update |
| DELETE | /delete | 删除 | oa:supply-apply-bill:delete |
| GET | /get | 获取详情(含明细列表) | oa:supply-apply-bill:query |
| GET | /page | 分页查询 | oa:supply-apply-bill:query |
保存/提交请求参数:
json
{
"id": null,
"billCode": "OA-SUPPLY-20260319-001",
"applyReason": "部门日常办公需要",
"remark": "",
"items": [
{
"supplyId": 1,
"supplyName": "A4打印纸",
"supplySpec": "70g",
"supplyUnit": "包",
"managementType": 1,
"applyQuantity": 5
},
{
"supplyId": 2,
"supplyName": "签字笔",
"supplySpec": "0.5mm黑色",
"supplyUnit": "支",
"managementType": 1,
"applyQuantity": 10
}
],
"attachments": []
}6.3.3 领用明细(发放/归还) /admin-api/oa/supply-apply-item
| 方法 | 路径 | 说明 | 权限标识 |
|---|---|---|---|
| GET | /page | 分页查询明细(支持状态筛选) | oa:supply-apply-item:query |
| PUT | /issue | 确认发放 | oa:supply-apply-item:issue |
| PUT | /batch-issue | 批量发放 | oa:supply-apply-item:issue |
| PUT | /confirm-return | 确认归还 | oa:supply-apply-item:return |
发放接口参数:
json
{
"id": 1, // 明细ID
"issueQuantity": 5, // 实发数量
"issueRemark": "" // 发放备注
}确认归还接口参数:
json
{
"id": 1, // 明细ID
"returnQuantity": 5, // 归还数量
"returnRemark": "完好归还" // 归还备注
}6.4 BPM 流程回调核心逻辑
SupplyApplyBillServiceImpl.updateProcessStatus() 的核心逻辑:
java
@Override
public void updateProcessStatus(String businessKey, Integer status) {
Long id = Long.parseLong(businessKey);
// 更新申请单流程状态
SupplyApplyBillDO updateObj = new SupplyApplyBillDO();
updateObj.setId(id);
updateObj.setProcessStatus(status);
supplyApplyBillMapper.updateById(updateObj);
// 审批通过时:将所有明细状态置为"待领用"
if (APPROVE.getStatus().equals(status)) {
supplyApplyItemMapper.updateItemStatusByBillId(id,
SupplyItemStatusEnum.PENDING_ISSUE.getStatus());
}
}6.5 发放核心逻辑
1. 校验明细状态为"待领用"
2. 校验实发数量 ≤ 申请数量
3. 校验库存充足(stockQuantity ≥ issueQuantity)
4. 更新明细:
- 消耗品 → itemStatus = 1(已领用)
- 借用品/资产品 → itemStatus = 2(已领用待归还)
- 记录 issueQuantity, issueTime, issueBy
5. 扣减库存:supply.stockQuantity -= issueQuantity6.6 归还核心逻辑
1. 校验明细状态为"已领用待归还"
2. 校验归还数量 ≤ 实发数量 - 已归还数量
3. 更新明细:
- 累加 returnQuantity
- 全部归还 → itemStatus = 3(已归还)
- 记录 returnTime, returnBy, returnRemark
4. 恢复库存:supply.stockQuantity += returnQuantity七、前端页面设计
7.1 目录结构
views/oa/supply/
├── supplyinfo/ # 办公用品台账
│ ├── index.vue # 主页面(左侧类别 + 右侧列表)
│ ├── data.ts # 表格列、搜索表单、弹窗表单 schema
│ └── modules/
│ ├── form.vue # 新增/编辑弹窗
│ └── instock-form.vue # 入库弹窗
├── supplyapply/ # 领用申请管理
│ ├── info/
│ │ ├── index.vue # 申请表单页(BPM流程表单)
│ │ └── data.ts # 表单 schema
│ └── list/
│ ├── index.vue # 申请单列表页
│ └── data.ts # 表格列、搜索 schema
├── supplyrecord/ # 领用发放管理
│ ├── index.vue # 发放/归还管理页面(含Tab页签)
│ └── data.ts # 表格列定义
└── components/ # 公共组件
├── index.ts
├── supply-select-modal.vue # 办公用品选择弹窗(多选)
└── supply-select-data.ts # 选择弹窗的列和搜索定义7.2 API 层结构
api/oa/supply/
├── index.ts # 导出
├── supplyinfo/index.ts # 办公用品台账 API
├── supplyapply/index.ts # 领用申请单 API
└── supplyrecord/index.ts # 领用明细 API7.3 办公用品台账页面
布局方案(参考车辆管理)
┌──────────────────────────────────────────────────────────────────┐
│ 办公用品台账 │
├────────┬─────────────────────────────────────────────────────────┤
│ 物品类别 │ 搜索栏:[物品名称] [管理类型▼] [状态▼] [搜索] [重置] │
│ │─────────────────────────────────────────────────────────│
│ ● 全部 │ [+ 新增办公用品] [↓ 导出] [批量删除] │
│ ○ 文具类 │─────────────────────────────────────────────────────────│
│ ○ 打印耗材│ 物品名称 │ 规格型号 │ 单位 │ 管理类型 │ 库存 │ 预警值│状态│操作│
│ ○ 生活用品│─────────────────────────────────────────────────────────│
│ ○ 电脑办公│ A4打印纸 │ 70g │ 包 │ 消耗品 │ 150 │ 50 │正常│编辑│
│ ○ 办公设备│ 签字笔 │ 0.5mm │ 支 │ 消耗品 │ 30 │ 20 │正常│入库│
│ ○ 财务用品│ 鼠标 │ 无线 │ 个 │ 借用品 │⚠ 2 │ 5 │正常│删除│
│ │ 笔记本电脑│ i7/16G │ 台 │ 资产品 │ 5 │ 2 │正常│ │
└────────┴─────────────────────────────────────────────────────────┘实现要点:
- 左侧:使用
Menu组件渲染类别列表(字典驱动),与车辆管理一致 - 右侧:使用
useVbenVxeGrid渲染表格,查询时合并类别筛选条件 - 库存列:低于
min_stock时显示红色 + 警告图标 - 行操作:编辑、入库、删除
入库弹窗
┌───────────────────────────────────┐
│ 办公用品入库 │
├───────────────────────────────────┤
│ 物品名称:A4打印纸 │
│ 当前库存:150 │
│ 入库数量:[________] *必填 │
│ 备 注:[________________] │
├───────────────────────────────────┤
│ [取消] [确定] │
└───────────────────────────────────┘7.4 领用申请表单
表单布局
┌──────────────────────────────────────────────────────────────────┐
│ 办公用品领用申请单 [保存] [提交] [关闭] │
├──────────────────────────────────────────────────────────────────┤
│ 单据编号:OA-SUPPLY-20260319-001 申请人:张三 │
│ 申请事由:[部门日常办公需要_________________________] *必填 │
│ 备 注:[__________________________________________] │
├──────────────────────────────────────────────────────────────────┤
│ 领用明细 [+ 添加办公用品] │
│ ┌──────┬──────┬──────┬──────┬──────┬──────┬──────┐ │
│ │ 物品名称│ 规格型号│ 计量单位│ 管理类型│ 库存数量│ 领用数量│ 操作 │ │
│ ├──────┼──────┼──────┼──────┼──────┼──────┼──────┤ │
│ │ A4打印纸│ 70g │ 包 │ 消耗品 │ 150 │ [5] │ 删除 │ │
│ │ 签字笔 │0.5mm │ 支 │ 消耗品 │ 30 │ [10] │ 删除 │ │
│ │ 鼠标 │ 无线 │ 个 │ 借用品 │ 2 │ [1] │ 删除 │ │
│ └──────┴──────┴──────┴──────┴──────┴──────┴──────┘ │
├──────────────────────────────────────────────────────────────────┤
│ 附件信息 │
│ [上传附件] │
└──────────────────────────────────────────────────────────────────┘办公用品选择弹窗(多选)
┌───────────────────────────────────────────────────────────┐
│ 选择办公用品 │
├───────────────────────────────────────────────────────────┤
│ 搜索:[物品名称] [类别▼] [搜索] [重置] │
│ ┌──┬──────┬──────┬──────┬──────┬──────┐ │
│ │☑ │ 物品名称│ 规格型号│ 计量单位│ 管理类型│ 库存数量│ │
│ ├──┼──────┼──────┼──────┼──────┼──────┤ │
│ │☐ │ A4打印纸│ 70g │ 包 │ 消耗品 │ 150 │ │
│ │☑ │ 签字笔 │ 0.5mm │ 支 │ 消耗品 │ 30 │ │
│ │☐ │ 鼠标 │ 无线 │ 个 │ 借用品 │ 2 │ │
│ └──┴──────┴──────┴──────┴──────┴──────┘ │
│ 1 / 1 10条/页 │
├───────────────────────────────────────────────────────────┤
│ [取消] [确定] │
└───────────────────────────────────────────────────────────┘与车辆选择弹窗的区别:
- 车辆选择是单选(
radioConfig),办公用品选择是多选(checkboxConfig) - 选择后插入明细表格行,用户可修改每行的领用数量
- 已添加的物品不可重复选择
7.5 领用发放管理页面
布局方案
┌──────────────────────────────────────────────────────────────────┐
│ 领用发放管理 │
├──────────────────────────────────────────────────────────────────┤
│ [待发放(3)] [已领用(12)] [待归还(5)] [已归还(8)] [全部] │
├──────────────────────────────────────────────────────────────────┤
│ 搜索栏:[物品名称] [申请人] [申请单号] [搜索] [重置] │
│ ┌──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┐│
│ │申请单号│申请人 │物品名称│规格型号│申请数量│实发数量│管理类型│ 状态 │ 操作 ││
│ ├──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┤│
│ │OA-001│张三 │A4打印纸│ 70g │ 5 │ - │消耗品│待领用 │[发放] ││
│ │OA-001│张三 │鼠标 │ 无线 │ 1 │ - │借用品│待领用 │[发放] ││
│ │OA-002│李四 │键盘 │ 机械 │ 1 │ 1 │借用品│待归还 │[归还] ││
│ └──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┘│
└──────────────────────────────────────────────────────────────────┘交互说明:
- Tab 页签:按状态快速切换视图(待发放/已领用/待归还/已归还/全部)
- 发放操作:点击后弹出确认弹窗,输入实发数量(默认等于申请数量),确认后自动扣减库存
- 归还操作:点击后弹出确认弹窗,输入归还数量(默认等于实发数量),确认后自动恢复库存
- 批量发放:勾选多条待发放明细,点击工具栏"批量发放"按钮
八、菜单与权限设计
8.1 菜单结构
OA协同办公 (已有)
└── 办公用品管理 (新增一级菜单)
├── 办公用品台账 /oa/supply/supply-info
├── 领用申请管理 /oa/supply/supply-apply-list
└── 领用发放管理 /oa/supply/supply-record8.2 权限标识清单
| 权限标识 | 说明 |
|---|---|
oa:supply:create | 创建办公用品 |
oa:supply:update | 编辑办公用品 |
oa:supply:delete | 删除办公用品 |
oa:supply:query | 查询办公用品 |
oa:supply:export | 导出办公用品 |
oa:supply:instock | 办公用品入库 |
oa:supply-apply-bill:create | 创建领用申请 |
oa:supply-apply-bill:update | 修改领用申请 |
oa:supply-apply-bill:delete | 删除领用申请 |
oa:supply-apply-bill:query | 查询领用申请 |
oa:supply-apply-item:query | 查询领用明细 |
oa:supply-apply-item:issue | 确认发放 |
oa:supply-apply-item:return | 确认归还 |
8.3 前端路由配置
typescript
// router/routes/modules/oa.ts 中新增
{
path: '/oa/supply',
name: 'OaSupply',
meta: { title: '办公用品管理' },
children: [
{
path: 'supply-info',
name: 'OaSupplyInfo',
component: () => import('#/views/oa/supply/supplyinfo/index.vue'),
meta: { title: '办公用品台账' },
},
{
path: 'supply-apply-list',
name: 'OaSupplyApplyList',
component: () => import('#/views/oa/supply/supplyapply/list/index.vue'),
meta: { title: '领用申请管理' },
},
{
path: 'supply-apply-info',
name: 'OaSupplyApplyInfo',
component: () => import('#/views/oa/supply/supplyapply/info/index.vue'),
meta: { title: '领用申请' },
},
{
path: 'supply-record',
name: 'OaSupplyRecord',
component: () => import('#/views/oa/supply/supplyrecord/index.vue'),
meta: { title: '领用发放管理' },
},
],
}九、BPM 流程配置
9.1 流程定义
| 配置项 | 值 |
|---|---|
| 流程定义 Key | oa_supply_apply_bill |
| 流程名称 | 办公用品领用申请 |
| 表单类型 | 业务表单 |
| 创建页路径 | /oa/supply/supply-apply-info |
| 详情页路径 | /oa/supply/supplyapply/info/index.vue |
| 通知方式 | MQ(与用车申请一致) |
9.2 推荐审批流程(简化版)
发起申请 → 部门主管审批 → 结束(自动生成待领用明细)中小企业通常只需一级审批,复杂场景可通过 BPM 设计器自定义。
十、开发计划与排期
10.1 分阶段开发计划
第一阶段:基础数据(预计 2 天)
| 序号 | 任务 | 工作量 | 说明 |
|---|---|---|---|
| 1.1 | 创建数据库表(DDL + 字典 DML) | 0.5d | oa_supply、oa_supply_apply_bill、oa_supply_apply_item + 字典数据 |
| 1.2 | 后端 - 办公用品台账 CRUD | 1d | DO、Mapper、Service、Controller、VO,含入库接口 |
| 1.3 | 前端 - 字典常量注册 | 0.5d | DICT_TYPE 新增 OA_SUPPLY_CATEGORY、OA_SUPPLY_MANAGEMENT_TYPE、OA_SUPPLY_ITEM_STATUS |
第二阶段:台账页面(预计 2 天)
| 序号 | 任务 | 工作量 | 说明 |
|---|---|---|---|
| 2.1 | 前端 - 办公用品台账页面 | 1d | 左侧类别 + 右侧列表,参考车辆管理 carinfo/index.vue |
| 2.2 | 前端 - 新增/编辑弹窗 | 0.5d | 参考车辆管理 form.vue |
| 2.3 | 前端 - 入库弹窗 | 0.5d | 简单数量输入弹窗 |
第三阶段:领用申请(预计 3 天)
| 序号 | 任务 | 工作量 | 说明 |
|---|---|---|---|
| 3.1 | 后端 - 领用申请单 CRUD + BPM 集成 | 1d | FlowBillService 实现,OaBillTypeEnum 注册 |
| 3.2 | 后端 - 领用明细管理 | 0.5d | 明细的 CRUD,含状态查询接口 |
| 3.3 | 前端 - 办公用品选择弹窗(多选) | 0.5d | 参考 car-select-modal.vue,改为 checkbox 多选 |
| 3.4 | 前端 - 领用申请表单页 | 0.5d | BasicForm + 明细子表格,参考用车申请表单 |
| 3.5 | 前端 - 领用申请列表页 | 0.5d | 参考用车申请列表 |
第四阶段:发放与归还(预计 2 天)
| 序号 | 任务 | 工作量 | 说明 |
|---|---|---|---|
| 4.1 | 后端 - 发放接口 | 0.5d | 状态更新 + 库存扣减,事务保证 |
| 4.2 | 后端 - 归还接口 | 0.5d | 状态更新 + 库存恢复 |
| 4.3 | 前端 - 领用发放管理页面 | 1d | Tab 页签 + 发放/归还操作弹窗 |
第五阶段:收尾(预计 1 天)
| 序号 | 任务 | 工作量 | 说明 |
|---|---|---|---|
| 5.1 | 菜单初始化 SQL | 0.2d | 菜单数据 + 权限按钮 |
| 5.2 | BPM 流程部署 | 0.3d | 设计审批流程 + 配置通知 |
| 5.3 | 联调测试 | 0.5d | 全流程走通:录入→申请→审批→发放→归还 |
10.2 总工期
| 阶段 | 工时 |
|---|---|
| 第一阶段:基础数据 | 2d |
| 第二阶段:台账页面 | 2d |
| 第三阶段:领用申请 | 3d |
| 第四阶段:发放与归还 | 2d |
| 第五阶段:收尾 | 1d |
| 合计 | 10d |
十一、后续扩展规划(非本期范围)
| 功能 | 优先级 | 说明 |
|---|---|---|
| 采购管理 | P1 | 独立采购申请流程,关联库存入库 |
| 资产模块对接 | P1 | 资产品发放时自动创建资产记录,关联资产编号 |
| 库存盘点 | P2 | 定期盘点功能,支持盘盈盘亏调整 |
| 库存预警通知 | P2 | 低于预警值时自动发送站内消息/邮件通知管理员 |
| 统计报表 | P2 | 按部门/人员/物品维度的领用统计报表 |
| 员工离职检查 | P3 | 离职流程中自动检查未归还物品 |
| 领用额度控制 | P3 | 按部门/个人设置月度领用限额 |
| 移动端页面 | P3 | UniApp 移动端适配(领用申请 + 我的领用) |
十二、与现有模块的技术对比
| 维度 | 车辆管理(参考) | 办公用品管理(本设计) |
|---|---|---|
| 台账布局 | 左侧字典分类 + 右侧列表 | 左侧字典分类 + 右侧列表(一致) |
| 分类管理 | 字典 oa_car_cls | 字典 oa_supply_category(一致) |
| 申请单 | 单一对象(1车1单) | 主子表结构(1单N物品明细) |
| BPM 集成 | FlowBillService | FlowBillService(一致) |
| 归还管理 | 独立还车申请单(走BPM) | 管理员在线确认归还(无需BPM) |
| 库存管理 | 无库存概念 | 实时库存 + 自动增减 |
| 选择弹窗 | 单选(radio) | 多选(checkbox) |
简化设计决策:办公用品归还不走 BPM 流程(与还车不同),因为办公用品归还是管理员线下确认后在线操作,不需要审批环节,这更符合中小企业的实际操作场景。
十三、常见物品预设数据(建议初始化)
| 物品名称 | 类别 | 管理类型 | 规格 | 单位 | 建议预警值 |
|---|---|---|---|---|---|
| A4打印纸 | 打印耗材 | 消耗品 | 70g/500张 | 包 | 20 |
| 墨盒 | 打印耗材 | 消耗品 | HP 黑色 | 个 | 3 |
| 碳粉 | 打印耗材 | 消耗品 | 通用 | 瓶 | 2 |
| 签字笔 | 文具类 | 消耗品 | 0.5mm 黑色 | 支 | 20 |
| 笔记本 | 文具类 | 消耗品 | A5 | 本 | 10 |
| 文件夹 | 文具类 | 消耗品 | A4 | 个 | 10 |
| 订书钉 | 文具类 | 消耗品 | 24/6 | 盒 | 5 |
| 胶带 | 文具类 | 消耗品 | 透明 | 卷 | 5 |
| 抽纸 | 生活用品 | 消耗品 | 200抽 | 包 | 30 |
| 垃圾袋 | 生活用品 | 消耗品 | 大号 | 卷 | 10 |
| 一次性纸杯 | 生活用品 | 消耗品 | 250ml | 包 | 10 |
| 订书机 | 文具类 | 借用品 | 标准 | 个 | 3 |
| 计算器 | 财务用品 | 借用品 | 12位 | 个 | 3 |
| 鼠标 | 电脑办公 | 借用品 | 无线 | 个 | 5 |
| 键盘 | 电脑办公 | 借用品 | 有线 | 个 | 3 |
| U盘 | 电脑办公 | 借用品 | 32GB | 个 | 3 |
| 笔记本电脑 | 电脑办公 | 资产品 | i7/16GB | 台 | 2 |
| 台式机 | 电脑办公 | 资产品 | i5/8GB | 台 | 2 |
| 投影仪 | 办公设备/电器 | 资产品 | 1080P | 台 | 1 |
| 打印机 | 办公设备/电器 | 资产品 | 激光黑白 | 台 | 1 |
| 碎纸机 | 办公设备/电器 | 借用品 | 4级保密 | 台 | 1 |
| 饮水机 | 办公设备/电器 | 借用品 | 立式 | 台 | 1 |
