- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
173 lines
20 KiB
Markdown
173 lines
20 KiB
Markdown
# combat.flying_projectile —— 飞行物、目标、地形碰撞、命中和回收
|
||
|
||
状态:`PARTIAL`
|
||
|
||
本合同覆盖 40250 客户端的两条飞行物来源:
|
||
|
||
- 普攻/弓箭的 `.msa FLY` 事件 → `OnSetFlyTarget` / `OnShoot` → `CG_FLY_TARGETING`、`CG_SHOOT`。
|
||
- 服务端 `GC_CREATE_FLY`、`GC_FLY_TARGETING`、`GC_ADD_FLY_TARGETING` → 客户端 `CFlyingManager` 弹道、目标追踪、背景/Actor 碰撞和爆炸回调。
|
||
|
||
## 40250 参考调用链
|
||
|
||
### 客户端发射事件
|
||
|
||
- `GameLib/ActorInstanceFly.cpp` `OnGetFlyTargetPosition`
|
||
- 从目标 Actor 的飞行目标包围球读取位置。
|
||
- `UserInterface/PythonPlayerEventHandler.cpp:232` `CNormalBowAttack_FlyEventHandler_AutoClear::OnSetFlyTarget`
|
||
- 读取主角位置/朝向并发送 `SendFlyTargetingPacket(target VID, target position)`。
|
||
- `UserInterface/PythonPlayerEventHandler.cpp:241` `OnShoot`
|
||
- 在动作资源的 FLY 事件帧发送 `SendShootPacket(skill)`。
|
||
- `UserInterface/PythonPlayerEventHandler.cpp:259` `OnExplodingAtAnotherTarget`
|
||
- 若启用对应处理,向另一 Actor 发送攻击包并调用目标 `OnShootDamage`;当前参考实现该函数主体被直接 `return`,必须保留这个可达性事实,不能凭注释臆造伤害链。
|
||
|
||
### 飞行数据和弹道
|
||
|
||
- `GameLib/FlyingData.cpp` `CFlyingData::LoadScriptFile`
|
||
- `.fly` 资源读取 initial velocity、cone/roll、angular velocity、gravity、range、acceleration、homing、bomb effect、hit-on-background、hit-on-another-monster、pierce count、bomb range 和 attach data。
|
||
- `GameLib/FlyingInstance.cpp` `CFlyingInstance::Create`
|
||
- 绑定 `CFlyTarget`、`canAttack`、起点、旋转方向、局部初速/加速度和剩余射程。
|
||
- `GameLib/FlyingInstance.cpp:347` `CFlyingInstance::Update`
|
||
- homing → 速度/加速度推进 → 维护 attach effect → 超程 → 目标线段命中 → 穿透/爆炸 → 其它 Actor 动态碰撞 → 地形高度/静态背景碰撞。
|
||
- `GameLib/FlyTarget.cpp` `CFlyTarget`
|
||
- 目标可以是对象或坐标;对象被删除时转为最后目标位置,避免悬空指针。
|
||
- `GameLib/FlyingObjectManager.cpp`
|
||
- Update 返回 false 后从实例表删除;地图/场景销毁时删除全部实例和挂接特效。
|
||
|
||
### 网络收包
|
||
|
||
- `UserInterface/PythonNetworkStreamPhaseGame.cpp:2559` `RecvAddFlyTargetingPacket`
|
||
- 找不到射手时只记录并返回;存在目标 VID 时绑定对象,否则通过地图高度构造坐标目标。
|
||
- `:2599` `RecvFlyTargetingPacket`
|
||
- 与上面相同,但替换当前目标而不是追加。
|
||
- `:2697` `RecvCreateFlyPacket`
|
||
- 起点或终点实例不存在时不创建;否则 `CreateIndexedFly(type, start, end)`。
|
||
- `:2637-2695` `SendShootPacket`、`SendAddFlyTargetingPacket`、`SendFlyTargetingPacket`
|
||
- 每个发送操作后都发送 sequence。
|
||
|
||
## 当前端实现映射
|
||
|
||
- `project/fly_object.gd`
|
||
- `FlyData`、`FlyInstance`、`FlyManager` 对应 `CFlyingData/CFlyingInstance/CFlyingManager`。
|
||
- 已实现 `.msf` 的 `CFlyingData::LoadScriptFile` 字段解析和 cm→m 单位适配,并保留目标对象/坐标、homing、线段到点命中、超程、地形高度/静态 Physics layer 2 碰撞、穿透计数、爆点和地图清理。
|
||
- `project/net_world.gd`
|
||
- `_on_fly` 按 `playersettingmodule.py` 的索引表加载 `.msf` 并消费服务端飞行 cue;`_on_fly_targeting` 暂存 shooter 的目标队列;`clear_for_map_change` 清理飞行物和爆点。
|
||
- 服务端索引经验球通过 `FLY_EXP` 加载 `ga_piece_yellow_small2.msf`;离线 `spawn_exp_fly` 仍是独立的多球测试/表现辅助入口。
|
||
- `project/net_play.gd`
|
||
- `_emit_swing` 在弓箭起手时调用 `_send_fly_target`,并由 `bow_shot_fired` 进入发射链。
|
||
- `send_fly_targeting` 处理扇形/圆形目标追加。
|
||
- `project/world_shot.gd`、`project/fx/skill_fx.gd`
|
||
- 提供世界投射物/技能表现层。
|
||
- `extension/src/net/*`
|
||
- 当前 classic parser/store/client 提供飞行事件和目标坐标的网络入口。
|
||
|
||
## 分支等价矩阵
|
||
|
||
| 参考判据/副作用 | 当前实现 | 结论 |
|
||
|---|---|---|
|
||
| `.fly`/`.msf` 资源读取飞行参数和 attach data | `FlyData.load_msf` 解析参考字段、相对/绝对资源路径和 cm→m 单位;`FlyInstance` 已创建 AttachFile/FlyTrace,`NetWorld._indexed_fly_data` 绑定 40250 注册资源;远端 Actor 的 MSA FLY 也进入同一实例入口 | 部分等价;精确远端 skill 上下文、相机尾迹几何和所有资源矩阵仍缺 |
|
||
| 起点/终点实例缺失则不创建飞行物 | `_on_fly` 用 `Vector3.INF`/节点存在门控后返回 | 基本等价;完整 packet handler/sequence 仍未 live 验证 |
|
||
| 对象目标随 Actor 移动,目标删除后转位置 | `FlyTargetAnchor.fly_target_position` 使用包围球中心;`notify_target_despawn` 在渐隐/替换前立即转为位置目标 | 基本等价;迟到目标包和 VID 重用的包级矩阵仍未完成 |
|
||
| homing、速度/加速度、射程和线段到点命中 | `FlyInstance._adjust_homing`/`update` | 基本等价;坐标轴和单位转换需真实资源验证 |
|
||
| `m_fCollisionSphereRadius = max(move distance*2, configured radius)` | `FlyInstance.update` 在同一顺序计算膨胀半径,并通过 `actor_provider` 查询当前可见 Actor | 基本等价;Actor 碰撞球半径的真实模型标定仍未完全证明 |
|
||
| `hitonanothermonster` + 已命中对象集合 + `OnExplodingAtAnotherTarget` | `FlyInstance._find_another_actor`、`hitted_objects`、`at_another` 回调和穿透分支已接入;射手被排除 | 部分等价;EffectManager/真实动态 culling 仍未完全复现 |
|
||
| hit-on-background 先地形高度后静态背景碰撞 | 当前动态 Actor 分支后仍是 `sample_height` 后 Physics layer 2 ray | 基本等价的 Godot 平台适配;真实 culling 半径/查询范围未证明相同 |
|
||
| pierce count:命中后 bomb,减计数,耗尽才 explode | `FlyInstance.pierce`/`target_hitted` 与动态 `at_another` 分支均执行相同的 bomb/继续/爆炸顺序 | 基本等价;多种真实资源与同帧背景竞争仍未完整验证 |
|
||
| `OnShootDamage` 仅在 `canAttack` 对象目标命中时触发 | 当前 `shoot_damage` signal 有入口,但服务端 GC 弹道使用 `can_attack=false` | 基本等价;真实本地弓箭事件到服务端回包链未完整证明 |
|
||
| 超程 `OnExplodingOutOfRange`、背景/目标回调和删除 | `exploded` signal + manager 删除;BombEffect 优先走 EffectRegistry,资源不可用才 fallback flash | 基本等价;EffectManager 真实生命周期和全部回调包序仍未完整验证 |
|
||
| Add/Set FlyTargeting 追加与替换 | 入站通过 shooter meta `fly_target_queue`、`append`;出站普通弓箭走独立 `fly_targeting`/`CG_FLY_TARGETING`,附加目标走 `add_fly_targeting`/`CG_ADD_FLY_TARGETING` | 基本等价;shooter 不可见/本地主角/VID 重用分支待验证 |
|
||
| `GC_CREATE_FLY` indexed normal/firecracker/auto-fire 类型 | `INDEXED_FLY_TYPES` 与 40250 注册表一致;`_on_fly` 已分别复刻普通、随机位置烟花和 +100cm AUTO_FIRE 起点,AttachFile 优先作为实际视觉 | 基本等价;资源缺失 fallback、真实模型半径和包序仍未完全证明 |
|
||
| 每个 outbound 飞行目标/射击包后发送 sequence | ClassicSession 字节级验证 `CG_FLY_TARGETING`、`CG_ADD_FLY_TARGETING`、`CG_SHOOT` 均追加正确 sequence;完整动作队列与真实 socket 包序仍未 live 验证 | 部分等价 |
|
||
|
||
## 已执行测试
|
||
|
||
- `project/fly_test.gd`:PASS;覆盖 `CFlyingManager/CFlyingInstance` 基础弹道、命中、超程和 `__CanShot`。
|
||
- `project/fly_reset_test.gd`:PASS;覆盖地图切换时飞行物和爆点清理。
|
||
- `project/test_exp_fly_parity.gd`:6/6 PASS;覆盖经验光球飞行和吸收。
|
||
- `project/fly_target_bounds_test.gd`:0 failures;覆盖模型目标包围球中心和 CPU/GPU 一致性,但有 ObjectDB leak warning。
|
||
- `project/test_click_target_effect_parity.gd`:0 failures;覆盖静态障碍碰撞和目标效果清理,但有 ObjectDB/RID 清理警告。
|
||
- `project/combat_fx_test.gd`:PASS;覆盖命中/连击/效果主链。
|
||
- `project/fly_data_msf_test.gd`:PASS;覆盖 `geompung.msf`、经验球和 `arrow_01.msf` 的字段、相对资源路径、attach data、枚举及 cm→m 转换。
|
||
- `project/indexed_fly_type_test.gd`:PASS;覆盖 40250 NORMAL/FIRE_CRACKER/AUTO_FIRE 的索引类型、起点高度、对象/位置目标和随机距离范围。
|
||
- `project/fly_dynamic_collision_test.gd`:PASS;覆盖动态 Actor 双目标穿透和同一 Actor 的 `HittedObjectSet` 去重。
|
||
- `project/fly_target_lifecycle_test.gd`:PASS;覆盖包围球目标中心和 Actor 销毁时立即转位置目标。
|
||
- `project/fly_attachment_effect_test.gd`:PASS;覆盖绝对 AttachFile 解析、EffectRegistry 实例、FlyTrace 轨迹、BombEffect 和资源视觉不重复绘制。
|
||
- `project/remote_motion_fly_test.gd`:PASS;覆盖远端 Actor `GC_FLY_TARGETING` 队列、MSA FLY 事件、owner VID/skill 和资源飞行实例创建。
|
||
|
||
## Implementation fix round 2026-09-21T06:34Z
|
||
|
||
按 `FlyingObjectManager::CreateIndexedFly` 接入 `INDEXED_FLY_TYPES`:NORMAL 保持射手根位置和对象目标,FIRE_CRACKER 使用 +200cm 起点、-90° 基准方向与 20..50m/10..25m 随机位置目标,AUTO_FIRE 使用 +100cm 起点并保留对象目标。新增 `indexed_fly_type_test.gd`,修复前 FIRE_CRACKER/AUTO_FIRE 断言失败,修复后通过。
|
||
|
||
按 `FlyingInstance::Update` 接入动态 Actor 碰撞:每帧使用 `max(move_distance * 2, collision_sphere_radius)`,排除 owner,按节点实例身份维护 `hitted_objects`,触发 `at_another` 并复刻 pierce/bomb/explode 分支。按 `FlyTarget`/`ActorInstanceFly` 接入 `FlyTargetAnchor` 包围球中心,并在 NetWorld 的 despawn、同 VID 替换前调用 `notify_target_despawn`,保证渐隐节点不再继续移动飞行目标。新增 `fly_dynamic_collision_test.gd` 和 `fly_target_lifecycle_test.gd`,均通过。
|
||
|
||
修复后 `fly_test`、`fly_reset_test`、`fly_data_msf_test`、`motion_event_fly_test`、`test_exp_fly_parity`、`netbridge_test`、`combat_fx_test`、`netplay_test` 和静态建筑碰撞回归通过。真实 `EffectManager`/`FlyTrace` 资源表现、真实模型动态半径、包序和不可见 Actor 生命周期仍使合同保持 `PARTIAL`。
|
||
|
||
## Implementation fix round 2026-09-22T07:55Z
|
||
|
||
复核 `CFlyingManager::DeleteAllInstances` 的销毁边界时发现,当前 `FlyInstance.handler` 闭包捕获实例自身,而实例又持有该 Callable;地图清理只清数组会留下 `RefCounted` 环。现新增 `_release_instance()`,在地图清理和自然过期两个删除路径中同步解除 handler、target、world、data 引用,再移除实例;地图清理的 visual/flash 节点也按 Loading 的同步删除边界直接释放。
|
||
|
||
修复前 `fly_reset_test.gd` 虽 PASS 但退出报告 5 个 ObjectDB 泄漏;修复后退出无 ObjectDB 泄漏。`test_exp_fly_parity.gd` 行为断言仍为 6/6 PASS,但其旧式单函数 fixture 仍报告 3 个 ObjectDB/不在 SceneTree 的路径警告,属于测试 harness 生命周期待清理,不将其伪装成完全干净证据。动作事件 FLY 的 owner/skill/包序、真实模型半径、远端不可见 Actor 和 EffectManager 全量生命周期仍保持 `PARTIAL`。
|
||
|
||
## Implementation fix round 2026-09-21T06:46Z
|
||
|
||
继续按 40250 `FlyingData::LoadScriptFile`、`FlyTrace` 和 `FlyingObjectManager` 的资源链修复飞行特效:`TailLength` 按参考保持秒单位,`TailSize` 只做 cm→m 转换;`AttachData` 现在会实例化 `AttachFile`,并维护 line/multi-line/sine/exp 四类尾迹历史和按时间衰减的轨迹几何。`BombEffect` 优先通过 `EffectRegistry` 资源实例化,只有资源不存在时才使用兼容性 flash,避免资源特效和通用球体重复绘制。
|
||
|
||
同时修复 `EffectRegistry` 对 `.msf` 内绝对资源路径的解析:存在的绝对路径不再被重复拼接到资源根目录。新增 `fly_attachment_effect_test.gd` 覆盖 AttachFile 实例、FlyTrace 历史、BombEffect、资源视觉去重和地图清理;`fly_data_msf_test.gd` 增加 `TailLength` 单位回归。资源特效链已进入正式运行路径,但精确相机朝向、所有远端 FLY/SHOOT owner-skill 组合、EffectManager 的每种资源生命周期和真实包序仍未完成,因此合同继续保持 `PARTIAL`。
|
||
|
||
## Implementation fix round 2026-09-21T06:54Z
|
||
|
||
按 40250 `CActorInstance::ProcessMotionEventFly` 补齐远端 Actor 的动作事件飞行链:`NetWorld` 现在从 `GC_FLY_TARGETING/GC_ADD_FLY_TARGETING` 保存的当前目标队列取目标,在远端 MSA 的 type 6 事件帧创建同一个 `.msf` 飞行实例,使用 Actor 动作位置/挂骨骼位置作为起点,并传递 owner VID 与 skill index;对象目标、坐标目标和目标队列消费均保持分支语义。`GC_CREATE_FLY` 的服务端索引飞行仍与动作事件路径分离。
|
||
|
||
新增 `remote_motion_fly_test.gd` 覆盖远端目标队列、资源实例、owner/skill 和单次消费,修复后的测试无 ObjectDB 泄漏。远端动作事件没有原生 `m_kCurMotNode.uSkill` 的完整网络字段时仍只能使用事件字段或当前动作参数回退,精确 skill 上下文、包序、不可见 Actor 和全量资源矩阵继续保持 `PARTIAL`。
|
||
|
||
## Implementation fix round 2026-09-21T06:59Z
|
||
|
||
按 40250 `CNormalBowAttack_FlyEventHandler_AutoClear::OnSetFlyTarget` 与 `CPythonNetworkStream::SendFlyTargetingPacket` 修正出站主目标链:新增 `M2Client.fly_targeting`、`ClassicSession::send_fly_targeting` 和 Godot 绑定,普通弓箭不再误发 `CG_ADD_FLY_TARGETING`;扇形/圆形技能的附加目标继续使用独立的 `add_fly_targeting`。ClassicSession 回归逐字节验证两种 header 和 sequence,战斗回归验证弓起手优先调用主目标 API。
|
||
|
||
该修复只闭合了主/附加目标包类型和局部 sequence 证据;不可见 shooter、VID 重用、真实 socket 中乱序/重连和完整 MSA→CG_SHOOT 时序仍保持 `PARTIAL`。
|
||
|
||
## Implementation fix round 2026-09-21T07:03Z
|
||
|
||
继续核对 `FlyingInstance::UpdateAttachInstance` 后修正尾迹几何:40250 的
|
||
`MULTI_LINE`、`SINE`、`EXP` 分支使用 `(-sin(roll) * offset, 0,
|
||
-cos(roll) * offset)`,当前端原先把局部 Z 号写反,导致资源飞行物的尾迹/AttachFile
|
||
偏到相反一侧;现已改为同号。`LINE` 的 effect 朝向按参考只使用基础飞行旋转,其他三种
|
||
偏移类型才叠加 `m_qAttachRotation`。新增直接检查 `MULTI_LINE` 局部 Z 偏移的回归断言。
|
||
|
||
`fly_attachment_effect_test`、`fly_data_msf_test`、`fly_test`、`fly_dynamic_collision_test`、
|
||
`fly_target_lifecycle_test`、`fly_reset_test` 均通过。`coneangle/rollangle` 初始旋转、
|
||
相机相关 FlyTrace 顶点生成、完整资源矩阵和远端原生 skill 上下文仍未闭合,合同保持 `PARTIAL`。
|
||
|
||
### Active GameLib flying-core review
|
||
|
||
- `GameLib/FlyingData.h` 定义 `.fly` 的初速、cone/roll、角速度、重力、加速度、homing、range、bomb effect、background/another-monster 命中、pierce、collision sphere 和 attach tail;`FlyingInstance.h` 保存速度/旋转/剩余射程、目标、已命中集合和 attach effect 生命周期。
|
||
- `FlyingObjectManager.h` 按 index/type 注册飞行资源,创建/更新/渲染/删除实例;`FlyTrace.cpp` 则用动态池记录位置时间 deque,按 tail length 衰减并生成相机相关的飞行尾迹。当前 `fly_object.gd` 已按索引读取 `.msf`,接入动态 Actor 碰撞/已命中集合、AttachFile/FlyTrace、BombEffect 资源清理和远端 MSA FLY 创建;精确相机朝向、模型半径标定、全部资源组合和远端原生 skill 上下文仍缺证据。
|
||
- 本轮完成 `FlyTarget`/`FlyingData`/`FlyingInstance`/`FlyingObjectManager`/`FlyTrace` 的活跃源码静态核对;测试通过只证明基础 Godot 弹道,不提升合同状态。
|
||
|
||
## 已确认差异和未验证项
|
||
|
||
1. 普通 GC 飞行物已从 40250 索引注册表加载 `.msf` 建立 `FlyData`,本地主角和远端 Actor 的动作事件 type 6 都进入同一实例入口;远端原生 `m_kCurMotNode.uSkill` 上下文、动作/网络包序仍未闭合。
|
||
2. `hitonanothermonster` 已接入动态 Actor 碰撞、按节点身份的 `HittedObjectSet` 去重、穿透后继续飞行和另一目标回调;真实客户端的 culling 范围、模型动态半径和背景/Actor 同帧竞争仍未证明一致。
|
||
3. 正式目标命中已经使用 `FlyTargetAnchor` 包围球中心,目标销毁也会转为最后坐标;`.fly` 的 bomb range/collision sphere 与真实模型资源组合仍没有逐类标定矩阵。
|
||
4. `_on_fly_targeting` 只把目标队列挂在可见 shooter 节点;40250 的 `CPythonCharacterManager` 实例表与当前 `NetWorld` 可见节点表不是同一生命周期,远端暂不可见、主角本地节点、VID 重用和迟到 `GC_CREATE_FLY` 尚未证明一致。
|
||
5. `bombeffect` 已优先走 `EffectRegistry`,AttachFile/FlyTrace 也已进入飞行实例生命周期;精确相机尾迹、颜色/材质、所有资源组合和 EffectManager 的逐资源回收仍未证明一致。
|
||
6. 已有测试覆盖 `.msf` 字段、索引类型、动态 Actor 双目标穿透/去重、目标删除、AttachFile/FlyTrace/BombEffect、主/附加目标 header+sequence 和地图清理;仍缺 Add/Set 乱序、真实服务端包序、完整资源矩阵和背景/Actor 同帧竞争。
|
||
|
||
## Audit round 2026-09-21T06:24Z
|
||
|
||
本轮沿 `FlyingObjectManager::CreateIndexedFly`、`FlyingInstance::Update`、`FlyTarget::NotifyTargetClear` 和 `CActorInstance::OnGetFlyTargetPosition` 做了源码级闭环核对,并验证了当前资源目录包含 40250 注册的 7 个 FIRE_CRACKER `.msf`、1 个 AUTO_FIRE `.msf` 以及普通索引 `.msf`。
|
||
|
||
- `playersettingmodule.py` 的 16 个索引资源路径已在当前 `INDEXED_FLY_FILES` 中出现,但类型元数据没有进入当前表;`NetWorld._on_fly` 所有索引都统一创建普通对象目标,未复刻 FIRE_CRACKER 的 `+200cm` 起点/随机位置目标和 AUTO_FIRE 的 `+100cm` 起点。
|
||
- 40250 每帧按 `max(move_distance * 2, collision_sphere_radius)` 扫描动态 Actor,并用 `HittedObjectSet` 去重;当前已按同一顺序实现 provider 查询、owner 排除、去重和 `at_another` 分支,但 provider 的可见性边界与真实模型半径仍是适配层差异。
|
||
- 40250 目标 Actor 销毁时立即 `ClearFlyTargeter()`,飞行物切换为最后目标坐标;当前 `_on_despawn` 先走渐隐/延迟释放,`FlyInstance` 仍持有旧 Node3D,目标删除、同 VID 重建和迟到 `GC_CREATE_FLY` 尚未达到同一时序。
|
||
- 40250 对象目标位置来自 `CActorInstance::OnGetFlyTargetPosition` 的包围球中心;当前 `FlyInstance.target_position()` 读取 Node3D 根位置,`fly_target_bounds_test` 的包围球 helper 尚未接入正式飞行命中链。
|
||
- 40250 的 `bombeffect`、attach/tail 和 FIRE_CRACKER/AUTO_FIRE 的资源表现由 `EffectManager`/`FlyTrace` 管理;当前只生成通用 SphereMesh/flash,资源路径虽能解析但尚未真正消费。
|
||
|
||
因此本轮没有提升合同状态;当前结论仍为 `PARTIAL`。资源消费、动态碰撞和目标生命周期已从“缺失”推进到“有运行证据的部分等价”,后续应优先补远端动作事件 FLY、包序/乱序、不可见 Actor 与完整资源生命周期矩阵。
|
||
|
||
## 下一轮验证入口
|
||
|
||
- 为动作事件 FLY 增加远端 Actor 的原生 skill 上下文和 `CG_FLY_TARGETING → CG_SHOOT → sequence` 真实状态机/包序测试。
|
||
- 增加背景与 Actor 同帧竞争、三 Actor/多种 collision sphere 的真实可见性与半径矩阵。
|
||
- 增加 `GC_FLY_TARGETING → GC_ADD_FLY_TARGETING → GC_CREATE_FLY` 乱序、不可见 shooter、目标删除/VID 重用和 map reset 测试。
|
||
- 对照每个 `INDEX_FLY_TYPE` 的 AttachFile、BombEffect、尾迹材质、颜色和回收时序,补齐资源矩阵后再决定是否提升合同状态。
|