diff --git a/sql/11-approval-facility.sql b/sql/11-approval-facility.sql
new file mode 100644
index 0000000..e50c7aa
--- /dev/null
+++ b/sql/11-approval-facility.sql
@@ -0,0 +1,41 @@
+-- 设施价格表(设施损坏修复与租用价格表)业务表(可重复执行)
+-- 目标库:db_gxtyzx(master)
+-- 执行顺序:05-approval_phase2.sql -> ... -> 11-approval-facility.sql
+--
+-- ADR 0012:审批实例即版本,不建独立价格表主数据表。
+-- approval_facility_form 每个审批实例一行,业务字段只有生效日期(必填)
+-- approval_facility_item 实例的明细行,行即该版本条目,金额服务端重算
+--
+-- 当前生效版本 = 同租户同 flow_code 下 status=ARCHIVED 且 effective_date <= today
+-- 中 effective_date 最大者;历史版本按 effective_date 倒序(查询时算,不落库)。
+
+CREATE TABLE IF NOT EXISTS approval_facility_form (
+ id BIGINT NOT NULL AUTO_INCREMENT,
+ tenant_id INT NOT NULL DEFAULT 10150,
+ instance_id BIGINT NOT NULL,
+ effective_date DATE NOT NULL COMMENT '生效日期,不允许早于归档日',
+ create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (id),
+ UNIQUE KEY uk_instance (instance_id),
+ KEY idx_effective (tenant_id, effective_date)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='设施价格表';
+
+CREATE TABLE IF NOT EXISTS approval_facility_item (
+ id BIGINT NOT NULL AUTO_INCREMENT,
+ tenant_id INT NOT NULL DEFAULT 10150,
+ instance_id BIGINT NOT NULL,
+ line_no INT NOT NULL COMMENT '行号,按提交顺序 1..N',
+ item_name VARCHAR(200) NOT NULL COMMENT '名称',
+ location VARCHAR(200) DEFAULT NULL COMMENT '位置',
+ unit VARCHAR(20) NOT NULL COMMENT '单位',
+ quantity DECIMAL(12,3) NOT NULL COMMENT '数量',
+ unit_price DECIMAL(12,2) NOT NULL COMMENT '单价',
+ amount DECIMAL(12,2) NOT NULL COMMENT '金额,服务端按 quantity × unit_price 重算',
+ remark VARCHAR(200) DEFAULT NULL COMMENT '备注',
+ create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (id),
+ UNIQUE KEY uk_instance_line (instance_id, line_no),
+ KEY idx_instance (instance_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='设施价格表明细';
diff --git a/src/main/java/com/gxwebsoft/approval/doc/facility/FacilityDocumentType.java b/src/main/java/com/gxwebsoft/approval/doc/facility/FacilityDocumentType.java
new file mode 100644
index 0000000..3e8c145
--- /dev/null
+++ b/src/main/java/com/gxwebsoft/approval/doc/facility/FacilityDocumentType.java
@@ -0,0 +1,313 @@
+package com.gxwebsoft.approval.doc.facility;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.gxwebsoft.approval.constant.ApprovalConstants;
+import com.gxwebsoft.approval.document.AbstractApprovalDocumentType;
+import com.gxwebsoft.approval.document.ApprovalDocumentParam;
+import com.gxwebsoft.approval.document.ApprovalLineSupport;
+import com.gxwebsoft.approval.entity.ApprovalFacilityForm;
+import com.gxwebsoft.approval.entity.ApprovalFacilityItem;
+import com.gxwebsoft.approval.entity.ApprovalInstance;
+import com.gxwebsoft.approval.mapper.ApprovalFacilityFormMapper;
+import com.gxwebsoft.approval.mapper.ApprovalFacilityItemMapper;
+import com.gxwebsoft.approval.param.ApprovalFacilityParam;
+import com.gxwebsoft.approval.support.ApprovalLineSpec;
+import com.gxwebsoft.approval.vo.ApprovalDetail;
+import com.gxwebsoft.common.core.exception.BusinessException;
+import com.gxwebsoft.common.system.entity.User;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 设施价格表(设施损坏修复与租用价格表,ADR 0012):
+ * 报送人 → 报送部门负责人 → 四部门会签 → 分管领导 → 总经理 → 存档(报送人 + 运营管理部)→ 归档。
+ *
+ *
只做价格目录,不含损坏描述/报修时间/修复内容——那是价格表被使用的场景,不是第二张单。
+ * 审批实例即版本:每次归档生成一版,明细行即该版条目;不建独立价格表主数据表。
+ *
+ * 生效日期允许未来(提前批),不允许早于当天(追溯修改会让历史结算失去依据):
+ * 草稿保存即拒绝早于今天的日期,归档前由 {@link #validateBeforeArchive} 再校验一次。
+ */
+@Component
+public class FacilityDocumentType extends AbstractApprovalDocumentType {
+
+ private static final String NODES_JSON = "["
+ + "{\"key\":\"reportLeader\",\"type\":\"APPROVE\",\"resolver\":\"reporterOrgLeader\","
+ + "\"name\":\"报送部门负责人\"},"
+ + "{\"key\":\"deptCountersign\",\"type\":\"COUNTERSIGN\",\"name\":\"四部门会签\",\"groups\":["
+ + "{\"key\":\"venue\",\"name\":\"场馆部\",\"resolver\":\"orgLeaderByCode\",\"orgCode\":\"APPROVAL_VENUE\"},"
+ + "{\"key\":\"ops\",\"name\":\"运营管理部\",\"resolver\":\"orgLeaderByCode\",\"orgCode\":\"APPROVAL_OPS\"},"
+ + "{\"key\":\"safety\",\"name\":\"安全运保部\",\"resolver\":\"orgLeaderByCode\",\"orgCode\":\"APPROVAL_SAFETY\"},"
+ + "{\"key\":\"finance\",\"name\":\"财务部\",\"resolver\":\"orgLeaderByCode\",\"orgCode\":\"APPROVAL_FINANCE\"}"
+ + "]},"
+ + "{\"key\":\"deputyLeader\",\"type\":\"APPROVE\",\"resolver\":\"reporterOrgDeputy\","
+ + "\"name\":\"分管领导\"},"
+ + "{\"key\":\"generalManager\",\"type\":\"APPROVE\",\"resolver\":\"roleGeneralManager\","
+ + "\"name\":\"总经理\"},"
+ + "{\"key\":\"confirm\",\"type\":\"CONFIRM\",\"name\":\"存档\",\"groups\":["
+ + "{\"key\":\"reporter\",\"name\":\"报送人\",\"resolver\":\"reporter\"},"
+ + "{\"key\":\"ops\",\"name\":\"运营管理部\",\"resolver\":\"roleTypist\"}"
+ + "]},"
+ + "{\"key\":\"archive\",\"type\":\"ARCHIVE\",\"resolver\":\"archivist\",\"name\":\"归档\"}"
+ + "]";
+
+ /** 检索文本里最多拼接的明细名称条数,避免超出 search_text 长度。 */
+ private static final int SEARCH_ITEM_LIMIT = 10;
+
+ @Resource
+ private ApprovalFacilityFormMapper facilityFormMapper;
+ @Resource
+ private ApprovalFacilityItemMapper facilityItemMapper;
+
+ @Override
+ public String flowCode() {
+ return ApprovalConstants.FLOW_FACILITY;
+ }
+
+ @Override
+ public String docType() {
+ return ApprovalConstants.FLOW_FACILITY;
+ }
+
+ @Override
+ public String flowName() {
+ return "设施损坏修复与租用价格表";
+ }
+
+ @Override
+ public String nodesJson() {
+ return NODES_JSON;
+ }
+
+ @Override
+ public String noPrefix() {
+ return ApprovalConstants.NO_PREFIX_FACILITY;
+ }
+
+ /** 明细列:名称/位置/单位/数量/单价/金额(服务端重算)/备注。 */
+ @Override
+ public List lineColumns() {
+ List columns = new ArrayList<>();
+ columns.add(ApprovalLineSpec.text("itemName", "名称", true, 200));
+ columns.add(ApprovalLineSpec.text("location", "位置", false, 200));
+ columns.add(ApprovalLineSpec.text("unit", "单位", true, 20));
+ columns.add(ApprovalLineSpec.decimal("quantity", "数量", true, 3));
+ columns.add(ApprovalLineSpec.decimal("unitPrice", "单价", true, 2));
+ // 金额由服务端重算,客户端不传也允许(客户端传了则必须与 数量 × 单价 一致)
+ columns.add(ApprovalLineSpec.decimal("amount", "金额", false, 2).asMoney());
+ columns.add(ApprovalLineSpec.text("remark", "备注", false, 200));
+ return columns;
+ }
+
+ @Override
+ public String requiredAttachmentCategory() {
+ return ApprovalConstants.CATEGORY_SIGNED;
+ }
+
+ @Override
+ public Class extends ApprovalDocumentParam> paramClass() {
+ return ApprovalFacilityParam.class;
+ }
+
+ /**
+ * 草稿校验:生效日期必填且不早于今天;明细逐行校验并重算金额。
+ */
+ @Override
+ public void validate(ApprovalDocumentParam param, User user) {
+ ApprovalFacilityParam facility = cast(param);
+ requireEffectiveDate(facility.getEffectiveDate());
+ ApprovalLineSupport.normalize(facility.getLines(), lineColumns());
+ }
+
+ @Override
+ public Long persist(Long instanceId, Long bizId, ApprovalDocumentParam param, User user) {
+ ApprovalFacilityParam facility = cast(param);
+ LocalDate effectiveDate = requireEffectiveDate(facility.getEffectiveDate());
+ List