@@ -23,11 +23,17 @@ export class AppSettings {
|
||||
// 否则一旦某次因故没显示出来,旧标记会把功能永久锁死(v2 正是这样被锁住 → 本次升到 v3)。
|
||||
private static readonly KEY_TIPS_SHOWN: string = 'tips_shown_v3';
|
||||
|
||||
/** 隐私政策网址(华为 AGC 隐私政策托管服务生成,上架时填此地址) */
|
||||
static readonly PRIVACY_URL: string =
|
||||
'https://agreement-drcn.hispace.dbankcloud.cn/index.html?lang=zh&agreementId=2039401852717510592';
|
||||
// 隐私政策 / 用户服务协议网址(自托管,AGC 上架的"隐私政策网址"填 PRIVACY_URL)。
|
||||
// ⚠️ 两份文件必须与安装包实际申请的 user_grant 权限保持一致:
|
||||
// 应用仅申请 READ_CALENDAR / READ_WHOLE_CALENDAR / LOCATION / APPROXIMATELY_LOCATION(均前台),
|
||||
// 文档中不得出现"在后台获取位置"(LOCATION_IN_BACKGROUND)与"添加/修改/删除日历活动"(WRITE_CALENDAR)。
|
||||
/** 隐私政策网址 */
|
||||
static readonly PRIVACY_URL: string = 'https://synccalendar.yangyq.net/upa.html';
|
||||
/** 用户服务协议网址 */
|
||||
static readonly AGREEMENT_URL: string = 'https://synccalendar.yangyq.net/usa.html';
|
||||
/** 文档标题(内置浏览器标题栏用) */
|
||||
static readonly PRIVACY_TITLE: string = '隐私政策';
|
||||
static readonly AGREEMENT_TITLE: string = '用户服务协议';
|
||||
|
||||
/**
|
||||
* 是否已同意《隐私政策》与《用户协议》(首启同意弹窗)。
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// entry/src/main/ets/common/DocViewer.ets
|
||||
// 内置文档浏览器:整页覆盖层 + Web 组件,用于在应用内展示《隐私政策》《用户服务协议》。
|
||||
// 为什么不用系统浏览器 / 弹窗:
|
||||
// 1) 用户要求"点了就在应用里看,随手可关",不跳出应用;
|
||||
// 2) 本环境实测系统弹层(CustomDialogController / bindSheet)由异步流程驱动时不可靠,
|
||||
// 而"必须有"的界面一律用整页覆盖层(与首启同意门禁 consentGate 同一套路)。
|
||||
// 宿主用法:@State showDoc / docTitle / docUrl,根 Stack 最后一层 if (this.showDoc) { DocViewer({...}) }。
|
||||
import { webview } from '@kit.ArkWeb';
|
||||
|
||||
@Component
|
||||
export struct DocViewer {
|
||||
/** 标题栏文案(如"隐私政策") */
|
||||
title: string = '';
|
||||
/** 文档地址(http / https) */
|
||||
url: string = '';
|
||||
/** 点击"关闭"时回调 —— 由宿主把 showDoc 置回 false */
|
||||
onClose: () => void = () => {};
|
||||
|
||||
private controller: webview.WebviewController = new webview.WebviewController();
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
// 标题栏:左标题、右关闭(点击即退出,符合"随手关掉"的预期)
|
||||
Row() {
|
||||
Text(this.title)
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.maxLines(1)
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
.layoutWeight(1)
|
||||
Text('✕')
|
||||
.fontSize(16)
|
||||
.fontColor($r('app.color.text_secondary'))
|
||||
.padding({ left: 14, right: 14, top: 10, bottom: 10 })
|
||||
.onClick((): void => {
|
||||
this.onClose();
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.height(52)
|
||||
.padding({ left: 16, right: 4 })
|
||||
.backgroundColor($r('app.color.card_bg'))
|
||||
.border({ width: { bottom: 0.5 }, color: { bottom: $r('app.color.shadow_color') } })
|
||||
|
||||
// 文档正文:交给系统 Web 内核渲染(页面自身已适配移动端与深色模式)
|
||||
Web({ src: this.url, controller: this.controller })
|
||||
.width('100%')
|
||||
.layoutWeight(1)
|
||||
.domStorageAccess(true)
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.backgroundColor($r('app.color.page_bg'))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user