You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
514 lines
19 KiB
514 lines
19 KiB
|
1 day ago
|
import {
|
||
|
|
Button, Color, EditBox, Graphics, Label, Layout, Mask, Node, ScrollView, UITransform, Widget,
|
||
|
|
HorizontalTextAlignment, VerticalTextAlignment, Layers, Overflow,
|
||
|
|
} from 'cc';
|
||
|
|
import type { IGmContentPanel, IGmPanelContext } from '../../mx/module/gm';
|
||
|
|
import { Doc } from '../game/GameData';
|
||
|
|
import { ProjectGmActions } from './ProjectGmActions';
|
||
|
|
import MTools from '../../mx/tools/MTools';
|
||
|
|
|
||
|
|
const C = {
|
||
|
|
text: new Color(255, 255, 255, 255),
|
||
|
|
dim: new Color(180, 190, 210, 255),
|
||
|
|
accent: new Color(255, 220, 70, 255),
|
||
|
|
rowBg: new Color(28, 36, 56, 255),
|
||
|
|
inputBg: new Color(12, 16, 28, 255),
|
||
|
|
inputLine: new Color(100, 160, 240, 255),
|
||
|
|
btn: new Color(36, 130, 95, 255),
|
||
|
|
btnSet: new Color(210, 120, 35, 255),
|
||
|
|
btnSave: new Color(45, 105, 190, 255),
|
||
|
|
btnCancel: new Color(70, 78, 96, 255),
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 固定字号,避免 Overflow.SHRINK 把字压到看不清 */
|
||
|
|
const FONT = {
|
||
|
|
section: 26,
|
||
|
|
label: 24,
|
||
|
|
input: 24,
|
||
|
|
tip: 20,
|
||
|
|
btn: 26,
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Doc 字段中文名 */
|
||
|
|
const DOC_LABELS: { [key: string]: string } = {
|
||
|
|
key: '存档key',
|
||
|
|
uid: '用户uid',
|
||
|
|
roleId: '角色roleId',
|
||
|
|
playerTitleLevel: '称号等级',
|
||
|
|
dataVersion: 'dataVersion',
|
||
|
|
rankId: '段位id',
|
||
|
|
rankStars: '总星数',
|
||
|
|
pendingBattleOppRankId: '未结算对手段位',
|
||
|
|
matchWinCount: '匹配胜场',
|
||
|
|
matchLoseCount: '匹配负场',
|
||
|
|
totalBattleCount: '总挑战次数',
|
||
|
|
matchWinStatsDate: '胜率统计日',
|
||
|
|
matchWinStreak: '连胜',
|
||
|
|
matchLoseStreak: '连败',
|
||
|
|
dailyWins: '今日胜场',
|
||
|
|
yesterdayWins: '昨日胜场',
|
||
|
|
dailyWinsDate: '今日胜场日期',
|
||
|
|
rankLastSyncDailyWins: '同步每日胜场',
|
||
|
|
rankLastSyncDailyWinsDate: '同步每日胜场日',
|
||
|
|
userName: '昵称',
|
||
|
|
userAvatar: '头像url',
|
||
|
|
userProvince: '省份',
|
||
|
|
rankUserAuthPrompted: '已弹授权',
|
||
|
|
rankSyncedOnce: '已同步排行',
|
||
|
|
rankLastSyncStars: '同步星数',
|
||
|
|
rankLastSyncProvince: '同步省份',
|
||
|
|
rankLastSyncNick: '同步昵称',
|
||
|
|
rankLastSyncAvatar: '同步头像',
|
||
|
|
rankLastSyncRegion: '同步地区',
|
||
|
|
emolumentSnapStars: '俸禄待领星',
|
||
|
|
emolumentSnapWins: '俸禄待领胜',
|
||
|
|
emolumentSnapDate: '俸禄快照日',
|
||
|
|
gmAwaitEmolumentPop: 'GM弹俸禄',
|
||
|
|
headIconId: '头像id',
|
||
|
|
battleIllustratedGuideClicked: '已点图鉴',
|
||
|
|
level: '关卡level',
|
||
|
|
itemCount: '道具itemCount',
|
||
|
|
status: '状态status',
|
||
|
|
statistics: '统计statistics',
|
||
|
|
guide: '引导guide',
|
||
|
|
other: '其他other',
|
||
|
|
onlyLocal: '仅本地onlyLocal',
|
||
|
|
failCount: '上报失败次数',
|
||
|
|
lastFailCount: '上次上报失败次数',
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 存档页:复制 / 设置(必弹粘贴层)+ Doc 全字段上下布局编辑。
|
||
|
|
*/
|
||
|
|
export class GmSaveEditorPanel implements IGmContentPanel {
|
||
|
|
private _root: Node | null = null;
|
||
|
|
private _ctx: IGmPanelContext | null = null;
|
||
|
|
private _scrollContent: Node | null = null;
|
||
|
|
private _listW = 660;
|
||
|
|
private _fieldEdits: { key: string; edit: EditBox }[] = [];
|
||
|
|
private _pasteLayer: Node | null = null;
|
||
|
|
private _pasteEdit: EditBox | null = null;
|
||
|
|
|
||
|
|
open(parent: Node, ctx: IGmPanelContext): void {
|
||
|
|
this.close();
|
||
|
|
this._ctx = ctx;
|
||
|
|
const pUt = parent.getComponent(UITransform);
|
||
|
|
const W = pUt?.width || 660;
|
||
|
|
const H = pUt?.height || 900;
|
||
|
|
this._listW = W - 24;
|
||
|
|
|
||
|
|
this._root = new Node('saveEditor');
|
||
|
|
this._root.layer = Layers.Enum.UI_2D;
|
||
|
|
this._root.addComponent(UITransform).setContentSize(W, H);
|
||
|
|
const rw = this._root.addComponent(Widget);
|
||
|
|
rw.isAlignLeft = rw.isAlignRight = rw.isAlignTop = rw.isAlignBottom = true;
|
||
|
|
rw.left = rw.right = rw.top = rw.bottom = 0;
|
||
|
|
parent.addChild(this._root);
|
||
|
|
|
||
|
|
const topH = 118;
|
||
|
|
const top = new Node('top');
|
||
|
|
top.layer = Layers.Enum.UI_2D;
|
||
|
|
top.addComponent(UITransform).setContentSize(W, topH);
|
||
|
|
const tw = top.addComponent(Widget);
|
||
|
|
tw.isAlignTop = tw.isAlignLeft = tw.isAlignRight = true;
|
||
|
|
tw.top = 0;
|
||
|
|
tw.left = tw.right = 0;
|
||
|
|
this._root.addChild(top);
|
||
|
|
|
||
|
|
this._makeBtn(top, '复制存档', 200, 52, C.btn, () => {
|
||
|
|
ProjectGmActions.copySave();
|
||
|
|
}).setPosition(-120, 28);
|
||
|
|
|
||
|
|
this._makeBtn(top, '设置存档', 200, 52, C.btnSet, () => {
|
||
|
|
this._openSetSaveFlow();
|
||
|
|
}).setPosition(120, 28);
|
||
|
|
|
||
|
|
const tip = new Node('tip');
|
||
|
|
tip.layer = Layers.Enum.UI_2D;
|
||
|
|
tip.addComponent(UITransform).setContentSize(W - 32, 44);
|
||
|
|
const tipLb = tip.addComponent(Label);
|
||
|
|
tipLb.string = '设置存档会打开粘贴框;下方每字段:上名称、下输入';
|
||
|
|
tipLb.fontSize = FONT.tip;
|
||
|
|
tipLb.lineHeight = 24;
|
||
|
|
tipLb.color = C.dim;
|
||
|
|
tipLb.isBold = true;
|
||
|
|
tipLb.horizontalAlign = HorizontalTextAlignment.CENTER;
|
||
|
|
tip.setPosition(0, -32);
|
||
|
|
top.addChild(tip);
|
||
|
|
|
||
|
|
const bottomH = 76;
|
||
|
|
const { host, content } = this._makeScroll(this._listW, Math.max(200, H - topH - bottomH - 8));
|
||
|
|
this._scrollContent = content;
|
||
|
|
const sw = host.addComponent(Widget);
|
||
|
|
sw.isAlignTop = sw.isAlignBottom = sw.isAlignLeft = sw.isAlignRight = true;
|
||
|
|
sw.top = topH;
|
||
|
|
sw.bottom = bottomH;
|
||
|
|
sw.left = sw.right = 12;
|
||
|
|
this._root.addChild(host);
|
||
|
|
|
||
|
|
this._rebuildFieldList();
|
||
|
|
|
||
|
|
const bottom = new Node('bottom');
|
||
|
|
bottom.layer = Layers.Enum.UI_2D;
|
||
|
|
bottom.addComponent(UITransform).setContentSize(W, bottomH);
|
||
|
|
const bw = bottom.addComponent(Widget);
|
||
|
|
bw.isAlignBottom = bw.isAlignLeft = bw.isAlignRight = true;
|
||
|
|
bw.bottom = 0;
|
||
|
|
bw.left = bw.right = 0;
|
||
|
|
this._root.addChild(bottom);
|
||
|
|
|
||
|
|
this._makeBtn(bottom, '保存全部字段', 320, 54, C.btnSave, () => {
|
||
|
|
this._applyFieldEdits();
|
||
|
|
}).setPosition(0, 4);
|
||
|
|
}
|
||
|
|
|
||
|
|
close(): void {
|
||
|
|
this._hidePasteLayer();
|
||
|
|
if (this._root?.isValid) this._root.destroy();
|
||
|
|
this._root = null;
|
||
|
|
this._ctx = null;
|
||
|
|
this._scrollContent = null;
|
||
|
|
this._fieldEdits = [];
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 每次点击必有界面反馈:打开粘贴层,并尝试自动填入剪切板 */
|
||
|
|
private _openSetSaveFlow(): void {
|
||
|
|
const host = this._ctx?.host;
|
||
|
|
if (this._pasteLayer?.isValid) {
|
||
|
|
host?.toast('请在弹层中粘贴或确认');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._showPasteLayer('可粘贴存档 JSON;若剪切板有内容将自动填入');
|
||
|
|
host?.toast('请粘贴或确认存档');
|
||
|
|
void this._tryFillClipboard();
|
||
|
|
}
|
||
|
|
|
||
|
|
private async _tryFillClipboard(): Promise<void> {
|
||
|
|
const r = await MTools.readClipboardResult(1500);
|
||
|
|
if (!this._pasteEdit || !this._pasteLayer?.isValid) return;
|
||
|
|
if (r.err || !r.text?.trim()) return;
|
||
|
|
this._pasteEdit.string = r.text.trim();
|
||
|
|
this._ctx?.host.toast('已从剪切板填入,请点确认设置');
|
||
|
|
}
|
||
|
|
|
||
|
|
private _rebuildFieldList(): void {
|
||
|
|
if (!this._scrollContent?.isValid) return;
|
||
|
|
this._scrollContent.removeAllChildren();
|
||
|
|
this._fieldEdits = [];
|
||
|
|
|
||
|
|
const doc = gg.data.doc as unknown as { [key: string]: unknown };
|
||
|
|
const template = new Doc() as unknown as { [key: string]: unknown };
|
||
|
|
const keySet: { [k: string]: boolean } = {};
|
||
|
|
const keys: string[] = [];
|
||
|
|
const addKey = (k: string): void => {
|
||
|
|
if (keySet[k]) return;
|
||
|
|
keySet[k] = true;
|
||
|
|
keys.push(k);
|
||
|
|
};
|
||
|
|
const tKeys = Object.keys(template);
|
||
|
|
for (let i = 0; i < tKeys.length; i++) addKey(tKeys[i]);
|
||
|
|
const dKeys = Object.keys(doc);
|
||
|
|
for (let i = 0; i < dKeys.length; i++) addKey(dKeys[i]);
|
||
|
|
|
||
|
|
this._addSection('标量字段');
|
||
|
|
for (let i = 0; i < keys.length; i++) {
|
||
|
|
const key = keys[i];
|
||
|
|
const cur = doc[key] !== undefined ? doc[key] : template[key];
|
||
|
|
if (Array.isArray(cur)) continue;
|
||
|
|
const title = DOC_LABELS[key] || key;
|
||
|
|
const sub = DOC_LABELS[key] ? key : '';
|
||
|
|
const row = this._addFieldRow(title, sub, false);
|
||
|
|
row.edit.string = cur === undefined || cur === null ? '' : String(cur);
|
||
|
|
this._fieldEdits.push({ key, edit: row.edit });
|
||
|
|
}
|
||
|
|
|
||
|
|
this._addSection('数组字段(JSON)');
|
||
|
|
for (let i = 0; i < keys.length; i++) {
|
||
|
|
const key = keys[i];
|
||
|
|
const cur = doc[key] !== undefined ? doc[key] : template[key];
|
||
|
|
if (!Array.isArray(cur)) continue;
|
||
|
|
const title = DOC_LABELS[key] || key;
|
||
|
|
const sub = DOC_LABELS[key] ? key : '';
|
||
|
|
const row = this._addFieldRow(title, sub, true);
|
||
|
|
try {
|
||
|
|
row.edit.string = JSON.stringify(cur);
|
||
|
|
} catch {
|
||
|
|
row.edit.string = '[]';
|
||
|
|
}
|
||
|
|
this._fieldEdits.push({ key, edit: row.edit });
|
||
|
|
}
|
||
|
|
|
||
|
|
this._scrollContent.getComponent(Layout)?.updateLayout();
|
||
|
|
}
|
||
|
|
|
||
|
|
private _showPasteLayer(reason: string): void {
|
||
|
|
this._hidePasteLayer();
|
||
|
|
if (!this._root?.isValid) return;
|
||
|
|
const W = this._root.getComponent(UITransform)!.width;
|
||
|
|
const H = this._root.getComponent(UITransform)!.height;
|
||
|
|
|
||
|
|
this._pasteLayer = new Node('pasteLayer');
|
||
|
|
this._pasteLayer.layer = Layers.Enum.UI_2D;
|
||
|
|
this._pasteLayer.addComponent(UITransform).setContentSize(W, H);
|
||
|
|
const g = this._pasteLayer.addComponent(Graphics);
|
||
|
|
g.fillColor = new Color(0, 0, 0, 210);
|
||
|
|
g.rect(-W / 2, -H / 2, W, H);
|
||
|
|
g.fill();
|
||
|
|
this._root.addChild(this._pasteLayer);
|
||
|
|
|
||
|
|
const cardW = Math.min(W - 32, 640);
|
||
|
|
const cardH = 400;
|
||
|
|
const card = new Node('card');
|
||
|
|
card.layer = Layers.Enum.UI_2D;
|
||
|
|
card.addComponent(UITransform).setContentSize(cardW, cardH);
|
||
|
|
this._drawRound(card, C.rowBg, cardW, cardH, 16);
|
||
|
|
this._pasteLayer.addChild(card);
|
||
|
|
|
||
|
|
const title = new Node('t');
|
||
|
|
title.layer = Layers.Enum.UI_2D;
|
||
|
|
title.addComponent(UITransform).setContentSize(cardW - 24, 40);
|
||
|
|
const tl = title.addComponent(Label);
|
||
|
|
tl.string = '设置存档';
|
||
|
|
tl.fontSize = 30;
|
||
|
|
tl.isBold = true;
|
||
|
|
tl.color = C.accent;
|
||
|
|
tl.horizontalAlign = HorizontalTextAlignment.CENTER;
|
||
|
|
title.setPosition(0, cardH / 2 - 32);
|
||
|
|
card.addChild(title);
|
||
|
|
|
||
|
|
const reasonN = new Node('r');
|
||
|
|
reasonN.layer = Layers.Enum.UI_2D;
|
||
|
|
reasonN.addComponent(UITransform).setContentSize(cardW - 32, 48);
|
||
|
|
const rl = reasonN.addComponent(Label);
|
||
|
|
rl.string = reason;
|
||
|
|
rl.fontSize = FONT.tip;
|
||
|
|
rl.color = C.dim;
|
||
|
|
rl.isBold = true;
|
||
|
|
rl.horizontalAlign = HorizontalTextAlignment.CENTER;
|
||
|
|
rl.overflow = Overflow.RESIZE_HEIGHT;
|
||
|
|
reasonN.setPosition(0, cardH / 2 - 78);
|
||
|
|
card.addChild(reasonN);
|
||
|
|
|
||
|
|
const editW = cardW - 40;
|
||
|
|
const editH = 180;
|
||
|
|
const editN = new Node('edit');
|
||
|
|
editN.layer = Layers.Enum.UI_2D;
|
||
|
|
editN.addComponent(UITransform).setContentSize(editW, editH);
|
||
|
|
this._drawRound(editN, C.inputBg, editW, editH, 10, C.inputLine);
|
||
|
|
const textLbN = new Node('TEXT_LABEL');
|
||
|
|
textLbN.layer = Layers.Enum.UI_2D;
|
||
|
|
textLbN.addComponent(UITransform).setContentSize(editW - 16, editH - 16);
|
||
|
|
const textLb = textLbN.addComponent(Label);
|
||
|
|
textLb.fontSize = FONT.input;
|
||
|
|
textLb.color = C.accent;
|
||
|
|
textLb.isBold = true;
|
||
|
|
textLb.horizontalAlign = HorizontalTextAlignment.LEFT;
|
||
|
|
textLb.verticalAlign = VerticalTextAlignment.TOP;
|
||
|
|
textLb.overflow = Overflow.CLAMP;
|
||
|
|
editN.addChild(textLbN);
|
||
|
|
const phN = new Node('PLACEHOLDER_LABEL');
|
||
|
|
phN.layer = Layers.Enum.UI_2D;
|
||
|
|
phN.addComponent(UITransform).setContentSize(editW - 16, editH - 16);
|
||
|
|
const phLb = phN.addComponent(Label);
|
||
|
|
phLb.string = '在此粘贴存档 JSON';
|
||
|
|
phLb.fontSize = FONT.input;
|
||
|
|
phLb.color = C.dim;
|
||
|
|
phLb.horizontalAlign = HorizontalTextAlignment.CENTER;
|
||
|
|
phLb.verticalAlign = VerticalTextAlignment.CENTER;
|
||
|
|
editN.addChild(phN);
|
||
|
|
this._pasteEdit = editN.addComponent(EditBox);
|
||
|
|
this._pasteEdit.textLabel = textLb;
|
||
|
|
this._pasteEdit.placeholderLabel = phLb;
|
||
|
|
this._pasteEdit.maxLength = 500000;
|
||
|
|
this._pasteEdit.inputMode = EditBox.InputMode.ANY;
|
||
|
|
editN.setPosition(0, 8);
|
||
|
|
card.addChild(editN);
|
||
|
|
|
||
|
|
this._makeBtn(card, '确认设置', 170, 52, C.btnSet, () => {
|
||
|
|
const raw = this._pasteEdit?.string ?? '';
|
||
|
|
if (!raw.trim()) {
|
||
|
|
this._ctx?.host.toast('内容为空');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const ok = ProjectGmActions.applySaveJson(raw, false);
|
||
|
|
if (ok) {
|
||
|
|
this._hidePasteLayer();
|
||
|
|
this._rebuildFieldList();
|
||
|
|
}
|
||
|
|
}).setPosition(-100, -cardH / 2 + 44);
|
||
|
|
|
||
|
|
this._makeBtn(card, '取消', 170, 52, C.btnCancel, () => {
|
||
|
|
this._hidePasteLayer();
|
||
|
|
}).setPosition(100, -cardH / 2 + 44);
|
||
|
|
}
|
||
|
|
|
||
|
|
private _hidePasteLayer(): void {
|
||
|
|
if (this._pasteLayer?.isValid) this._pasteLayer.destroy();
|
||
|
|
this._pasteLayer = null;
|
||
|
|
this._pasteEdit = null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private _applyFieldEdits(): void {
|
||
|
|
const fields: { [key: string]: string } = {};
|
||
|
|
for (let i = 0; i < this._fieldEdits.length; i++) {
|
||
|
|
const f = this._fieldEdits[i];
|
||
|
|
fields[f.key] = f.edit.string ?? '';
|
||
|
|
}
|
||
|
|
ProjectGmActions.applySaveFieldEdits(fields);
|
||
|
|
this._rebuildFieldList();
|
||
|
|
}
|
||
|
|
|
||
|
|
private _makeScroll(w: number, h: number): { host: Node; content: Node } {
|
||
|
|
const host = new Node('scroll');
|
||
|
|
host.layer = Layers.Enum.UI_2D;
|
||
|
|
host.addComponent(UITransform).setContentSize(w, h);
|
||
|
|
const view = new Node('view');
|
||
|
|
view.layer = Layers.Enum.UI_2D;
|
||
|
|
view.addComponent(UITransform).setContentSize(w, h);
|
||
|
|
view.addComponent(Mask);
|
||
|
|
const vw = view.addComponent(Widget);
|
||
|
|
vw.isAlignLeft = vw.isAlignRight = vw.isAlignTop = vw.isAlignBottom = true;
|
||
|
|
vw.left = vw.right = vw.top = vw.bottom = 0;
|
||
|
|
host.addChild(view);
|
||
|
|
const content = new Node('content');
|
||
|
|
content.layer = Layers.Enum.UI_2D;
|
||
|
|
const cut = content.addComponent(UITransform);
|
||
|
|
cut.setContentSize(w, h);
|
||
|
|
cut.setAnchorPoint(0.5, 1);
|
||
|
|
content.setPosition(0, h / 2);
|
||
|
|
const layout = content.addComponent(Layout);
|
||
|
|
layout.type = Layout.Type.VERTICAL;
|
||
|
|
layout.resizeMode = Layout.ResizeMode.CONTAINER;
|
||
|
|
layout.spacingY = 12;
|
||
|
|
layout.paddingTop = 8;
|
||
|
|
layout.paddingBottom = 28;
|
||
|
|
view.addChild(content);
|
||
|
|
const sv = host.addComponent(ScrollView);
|
||
|
|
sv.content = content;
|
||
|
|
sv.horizontal = false;
|
||
|
|
sv.vertical = true;
|
||
|
|
return { host, content };
|
||
|
|
}
|
||
|
|
|
||
|
|
private _addSection(title: string): void {
|
||
|
|
if (!this._scrollContent) return;
|
||
|
|
const n = new Node('sec');
|
||
|
|
n.layer = Layers.Enum.UI_2D;
|
||
|
|
n.addComponent(UITransform).setContentSize(this._listW, 40);
|
||
|
|
const lb = n.addComponent(Label);
|
||
|
|
lb.string = title;
|
||
|
|
lb.fontSize = FONT.section;
|
||
|
|
lb.isBold = true;
|
||
|
|
lb.color = C.accent;
|
||
|
|
lb.horizontalAlign = HorizontalTextAlignment.LEFT;
|
||
|
|
lb.overflow = Overflow.NONE;
|
||
|
|
this._scrollContent.addChild(n);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 上下布局:上行标题(固定字号),下行全宽输入框(固定字号)。
|
||
|
|
*/
|
||
|
|
private _addFieldRow(title: string, subKey: string, tall: boolean): { edit: EditBox } {
|
||
|
|
const rowH = tall ? 120 : 100;
|
||
|
|
const w = this._listW;
|
||
|
|
const row = new Node(title);
|
||
|
|
row.layer = Layers.Enum.UI_2D;
|
||
|
|
row.addComponent(UITransform).setContentSize(w, rowH);
|
||
|
|
this._drawRound(row, C.rowBg, w, rowH, 12);
|
||
|
|
|
||
|
|
const headH = 36;
|
||
|
|
const lbN = new Node('lb');
|
||
|
|
lbN.layer = Layers.Enum.UI_2D;
|
||
|
|
lbN.addComponent(UITransform).setContentSize(w - 24, headH);
|
||
|
|
const lb = lbN.addComponent(Label);
|
||
|
|
lb.string = subKey ? `${title} · ${subKey}` : title;
|
||
|
|
lb.fontSize = FONT.label;
|
||
|
|
lb.isBold = true;
|
||
|
|
lb.color = C.text;
|
||
|
|
lb.horizontalAlign = HorizontalTextAlignment.LEFT;
|
||
|
|
lb.verticalAlign = VerticalTextAlignment.CENTER;
|
||
|
|
lb.overflow = Overflow.CLAMP;
|
||
|
|
lb.enableWrapText = false;
|
||
|
|
lbN.setPosition(0, rowH / 2 - headH / 2 - 6);
|
||
|
|
row.addChild(lbN);
|
||
|
|
|
||
|
|
const editW = w - 24;
|
||
|
|
const editH = tall ? 68 : 48;
|
||
|
|
const editN = new Node('edit');
|
||
|
|
editN.layer = Layers.Enum.UI_2D;
|
||
|
|
editN.addComponent(UITransform).setContentSize(editW, editH);
|
||
|
|
this._drawRound(editN, C.inputBg, editW, editH, 8, C.inputLine);
|
||
|
|
|
||
|
|
const textLbN = new Node('TEXT_LABEL');
|
||
|
|
textLbN.layer = Layers.Enum.UI_2D;
|
||
|
|
textLbN.addComponent(UITransform).setContentSize(editW - 16, editH - 10);
|
||
|
|
const textLb = textLbN.addComponent(Label);
|
||
|
|
textLb.fontSize = FONT.input;
|
||
|
|
textLb.isBold = true;
|
||
|
|
textLb.color = C.accent;
|
||
|
|
textLb.horizontalAlign = HorizontalTextAlignment.LEFT;
|
||
|
|
textLb.verticalAlign = tall ? VerticalTextAlignment.TOP : VerticalTextAlignment.CENTER;
|
||
|
|
textLb.overflow = Overflow.CLAMP;
|
||
|
|
editN.addChild(textLbN);
|
||
|
|
|
||
|
|
const phN = new Node('PLACEHOLDER_LABEL');
|
||
|
|
phN.layer = Layers.Enum.UI_2D;
|
||
|
|
phN.addComponent(UITransform).setContentSize(editW - 16, editH - 10);
|
||
|
|
const phLb = phN.addComponent(Label);
|
||
|
|
phLb.string = tall ? '输入 JSON 数组' : '点击输入';
|
||
|
|
phLb.fontSize = FONT.input;
|
||
|
|
phLb.color = C.dim;
|
||
|
|
phLb.horizontalAlign = HorizontalTextAlignment.LEFT;
|
||
|
|
phLb.verticalAlign = VerticalTextAlignment.CENTER;
|
||
|
|
editN.addChild(phN);
|
||
|
|
|
||
|
|
const eb = editN.addComponent(EditBox);
|
||
|
|
eb.textLabel = textLb;
|
||
|
|
eb.placeholderLabel = phLb;
|
||
|
|
eb.maxLength = tall ? 200000 : 512;
|
||
|
|
eb.inputMode = tall ? EditBox.InputMode.ANY : EditBox.InputMode.SINGLE_LINE;
|
||
|
|
editN.setPosition(0, -rowH / 2 + editH / 2 + 8);
|
||
|
|
row.addChild(editN);
|
||
|
|
|
||
|
|
this._scrollContent!.addChild(row);
|
||
|
|
return { edit: eb };
|
||
|
|
}
|
||
|
|
|
||
|
|
private _makeBtn(parent: Node, text: string, w: number, h: number, bg: Color, onClick: () => void): Node {
|
||
|
|
const n = new Node(text);
|
||
|
|
n.layer = Layers.Enum.UI_2D;
|
||
|
|
n.addComponent(UITransform).setContentSize(w, h);
|
||
|
|
this._drawRound(n, bg, w, h, 12);
|
||
|
|
const lbN = new Node('lb');
|
||
|
|
lbN.layer = Layers.Enum.UI_2D;
|
||
|
|
lbN.addComponent(UITransform).setContentSize(w - 8, h - 4);
|
||
|
|
const lb = lbN.addComponent(Label);
|
||
|
|
lb.string = text;
|
||
|
|
lb.fontSize = FONT.btn;
|
||
|
|
lb.isBold = true;
|
||
|
|
lb.color = C.text;
|
||
|
|
lb.horizontalAlign = HorizontalTextAlignment.CENTER;
|
||
|
|
lb.verticalAlign = VerticalTextAlignment.CENTER;
|
||
|
|
lb.overflow = Overflow.NONE;
|
||
|
|
n.addChild(lbN);
|
||
|
|
n.addComponent(Button);
|
||
|
|
n.on(Button.EventType.CLICK, onClick, this);
|
||
|
|
parent.addChild(n);
|
||
|
|
return n;
|
||
|
|
}
|
||
|
|
|
||
|
|
private _drawRound(node: Node, fill: Color, w: number, h: number, r: number, stroke?: Color): void {
|
||
|
|
const g = node.getComponent(Graphics) || node.addComponent(Graphics);
|
||
|
|
g.clear();
|
||
|
|
g.fillColor = fill;
|
||
|
|
g.roundRect(-w / 2, -h / 2, w, h, r);
|
||
|
|
g.fill();
|
||
|
|
if (stroke) {
|
||
|
|
g.strokeColor = stroke;
|
||
|
|
g.lineWidth = 2;
|
||
|
|
g.roundRect(-w / 2, -h / 2, w, h, r);
|
||
|
|
g.stroke();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|