refactor(ui): 重构装备和英雄的词条展示逻辑

1. 替换单个Label词条为RichText多行展示
2. 统一使用buildEquipRich和buildSkillDescRich生成带高亮的词条文本
3. 调整prefab的UI元素尺寸适配新的富文本展示
4. 新增showName参数适配不同场景的技能名显示需求
This commit is contained in:
pan
2026-07-31 17:12:47 +08:00
parent b4a42baee5
commit e026ee0e35
8 changed files with 1981 additions and 1616 deletions

View File

@@ -197,13 +197,16 @@ function buildEffectLine(head: string, skill: SkillConfig): ISkillLine {
*
* Why: FieldSkillConfig.info 是手写文案,改 value 易漂移。这里以 FieldSkillType
* 为 key 查标准动词,数值按 fmt比例/整数/减免)从 value 实时渲染。
*
* @param showName 是否在行中包含「技能名」片段(英雄面板需要,装备商店不需要)
*/
function buildFieldLine(head: string, uuid: number): ISkillLine | null {
function buildFieldLine(head: string, uuid: number, showName: boolean = true): ISkillLine | null {
const fs = FieldSkillSet[uuid];
if (!fs) return null;
const desc = FieldDescSet[fs.type];
const nameSeg = showName ? `${fs.name}` : "";
// 未入表类型回退基础备注 info整行不高亮
if (!desc) return { prefix: `${head}${fs.name}${fs.info}`, value: "", suffix: "" };
if (!desc) return { prefix: `${head}${nameSeg}${fs.info}`, value: "", suffix: "" };
// 数值按格式渲染为高亮片段
let valueText: string;
@@ -219,7 +222,7 @@ function buildFieldLine(head: string, uuid: number): ISkillLine | null {
valueText = `+${fs.value}`;
break;
}
return { prefix: `${head}${fs.name}${desc.verb}`, value: valueText, suffix: "" };
return { prefix: `${head}${nameSeg}${desc.verb}`, value: valueText, suffix: "" };
}
/**
@@ -291,7 +294,7 @@ function buildSkillLines(source: ISkillDescSource): ISkillLine[] {
if (fieldUuids?.length) {
const tpl = SkillTriggerName[SkillTriggerType.Field] ?? "光环";
for (const uuid of fieldUuids) {
const line = buildFieldLine(`${tpl}:`, uuid);
const line = buildFieldLine(`${tpl}:`, uuid, true);
if (line) lines.push(line);
}
}
@@ -362,15 +365,16 @@ export function buildSingleSkillRich(skillUuid: number, overrides?: SkillOverrid
}
/**
* 装备详情富文本IBox 弹窗用):展示装备包含的全部驻场光环词条
* 装备/驻场光环详情富文本:展示全部词条,数值绿色高亮
* @param fieldUuids FieldSkillSet 驻场光环 UUID 数组
* @param showName 是否包含「技能名」片段(英雄面板 true装备商店 false
* @returns 多行富文本串,每行一个词条
*/
export function buildEquipRich(fieldUuids: number[]): string {
export function buildEquipRich(fieldUuids: number[], showName: boolean = false): string {
if (!fieldUuids?.length) return "无词条";
const lines: string[] = [];
for (const uuid of fieldUuids) {
const line = buildFieldLine("", uuid);
const line = buildFieldLine("", uuid, showName);
if (!line) continue;
const prefix = line.prefix.replace(SKILL_NAME_PATTERN, `「<color=${RICH_NAME_COLOR}>$1</color>」`);
const text = line.value

View File

@@ -16,11 +16,12 @@
* - 英雄卡效果事件为 GameEvent.CallHero而非 UseSkillCard。
*/
import { mLogger } from "../common/Logger";
import { _decorator, Node, Sprite, Label, NodeEventType, Vec3, Tween, tween, UIOpacity, SpriteFrame, resources, AnimationClip } from "cc";
import { _decorator, Node, Sprite, Label, RichText, NodeEventType, Vec3, Tween, tween, UIOpacity, SpriteFrame, resources, AnimationClip } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { CardConfig, CardType } from "../common/config/CardSet";
import { HeroInfo } from "../common/config/heroSet";
import { buildSkillDescRich } from "../common/config/HeroSkillDesc";
import { oops } from "db://oops-framework/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { smc } from "../common/SingletonModuleComp";
@@ -66,6 +67,10 @@ export class CHeroComp extends CCComp {
@property(Label)
private fied3: Label = null;
/** 描述富文本(多行,数值绿色高亮、技能名蓝色,由 buildSkillDescRich 生成) */
@property(RichText)
private info_rich: RichText = null;
/** 等级标签 */
@property(Label)
private level_label: Label = null;
@@ -213,12 +218,9 @@ export class CHeroComp extends CCComp {
this.node.setScale(1, 1, 1);
if (this.name_label) this.name_label.string = "";
if (this.level_label) this.level_label.string = "";
const fieldLabels = [this.fied1, this.fied2, this.fied3];
for (const label of fieldLabels) {
if (label) {
label.string = "";
label.node.active = false;
}
if (this.info_rich) {
this.info_rich.string = "";
this.info_rich.node.active = false;
}
if (this.icon_node) {
const sprite = this.icon_node.getComponent(Sprite) || this.icon_node.getComponentInChildren(Sprite);
@@ -286,13 +288,11 @@ export class CHeroComp extends CCComp {
// 背景:按 card_lv 激活对应颜色子节点1→green 2→blue 3→purple 4→red 5→yellow
this.updateBgNode();
// 描述词条(最多显示 3 条,对应 fied1/fied2/fied3
const fieldLabels = [this.fied1, this.fied2, this.fied3];
const desc = hero?.info || this.cardData.info || "";
for (let i = 0; i < fieldLabels.length; i++) {
if (!fieldLabels[i]) continue;
fieldLabels[i].string = i === 0 ? desc : "";
fieldLabels[i].node.active = i === 0 && !!desc;
// 描述富文本(英雄触发技能,数值随等级配置高亮
if (this.info_rich) {
const desc = hero ? buildSkillDescRich(hero) : (this.cardData.info || "");
this.info_rich.string = desc;
this.info_rich.node.active = !!desc;
}
// 图标

View File

@@ -12,12 +12,12 @@
* EquipBoxComp 按 Field 类型被动驻场,属性加成由 FieldSkillHelper 全局聚合。
*/
import { mLogger } from "../common/Logger";
import { _decorator, Node, Label, NodeEventType, Vec3, UIOpacity, tween, Tween } from "cc";
import { _decorator, Node, Label, RichText, NodeEventType, Vec3, UIOpacity, tween, Tween } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { CardConfig } from "../common/config/CardSet";
import { EquipPoolList } from "../common/config/EquipSet";
import { FieldSkillSet } from "../common/config/SkillSet";
import { buildEquipRich } from "../common/config/HeroSkillDesc";
import { oops } from "db://oops-framework/core/Oops";
import { getCardIconId, setSpriteFrame } from "../common/CardIconHelper";
import { GameEvent } from "../common/config/GameEvent";
@@ -50,15 +50,9 @@ export class EquipListComp extends CCComp {
@property(Label)
private name_label: Label = null;
/** 属性词条 1 */
@property(Label)
private fied1: Label = null;
/** 属性词条 2 */
@property(Label)
private fied2: Label = null;
/** 属性词条 3 */
@property(Label)
private fied3: Label = null;
/** 属性词条富文本(多行,数值绿色高亮,由 buildEquipRich 按 FieldDescSet 实时渲染) */
@property(RichText)
private info_rich: RichText = null;
/** 等级标签 */
@property(Label)
@@ -161,19 +155,11 @@ export class EquipListComp extends CCComp {
// 背景:按 card_lv 激活对应颜色子节点1→green 2→blue 3→purple 4→red 5→yellow
this.updateBgNode();
// 属性词条(最多显示 3 条,对应 fied1/fied2/fied3
const fieldLabels = [this.fied1, this.fied2, this.fied3];
const fields = this.cardData.field || [];
for (let i = 0; i < fieldLabels.length; i++) {
if (!fieldLabels[i]) continue;
if (i < fields.length) {
const fieldConfig = FieldSkillSet[fields[i]];
fieldLabels[i].string = fieldConfig?.info || "";
fieldLabels[i].node.active = true;
} else {
fieldLabels[i].string = "";
fieldLabels[i].node.active = false;
}
// 属性词条富文本(多词条装备由 buildEquipRich 按 \n 多行渲染,数值实时高亮
if (this.info_rich) {
const desc = buildEquipRich(this.cardData.field || []);
this.info_rich.string = desc;
this.info_rich.node.active = !!desc;
}
// 图标共享工具解析cardData.icon → FieldSkillSet → SkillSet