import promptAction from '@ohos.promptAction';
import window from '@ohos.window';
import common from '@ohos.app.ability.common';
import { ComponentContent } from '@ohos.arkui.node';
/** 弹窗交互结果。 */
interface DialogResult {
index: number;
}
/** `prompt` 弹窗参数。 */
class PromptDialogParams {
public message: string = '';
public defaultValue: string = '';
public inputValue: string = '';
public onConfirm: (value: string) => void = (_v: string): void => {};
public onCancel: () => void = (): void => {};
constructor(
message: string,
defaultValue: string,
onConfirm: (value: string) => void,
onCancel: () => void
) {
this.message = message;
this.defaultValue = defaultValue;
this.inputValue = defaultValue;
this.onConfirm = onConfirm;
this.onCancel = onCancel;
}
}
@Builder
function buildPromptDialog(params: PromptDialogParams): void {
Column() {
Text('提示')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#000000')
.width('100%')
.textAlign(TextAlign.Start)
.margin({ bottom: 12 });
Text(params.message)
.fontSize(14)
.fontColor('#333333')
.width('100%')
.textAlign(TextAlign.Start)
.margin({ bottom: 12 });
TextInput({ text: params.defaultValue, placeholder: '请输入' })
.width('100%')
.height(40)
.fontSize(14)
.fontColor('#222222')
.placeholderColor('#999999')
.caretColor('#1989FA')
.backgroundColor('#F5F5F5')
.borderRadius(6)
.padding({ left: 12, right: 12 })
.margin({ bottom: 16 })
.onChange((value: string): void => {
params.inputValue = value;
});
Row() {
Button('取消')
.type(ButtonType.Normal)
.backgroundColor(Color.Transparent)
.fontColor('#999999')
.layoutWeight(1)
.height(44)
.onClick((): void => {
params.onCancel();
});
Divider()
.vertical(true)
.height(20)
.color('#E5E5E5');
Button('确定')
.type(ButtonType.Normal)
.backgroundColor(Color.Transparent)
.fontColor('#000000')
.fontWeight(FontWeight.Medium)
.layoutWeight(1)
.height(44)
.onClick((): void => {
params.onConfirm(params.inputValue);
});
}
.width('100%')
.alignItems(VerticalAlign.Center);
}
.padding({ top: 20, left: 20, right: 20, bottom: 4 })
.backgroundColor('#FFFFFF')
.borderRadius(14)
.width('80%');
}
/**
* 处理 WebView 中 JS `alert` / `confirm` / `prompt` 弹窗。
*/
export class JsDialogHandler {
/** 弹出 alert 对话框。 */
public static async showAlert(context: common.UIAbilityContext, url: string, message: string): Promise<boolean> {
const safeMsg: string = message ?? '';
try {
const uc: UIContext | null = await JsDialogHandler.getUIContext(context);
if (uc !== null) {
await uc.getPromptAction().showDialog({
title: '提示',
message: safeMsg,
buttons: [{ text: '确定', color: '#1989FA' }]
});
} else {
await promptAction.showDialog({
title: '提示',
message: safeMsg,
buttons: [{ text: '确定', color: '#1989FA' }]
});
}
return true;
} catch (_e) {
return false;
}
}
/** 弹出 confirm 对话框。 */
public static async showConfirm(context: common.UIAbilityContext, url: string, message: string): Promise<boolean> {
const safeMsg: string = message ?? '';
try {
const uc: UIContext | null = await JsDialogHandler.getUIContext(context);
let result: DialogResult;
if (uc !== null) {
result = await uc.getPromptAction().showDialog({
title: '提示',
message: safeMsg,
buttons: [
{ text: '取消', color: '#999999' },
{ text: '确定', color: '#1989FA' }
]
}) as DialogResult;
} else {
result = await promptAction.showDialog({
title: '提示',
message: safeMsg,
buttons: [
{ text: '取消', color: '#999999' },
{ text: '确定', color: '#1989FA' }
]
}) as DialogResult;
}
return result.index === 1;
} catch (_e) {
return false;
}
}
/** 弹出 prompt 对话框(含文本输入)。 */
public static async showPrompt(
context: common.UIAbilityContext,
url: string,
message: string,
defaultValue: string
): Promise<string | null> {
const safeMsg: string = message ?? '';
const safeDefault: string = defaultValue ?? '';
let uiCtx: UIContext | null = await JsDialogHandler.getUIContext(context);
if (uiCtx === null) {
return JsDialogHandler.showPromptFallback(safeMsg, safeDefault);
}
return new Promise<string | null>((resolve: (v: string | null) => void): void => {
const finalUiCtx: UIContext = uiCtx as UIContext;
let contentNode: ComponentContent<PromptDialogParams> | null = null;
const closeAndResolve = (value: string | null): void => {
try {
if (contentNode !== null) {
finalUiCtx.getPromptAction().closeCustomDialog(contentNode);
}
} catch (_e) {
// ignore
}
resolve(value);
};
const params: PromptDialogParams = new PromptDialogParams(
safeMsg,
safeDefault,
(value: string): void => { closeAndResolve(value); },
(): void => { closeAndResolve(null); }
);
try {
contentNode = new ComponentContent<PromptDialogParams>(
finalUiCtx,
wrapBuilder<[PromptDialogParams]>(buildPromptDialog),
params
);
finalUiCtx.getPromptAction().openCustomDialog(contentNode, {
alignment: DialogAlignment.Center,
autoCancel: false,
maskColor: '#80000000'
}).catch((_e: Object): void => { resolve(null); });
} catch (_e) {
resolve(null);
}
});
}
/** prompt 对话框的简化实现(不含自定义输入控件)。 */
private static async showPromptFallback(message: string, defaultValue: string): Promise<string | null> {
const composedMessage: string = message
+ (defaultValue.length > 0 ? ('\n\n默认值: ' + defaultValue) : '');
try {
const result = await promptAction.showDialog({
title: '提示',
message: composedMessage,
buttons: [
{ text: '取消', color: '#999999' },
{ text: '确定', color: '#1989FA' }
]
}) as DialogResult;
return result.index === 1 ? defaultValue : null;
} catch (_e) {
return null;
}
}
/** 获取当前窗口的 UIContext。 */
private static async getUIContext(context: common.UIAbilityContext): Promise<UIContext | null> {
try {
const win: window.Window = await window.getLastWindow(context);
return win.getUIContext();
} catch (_e) {
return null;
}
}
private constructor() {}
}
|