koishi-plugin-dew-bot 1.0.261 → 1.0.262
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +84 -45
- package/lib/plugin/characterCardAssets.d.ts +3 -1
- package/lib/plugin/characterCardStyles.d.ts +1 -1
- package/lib/shared/bot/inlineCommands.d.ts +11 -0
- package/lib/shared/face/index.d.ts +3 -1
- package/package.json +1 -1
- package/src/plugin/bloodlineCardTemplate.ts +2 -4
- package/src/plugin/cardLayout.ts +1 -1
- package/src/plugin/characterCardAssets.ts +9 -1
- package/src/plugin/characterCardStyles.ts +6 -4
- package/src/plugin/characterCardTemplate.ts +9 -8
- package/src/plugin/serverHandel/qqCommandMessage.ts +6 -2
- package/src/plugin/serverHandel/qqPageMessage.ts +2 -19
- package/src/shared/bot/analysisMsg.ts +4 -1
- package/src/shared/bot/inlineCommands.ts +39 -0
- package/src/shared/bot/serviceProto.ts +9 -1
- package/src/shared/face/index.ts +3 -1
package/lib/index.js
CHANGED
|
@@ -67,7 +67,7 @@ var serviceProto;
|
|
|
67
67
|
var init_serviceProto = __esm({
|
|
68
68
|
"src/shared/bot/serviceProto.ts"() {
|
|
69
69
|
serviceProto = {
|
|
70
|
-
"version":
|
|
70
|
+
"version": 38,
|
|
71
71
|
"services": [
|
|
72
72
|
{
|
|
73
73
|
"id": 0,
|
|
@@ -751,6 +751,14 @@ var init_serviceProto = __esm({
|
|
|
751
751
|
}
|
|
752
752
|
},
|
|
753
753
|
"optional": true
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
"id": 14,
|
|
757
|
+
"name": "explorationRank",
|
|
758
|
+
"type": {
|
|
759
|
+
"type": "String"
|
|
760
|
+
},
|
|
761
|
+
"optional": true
|
|
754
762
|
}
|
|
755
763
|
]
|
|
756
764
|
},
|
|
@@ -2660,15 +2668,17 @@ var characterCardStyles = `
|
|
|
2660
2668
|
.character-sheet .companion-portrait{padding:10px;border-radius:18px;flex:0 0 auto;background:linear-gradient(135deg,#fffefa 2%,var(--edge) 18%,#ffffff 30%,var(--accent) 41%,#fffdf2 51%,var(--edge) 71%,#ffffff 82%,var(--metal-shadow) 100%);box-shadow:inset 0 0 0 1px #ffffffd9,0 3px 9px #51628038}
|
|
2661
2669
|
.character-sheet .companion-portrait:before{inset:5px;border-radius:12px;border-color:#fffdf1cf;box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 43%,transparent)}.character-sheet .companion-portrait:after{inset:2px;border-radius:15px;border-color:#fffefa9c}.character-sheet .companion-portrait .panel-corner{width:var(--portrait-ornament-size);height:var(--portrait-ornament-size)}
|
|
2662
2670
|
.character-sheet .portrait-window{height:auto;border:2px solid var(--edge);border-radius:6px;overflow:hidden;background:var(--paper)}.character-artwork{display:block;width:100%;height:auto;object-fit:contain}.character-sheet .portrait-placeholder,.character-sheet .placeholder{height:100%;width:100%;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;color:var(--subtle);font:21px/1.5 "Microsoft YaHei",sans-serif}.character-sheet .placeholder small{font-size:16px}.character-sheet .portrait-window>.placeholder{height:448px}
|
|
2663
|
-
.character-stats{padding:17px 18px 15px;display:flex;flex-direction:column}.character-stats>.character-identity,.character-stats>.
|
|
2671
|
+
.character-stats{padding:17px 18px 15px;display:flex;flex-direction:column}.character-stats>.character-identity,.character-stats>.resource,.character-stats>.attribute-panel{position:relative;z-index:4}
|
|
2664
2672
|
.character-identity{text-align:center;min-width:0}.title-image-slot{position:absolute;inset:12px;display:flex;align-items:center;justify-content:center;min-width:0;z-index:4;pointer-events:none}.title-artwork{display:block;width:auto;height:auto;max-width:100%;max-height:min(110px,100%);object-fit:contain;filter:drop-shadow(0 2px 3px #17213a70)}.title-artwork[alt="称号图片占位"]{max-width:min(244px,100%);max-height:min(44px,100%)}
|
|
2665
2673
|
.character-name{font-size:43px;line-height:1.17;font-weight:700;letter-spacing:3px;margin:0 0 3px;overflow-wrap:anywhere;color:var(--ink);text-shadow:0 1px 0 #ffffff}.character-level{font:27px/1.25 Georgia,"Microsoft YaHei",serif;margin:0;color:var(--subtle);display:flex;align-items:baseline;justify-content:center;gap:7px;min-width:0}.character-level strong{font-size:28px;font-weight:500;overflow-wrap:anywhere;min-width:0}
|
|
2666
2674
|
.gene-panel{position:relative;margin:8px auto 0;padding:4px 12px 4px 7px;display:flex;align-items:center;justify-content:center;gap:6px;width:fit-content;max-width:100%;border:1px solid color-mix(in srgb,var(--edge) 80%,#ffffff);border-radius:7px;background:linear-gradient(#ffffffd6,color-mix(in srgb,var(--paper) 75%,#ffffff));box-shadow:inset 0 0 0 2px #ffffffaa,0 1px 2px #54628210}
|
|
2667
2675
|
.gene-panel:before,.gene-panel:after{content:"";position:absolute;top:50%;width:6px;height:6px;background:var(--light-edge);border:1px solid var(--edge);transform:translateY(-50%) rotate(45deg)}.gene-panel:before{left:-4px}.gene-panel:after{right:-4px}.gene-crest{flex:0 0 26px;height:29px;color:var(--accent)}.gene-crest svg{display:block;width:100%;height:100%}.gene-rank{font-size:18px;line-height:1.35;letter-spacing:1px;overflow-wrap:anywhere;font-weight:700;text-align:center;min-width:0;color:var(--ink)}
|
|
2668
|
-
.
|
|
2676
|
+
.exploration-rank-row{display:flex;align-items:center;justify-content:center;gap:7px;margin:10px 0 0;font:16px/1.4 "KaiTi","STKaiti","Microsoft YaHei",sans-serif;letter-spacing:1px;color:var(--subtle)}.exploration-rank-row>svg{width:17px;height:17px;flex-shrink:0;fill:none;stroke:var(--accent);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}.exploration-rank-row>span{white-space:nowrap}.exploration-rank-row strong{font-size:18px;font-weight:700;color:var(--ink);overflow-wrap:anywhere;min-width:0}
|
|
2677
|
+
.combat-row{display:flex;align-items:center;justify-content:center;gap:8px;margin:12px 0 0;padding:0 6px;min-width:0;font:28px/1.2 "KaiTi","STKaiti","Microsoft YaHei",sans-serif;position:relative;z-index:4}.power-icon{flex:0 0 34px;height:34px;display:grid;place-items:center;color:var(--accent)}.power-icon svg{display:block;width:34px;height:34px;overflow:visible}.power-label{font:inherit;white-space:nowrap}.power-value{min-width:0;flex:0 1 auto;text-align:center;overflow-wrap:anywhere;font:inherit;color:var(--accent);letter-spacing:0}
|
|
2669
2678
|
.companion-resource{font-family:"Microsoft YaHei",sans-serif;margin-bottom:12px}.resource-heading{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-size:17px;color:var(--subtle);line-height:1.35}.resource-label{display:flex;align-items:center;gap:6px;font-weight:600;flex-shrink:0}.resource-label svg{width:18px;height:18px;fill:var(--health)}.resource-number{text-align:right;overflow-wrap:anywhere;min-width:0;font-size:15px}
|
|
2670
|
-
.resource-track{height:18px;position:relative;margin-top:5px;border:1px solid var(--track-edge);border-radius:10px;overflow:hidden;background:linear-gradient(var(--track),#f2f5ed);box-shadow:inset 0 1px 2px #6e805825}.resource-fill{display:block;position:absolute;top:0;bottom:0;left:0;border-radius:9px;background:linear-gradient(var(--health-light),var(--health) 55%,color-mix(in srgb,var(--health) 80%,var(--health-light)));border-right:1px solid #fff9}.resource-percent{position:absolute;inset:0;display:grid;place-items:center;font:11px/1 "Microsoft YaHei",sans-serif;color:#fffef7;text-shadow:0 1px 2px #435443}.exp-resource
|
|
2671
|
-
.
|
|
2679
|
+
.resource-track{height:18px;position:relative;margin-top:5px;border:1px solid var(--track-edge);border-radius:10px;overflow:hidden;background:linear-gradient(var(--track),#f2f5ed);box-shadow:inset 0 1px 2px #6e805825}.resource-fill{display:block;position:absolute;top:0;bottom:0;left:0;border-radius:9px;background:linear-gradient(var(--health-light),var(--health) 55%,color-mix(in srgb,var(--health) 80%,var(--health-light)));border-right:1px solid #fff9}.resource-percent{position:absolute;inset:0;display:grid;place-items:center;font:11px/1 "Microsoft YaHei",sans-serif;color:#fffef7;text-shadow:0 1px 2px #435443}.exp-resource{width:calc(100% - 20px);align-self:center;margin:0 0 14px}.exp-resource .resource-track{height:6px;margin-top:0;border-color:#d5c48b;border-radius:4px;background:#eee9d7;box-shadow:inset 0 1px 1px #9d82351a}.exp-resource .resource-fill{border-radius:3px;border-right:0;background:linear-gradient(#fff0a0,#e8bd48 60%,#d6a934)}
|
|
2680
|
+
.hp-resource{display:flex;align-items:center;margin-top:16px;margin-bottom:0}.hp-resource .resource-track{flex:1;min-width:0;height:20px;margin-top:0}.hp-bar-value{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:0 8px;white-space:nowrap;font:12px/1 "Microsoft YaHei",sans-serif;color:#fffef7;text-shadow:0 1px 2px #435443,0 0 2px #435443}
|
|
2681
|
+
.companion-attributes{margin-top:5px;min-width:0;flex:1;display:flex;flex-direction:column;justify-content:center}.attribute-divider{height:28px;margin:0 0 3px;display:flex;align-items:center;justify-content:center}.attribute-divider svg{display:block;width:100%;height:36px}.companion-radar{width:100%;height:260px;display:block;overflow:visible}
|
|
2672
2682
|
.radar-grid{fill:none;stroke:var(--radar-grid);stroke-width:1.1}.radar-axis{stroke:var(--radar-grid);stroke-width:1;opacity:.8}.radar-area{fill:var(--radar-fill);stroke:var(--radar);stroke-width:2.3;stroke-linejoin:round}.radar-dot{fill:#fffefa;stroke:var(--radar);stroke-width:2}.radar-label{font:19px "KaiTi","STKaiti","Microsoft YaHei",sans-serif;fill:var(--ink)}.radar-value{font:20px Georgia,"Microsoft YaHei",serif;fill:var(--ink)}.radar-scale{font:11px Georgia,serif;fill:var(--subtle)}.empty-attributes{padding:45px 10px;color:var(--subtle);font:18px/1.6 "Microsoft YaHei",sans-serif;text-align:center}.custom-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:5px 10px;margin:6px 0 0;font:15px/1.5 "Microsoft YaHei",sans-serif;color:var(--subtle)}.custom-attributes span{overflow-wrap:anywhere}.custom-attributes b{font-weight:500;color:var(--ink)}
|
|
2673
2683
|
`;
|
|
2674
2684
|
|
|
@@ -2721,6 +2731,12 @@ function characterGeneCrest(tier) {
|
|
|
2721
2731
|
return `<svg viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="m30 4 20 10v20L30 55 10 34V14Z" fill="var(--paper)" stroke="currentColor" stroke-width="1.6"/><path d="m30 9 15 8v16L30 49 15 33V17Z" fill="none" stroke="var(--light-edge)" stroke-width="1"/><path d="M23 27v-6a7 7 0 0 1 14 0v6" fill="none" stroke="currentColor" stroke-width="2.5"/><rect x="20" y="26" width="20" height="15" rx="3" fill="currentColor"/><circle cx="30" cy="32" r="2" fill="var(--light-edge)"/><path d="M30 33v4" stroke="var(--light-edge)" stroke-width="1.8"/>${tier >= 3 ? '<path d="m30 2 3 4-3 4-3-4Z" fill="var(--gem)" stroke="var(--light-edge)"/>' : ""}${tier >= 5 ? '<path d="m18 12 1-7 6 4 5-7 5 7 6-4 1 7Z" fill="var(--accent)" stroke="var(--light-edge)" stroke-width=".7"/>' : ""}</svg>`;
|
|
2722
2732
|
}
|
|
2723
2733
|
__name(characterGeneCrest, "characterGeneCrest");
|
|
2734
|
+
var characterAttributeDivider = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 310 36">
|
|
2735
|
+
${ornamentPaint}
|
|
2736
|
+
<g fill="none" stroke="var(--edge)" stroke-width=".8"><path d="M5 18h91m118 0h91"/><path d="M75 18c18 0 29-8 47-8m66 0c18 0 29 8 47 8"/><path d="M102 18c12 0 21 6 31 6m44 0c10 0 19-6 31-6"/></g>
|
|
2737
|
+
<g fill="url(#character-leaf)" stroke="var(--light-edge)" stroke-width=".6"><path d="M120 11c-10-1-14-6-16-10 10 0 17 3 16 10Zm14 12c-10 2-18-1-22-6 10-2 18-1 22 6Zm56-12c10-1 14-6 16-10-10 0-17 3-16 10Zm-14 12c10 2 18-1 22-6-10-2-18-1-22 6Z"/></g>
|
|
2738
|
+
${flower(155, 18, 0.5)}<g fill="var(--accent)"><path d="m94 18 3-3 3 3-3 3Zm116 0 3-3 3 3-3 3Z"/></g>
|
|
2739
|
+
</svg>`;
|
|
2724
2740
|
|
|
2725
2741
|
// src/plugin/characterCardTemplate.ts
|
|
2726
2742
|
var finite = /* @__PURE__ */ __name((value) => Number.isFinite(value) ? value : 0, "finite");
|
|
@@ -2735,7 +2751,6 @@ var primaryAttributes = [
|
|
|
2735
2751
|
["resistance", "抗性"]
|
|
2736
2752
|
];
|
|
2737
2753
|
var primaryIds = new Set(primaryAttributes.map(([id]) => id));
|
|
2738
|
-
var heading = /* @__PURE__ */ __name((label) => `<h2 class="ornament-heading"><span class="heading-star" aria-hidden="true">✦</span>${cardEscape(label)}<span class="heading-star" aria-hidden="true">✦</span></h2>`, "heading");
|
|
2739
2754
|
var corners = /* @__PURE__ */ __name((tier, positions = ["tl", "tr", "bl", "br"]) => positions.map((position) => `<span class="panel-corner corner-${position}" data-decoration-level="${tier}">${characterTierOrnament(tier)}</span>`).join(""), "corners");
|
|
2740
2755
|
function radar(attributes) {
|
|
2741
2756
|
if (!attributes.length) return '<p class="empty-attributes">暂无一级属性</p>';
|
|
@@ -2781,14 +2796,16 @@ function characterCardHtml(card, artwork, _frame, defaultArtwork, titleArtwork,
|
|
|
2781
2796
|
const hpPercent = ratio(card.hp, card.maxHp) * 100;
|
|
2782
2797
|
const experience = Math.max(0, Math.min(100, finite(card.experiencePercent)));
|
|
2783
2798
|
const geneRank = card.geneLockRankName || "基因锁未开启";
|
|
2799
|
+
const explorationRank = card.explorationRank?.trim();
|
|
2784
2800
|
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><style>${characterCardStyles}</style></head><body><main id="capture" class="companion-sheet character-adventure character-sheet gene-tier-${tier}" data-gene-lock-tier="${tier}" data-decoration-level="${tier}"><span class="character-ambient" aria-hidden="true">${characterFloralWatermark}</span><div class="character-card companion-main">
|
|
2785
2801
|
<div class="portrait-column"><div class="companion-panel companion-portrait character-portrait">${corners(tier)}<div class="portrait-window portrait">${portrait ? `<img id="character-image" class="character-artwork" src="${cardEscape(portrait)}" data-fallback="${cardEscape(defaultArtwork ?? "")}" alt="${cardEscape(card.name)}的形象图">` : '<div class="placeholder"><span>形象尚未生成</span><small>角色形象</small></div>'}</div>
|
|
2786
|
-
|
|
2787
|
-
<
|
|
2788
|
-
|
|
2789
|
-
<
|
|
2790
|
-
<div class="resource companion-resource
|
|
2791
|
-
<
|
|
2802
|
+
${titleArtwork || card.titleImageUrl ? `<div class="title-image-slot character-title-centered"><img id="title-image" class="title-artwork" src="${cardEscape(titleArtwork || characterTitlePlaceholder)}" data-fallback="${cardEscape(characterTitlePlaceholder)}" alt="${titleArtwork ? "称号图片" : "称号图片占位"}"></div>` : ""}</div>
|
|
2803
|
+
<div class="combat-row companion-power-row"><span class="power-emblem power-icon" aria-hidden="true"><svg class="crossed-weapons" viewBox="0 0 42 42"><g fill="currentColor" stroke="var(--panel)" stroke-width=".9" stroke-linejoin="round"><g transform="rotate(-45 21 21)"><path d="M21 2 26 9v14l-5 4-5-4V9Z"/><path d="M12 26h18l-1 4H13Zm7 4h4v8h-4Zm-1 8h6v3h-6Z"/><path d="M21 7v15" fill="none" stroke="var(--light-edge)" stroke-width="1.1"/></g><g transform="rotate(45 21 21)"><path d="M21 2 26 9v14l-5 4-5-4V9Z"/><path d="M12 26h18l-1 4H13Zm7 4h4v8h-4Zm-1 8h6v3h-6Z"/><path d="M21 7v15" fill="none" stroke="var(--light-edge)" stroke-width="1.1"/></g></g></svg></span><span class="power-label companion-power-label">战力</span><strong id="combat-power" class="power-value companion-power">${number2(card.power)}</strong></div>
|
|
2804
|
+
</div>
|
|
2805
|
+
<section class="companion-panel companion-stats character-stats" aria-label="角色属性"><span class="character-paper-pattern" aria-hidden="true">${characterFloralWatermark}</span>${corners(tier, ["tr", "br"])}<div class="identity character-identity"><h1 id="character-name" class="character-name" title="${cardEscape(card.name)}">${cardEscape(card.name)}</h1><p class="level character-level"><span>Lv.</span><strong id="character-level">${number2(card.level)}</strong></p><div class="gene-panel"><span class="gene-crest" aria-hidden="true">${characterGeneCrest(tier)}</span><div id="gene-rank" class="gene-rank" title="${cardEscape(geneRank)}">${cardEscape(geneRank)}</div></div><p class="exploration-rank-row"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M19.8 7.7A8 8 0 1 0 20 16M20 3v5h-5M15.8 12a3.8 3.8 0 1 1-3.8-3.8"/></svg><span>轮回等级</span> <strong id="exploration-rank">${cardEscape(explorationRank ? explorationRank + "级" : "—")}</strong></p></div>
|
|
2806
|
+
<div class="resource companion-resource hp-resource"><div class="resource-track" role="progressbar" aria-label="生命值" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${hpPercent}" aria-valuetext="${number2(card.hp)} / ${number2(card.maxHp)}"><span class="resource-fill fill" style="width:${hpPercent}%"></span><span id="hp-numbers" class="hp-bar-value">${number2(card.hp)} / ${number2(card.maxHp)}</span></div></div>
|
|
2807
|
+
<div class="resource companion-resource exp-resource"><div id="experience-track" class="resource-track" role="progressbar" aria-label="经验进度" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${experience}"><span class="resource-fill" style="width:${experience}%"></span></div></div>
|
|
2808
|
+
<section class="attribute-panel companion-attributes" aria-label="一级属性"><div class="attribute-divider" aria-hidden="true">${characterAttributeDivider}</div>${radar(card.attributes)}</section></section>
|
|
2792
2809
|
</div></main></body></html>`;
|
|
2793
2810
|
}
|
|
2794
2811
|
__name(characterCardHtml, "characterCardHtml");
|
|
@@ -2854,7 +2871,7 @@ var primaryAttributes2 = [
|
|
|
2854
2871
|
];
|
|
2855
2872
|
var primaryIds2 = new Set(primaryAttributes2.map(([id]) => id));
|
|
2856
2873
|
var corners2 = /* @__PURE__ */ __name((positions = ["tl", "tr", "bl", "br"]) => positions.map((position) => `<span class="panel-corner corner-${position}">${companionCornerDecoration}</span>`).join(""), "corners");
|
|
2857
|
-
var
|
|
2874
|
+
var heading = /* @__PURE__ */ __name((title) => `<h2 class="ornament-heading"><span class="heading-star" aria-hidden="true">✦</span>${cardEscape(title)}<span class="heading-star" aria-hidden="true">✦</span></h2>`, "heading");
|
|
2858
2875
|
var paw = '<svg viewBox="0 0 28 28" aria-hidden="true"><ellipse cx="5" cy="10" rx="3" ry="4"/><ellipse cx="11" cy="5" rx="3" ry="4"/><ellipse cx="18" cy="5" rx="3" ry="4"/><ellipse cx="24" cy="10" rx="3" ry="4"/><path d="M5 21c0-5 4-4 6-9 1-3 5-3 6 0 2 5 6 4 6 9 0 5-6 4-9 2-3 2-9 3-9-2Z"/></svg>';
|
|
2859
2876
|
var crest = '<svg viewBox="0 0 32 32" aria-hidden="true" fill="currentColor"><path d="M15 28C5 24 3 16 4 7c8 0 11 9 11 21ZM17 28c10-4 12-12 11-21-8 0-11 9-11 21ZM16 18C9 13 10 7 16 2c6 5 7 11 0 16Z"/></svg>';
|
|
2860
2877
|
var sword = '<svg viewBox="0 0 42 42" aria-hidden="true"><path d="m9 5 5 1 16 21-4 4L9 11Zm24 0-5 1L12 27l4 4L33 11ZM14 27l14 10m0-10L14 37M9 35l4-4m20 4-4-4"/></svg>';
|
|
@@ -2898,13 +2915,13 @@ function radar2(card) {
|
|
|
2898
2915
|
}
|
|
2899
2916
|
__name(radar2, "radar");
|
|
2900
2917
|
function bloodlines(card, icons) {
|
|
2901
|
-
return `<section class="companion-panel bloodline-panel" aria-label="血统">${
|
|
2918
|
+
return `<section class="companion-panel bloodline-panel" aria-label="血统">${heading("血统")}${card.bloodlines.length ? `<div class="bloodline-list">${card.bloodlines.map((bloodline, index) => `<div class="bloodline-row"><span class="bloodline-crest${icons?.bloodlines?.[index] ? " has-entry-artwork" : ""}" aria-hidden="true">${bloodline.emoji ? cardEscape(bloodline.emoji) : crest}${icons?.bloodlines?.[index] ? `<img class="bloodline-entry-artwork" data-entry-index="${index}" src="${cardEscape(icons.bloodlines[index])}" alt="">` : ""}</span><span class="bloodline-name">${cardEscape(bloodline.name)}</span><span class="bloodline-quality">${cardEscape(bloodline.quality)}</span></div>`).join("")}</div>` : '<p class="empty-list">暂无血统</p>'}</section>`;
|
|
2902
2919
|
}
|
|
2903
2920
|
__name(bloodlines, "bloodlines");
|
|
2904
2921
|
function skills(card, icons) {
|
|
2905
2922
|
const active = '<path d="m8 24 16-16 2-3 4 4-3 2-16 16M7 21l9 9M7 31l5-5M5 33l2-2"/>';
|
|
2906
2923
|
const passive = '<path d="M17 30V14M17 24C7 22 4 14 5 8c9 1 13 7 12 16ZM17 19c1-9 5-14 13-15 0 8-4 14-13 15Z"/>';
|
|
2907
|
-
return `<section class="companion-panel companion-skills" aria-label="技能">${corners2()}${
|
|
2924
|
+
return `<section class="companion-panel companion-skills" aria-label="技能">${corners2()}${heading("技能")}${card.skills.length ? `<div class="skill-grid">${card.skills.map((skill, index) => `<div class="companion-skill" data-skill-id="${cardEscape(skill.id)}"><span class="skill-icon" aria-hidden="true"><svg viewBox="0 0 36 36">${skill.type === "passive" ? passive : active}</svg>${icons?.skills?.[index] ? `<img class="skill-entry-artwork" data-entry-index="${index}" src="${cardEscape(icons.skills[index])}" alt="">` : ""}</span><span class="skill-name">${cardEscape(skill.name)}</span><span class="skill-level">Lv.${number3(skill.rank)}</span></div>`).join("")}</div>` : '<p class="empty-list">暂无技能</p>'}</section>`;
|
|
2908
2925
|
}
|
|
2909
2926
|
__name(skills, "skills");
|
|
2910
2927
|
function companionCardHtml(card, artwork, icons) {
|
|
@@ -2920,7 +2937,7 @@ function companionCardHtml(card, artwork, icons) {
|
|
|
2920
2937
|
<div class="companion-power-row"><span class="power-icon" aria-hidden="true">${sword}</span><span class="companion-power-label">战力</span><strong id="companion-power" class="companion-power">${number3(card.power)}</strong></div>
|
|
2921
2938
|
<div class="companion-resource hp-resource"><div class="resource-heading"><span class="resource-label"><svg viewBox="0 0 32 32" aria-hidden="true"><path d="M16 28C6 21 2 17 2 10a7 7 0 0 1 14-2 7 7 0 0 1 14 2c0 7-4 11-14 18Z"/></svg>生命值</span><span id="companion-hp" class="resource-number">${number3(card.hp)} / ${number3(card.maxHp)}</span></div><div class="resource-track" role="progressbar" aria-label="生命值" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${healthPercent}"><span class="resource-fill" style="width:${healthPercent}%"></span><span class="resource-percent">${number3(healthPercent)}%</span></div></div>
|
|
2922
2939
|
${pet ? `<div class="companion-resource exp-resource"><div class="resource-heading"><span class="resource-label"><svg viewBox="0 0 32 32" aria-hidden="true"><path d="m16 2 4.5 9.1 10 1.4-7.3 7.1 1.7 10-8.9-4.7-8.9 4.7 1.7-10-7.3-7.1 10-1.4Z"/></svg>经验进度</span><span class="resource-number">${number3(experience)}%</span></div><div class="resource-track" role="progressbar" aria-label="经验进度" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${experience}"><span class="resource-fill" style="width:${experience}%"></span><span class="resource-percent">${number3(experience)}%</span></div></div>` : ""}
|
|
2923
|
-
<section class="companion-attributes" aria-label="一级属性">${
|
|
2940
|
+
<section class="companion-attributes" aria-label="一级属性">${heading("一级属性")}${radar2(card)}</section></section>
|
|
2924
2941
|
</div>${skills(card, icons)}</main></body></html>`;
|
|
2925
2942
|
}
|
|
2926
2943
|
__name(companionCardHtml, "companionCardHtml");
|
|
@@ -3419,15 +3436,13 @@ function radar4(card) {
|
|
|
3419
3436
|
const attribute = card.attributes.find((value) => value.id === id);
|
|
3420
3437
|
return { name: attribute?.name?.trim() || name2, value: finite4(attribute?.value ?? 0) };
|
|
3421
3438
|
});
|
|
3422
|
-
const
|
|
3423
|
-
const magnitude = 10 ** Math.floor(Math.log10(max));
|
|
3424
|
-
const ceiling = Math.ceil(max / magnitude) * magnitude;
|
|
3439
|
+
const ceiling = Math.max(0, ...attributes.map((attribute) => attribute.value));
|
|
3425
3440
|
const point = /* @__PURE__ */ __name((index, radius) => {
|
|
3426
3441
|
const angle = -Math.PI / 2 + index * Math.PI / 3;
|
|
3427
3442
|
return [320 + Math.cos(angle) * radius, 190 + Math.sin(angle) * radius];
|
|
3428
3443
|
}, "point");
|
|
3429
3444
|
const polygon = /* @__PURE__ */ __name((radius) => attributes.map((_, index) => point(index, radius).join(",")).join(" "), "polygon");
|
|
3430
|
-
const data = attributes.map((attribute, index) => point(index, 122 *
|
|
3445
|
+
const data = attributes.map((attribute, index) => point(index, 122 * (ceiling > 0 ? Math.max(0, attribute.value / ceiling) : 0)));
|
|
3431
3446
|
return `<div class="radar-panel"><svg class="bloodline-radar" viewBox="0 0 640 396" role="img" aria-label="血统六维属性加成雷达图" xmlns="http://www.w3.org/2000/svg">
|
|
3432
3447
|
<defs><linearGradient id="bloodline-radar-fill" x1="0" y1="0" x2="1" y2="1"><stop stop-color="var(--quality-accent)" stop-opacity=".35"/><stop offset="1" stop-color="var(--quality-accent)" stop-opacity=".12"/></linearGradient></defs>
|
|
3433
3448
|
${[0.2, 0.4, 0.6, 0.8, 1].map((scale) => `<polygon points="${polygon(122 * scale)}" fill="none" stroke="#b9bdad" stroke-width="1.2"/>`).join("")}
|
|
@@ -4080,6 +4095,42 @@ function renderQQRewardMarkdown(data, showGreeting) {
|
|
|
4080
4095
|
}
|
|
4081
4096
|
__name(renderQQRewardMarkdown, "renderQQRewardMarkdown");
|
|
4082
4097
|
|
|
4098
|
+
// src/shared/bot/inlineCommands.ts
|
|
4099
|
+
function inlineCommandSpans(content) {
|
|
4100
|
+
const spans = [];
|
|
4101
|
+
let depth = 0, start = 0, labelStart = 0;
|
|
4102
|
+
for (let index = 0; index < content.length; index++) {
|
|
4103
|
+
if (content[index] === "[") {
|
|
4104
|
+
if (depth === 0) {
|
|
4105
|
+
start = index > 0 && content[index - 1] === "\\" ? index - 1 : index;
|
|
4106
|
+
labelStart = index + 1;
|
|
4107
|
+
}
|
|
4108
|
+
depth++;
|
|
4109
|
+
} else if (content[index] === "]" && depth > 0 && --depth === 0) {
|
|
4110
|
+
const label = content.slice(labelStart, index).replace(/\\$/, "");
|
|
4111
|
+
if (!label.trim() || /[\[\]\r\n]/.test(label) || /^\d+$/.test(label.trim())) continue;
|
|
4112
|
+
const alias = /^\(command:([^()[\]\r\n]+)\)/.exec(content.slice(index + 1));
|
|
4113
|
+
const command = alias ? alias[1].trim() : label.split(/[++]/, 1)[0].trim().replace(/^🔄\s*/u, "");
|
|
4114
|
+
if (!command) continue;
|
|
4115
|
+
const end = index + 1 + (alias?.[0].length ?? 0);
|
|
4116
|
+
spans.push({ start, end, label, command, ...alias ? { aliased: true } : {} });
|
|
4117
|
+
if (alias) index = end - 1;
|
|
4118
|
+
}
|
|
4119
|
+
}
|
|
4120
|
+
return spans;
|
|
4121
|
+
}
|
|
4122
|
+
__name(inlineCommandSpans, "inlineCommandSpans");
|
|
4123
|
+
function renderPlainInlineCommandAliases(content) {
|
|
4124
|
+
let result = "", offset = 0;
|
|
4125
|
+
for (const span of inlineCommandSpans(content)) {
|
|
4126
|
+
if (!span.aliased) continue;
|
|
4127
|
+
result += content.slice(offset, span.start) + (span.label.trim() === span.command ? `[${span.command}]` : `${span.label}[${span.command}]`);
|
|
4128
|
+
offset = span.end;
|
|
4129
|
+
}
|
|
4130
|
+
return result + content.slice(offset);
|
|
4131
|
+
}
|
|
4132
|
+
__name(renderPlainInlineCommandAliases, "renderPlainInlineCommandAliases");
|
|
4133
|
+
|
|
4083
4134
|
// src/plugin/serverHandel/qqPageMessage.ts
|
|
4084
4135
|
function compactListLabel(value) {
|
|
4085
4136
|
const label = compactDisplayText(value);
|
|
@@ -4099,36 +4150,21 @@ function inlineCommandUrl(command) {
|
|
|
4099
4150
|
return `mqqapi://aio/inlinecmd?command=${encoded}&enter=true&reply=false`;
|
|
4100
4151
|
}
|
|
4101
4152
|
__name(inlineCommandUrl, "inlineCommandUrl");
|
|
4102
|
-
function
|
|
4103
|
-
const spans =
|
|
4104
|
-
let depth = 0, start = 0, labelStart = 0;
|
|
4105
|
-
for (let index = 0; index < content.length; index++) {
|
|
4106
|
-
if (content[index] === "[") {
|
|
4107
|
-
if (depth === 0) {
|
|
4108
|
-
start = index > 0 && content[index - 1] === "\\" ? index - 1 : index;
|
|
4109
|
-
labelStart = index + 1;
|
|
4110
|
-
}
|
|
4111
|
-
depth++;
|
|
4112
|
-
} else if (content[index] === "]" && depth > 0 && --depth === 0) {
|
|
4113
|
-
const label = content.slice(labelStart, index).replace(/\\$/, "");
|
|
4114
|
-
if (!label.trim() || /[\[\]\r\n]/.test(label) || /^\d+$/.test(label.trim())) continue;
|
|
4115
|
-
const command = label.split(/[++]/, 1)[0].trim().replace(/^🔄\s*/u, "");
|
|
4116
|
-
if (command) spans.push({ start, end: index + 1, label, command });
|
|
4117
|
-
}
|
|
4118
|
-
}
|
|
4153
|
+
function inlineCommandSpans2(content) {
|
|
4154
|
+
const spans = inlineCommandSpans(content);
|
|
4119
4155
|
const logLinks = battleLogLinkSpans(content);
|
|
4120
4156
|
return spans.filter((span) => !logLinks.some((link) => span.start < link.end && span.end > link.start));
|
|
4121
4157
|
}
|
|
4122
|
-
__name(
|
|
4158
|
+
__name(inlineCommandSpans2, "inlineCommandSpans");
|
|
4123
4159
|
function hasInlineCommands(content) {
|
|
4124
|
-
return
|
|
4160
|
+
return inlineCommandSpans2(content).length > 0;
|
|
4125
4161
|
}
|
|
4126
4162
|
__name(hasInlineCommands, "hasInlineCommands");
|
|
4127
4163
|
function renderInlineCommands(content) {
|
|
4128
4164
|
const parts = [];
|
|
4129
4165
|
let offset = 0;
|
|
4130
4166
|
const spans = [
|
|
4131
|
-
...
|
|
4167
|
+
...inlineCommandSpans2(content).map((span) => ({ ...span, rendered: "[" + escapeMarkdown(span.label) + "](" + inlineCommandUrl(span.command) + ")" })),
|
|
4132
4168
|
...battleLogLinkSpans(content).map((span) => ({ ...span, rendered: renderBattleLogLink(span) }))
|
|
4133
4169
|
].sort((a, b) => a.start - b.start);
|
|
4134
4170
|
for (const span of spans) {
|
|
@@ -4431,7 +4467,8 @@ var AnalysisMsg = class {
|
|
|
4431
4467
|
case 1 /* line */:
|
|
4432
4468
|
const labeledRow = labeledEntries.get(lineIndex);
|
|
4433
4469
|
const content = labeledRow ? labeledRow.map((entry) => entry.label + (entry.description ? " · " + entry.description : "") + ` [${entry.viewCommand}]`).join("") : withCommandHint(item.content, commands.get(lineIndex));
|
|
4434
|
-
|
|
4470
|
+
const plainContent = item.codeBlock || item.mailPart === "body" || labeledRow ? content : renderPlainInlineCommandAliases(content);
|
|
4471
|
+
msg += `${plainContent}
|
|
4435
4472
|
`;
|
|
4436
4473
|
break;
|
|
4437
4474
|
case 2 /* error */:
|
|
@@ -4457,12 +4494,12 @@ function renderQQCommandMarkdown(data, showGreeting) {
|
|
|
4457
4494
|
return renderInlineCommands(onlyLine.content);
|
|
4458
4495
|
}
|
|
4459
4496
|
const title = data.line.find((item) => item.type === 0 /* title */)?.content;
|
|
4460
|
-
const
|
|
4497
|
+
const heading2 = title === void 0 ? "**🔔** 系统提示" : `**${escapeMarkdown(title)}**`;
|
|
4461
4498
|
const body = data.line.filter((item) => item.type !== 0 /* title */).flatMap((item) => {
|
|
4462
4499
|
const content = item.type === 2 /* error */ ? `❌ ${item.content}` : item.content;
|
|
4463
4500
|
return content.replace(/\r\n?/g, "\n").split("\n").map((line) => "> " + renderInlineCommands(line));
|
|
4464
4501
|
}).join(" \n");
|
|
4465
|
-
return
|
|
4502
|
+
return heading2 + (body ? "\n\n" + body : "");
|
|
4466
4503
|
}
|
|
4467
4504
|
const rewardMessage = isRewardMessage(data);
|
|
4468
4505
|
if (!data.commandHelp && !data.pageNav && data.line.some((item) => item.type === 1 /* line */ && !item.reward && /^\[\d+\]\s*[^\r\n]+$/.test(item.content))) {
|
|
@@ -4494,8 +4531,10 @@ function renderQQCommandMarkdown(data, showGreeting) {
|
|
|
4494
4531
|
break;
|
|
4495
4532
|
}
|
|
4496
4533
|
flushRewards();
|
|
4497
|
-
|
|
4498
|
-
|
|
4534
|
+
for (const line of item.content.replace(/\r\n?/g, "\n").split("\n")) {
|
|
4535
|
+
if (!line.trim()) flushBody();
|
|
4536
|
+
else bodyLines.push(renderInlineCommands(line));
|
|
4537
|
+
}
|
|
4499
4538
|
break;
|
|
4500
4539
|
case 2 /* error */:
|
|
4501
4540
|
flushBody();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Requested but unavailable title artwork has an independent image fallback. */
|
|
2
2
|
export declare const characterTitlePlaceholder: string;
|
|
3
3
|
/** Each tier adds finer foliage, white petal layers and metallic vinework. */
|
|
4
4
|
export declare function characterTierOrnament(tier: number): string;
|
|
@@ -6,3 +6,5 @@ export declare function characterTierOrnament(tier: number): string;
|
|
|
6
6
|
export declare const characterFloralWatermark = "<svg class=\"floral-watermark\" viewBox=\"0 0 760 880\" preserveAspectRatio=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <g fill=\"currentColor\">\n <path d=\"M-9 138C39 105 55 49 78-10c-8 64-37 121-87 148ZM17 107C-5 94-8 61-4 38c21 23 36 43 21 69ZM44 60C32 29 40 10 57-12c9 30 9 51-13 72ZM63 24c23-16 49-13 65-2-23 11-46 16-65 2Z\"/>\n <path d=\"M719 787c-2-52 10-98 42-137-9 66-21 110-42 137Zm12-66c-21-16-17-40-19-65 19 20 27 40 19 65Zm10-28c14-26 36-35 56-34-17 18-35 34-56 34ZM2 780c8-17 33-27 51-20-19 19-34 25-51 20Zm34-20c9-24 29-35 47-32-10 22-27 36-47 32Z\"/>\n <g transform=\"translate(58 839) scale(1.5)\"><path d=\"M0 0c-31-14-41-45-23-61 27-7 32 37 23 61Z\"/><path d=\"M0 0c3-31 19-59 44-49 20 19-13 43-44 49Z\"/><path d=\"M0 0c30-10 56-6 55 18-14 25-40 2-55-18Z\"/><path d=\"M0 0c20 20 22 49 0 53-23-7-12-35 0-53Z\"/><path d=\"M0 0c-23 16-51 8-48-15 11-17 35-2 48 15Z\"/></g>\n <g transform=\"translate(696 71) scale(1.4)\"><path d=\"M0 0c-31-14-41-45-23-61 27-7 32 37 23 61Z\"/><path d=\"M0 0c3-31 19-59 44-49 20 19-13 43-44 49Z\"/><path d=\"M0 0c30-10 56-6 55 18-14 25-40 2-55-18Z\"/><path d=\"M0 0c20 20 22 49 0 53-23-7-12-35 0-53Z\"/><path d=\"M0 0c-23 16-51 8-48-15 11-17 35-2 48 15Z\"/></g>\n <g transform=\"translate(63 425) scale(.9)\"><path d=\"M0 0c-31-14-41-45-23-61 27-7 32 37 23 61Z\"/><path d=\"M0 0c3-31 19-59 44-49 20 19-13 43-44 49Z\"/><path d=\"M0 0c30-10 56-6 55 18-14 25-40 2-55-18Z\"/><path d=\"M0 0c20 20 22 49 0 53-23-7-12-35 0-53Z\"/><path d=\"M0 0c-23 16-51 8-48-15 11-17 35-2 48 15Z\"/></g>\n </g>\n <g fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M-4 191C19 101 61 150 86 46M-8 803c84-50 100-82 93-147M705 868c-5-90 24-171 74-226M660-9c55 69 50 129 106 165\"/><path d=\"M85 45c17 2 20 27 7 30-9 1-13-14-5-16M85 674c-24 10-27 43-8 45 10-2 6-17-1-14\"/></g>\n</svg>";
|
|
7
7
|
/** The name of the configured gene-lock rank stays separate from this small crest. */
|
|
8
8
|
export declare function characterGeneCrest(tier: number): string;
|
|
9
|
+
/** Quiet botanical divider above the six-axis radar; carries no visible label. */
|
|
10
|
+
export declare const characterAttributeDivider: string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Character-only moon-white paper, metallic frames and six botanical gene-lock themes. */
|
|
2
|
-
export declare const characterCardStyles = "\n*{box-sizing:border-box}body{margin:0;width:760px}#capture{width:760px;position:relative;overflow:hidden;font-family:\"KaiTi\",\"STKaiti\",\"Microsoft YaHei\",sans-serif}\n.character-sheet{--ink:#374556;--subtle:#748192;--accent:#9b927d;--edge:#aab4bd;--light-edge:#fffefa;--metal-shadow:#8f9ba8;--panel:#fffefa;--panel-deep:#f0f3f5;--paper:#e8edf0;--flower:#fffefa;--leaf:#9aaabb;--leaf-light:#e2e9ed;--gem:#bbc9d4;--track:#e2e7dd;--track-edge:#afbea9;--health:#759569;--health-light:#b4cea2;--radar:#8995ae;--radar-fill:#aebbdc66;--radar-grid:#c4cbd7;--background:#dce3e9;--background-deep:#bac7d3;--ornament-size:86px;--portrait-ornament-size:74px;--frame-radius:27px;--panel-border:2px;padding:22px;color:var(--ink);background:radial-gradient(ellipse at 12% 6%,#fffefaef,transparent 51%),radial-gradient(ellipse at 85% 90%,#f6f8ffc4,transparent 51%),radial-gradient(ellipse at 78% 12%,#ffffff80,transparent 38%),linear-gradient(145deg,var(--background-deep),var(--background) 48%,var(--background-deep))}\n.gene-tier-0{--ink:#435162;--subtle:#7c8795;--accent:#989081;--edge:#b3bac1;--leaf:#9caab8;--leaf-light:#e4e9ef;--gem:#cbd3de;--background:#e3e8ed;--background-deep:#c6cfd9}\n.gene-tier-1{--ink:#365762;--subtle:#718b90;--accent:#b29d77;--edge:#bbc1b2;--metal-shadow:#949f9f;--panel-deep:#f0f6f3;--paper:#e7f0ec;--leaf:#81a6ad;--leaf-light:#d5e9e6;--gem:#a8d4cf;--radar:#7e9baf;--radar-fill:#b6d2dd69;--radar-grid:#bfced5;--background:#e5f0ed;--background-deep:#bfd6d5;--ornament-size:98px;--portrait-ornament-size:84px}\n.gene-tier-2{--ink:#354c69;--subtle:#72869f;--accent:#afa187;--edge:#b4bdcc;--metal-shadow:#8d9bb0;--panel-deep:#eef3f9;--paper:#e7edf6;--leaf:#829bbd;--leaf-light:#d5e1f1;--gem:#aac6e5;--radar:#8596c1;--radar-fill:#aebcde70;--radar-grid:#c1c9db;--background:#e2e9f5;--background-deep:#bccbdf;--ornament-size:110px;--portrait-ornament-size:94px}\n.gene-tier-3{--ink:#494867;--subtle:#827e9c;--accent:#b3a18b;--edge:#bdb7ca;--metal-shadow:#9992ad;--panel-deep:#f2f0f9;--paper:#ede8f6;--leaf:#9995c1;--leaf-light:#e1def2;--gem:#c0b5e6;--radar:#9b91c5;--radar-fill:#c1b7e16e;--radar-grid:#cdc5dd;--background:#eae6f4;--background-deep:#c9c1df;--ornament-size:123px;--portrait-ornament-size:104px}\n.gene-tier-4{--ink:#644b66;--subtle:#9a7f96;--accent:#b89880;--edge:#c8bac5;--metal-shadow:#ad97a6;--panel-deep:#f7eff4;--paper:#f2e8ee;--leaf:#b797b4;--leaf-light:#f0dce8;--gem:#d5b0ca;--radar:#b498bd;--radar-fill:#d2bddf6b;--radar-grid:#d9c9dc;--background:#f0e6ee;--background-deep:#dbc3d4;--ornament-size:137px;--portrait-ornament-size:115px}\n.gene-tier-5{--ink:#3c416e;--subtle:#797fa1;--accent:#b6995f;--edge:#c2b48f;--metal-shadow:#9c976f;--panel-deep:#f0effa;--paper:#e8e9f5;--leaf:#858dbf;--leaf-light:#d7ddf4;--gem:#b4b6e4;--radar:#9087c8;--radar-fill:#b8b0e476;--radar-grid:#c8c6dd;--background:#e4e5f5;--background-deep:#bdc5e1;--ornament-size:149px;--portrait-ornament-size:126px}\n.character-ambient,.character-paper-pattern{position:absolute;inset:0;pointer-events:none;overflow:hidden;color:var(--leaf)}.character-ambient{opacity:.23}.character-ambient .floral-watermark{width:100%;height:100%;display:block}.character-paper-pattern{opacity:.075;border-radius:25px}.character-paper-pattern .floral-watermark{width:100%;height:100%;display:block}\n.character-card{display:grid;grid-template-columns:344px minmax(0,1fr);gap:16px;align-items:stretch;position:relative;z-index:1}.portrait-column{min-width:0;display:flex;flex-direction:column;justify-content:center}\n.character-sheet .companion-panel{position:relative;min-width:0;border:2px solid var(--edge);border-radius:var(--frame-radius);background:radial-gradient(ellipse at 15% 6%,#ffffffbd,transparent 49%),linear-gradient(155deg,var(--panel),var(--panel-deep));box-shadow:inset 0 0 0 2px #ffffffb5,inset 0 0 0 3px color-mix(in srgb,var(--metal-shadow) 35%,transparent),0 2px 8px #52608026}\n.character-sheet .companion-panel:before{content:\"\";position:absolute;inset:7px;border:1px solid color-mix(in srgb,var(--edge) 65%,#ffffff);border-radius:calc(var(--frame-radius) - 7px);pointer-events:none}\n.character-sheet .companion-panel:after{content:\"\";position:absolute;inset:3px;border:1px solid #fffdf3b3;border-radius:calc(var(--frame-radius) - 2px);pointer-events:none}\n.character-sheet .panel-corner{position:absolute;width:var(--ornament-size);height:var(--ornament-size);pointer-events:none;z-index:3;color:var(--accent)}.panel-corner svg{width:100%;height:100%;display:block;overflow:visible;filter:drop-shadow(0 1px 1px #52608035)}.corner-tl{top:-13px;left:-13px}.corner-tr{top:-13px;right:-13px;transform:rotate(90deg)}.corner-bl{bottom:-13px;left:-13px;transform:rotate(-90deg)}.corner-br{bottom:-13px;right:-13px;transform:rotate(180deg)}\n.character-sheet .companion-portrait{padding:10px;border-radius:18px;flex:0 0 auto;background:linear-gradient(135deg,#fffefa 2%,var(--edge) 18%,#ffffff 30%,var(--accent) 41%,#fffdf2 51%,var(--edge) 71%,#ffffff 82%,var(--metal-shadow) 100%);box-shadow:inset 0 0 0 1px #ffffffd9,0 3px 9px #51628038}\n.character-sheet .companion-portrait:before{inset:5px;border-radius:12px;border-color:#fffdf1cf;box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 43%,transparent)}.character-sheet .companion-portrait:after{inset:2px;border-radius:15px;border-color:#fffefa9c}.character-sheet .companion-portrait .panel-corner{width:var(--portrait-ornament-size);height:var(--portrait-ornament-size)}\n.character-sheet .portrait-window{height:auto;border:2px solid var(--edge);border-radius:6px;overflow:hidden;background:var(--paper)}.character-artwork{display:block;width:100%;height:auto;object-fit:contain}.character-sheet .portrait-placeholder,.character-sheet .placeholder{height:100%;width:100%;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;color:var(--subtle);font:21px/1.5 \"Microsoft YaHei\",sans-serif}.character-sheet .placeholder small{font-size:16px}.character-sheet .portrait-window>.placeholder{height:448px}\n.character-stats{padding:17px 18px 15px;display:flex;flex-direction:column}.character-stats>.character-identity,.character-stats>.combat-row,.character-stats>.resource,.character-stats>.attribute-panel{position:relative;z-index:4}\n.character-identity{text-align:center;min-width:0}.title-image-slot{position:absolute;inset:12px;display:flex;align-items:center;justify-content:center;min-width:0;z-index:4;pointer-events:none}.title-artwork{display:block;width:auto;height:auto;max-width:100%;max-height:min(110px,100%);object-fit:contain;filter:drop-shadow(0 2px 3px #17213a70)}.title-artwork[alt=\"\u79F0\u53F7\u56FE\u7247\u5360\u4F4D\"]{max-width:min(244px,100%);max-height:min(44px,100%)}\n.character-name{font-size:43px;line-height:1.17;font-weight:700;letter-spacing:3px;margin:0 0 3px;overflow-wrap:anywhere;color:var(--ink);text-shadow:0 1px 0 #ffffff}.character-level{font:27px/1.25 Georgia,\"Microsoft YaHei\",serif;margin:0;color:var(--subtle);display:flex;align-items:baseline;justify-content:center;gap:7px;min-width:0}.character-level strong{font-size:28px;font-weight:500;overflow-wrap:anywhere;min-width:0}\n.gene-panel{position:relative;margin:8px auto 0;padding:4px 12px 4px 7px;display:flex;align-items:center;justify-content:center;gap:6px;width:fit-content;max-width:100%;border:1px solid color-mix(in srgb,var(--edge) 80%,#ffffff);border-radius:7px;background:linear-gradient(#ffffffd6,color-mix(in srgb,var(--paper) 75%,#ffffff));box-shadow:inset 0 0 0 2px #ffffffaa,0 1px 2px #54628210}\n.gene-panel:before,.gene-panel:after{content:\"\";position:absolute;top:50%;width:6px;height:6px;background:var(--light-edge);border:1px solid var(--edge);transform:translateY(-50%) rotate(45deg)}.gene-panel:before{left:-4px}.gene-panel:after{right:-4px}.gene-crest{flex:0 0 26px;height:29px;color:var(--accent)}.gene-crest svg{display:block;width:100%;height:100%}.gene-rank{font-size:18px;line-height:1.35;letter-spacing:1px;overflow-wrap:anywhere;font-weight:700;text-align:center;min-width:0;color:var(--ink)}\n.combat-row{display:flex;align-items:center;gap:8px;margin:14px 0 12px;min-width:0}.power-icon{flex:0 0 42px;height:42px;display:grid;place-items:center;border-radius:50%;border:1px solid var(--accent);box-shadow:inset 0 0 0 3px #fffef3b5;color:var(--accent);background:radial-gradient(ellipse at 38% 25%,#fffdf0,color-mix(in srgb,var(--accent) 14%,var(--panel)))}.power-icon svg{width:27px;height:27px;stroke:currentColor;fill:currentColor;stroke-width:2;stroke-linejoin:round}.power-label{font-size:21px;white-space:nowrap}.power-value{min-width:0;flex:1;text-align:right;overflow-wrap:anywhere;font:35px/1.2 Georgia,\"Microsoft YaHei\",serif;color:var(--accent);letter-spacing:-1px}\n.companion-resource{font-family:\"Microsoft YaHei\",sans-serif;margin-bottom:12px}.resource-heading{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-size:17px;color:var(--subtle);line-height:1.35}.resource-label{display:flex;align-items:center;gap:6px;font-weight:600;flex-shrink:0}.resource-label svg{width:18px;height:18px;fill:var(--health)}.resource-number{text-align:right;overflow-wrap:anywhere;min-width:0;font-size:15px}\n.resource-track{height:18px;position:relative;margin-top:5px;border:1px solid var(--track-edge);border-radius:10px;overflow:hidden;background:linear-gradient(var(--track),#f2f5ed);box-shadow:inset 0 1px 2px #6e805825}.resource-fill{display:block;position:absolute;top:0;bottom:0;left:0;border-radius:9px;background:linear-gradient(var(--health-light),var(--health) 55%,color-mix(in srgb,var(--health) 80%,var(--health-light)));border-right:1px solid #fff9}.resource-percent{position:absolute;inset:0;display:grid;place-items:center;font:11px/1 \"Microsoft YaHei\",sans-serif;color:#fffef7;text-shadow:0 1px 2px #435443}.exp-resource .resource-heading{color:var(--subtle)}.exp-resource .resource-label svg{fill:var(--radar)}.exp-resource .resource-track{height:16px;border-color:color-mix(in srgb,var(--radar) 60%,#fff);background:var(--paper)}.exp-resource .resource-fill{background:linear-gradient(var(--leaf-light),var(--radar) 56%,var(--leaf))}\n.companion-attributes{margin-top:5px;min-width:0;flex:1;display:flex;flex-direction:column;justify-content:center}.ornament-heading{display:flex;align-items:center;justify-content:center;gap:7px;margin:0 0 3px;font-size:22px;font-weight:700;letter-spacing:2px;line-height:1.3;color:var(--ink)}.ornament-heading:before,.ornament-heading:after{content:\"\";height:1px;flex:1;background:linear-gradient(90deg,transparent,var(--edge))}.ornament-heading:after{transform:rotate(180deg)}.heading-star{font-size:12px;color:var(--accent);letter-spacing:0}.companion-radar{width:100%;height:260px;display:block;overflow:visible}\n.radar-grid{fill:none;stroke:var(--radar-grid);stroke-width:1.1}.radar-axis{stroke:var(--radar-grid);stroke-width:1;opacity:.8}.radar-area{fill:var(--radar-fill);stroke:var(--radar);stroke-width:2.3;stroke-linejoin:round}.radar-dot{fill:#fffefa;stroke:var(--radar);stroke-width:2}.radar-label{font:19px \"KaiTi\",\"STKaiti\",\"Microsoft YaHei\",sans-serif;fill:var(--ink)}.radar-value{font:20px Georgia,\"Microsoft YaHei\",serif;fill:var(--ink)}.radar-scale{font:11px Georgia,serif;fill:var(--subtle)}.empty-attributes{padding:45px 10px;color:var(--subtle);font:18px/1.6 \"Microsoft YaHei\",sans-serif;text-align:center}.custom-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:5px 10px;margin:6px 0 0;font:15px/1.5 \"Microsoft YaHei\",sans-serif;color:var(--subtle)}.custom-attributes span{overflow-wrap:anywhere}.custom-attributes b{font-weight:500;color:var(--ink)}\n";
|
|
2
|
+
export declare const characterCardStyles = "\n*{box-sizing:border-box}body{margin:0;width:760px}#capture{width:760px;position:relative;overflow:hidden;font-family:\"KaiTi\",\"STKaiti\",\"Microsoft YaHei\",sans-serif}\n.character-sheet{--ink:#374556;--subtle:#748192;--accent:#9b927d;--edge:#aab4bd;--light-edge:#fffefa;--metal-shadow:#8f9ba8;--panel:#fffefa;--panel-deep:#f0f3f5;--paper:#e8edf0;--flower:#fffefa;--leaf:#9aaabb;--leaf-light:#e2e9ed;--gem:#bbc9d4;--track:#e2e7dd;--track-edge:#afbea9;--health:#759569;--health-light:#b4cea2;--radar:#8995ae;--radar-fill:#aebbdc66;--radar-grid:#c4cbd7;--background:#dce3e9;--background-deep:#bac7d3;--ornament-size:86px;--portrait-ornament-size:74px;--frame-radius:27px;--panel-border:2px;padding:22px;color:var(--ink);background:radial-gradient(ellipse at 12% 6%,#fffefaef,transparent 51%),radial-gradient(ellipse at 85% 90%,#f6f8ffc4,transparent 51%),radial-gradient(ellipse at 78% 12%,#ffffff80,transparent 38%),linear-gradient(145deg,var(--background-deep),var(--background) 48%,var(--background-deep))}\n.gene-tier-0{--ink:#435162;--subtle:#7c8795;--accent:#989081;--edge:#b3bac1;--leaf:#9caab8;--leaf-light:#e4e9ef;--gem:#cbd3de;--background:#e3e8ed;--background-deep:#c6cfd9}\n.gene-tier-1{--ink:#365762;--subtle:#718b90;--accent:#b29d77;--edge:#bbc1b2;--metal-shadow:#949f9f;--panel-deep:#f0f6f3;--paper:#e7f0ec;--leaf:#81a6ad;--leaf-light:#d5e9e6;--gem:#a8d4cf;--radar:#7e9baf;--radar-fill:#b6d2dd69;--radar-grid:#bfced5;--background:#e5f0ed;--background-deep:#bfd6d5;--ornament-size:98px;--portrait-ornament-size:84px}\n.gene-tier-2{--ink:#354c69;--subtle:#72869f;--accent:#afa187;--edge:#b4bdcc;--metal-shadow:#8d9bb0;--panel-deep:#eef3f9;--paper:#e7edf6;--leaf:#829bbd;--leaf-light:#d5e1f1;--gem:#aac6e5;--radar:#8596c1;--radar-fill:#aebcde70;--radar-grid:#c1c9db;--background:#e2e9f5;--background-deep:#bccbdf;--ornament-size:110px;--portrait-ornament-size:94px}\n.gene-tier-3{--ink:#494867;--subtle:#827e9c;--accent:#b3a18b;--edge:#bdb7ca;--metal-shadow:#9992ad;--panel-deep:#f2f0f9;--paper:#ede8f6;--leaf:#9995c1;--leaf-light:#e1def2;--gem:#c0b5e6;--radar:#9b91c5;--radar-fill:#c1b7e16e;--radar-grid:#cdc5dd;--background:#eae6f4;--background-deep:#c9c1df;--ornament-size:123px;--portrait-ornament-size:104px}\n.gene-tier-4{--ink:#644b66;--subtle:#9a7f96;--accent:#b89880;--edge:#c8bac5;--metal-shadow:#ad97a6;--panel-deep:#f7eff4;--paper:#f2e8ee;--leaf:#b797b4;--leaf-light:#f0dce8;--gem:#d5b0ca;--radar:#b498bd;--radar-fill:#d2bddf6b;--radar-grid:#d9c9dc;--background:#f0e6ee;--background-deep:#dbc3d4;--ornament-size:137px;--portrait-ornament-size:115px}\n.gene-tier-5{--ink:#3c416e;--subtle:#797fa1;--accent:#b6995f;--edge:#c2b48f;--metal-shadow:#9c976f;--panel-deep:#f0effa;--paper:#e8e9f5;--leaf:#858dbf;--leaf-light:#d7ddf4;--gem:#b4b6e4;--radar:#9087c8;--radar-fill:#b8b0e476;--radar-grid:#c8c6dd;--background:#e4e5f5;--background-deep:#bdc5e1;--ornament-size:149px;--portrait-ornament-size:126px}\n.character-ambient,.character-paper-pattern{position:absolute;inset:0;pointer-events:none;overflow:hidden;color:var(--leaf)}.character-ambient{opacity:.23}.character-ambient .floral-watermark{width:100%;height:100%;display:block}.character-paper-pattern{opacity:.075;border-radius:25px}.character-paper-pattern .floral-watermark{width:100%;height:100%;display:block}\n.character-card{display:grid;grid-template-columns:344px minmax(0,1fr);gap:16px;align-items:stretch;position:relative;z-index:1}.portrait-column{min-width:0;display:flex;flex-direction:column;justify-content:center}\n.character-sheet .companion-panel{position:relative;min-width:0;border:2px solid var(--edge);border-radius:var(--frame-radius);background:radial-gradient(ellipse at 15% 6%,#ffffffbd,transparent 49%),linear-gradient(155deg,var(--panel),var(--panel-deep));box-shadow:inset 0 0 0 2px #ffffffb5,inset 0 0 0 3px color-mix(in srgb,var(--metal-shadow) 35%,transparent),0 2px 8px #52608026}\n.character-sheet .companion-panel:before{content:\"\";position:absolute;inset:7px;border:1px solid color-mix(in srgb,var(--edge) 65%,#ffffff);border-radius:calc(var(--frame-radius) - 7px);pointer-events:none}\n.character-sheet .companion-panel:after{content:\"\";position:absolute;inset:3px;border:1px solid #fffdf3b3;border-radius:calc(var(--frame-radius) - 2px);pointer-events:none}\n.character-sheet .panel-corner{position:absolute;width:var(--ornament-size);height:var(--ornament-size);pointer-events:none;z-index:3;color:var(--accent)}.panel-corner svg{width:100%;height:100%;display:block;overflow:visible;filter:drop-shadow(0 1px 1px #52608035)}.corner-tl{top:-13px;left:-13px}.corner-tr{top:-13px;right:-13px;transform:rotate(90deg)}.corner-bl{bottom:-13px;left:-13px;transform:rotate(-90deg)}.corner-br{bottom:-13px;right:-13px;transform:rotate(180deg)}\n.character-sheet .companion-portrait{padding:10px;border-radius:18px;flex:0 0 auto;background:linear-gradient(135deg,#fffefa 2%,var(--edge) 18%,#ffffff 30%,var(--accent) 41%,#fffdf2 51%,var(--edge) 71%,#ffffff 82%,var(--metal-shadow) 100%);box-shadow:inset 0 0 0 1px #ffffffd9,0 3px 9px #51628038}\n.character-sheet .companion-portrait:before{inset:5px;border-radius:12px;border-color:#fffdf1cf;box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 43%,transparent)}.character-sheet .companion-portrait:after{inset:2px;border-radius:15px;border-color:#fffefa9c}.character-sheet .companion-portrait .panel-corner{width:var(--portrait-ornament-size);height:var(--portrait-ornament-size)}\n.character-sheet .portrait-window{height:auto;border:2px solid var(--edge);border-radius:6px;overflow:hidden;background:var(--paper)}.character-artwork{display:block;width:100%;height:auto;object-fit:contain}.character-sheet .portrait-placeholder,.character-sheet .placeholder{height:100%;width:100%;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;color:var(--subtle);font:21px/1.5 \"Microsoft YaHei\",sans-serif}.character-sheet .placeholder small{font-size:16px}.character-sheet .portrait-window>.placeholder{height:448px}\n.character-stats{padding:17px 18px 15px;display:flex;flex-direction:column}.character-stats>.character-identity,.character-stats>.resource,.character-stats>.attribute-panel{position:relative;z-index:4}\n.character-identity{text-align:center;min-width:0}.title-image-slot{position:absolute;inset:12px;display:flex;align-items:center;justify-content:center;min-width:0;z-index:4;pointer-events:none}.title-artwork{display:block;width:auto;height:auto;max-width:100%;max-height:min(110px,100%);object-fit:contain;filter:drop-shadow(0 2px 3px #17213a70)}.title-artwork[alt=\"\u79F0\u53F7\u56FE\u7247\u5360\u4F4D\"]{max-width:min(244px,100%);max-height:min(44px,100%)}\n.character-name{font-size:43px;line-height:1.17;font-weight:700;letter-spacing:3px;margin:0 0 3px;overflow-wrap:anywhere;color:var(--ink);text-shadow:0 1px 0 #ffffff}.character-level{font:27px/1.25 Georgia,\"Microsoft YaHei\",serif;margin:0;color:var(--subtle);display:flex;align-items:baseline;justify-content:center;gap:7px;min-width:0}.character-level strong{font-size:28px;font-weight:500;overflow-wrap:anywhere;min-width:0}\n.gene-panel{position:relative;margin:8px auto 0;padding:4px 12px 4px 7px;display:flex;align-items:center;justify-content:center;gap:6px;width:fit-content;max-width:100%;border:1px solid color-mix(in srgb,var(--edge) 80%,#ffffff);border-radius:7px;background:linear-gradient(#ffffffd6,color-mix(in srgb,var(--paper) 75%,#ffffff));box-shadow:inset 0 0 0 2px #ffffffaa,0 1px 2px #54628210}\n.gene-panel:before,.gene-panel:after{content:\"\";position:absolute;top:50%;width:6px;height:6px;background:var(--light-edge);border:1px solid var(--edge);transform:translateY(-50%) rotate(45deg)}.gene-panel:before{left:-4px}.gene-panel:after{right:-4px}.gene-crest{flex:0 0 26px;height:29px;color:var(--accent)}.gene-crest svg{display:block;width:100%;height:100%}.gene-rank{font-size:18px;line-height:1.35;letter-spacing:1px;overflow-wrap:anywhere;font-weight:700;text-align:center;min-width:0;color:var(--ink)}\n.exploration-rank-row{display:flex;align-items:center;justify-content:center;gap:7px;margin:10px 0 0;font:16px/1.4 \"KaiTi\",\"STKaiti\",\"Microsoft YaHei\",sans-serif;letter-spacing:1px;color:var(--subtle)}.exploration-rank-row>svg{width:17px;height:17px;flex-shrink:0;fill:none;stroke:var(--accent);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}.exploration-rank-row>span{white-space:nowrap}.exploration-rank-row strong{font-size:18px;font-weight:700;color:var(--ink);overflow-wrap:anywhere;min-width:0}\n.combat-row{display:flex;align-items:center;justify-content:center;gap:8px;margin:12px 0 0;padding:0 6px;min-width:0;font:28px/1.2 \"KaiTi\",\"STKaiti\",\"Microsoft YaHei\",sans-serif;position:relative;z-index:4}.power-icon{flex:0 0 34px;height:34px;display:grid;place-items:center;color:var(--accent)}.power-icon svg{display:block;width:34px;height:34px;overflow:visible}.power-label{font:inherit;white-space:nowrap}.power-value{min-width:0;flex:0 1 auto;text-align:center;overflow-wrap:anywhere;font:inherit;color:var(--accent);letter-spacing:0}\n.companion-resource{font-family:\"Microsoft YaHei\",sans-serif;margin-bottom:12px}.resource-heading{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-size:17px;color:var(--subtle);line-height:1.35}.resource-label{display:flex;align-items:center;gap:6px;font-weight:600;flex-shrink:0}.resource-label svg{width:18px;height:18px;fill:var(--health)}.resource-number{text-align:right;overflow-wrap:anywhere;min-width:0;font-size:15px}\n.resource-track{height:18px;position:relative;margin-top:5px;border:1px solid var(--track-edge);border-radius:10px;overflow:hidden;background:linear-gradient(var(--track),#f2f5ed);box-shadow:inset 0 1px 2px #6e805825}.resource-fill{display:block;position:absolute;top:0;bottom:0;left:0;border-radius:9px;background:linear-gradient(var(--health-light),var(--health) 55%,color-mix(in srgb,var(--health) 80%,var(--health-light)));border-right:1px solid #fff9}.resource-percent{position:absolute;inset:0;display:grid;place-items:center;font:11px/1 \"Microsoft YaHei\",sans-serif;color:#fffef7;text-shadow:0 1px 2px #435443}.exp-resource{width:calc(100% - 20px);align-self:center;margin:0 0 14px}.exp-resource .resource-track{height:6px;margin-top:0;border-color:#d5c48b;border-radius:4px;background:#eee9d7;box-shadow:inset 0 1px 1px #9d82351a}.exp-resource .resource-fill{border-radius:3px;border-right:0;background:linear-gradient(#fff0a0,#e8bd48 60%,#d6a934)}\n.hp-resource{display:flex;align-items:center;margin-top:16px;margin-bottom:0}.hp-resource .resource-track{flex:1;min-width:0;height:20px;margin-top:0}.hp-bar-value{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:0 8px;white-space:nowrap;font:12px/1 \"Microsoft YaHei\",sans-serif;color:#fffef7;text-shadow:0 1px 2px #435443,0 0 2px #435443}\n.companion-attributes{margin-top:5px;min-width:0;flex:1;display:flex;flex-direction:column;justify-content:center}.attribute-divider{height:28px;margin:0 0 3px;display:flex;align-items:center;justify-content:center}.attribute-divider svg{display:block;width:100%;height:36px}.companion-radar{width:100%;height:260px;display:block;overflow:visible}\n.radar-grid{fill:none;stroke:var(--radar-grid);stroke-width:1.1}.radar-axis{stroke:var(--radar-grid);stroke-width:1;opacity:.8}.radar-area{fill:var(--radar-fill);stroke:var(--radar);stroke-width:2.3;stroke-linejoin:round}.radar-dot{fill:#fffefa;stroke:var(--radar);stroke-width:2}.radar-label{font:19px \"KaiTi\",\"STKaiti\",\"Microsoft YaHei\",sans-serif;fill:var(--ink)}.radar-value{font:20px Georgia,\"Microsoft YaHei\",serif;fill:var(--ink)}.radar-scale{font:11px Georgia,serif;fill:var(--subtle)}.empty-attributes{padding:45px 10px;color:var(--subtle);font:18px/1.6 \"Microsoft YaHei\",sans-serif;text-align:center}.custom-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:5px 10px;margin:6px 0 0;font:15px/1.5 \"Microsoft YaHei\",sans-serif;color:var(--subtle)}.custom-attributes span{overflow-wrap:anywhere}.custom-attributes b{font-weight:500;color:var(--ink)}\n";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type InlineCommandSpan = {
|
|
2
|
+
start: number;
|
|
3
|
+
end: number;
|
|
4
|
+
label: string;
|
|
5
|
+
command: string;
|
|
6
|
+
aliased?: true;
|
|
7
|
+
};
|
|
8
|
+
/** Boxed commands may use [label](command:input) to show a different action label. */
|
|
9
|
+
export declare function inlineCommandSpans(content: string): InlineCommandSpan[];
|
|
10
|
+
/** Keep aliased actions usable when the platform falls back to ordinary text. */
|
|
11
|
+
export declare function renderPlainInlineCommandAliases(content: string): string;
|
|
@@ -57,7 +57,7 @@ export interface CharacterCardData {
|
|
|
57
57
|
}>;
|
|
58
58
|
/** 当前基因锁大阶的配置名称,不包含层级;未开启时为基因锁未开启。 */
|
|
59
59
|
geneLockRankName?: string;
|
|
60
|
-
/**
|
|
60
|
+
/** 当前称号的图片链接;未获得称号或图片不可用时省略,客户端不显示称号横幅。 */
|
|
61
61
|
titleImageUrl?: string;
|
|
62
62
|
/** 已获得的真实基因锁大阶(0~5);0 表示尚未解锁。 */
|
|
63
63
|
geneLockTier?: number;
|
|
@@ -78,6 +78,8 @@ export interface CharacterCardData {
|
|
|
78
78
|
type?: CompanionSkillType;
|
|
79
79
|
artworkUrl?: string;
|
|
80
80
|
}>;
|
|
81
|
+
/** 玩家当前的轮回探索品阶(F~SSS),与角色等级、基因锁阶级分开显示。 */
|
|
82
|
+
explorationRank?: string;
|
|
81
83
|
}
|
|
82
84
|
export declare enum CompanionCardKind {
|
|
83
85
|
pet = "pet",
|
package/package.json
CHANGED
|
@@ -19,15 +19,13 @@ function radar(card: BloodlineCardData): string {
|
|
|
19
19
|
const attribute = card.attributes.find(value => value.id === id)
|
|
20
20
|
return { name: attribute?.name?.trim() || name, value: finite(attribute?.value ?? 0) }
|
|
21
21
|
})
|
|
22
|
-
const
|
|
23
|
-
const magnitude = 10 ** Math.floor(Math.log10(max))
|
|
24
|
-
const ceiling = Math.ceil(max / magnitude) * magnitude
|
|
22
|
+
const ceiling = Math.max(0, ...attributes.map(attribute => attribute.value))
|
|
25
23
|
const point = (index: number, radius: number) => {
|
|
26
24
|
const angle = -Math.PI / 2 + index * Math.PI / 3
|
|
27
25
|
return [320 + Math.cos(angle) * radius, 190 + Math.sin(angle) * radius]
|
|
28
26
|
}
|
|
29
27
|
const polygon = (radius: number) => attributes.map((_, index) => point(index, radius).join(',')).join(' ')
|
|
30
|
-
const data = attributes.map((attribute, index) => point(index, 122 *
|
|
28
|
+
const data = attributes.map((attribute, index) => point(index, 122 * (ceiling > 0 ? Math.max(0, attribute.value / ceiling) : 0)))
|
|
31
29
|
return `<div class="radar-panel"><svg class="bloodline-radar" viewBox="0 0 640 396" role="img" aria-label="血统六维属性加成雷达图" xmlns="http://www.w3.org/2000/svg">
|
|
32
30
|
<defs><linearGradient id="bloodline-radar-fill" x1="0" y1="0" x2="1" y2="1"><stop stop-color="var(--quality-accent)" stop-opacity=".35"/><stop offset="1" stop-color="var(--quality-accent)" stop-opacity=".12"/></linearGradient></defs>
|
|
33
31
|
${[.2, .4, .6, .8, 1].map(scale => `<polygon points="${polygon(122 * scale)}" fill="none" stroke="#b9bdad" stroke-width="1.2"/>`).join('')}
|
package/src/plugin/cardLayout.ts
CHANGED
|
@@ -26,7 +26,7 @@ export async function layoutCard(document: Document = globalThis.document) {
|
|
|
26
26
|
portrait.replaceWith(placeholder)
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
//
|
|
29
|
+
// Requested title artwork has an independent fallback; untitled cards have no title element.
|
|
30
30
|
const titleArtwork = document.querySelector<HTMLImageElement>('.title-artwork')
|
|
31
31
|
if (titleArtwork) {
|
|
32
32
|
try { await titleArtwork.decode() } catch {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Requested but unavailable title artwork has an independent image fallback. */
|
|
2
2
|
export const characterTitlePlaceholder = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="420" height="84" viewBox="0 0 420 84">
|
|
3
3
|
<defs>
|
|
4
4
|
<linearGradient id="metal" x2="0" y2="1"><stop stop-color="#fffef4"/><stop offset=".3" stop-color="#bbb6a2"/><stop offset=".52" stop-color="#fffdf0"/><stop offset="1" stop-color="#9ba6bc"/></linearGradient>
|
|
@@ -53,3 +53,11 @@ export const characterFloralWatermark = `<svg class="floral-watermark" viewBox="
|
|
|
53
53
|
export function characterGeneCrest(tier: number): string {
|
|
54
54
|
return `<svg viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="m30 4 20 10v20L30 55 10 34V14Z" fill="var(--paper)" stroke="currentColor" stroke-width="1.6"/><path d="m30 9 15 8v16L30 49 15 33V17Z" fill="none" stroke="var(--light-edge)" stroke-width="1"/><path d="M23 27v-6a7 7 0 0 1 14 0v6" fill="none" stroke="currentColor" stroke-width="2.5"/><rect x="20" y="26" width="20" height="15" rx="3" fill="currentColor"/><circle cx="30" cy="32" r="2" fill="var(--light-edge)"/><path d="M30 33v4" stroke="var(--light-edge)" stroke-width="1.8"/>${tier >= 3 ? '<path d="m30 2 3 4-3 4-3-4Z" fill="var(--gem)" stroke="var(--light-edge)"/>' : ''}${tier >= 5 ? '<path d="m18 12 1-7 6 4 5-7 5 7 6-4 1 7Z" fill="var(--accent)" stroke="var(--light-edge)" stroke-width=".7"/>' : ''}</svg>`
|
|
55
55
|
}
|
|
56
|
+
|
|
57
|
+
/** Quiet botanical divider above the six-axis radar; carries no visible label. */
|
|
58
|
+
export const characterAttributeDivider = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 310 36">
|
|
59
|
+
${ornamentPaint}
|
|
60
|
+
<g fill="none" stroke="var(--edge)" stroke-width=".8"><path d="M5 18h91m118 0h91"/><path d="M75 18c18 0 29-8 47-8m66 0c18 0 29 8 47 8"/><path d="M102 18c12 0 21 6 31 6m44 0c10 0 19-6 31-6"/></g>
|
|
61
|
+
<g fill="url(#character-leaf)" stroke="var(--light-edge)" stroke-width=".6"><path d="M120 11c-10-1-14-6-16-10 10 0 17 3 16 10Zm14 12c-10 2-18-1-22-6 10-2 18-1 22 6Zm56-12c10-1 14-6 16-10-10 0-17 3-16 10Zm-14 12c10 2 18-1 22-6-10-2-18-1-22 6Z"/></g>
|
|
62
|
+
${flower(155, 18, .5)}<g fill="var(--accent)"><path d="m94 18 3-3 3 3-3 3Zm116 0 3-3 3 3-3 3Z"/></g>
|
|
63
|
+
</svg>`
|
|
@@ -17,14 +17,16 @@ export const characterCardStyles = `
|
|
|
17
17
|
.character-sheet .companion-portrait{padding:10px;border-radius:18px;flex:0 0 auto;background:linear-gradient(135deg,#fffefa 2%,var(--edge) 18%,#ffffff 30%,var(--accent) 41%,#fffdf2 51%,var(--edge) 71%,#ffffff 82%,var(--metal-shadow) 100%);box-shadow:inset 0 0 0 1px #ffffffd9,0 3px 9px #51628038}
|
|
18
18
|
.character-sheet .companion-portrait:before{inset:5px;border-radius:12px;border-color:#fffdf1cf;box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 43%,transparent)}.character-sheet .companion-portrait:after{inset:2px;border-radius:15px;border-color:#fffefa9c}.character-sheet .companion-portrait .panel-corner{width:var(--portrait-ornament-size);height:var(--portrait-ornament-size)}
|
|
19
19
|
.character-sheet .portrait-window{height:auto;border:2px solid var(--edge);border-radius:6px;overflow:hidden;background:var(--paper)}.character-artwork{display:block;width:100%;height:auto;object-fit:contain}.character-sheet .portrait-placeholder,.character-sheet .placeholder{height:100%;width:100%;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;color:var(--subtle);font:21px/1.5 "Microsoft YaHei",sans-serif}.character-sheet .placeholder small{font-size:16px}.character-sheet .portrait-window>.placeholder{height:448px}
|
|
20
|
-
.character-stats{padding:17px 18px 15px;display:flex;flex-direction:column}.character-stats>.character-identity,.character-stats>.
|
|
20
|
+
.character-stats{padding:17px 18px 15px;display:flex;flex-direction:column}.character-stats>.character-identity,.character-stats>.resource,.character-stats>.attribute-panel{position:relative;z-index:4}
|
|
21
21
|
.character-identity{text-align:center;min-width:0}.title-image-slot{position:absolute;inset:12px;display:flex;align-items:center;justify-content:center;min-width:0;z-index:4;pointer-events:none}.title-artwork{display:block;width:auto;height:auto;max-width:100%;max-height:min(110px,100%);object-fit:contain;filter:drop-shadow(0 2px 3px #17213a70)}.title-artwork[alt="称号图片占位"]{max-width:min(244px,100%);max-height:min(44px,100%)}
|
|
22
22
|
.character-name{font-size:43px;line-height:1.17;font-weight:700;letter-spacing:3px;margin:0 0 3px;overflow-wrap:anywhere;color:var(--ink);text-shadow:0 1px 0 #ffffff}.character-level{font:27px/1.25 Georgia,"Microsoft YaHei",serif;margin:0;color:var(--subtle);display:flex;align-items:baseline;justify-content:center;gap:7px;min-width:0}.character-level strong{font-size:28px;font-weight:500;overflow-wrap:anywhere;min-width:0}
|
|
23
23
|
.gene-panel{position:relative;margin:8px auto 0;padding:4px 12px 4px 7px;display:flex;align-items:center;justify-content:center;gap:6px;width:fit-content;max-width:100%;border:1px solid color-mix(in srgb,var(--edge) 80%,#ffffff);border-radius:7px;background:linear-gradient(#ffffffd6,color-mix(in srgb,var(--paper) 75%,#ffffff));box-shadow:inset 0 0 0 2px #ffffffaa,0 1px 2px #54628210}
|
|
24
24
|
.gene-panel:before,.gene-panel:after{content:"";position:absolute;top:50%;width:6px;height:6px;background:var(--light-edge);border:1px solid var(--edge);transform:translateY(-50%) rotate(45deg)}.gene-panel:before{left:-4px}.gene-panel:after{right:-4px}.gene-crest{flex:0 0 26px;height:29px;color:var(--accent)}.gene-crest svg{display:block;width:100%;height:100%}.gene-rank{font-size:18px;line-height:1.35;letter-spacing:1px;overflow-wrap:anywhere;font-weight:700;text-align:center;min-width:0;color:var(--ink)}
|
|
25
|
-
.
|
|
25
|
+
.exploration-rank-row{display:flex;align-items:center;justify-content:center;gap:7px;margin:10px 0 0;font:16px/1.4 "KaiTi","STKaiti","Microsoft YaHei",sans-serif;letter-spacing:1px;color:var(--subtle)}.exploration-rank-row>svg{width:17px;height:17px;flex-shrink:0;fill:none;stroke:var(--accent);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}.exploration-rank-row>span{white-space:nowrap}.exploration-rank-row strong{font-size:18px;font-weight:700;color:var(--ink);overflow-wrap:anywhere;min-width:0}
|
|
26
|
+
.combat-row{display:flex;align-items:center;justify-content:center;gap:8px;margin:12px 0 0;padding:0 6px;min-width:0;font:28px/1.2 "KaiTi","STKaiti","Microsoft YaHei",sans-serif;position:relative;z-index:4}.power-icon{flex:0 0 34px;height:34px;display:grid;place-items:center;color:var(--accent)}.power-icon svg{display:block;width:34px;height:34px;overflow:visible}.power-label{font:inherit;white-space:nowrap}.power-value{min-width:0;flex:0 1 auto;text-align:center;overflow-wrap:anywhere;font:inherit;color:var(--accent);letter-spacing:0}
|
|
26
27
|
.companion-resource{font-family:"Microsoft YaHei",sans-serif;margin-bottom:12px}.resource-heading{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-size:17px;color:var(--subtle);line-height:1.35}.resource-label{display:flex;align-items:center;gap:6px;font-weight:600;flex-shrink:0}.resource-label svg{width:18px;height:18px;fill:var(--health)}.resource-number{text-align:right;overflow-wrap:anywhere;min-width:0;font-size:15px}
|
|
27
|
-
.resource-track{height:18px;position:relative;margin-top:5px;border:1px solid var(--track-edge);border-radius:10px;overflow:hidden;background:linear-gradient(var(--track),#f2f5ed);box-shadow:inset 0 1px 2px #6e805825}.resource-fill{display:block;position:absolute;top:0;bottom:0;left:0;border-radius:9px;background:linear-gradient(var(--health-light),var(--health) 55%,color-mix(in srgb,var(--health) 80%,var(--health-light)));border-right:1px solid #fff9}.resource-percent{position:absolute;inset:0;display:grid;place-items:center;font:11px/1 "Microsoft YaHei",sans-serif;color:#fffef7;text-shadow:0 1px 2px #435443}.exp-resource
|
|
28
|
-
.
|
|
28
|
+
.resource-track{height:18px;position:relative;margin-top:5px;border:1px solid var(--track-edge);border-radius:10px;overflow:hidden;background:linear-gradient(var(--track),#f2f5ed);box-shadow:inset 0 1px 2px #6e805825}.resource-fill{display:block;position:absolute;top:0;bottom:0;left:0;border-radius:9px;background:linear-gradient(var(--health-light),var(--health) 55%,color-mix(in srgb,var(--health) 80%,var(--health-light)));border-right:1px solid #fff9}.resource-percent{position:absolute;inset:0;display:grid;place-items:center;font:11px/1 "Microsoft YaHei",sans-serif;color:#fffef7;text-shadow:0 1px 2px #435443}.exp-resource{width:calc(100% - 20px);align-self:center;margin:0 0 14px}.exp-resource .resource-track{height:6px;margin-top:0;border-color:#d5c48b;border-radius:4px;background:#eee9d7;box-shadow:inset 0 1px 1px #9d82351a}.exp-resource .resource-fill{border-radius:3px;border-right:0;background:linear-gradient(#fff0a0,#e8bd48 60%,#d6a934)}
|
|
29
|
+
.hp-resource{display:flex;align-items:center;margin-top:16px;margin-bottom:0}.hp-resource .resource-track{flex:1;min-width:0;height:20px;margin-top:0}.hp-bar-value{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:0 8px;white-space:nowrap;font:12px/1 "Microsoft YaHei",sans-serif;color:#fffef7;text-shadow:0 1px 2px #435443,0 0 2px #435443}
|
|
30
|
+
.companion-attributes{margin-top:5px;min-width:0;flex:1;display:flex;flex-direction:column;justify-content:center}.attribute-divider{height:28px;margin:0 0 3px;display:flex;align-items:center;justify-content:center}.attribute-divider svg{display:block;width:100%;height:36px}.companion-radar{width:100%;height:260px;display:block;overflow:visible}
|
|
29
31
|
.radar-grid{fill:none;stroke:var(--radar-grid);stroke-width:1.1}.radar-axis{stroke:var(--radar-grid);stroke-width:1;opacity:.8}.radar-area{fill:var(--radar-fill);stroke:var(--radar);stroke-width:2.3;stroke-linejoin:round}.radar-dot{fill:#fffefa;stroke:var(--radar);stroke-width:2}.radar-label{font:19px "KaiTi","STKaiti","Microsoft YaHei",sans-serif;fill:var(--ink)}.radar-value{font:20px Georgia,"Microsoft YaHei",serif;fill:var(--ink)}.radar-scale{font:11px Georgia,serif;fill:var(--subtle)}.empty-attributes{padding:45px 10px;color:var(--subtle);font:18px/1.6 "Microsoft YaHei",sans-serif;text-align:center}.custom-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:5px 10px;margin:6px 0 0;font:15px/1.5 "Microsoft YaHei",sans-serif;color:var(--subtle)}.custom-attributes span{overflow-wrap:anywhere}.custom-attributes b{font-weight:500;color:var(--ink)}
|
|
30
32
|
`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CharacterCardData } from '../shared/face'
|
|
2
2
|
import { cardEscape } from './detailCardTemplate'
|
|
3
3
|
import { characterCardStyles } from './characterCardStyles'
|
|
4
|
-
import { characterFloralWatermark, characterGeneCrest, characterTierOrnament, characterTitlePlaceholder } from './characterCardAssets'
|
|
4
|
+
import { characterFloralWatermark, characterGeneCrest, characterTierOrnament, characterTitlePlaceholder, characterAttributeDivider } from './characterCardAssets'
|
|
5
5
|
import type { CardEntryArtwork } from './companionCardTemplate'
|
|
6
6
|
|
|
7
7
|
const finite = (value: number) => Number.isFinite(value) ? value : 0
|
|
@@ -12,7 +12,6 @@ const primaryAttributes = [
|
|
|
12
12
|
['intelligence', '智力'], ['spirit', '精神力'], ['resistance', '抗性'],
|
|
13
13
|
] as const
|
|
14
14
|
const primaryIds: Set<string> = new Set(primaryAttributes.map(([id]) => id))
|
|
15
|
-
const heading = (label: string) => `<h2 class="ornament-heading"><span class="heading-star" aria-hidden="true">✦</span>${cardEscape(label)}<span class="heading-star" aria-hidden="true">✦</span></h2>`
|
|
16
15
|
const corners = (tier: number, positions: string[] = ['tl', 'tr', 'bl', 'br']) => positions.map(position => `<span class="panel-corner corner-${position}" data-decoration-level="${tier}">${characterTierOrnament(tier)}</span>`).join('')
|
|
17
16
|
|
|
18
17
|
function radar(attributes: CharacterCardData['attributes']): string {
|
|
@@ -57,13 +56,15 @@ export function characterCardHtml(card: CharacterCardData, artwork?: string, _fr
|
|
|
57
56
|
const hpPercent = ratio(card.hp, card.maxHp) * 100
|
|
58
57
|
const experience = Math.max(0, Math.min(100, finite(card.experiencePercent)))
|
|
59
58
|
const geneRank = card.geneLockRankName || '基因锁未开启'
|
|
59
|
+
const explorationRank = card.explorationRank?.trim()
|
|
60
60
|
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><style>${characterCardStyles}</style></head><body><main id="capture" class="companion-sheet character-adventure character-sheet gene-tier-${tier}" data-gene-lock-tier="${tier}" data-decoration-level="${tier}"><span class="character-ambient" aria-hidden="true">${characterFloralWatermark}</span><div class="character-card companion-main">
|
|
61
61
|
<div class="portrait-column"><div class="companion-panel companion-portrait character-portrait">${corners(tier)}<div class="portrait-window portrait">${portrait ? `<img id="character-image" class="character-artwork" src="${cardEscape(portrait)}" data-fallback="${cardEscape(defaultArtwork ?? '')}" alt="${cardEscape(card.name)}的形象图">` : '<div class="placeholder"><span>形象尚未生成</span><small>角色形象</small></div>'}</div>
|
|
62
|
-
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
<
|
|
66
|
-
<div class="resource companion-resource
|
|
67
|
-
<
|
|
62
|
+
${titleArtwork || card.titleImageUrl ? `<div class="title-image-slot character-title-centered"><img id="title-image" class="title-artwork" src="${cardEscape(titleArtwork || characterTitlePlaceholder)}" data-fallback="${cardEscape(characterTitlePlaceholder)}" alt="${titleArtwork ? '称号图片' : '称号图片占位'}"></div>` : ''}</div>
|
|
63
|
+
<div class="combat-row companion-power-row"><span class="power-emblem power-icon" aria-hidden="true"><svg class="crossed-weapons" viewBox="0 0 42 42"><g fill="currentColor" stroke="var(--panel)" stroke-width=".9" stroke-linejoin="round"><g transform="rotate(-45 21 21)"><path d="M21 2 26 9v14l-5 4-5-4V9Z"/><path d="M12 26h18l-1 4H13Zm7 4h4v8h-4Zm-1 8h6v3h-6Z"/><path d="M21 7v15" fill="none" stroke="var(--light-edge)" stroke-width="1.1"/></g><g transform="rotate(45 21 21)"><path d="M21 2 26 9v14l-5 4-5-4V9Z"/><path d="M12 26h18l-1 4H13Zm7 4h4v8h-4Zm-1 8h6v3h-6Z"/><path d="M21 7v15" fill="none" stroke="var(--light-edge)" stroke-width="1.1"/></g></g></svg></span><span class="power-label companion-power-label">战力</span><strong id="combat-power" class="power-value companion-power">${number(card.power)}</strong></div>
|
|
64
|
+
</div>
|
|
65
|
+
<section class="companion-panel companion-stats character-stats" aria-label="角色属性"><span class="character-paper-pattern" aria-hidden="true">${characterFloralWatermark}</span>${corners(tier, ['tr', 'br'])}<div class="identity character-identity"><h1 id="character-name" class="character-name" title="${cardEscape(card.name)}">${cardEscape(card.name)}</h1><p class="level character-level"><span>Lv.</span><strong id="character-level">${number(card.level)}</strong></p><div class="gene-panel"><span class="gene-crest" aria-hidden="true">${characterGeneCrest(tier)}</span><div id="gene-rank" class="gene-rank" title="${cardEscape(geneRank)}">${cardEscape(geneRank)}</div></div><p class="exploration-rank-row"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M19.8 7.7A8 8 0 1 0 20 16M20 3v5h-5M15.8 12a3.8 3.8 0 1 1-3.8-3.8"/></svg><span>轮回等级</span> <strong id="exploration-rank">${cardEscape(explorationRank ? explorationRank + '级' : '—')}</strong></p></div>
|
|
66
|
+
<div class="resource companion-resource hp-resource"><div class="resource-track" role="progressbar" aria-label="生命值" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${hpPercent}" aria-valuetext="${number(card.hp)} / ${number(card.maxHp)}"><span class="resource-fill fill" style="width:${hpPercent}%"></span><span id="hp-numbers" class="hp-bar-value">${number(card.hp)} / ${number(card.maxHp)}</span></div></div>
|
|
67
|
+
<div class="resource companion-resource exp-resource"><div id="experience-track" class="resource-track" role="progressbar" aria-label="经验进度" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${experience}"><span class="resource-fill" style="width:${experience}%"></span></div></div>
|
|
68
|
+
<section class="attribute-panel companion-attributes" aria-label="一级属性"><div class="attribute-divider" aria-hidden="true">${characterAttributeDivider}</div>${radar(card.attributes)}</section></section>
|
|
68
69
|
</div></main></body></html>`
|
|
69
70
|
}
|
|
@@ -52,8 +52,12 @@ export function renderQQCommandMarkdown(data: IMessage, showGreeting: boolean):
|
|
|
52
52
|
break
|
|
53
53
|
}
|
|
54
54
|
flushRewards()
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
// A single message item may contain a complete multiline battle summary.
|
|
56
|
+
// Keep its line/paragraph boundaries when log links select native Markdown.
|
|
57
|
+
for (const line of item.content.replace(/\r\n?/g, '\n').split('\n')) {
|
|
58
|
+
if (!line.trim()) flushBody()
|
|
59
|
+
else bodyLines.push(renderInlineCommands(line))
|
|
60
|
+
}
|
|
57
61
|
break
|
|
58
62
|
case MessageType.error:
|
|
59
63
|
flushBody()
|
|
@@ -5,6 +5,7 @@ import { compactDisplayText, escapeMarkdown, renderQQTitle } from './qqMarkdownH
|
|
|
5
5
|
import { isRewardMessage, renderRewardLine, renderRewardTitle } from './qqRewardMessage'
|
|
6
6
|
import { artworkIdentity } from '../skillArtwork'
|
|
7
7
|
import { battleLogLinkSpans, renderBattleLogLink } from './qqBattleLogLinks'
|
|
8
|
+
import { inlineCommandSpans as bracketedCommandSpans, type InlineCommandSpan } from '../../shared/bot/inlineCommands'
|
|
8
9
|
|
|
9
10
|
export { escapeMarkdown, renderQQTitle } from './qqMarkdownHelpers'
|
|
10
11
|
|
|
@@ -54,27 +55,9 @@ export function inlineCommandUrl(command: string): string {
|
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
|
|
57
|
-
type InlineCommandSpan = { start: number; end: number; label: string; command: string }
|
|
58
|
-
|
|
59
58
|
/** Bracketed commands may appear anywhere in prose, including escaped brackets. */
|
|
60
59
|
function inlineCommandSpans(content: string): InlineCommandSpan[] {
|
|
61
|
-
const spans
|
|
62
|
-
let depth = 0, start = 0, labelStart = 0
|
|
63
|
-
for (let index = 0; index < content.length; index++) {
|
|
64
|
-
if (content[index] === '[') {
|
|
65
|
-
if (depth === 0) {
|
|
66
|
-
start = index > 0 && content[index - 1] === '\\' ? index - 1 : index
|
|
67
|
-
labelStart = index + 1
|
|
68
|
-
}
|
|
69
|
-
depth++
|
|
70
|
-
} else if (content[index] === ']' && depth > 0 && --depth === 0) {
|
|
71
|
-
const label = content.slice(labelStart, index).replace(/\\$/, '')
|
|
72
|
-
if (!label.trim() || /[\[\]\r\n]/.test(label) || /^\d+$/.test(label.trim())) continue
|
|
73
|
-
// The refresh icon is part of the displayed label, not the command to send.
|
|
74
|
-
const command = label.split(/[++]/, 1)[0].trim().replace(/^🔄\s*/u, '')
|
|
75
|
-
if (command) spans.push({ start, end: index + 1, label, command })
|
|
76
|
-
}
|
|
77
|
-
}
|
|
60
|
+
const spans = bracketedCommandSpans(content)
|
|
78
61
|
const logLinks = battleLogLinkSpans(content)
|
|
79
62
|
return spans.filter(span => !logLinks.some(link => span.start < link.end && span.end > link.start))
|
|
80
63
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IMessage, MessageType, type PageNavData } from '../face'
|
|
2
|
+
import { renderPlainInlineCommandAliases } from './inlineCommands'
|
|
2
3
|
|
|
3
4
|
/** 把服务器下发的结构化行拼成纯文本;第一阶段只处理 title / line / error **/
|
|
4
5
|
export class AnalysisMsg {
|
|
@@ -31,7 +32,9 @@ export class AnalysisMsg {
|
|
|
31
32
|
? labeledRow.map(entry => entry.label! + (entry.description ? ' · ' + entry.description : '')
|
|
32
33
|
+ ` [${entry.viewCommand}]`).join('')
|
|
33
34
|
: withCommandHint(item.content, commands.get(lineIndex))
|
|
34
|
-
|
|
35
|
+
const plainContent = item.codeBlock || item.mailPart === 'body' || labeledRow
|
|
36
|
+
? content : renderPlainInlineCommandAliases(content)
|
|
37
|
+
msg += `${plainContent}\n`
|
|
35
38
|
break
|
|
36
39
|
case MessageType.error:
|
|
37
40
|
msg += `❌出错了!错误原因:${item.content},请反馈至联系开发者\n`
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type InlineCommandSpan = { start: number; end: number; label: string; command: string; aliased?: true }
|
|
2
|
+
|
|
3
|
+
/** Boxed commands may use [label](command:input) to show a different action label. */
|
|
4
|
+
export function inlineCommandSpans(content: string): InlineCommandSpan[] {
|
|
5
|
+
const spans: InlineCommandSpan[] = []
|
|
6
|
+
let depth = 0, start = 0, labelStart = 0
|
|
7
|
+
for (let index = 0; index < content.length; index++) {
|
|
8
|
+
if (content[index] === '[') {
|
|
9
|
+
if (depth === 0) {
|
|
10
|
+
start = index > 0 && content[index - 1] === '\\' ? index - 1 : index
|
|
11
|
+
labelStart = index + 1
|
|
12
|
+
}
|
|
13
|
+
depth++
|
|
14
|
+
} else if (content[index] === ']' && depth > 0 && --depth === 0) {
|
|
15
|
+
const label = content.slice(labelStart, index).replace(/\\$/, '')
|
|
16
|
+
if (!label.trim() || /[\[\]\r\n]/.test(label) || /^\d+$/.test(label.trim())) continue
|
|
17
|
+
const alias = /^\(command:([^()[\]\r\n]+)\)/.exec(content.slice(index + 1))
|
|
18
|
+
// Ordinary templates keep their existing command extraction rules.
|
|
19
|
+
const command = alias ? alias[1].trim() : label.split(/[++]/, 1)[0].trim().replace(/^🔄\s*/u, '')
|
|
20
|
+
if (!command) continue
|
|
21
|
+
const end = index + 1 + (alias?.[0].length ?? 0)
|
|
22
|
+
spans.push({ start, end, label, command, ...(alias ? { aliased: true as const } : {}) })
|
|
23
|
+
if (alias) index = end - 1
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return spans
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Keep aliased actions usable when the platform falls back to ordinary text. */
|
|
30
|
+
export function renderPlainInlineCommandAliases(content: string): string {
|
|
31
|
+
let result = '', offset = 0
|
|
32
|
+
for (const span of inlineCommandSpans(content)) {
|
|
33
|
+
if (!span.aliased) continue
|
|
34
|
+
result += content.slice(offset, span.start)
|
|
35
|
+
+ (span.label.trim() === span.command ? `[${span.command}]` : `${span.label}[${span.command}]`)
|
|
36
|
+
offset = span.end
|
|
37
|
+
}
|
|
38
|
+
return result + content.slice(offset)
|
|
39
|
+
}
|
|
@@ -25,7 +25,7 @@ export interface ServiceType {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export const serviceProto: ServiceProto<ServiceType> = {
|
|
28
|
-
"version":
|
|
28
|
+
"version": 38,
|
|
29
29
|
"services": [
|
|
30
30
|
{
|
|
31
31
|
"id": 0,
|
|
@@ -709,6 +709,14 @@ export const serviceProto: ServiceProto<ServiceType> = {
|
|
|
709
709
|
}
|
|
710
710
|
},
|
|
711
711
|
"optional": true
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
"id": 14,
|
|
715
|
+
"name": "explorationRank",
|
|
716
|
+
"type": {
|
|
717
|
+
"type": "String"
|
|
718
|
+
},
|
|
719
|
+
"optional": true
|
|
712
720
|
}
|
|
713
721
|
]
|
|
714
722
|
},
|
package/src/shared/face/index.ts
CHANGED
|
@@ -38,7 +38,7 @@ export interface CharacterCardData {
|
|
|
38
38
|
bloodlines: Array<{ name: string; quality: string; artworkUrl?: string }>;
|
|
39
39
|
/** 当前基因锁大阶的配置名称,不包含层级;未开启时为基因锁未开启。 */
|
|
40
40
|
geneLockRankName?: string;
|
|
41
|
-
/**
|
|
41
|
+
/** 当前称号的图片链接;未获得称号或图片不可用时省略,客户端不显示称号横幅。 */
|
|
42
42
|
titleImageUrl?: string;
|
|
43
43
|
/** 已获得的真实基因锁大阶(0~5);0 表示尚未解锁。 */
|
|
44
44
|
geneLockTier?: number;
|
|
@@ -46,6 +46,8 @@ export interface CharacterCardData {
|
|
|
46
46
|
equipment?: Array<{ id: string; name: string; quality: string; slot: string; enhancement?: number }>;
|
|
47
47
|
/** 当前构筑的全部技能,包括装备、递归附带与限时增益来源。 */
|
|
48
48
|
skills?: Array<{ id: string; name: string; rank: number; quality?: string; type?: CompanionSkillType; artworkUrl?: string }>;
|
|
49
|
+
/** 玩家当前的轮回探索品阶(F~SSS),与角色等级、基因锁阶级分开显示。 */
|
|
50
|
+
explorationRank?: string;
|
|
49
51
|
}
|
|
50
52
|
export enum CompanionCardKind {
|
|
51
53
|
pet = 'pet',
|