<mxfile host="65bd71144e" modified="2026-04-29T00:00:00.000Z" agent="Claude" version="22.0.0" type="device">
  <diagram id="dps" name="Domain-Pipeline-Service">
    <mxGraphModel dx="1422" dy="900" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1200" pageHeight="900" math="0" shadow="0">
      <root>
        <mxCell id="0" />
        <mxCell id="1" parent="0" />
        <mxCell id="title" value="表格模块 — Domain → Operation → Pipeline → Service 五层架构" style="text;html=1;align=center;fontSize=20;fontStyle=1" vertex="1" parent="1">
          <mxGeometry x="180" y="20" width="840" height="30" as="geometry" />
        </mxCell>
        <mxCell id="subtitle" value="自下而上：Domain(纯逻辑) → Operation(动作) → Pipeline(三模式) → Service(门面) → UI(订阅)" style="text;html=1;align=center;fontSize=12;fontStyle=2;fontColor=#666666" vertex="1" parent="1">
          <mxGeometry x="160" y="50" width="880" height="20" as="geometry" />
        </mxCell>
        <mxCell id="uiLayer" value="UI Layer — 现有，不动；通过订阅事件刷新" style="swimlane;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;startSize=30" vertex="1" parent="1">
          <mxGeometry x="40" y="80" width="1120" height="80" as="geometry" />
        </mxCell>
        <mxCell id="ui1" value="ui/table-bindings.js" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6" vertex="1" parent="uiLayer">
          <mxGeometry x="320" y="32" width="220" height="36" as="geometry" />
        </mxCell>
        <mxCell id="ui2" value="ui/message-table-renderer.js" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6" vertex="1" parent="uiLayer">
          <mxGeometry x="580" y="32" width="220" height="36" as="geometry" />
        </mxCell>
        <mxCell id="serviceLayer" value="Service Layer — 顶层门面，组合下层" style="swimlane;fontStyle=1;fillColor=#dae8fc;strokeColor=#6c8ebf;startSize=30" vertex="1" parent="1">
          <mxGeometry x="40" y="190" width="1120" height="80" as="geometry" />
        </mxCell>
        <mxCell id="svc" value="TableSystemService&#xa;processMessageUpdate / fillSecondary / fillBatch / reorganize / rollback" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=11" vertex="1" parent="serviceLayer">
          <mxGeometry x="280" y="20" width="560" height="50" as="geometry" />
        </mxCell>
        <mxCell id="pipelineLayer" value="Pipeline Layer — 三模式落地；formatter 可插拔" style="swimlane;fontStyle=1;fillColor=#d5e8d4;strokeColor=#82b366;startSize=30" vertex="1" parent="1">
          <mxGeometry x="40" y="300" width="1120" height="200" as="geometry" />
        </mxCell>
        <mxCell id="formattersGroup" value="formatters/" style="rounded=0;whiteSpace=wrap;html=1;fillColor=none;strokeColor=#82b366;dashed=1;verticalAlign=top;fontStyle=1" vertex="1" parent="pipelineLayer">
          <mxGeometry x="20" y="40" width="500" height="140" as="geometry" />
        </mxCell>
        <mxCell id="fmtIdx" value="index.js&#xa;按 settings 分发" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10" vertex="1" parent="formattersGroup">
          <mxGeometry x="160" y="30" width="180" height="40" as="geometry" />
        </mxCell>
        <mxCell id="fmtLeg" value="legacy.js&#xa;&lt;Amily2Edit&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10" vertex="1" parent="formattersGroup">
          <mxGeometry x="20" y="85" width="140" height="44" as="geometry" />
        </mxCell>
        <mxCell id="fmtJson" value="json.js&#xa;{operations}" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10" vertex="1" parent="formattersGroup">
          <mxGeometry x="180" y="85" width="140" height="44" as="geometry" />
        </mxCell>
        <mxCell id="fmtTC" value="toolcall.js&#xa;Bus tools" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10" vertex="1" parent="formattersGroup">
          <mxGeometry x="340" y="85" width="140" height="44" as="geometry" />
        </mxCell>
        <mxCell id="fillerGroup" value="filler/" style="rounded=0;whiteSpace=wrap;html=1;fillColor=none;strokeColor=#82b366;dashed=1;verticalAlign=top;fontStyle=1" vertex="1" parent="pipelineLayer">
          <mxGeometry x="560" y="40" width="540" height="140" as="geometry" />
        </mxCell>
        <mxCell id="fillShared" value="shared.js&#xa;worldbook + history + buildMessages + callModel" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10" vertex="1" parent="fillerGroup">
          <mxGeometry x="60" y="30" width="420" height="40" as="geometry" />
        </mxCell>
        <mxCell id="fillSec" value="secondary.js&#xa;触发条件 + 楼层扫描" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10" vertex="1" parent="fillerGroup">
          <mxGeometry x="20" y="85" width="160" height="44" as="geometry" />
        </mxCell>
        <mxCell id="fillBatch" value="batch.js&#xa;批次循环" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10" vertex="1" parent="fillerGroup">
          <mxGeometry x="200" y="85" width="160" height="44" as="geometry" />
        </mxCell>
        <mxCell id="fillReorg" value="reorganize.js" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10" vertex="1" parent="fillerGroup">
          <mxGeometry x="380" y="85" width="140" height="44" as="geometry" />
        </mxCell>
        <mxCell id="opLayer" value="Operation Layer — 统一动作；从 executor.js 抽出" style="swimlane;fontStyle=1;fillColor=#fff2cc;strokeColor=#d6b656;startSize=30" vertex="1" parent="1">
          <mxGeometry x="40" y="530" width="1120" height="80" as="geometry" />
        </mxCell>
        <mxCell id="op1" value="operations.js&#xa;applyOperations(state, ops) → { state, changes }&#xa;含 insertRow / updateRow / deleteRow 三内部函数" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=11" vertex="1" parent="opLayer">
          <mxGeometry x="320" y="10" width="480" height="60" as="geometry" />
        </mxCell>
        <mxCell id="domainLayer" value="Domain Layer — 拆自 manager.js；禁止 import UI" style="swimlane;fontStyle=1;fillColor=#f8cecc;strokeColor=#b85450;startSize=30" vertex="1" parent="1">
          <mxGeometry x="40" y="640" width="1120" height="120" as="geometry" />
        </mxCell>
        <mxCell id="dm1" value="store.js&#xa;currentTablesState&#xa;独占所有权" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=10" vertex="1" parent="domainLayer">
          <mxGeometry x="20" y="40" width="160" height="60" as="geometry" />
        </mxCell>
        <mxCell id="dm2" value="persist.js&#xa;commitToLastMessage&#xa;封装 16 处样板" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=10" vertex="1" parent="domainLayer">
          <mxGeometry x="200" y="40" width="160" height="60" as="geometry" />
        </mxCell>
        <mxCell id="dm3" value="mutations.js&#xa;addRow / addCol / ...&#xa;(16 个 UI 突变)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=10" vertex="1" parent="domainLayer">
          <mxGeometry x="380" y="40" width="180" height="60" as="geometry" />
        </mxCell>
        <mxCell id="dm4" value="rendering.js&#xa;toCsv * 3&#xa;(纯函数)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=10" vertex="1" parent="domainLayer">
          <mxGeometry x="580" y="40" width="160" height="60" as="geometry" />
        </mxCell>
        <mxCell id="dm5" value="templates.js&#xa;getter/setter" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=10" vertex="1" parent="domainLayer">
          <mxGeometry x="760" y="40" width="160" height="60" as="geometry" />
        </mxCell>
        <mxCell id="dm6" value="preset.js&#xa;import/export" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=10" vertex="1" parent="domainLayer">
          <mxGeometry x="940" y="40" width="160" height="60" as="geometry" />
        </mxCell>
        <mxCell id="e_svc_fillSec" style="endArrow=classic;html=1" edge="1" parent="1" source="svc" target="fillSec">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_svc_fillBatch" style="endArrow=classic;html=1" edge="1" parent="1" source="svc" target="fillBatch">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_svc_fillReorg" style="endArrow=classic;html=1" edge="1" parent="1" source="svc" target="fillReorg">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_svc_op" value="apply Op[]" style="endArrow=classic;html=1;fontSize=9" edge="1" parent="1" source="svc" target="op1">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_fillSec_shared" style="endArrow=classic;html=1" edge="1" parent="1" source="fillSec" target="fillShared">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_fillBatch_shared" style="endArrow=classic;html=1" edge="1" parent="1" source="fillBatch" target="fillShared">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_fillReorg_shared" style="endArrow=classic;html=1" edge="1" parent="1" source="fillReorg" target="fillShared">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_shared_fmtIdx" value="dispatch" style="endArrow=classic;html=1;fontSize=9" edge="1" parent="1" source="fillShared" target="fmtIdx">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_fmtIdx_leg" style="endArrow=open;html=1;dashed=1;endFill=0" edge="1" parent="1" source="fmtIdx" target="fmtLeg">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_fmtIdx_json" style="endArrow=open;html=1;dashed=1;endFill=0" edge="1" parent="1" source="fmtIdx" target="fmtJson">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_fmtIdx_tc" style="endArrow=open;html=1;dashed=1;endFill=0" edge="1" parent="1" source="fmtIdx" target="fmtTC">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_leg_op" value="Op[]" style="endArrow=classic;html=1;dashed=1;fontSize=9" edge="1" parent="1" source="fmtLeg" target="op1">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_json_op" value="Op[]" style="endArrow=classic;html=1;dashed=1;fontSize=9" edge="1" parent="1" source="fmtJson" target="op1">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_tc_op" value="Op[]" style="endArrow=classic;html=1;dashed=1;fontSize=9" edge="1" parent="1" source="fmtTC" target="op1">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_op_dm1" value="state" style="endArrow=classic;html=1;fontSize=9" edge="1" parent="1" source="op1" target="dm1">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_svc_dm2" value="commit" style="endArrow=classic;html=1;dashed=1;fontSize=9" edge="1" parent="1" source="svc" target="dm2">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_dm3_dm1" value="mutates" style="endArrow=classic;html=1;dashed=1;fontSize=9" edge="1" parent="1" source="dm3" target="dm1">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_dm3_dm2" value="commit" style="endArrow=classic;html=1;dashed=1;fontSize=9" edge="1" parent="1" source="dm3" target="dm2">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e_dm1_ui" value="subscribe / events" style="endArrow=classic;html=1;dashed=1;strokeColor=#9673a6;fontSize=9" edge="1" parent="1" source="dm1" target="ui1">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="legend" value="实线箭头 → 直接调用（自顶而下）&#10;虚线箭头 → 数据流向 / 跨层订阅&#10;红色 Domain 层最严格：禁止 import UI" style="text;html=1;align=left;fontSize=11;fillColor=#ffffff;strokeColor=#cccccc;rounded=0" vertex="1" parent="1">
          <mxGeometry x="40" y="780" width="380" height="60" as="geometry" />
        </mxCell>
        <mxCell id="note1" value="特点：&#10;• 五层洋葱模型，依赖单向自顶而下&#10;• 文件少（~14），manager.js 拆出后立即清晰&#10;• Domain 是纯逻辑岛，可独立测试&#10;• 无显式 DTO 层，shape 散在 JSDoc 注释里" style="text;html=1;align=left;fontSize=11;fillColor=#fff8e1;strokeColor=#ffb300;rounded=0" vertex="1" parent="1">
          <mxGeometry x="450" y="770" width="380" height="80" as="geometry" />
        </mxCell>
      </root>
    </mxGraphModel>
  </diagram>
</mxfile>
