新增设置页与相关协议 H5(头像底部 sheet+裁剪、昵称/退出/注销弹窗、页面不滚动、手势条避让)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="../../shared/fonts.css">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
body{font-family:'PuHuiTi',-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F5F5;color:#1A1A1A;padding:4px 14px 40px;-webkit-text-size-adjust:100%}
|
||||
.ag-title{font-size:19px;font-weight:700;line-height:1.4;color:#1A1A1A;text-align:center;margin:10px 0 6px}
|
||||
.ag-meta{font-size:12px;font-weight:400;line-height:1.7;color:#999;text-align:center;margin-bottom:14px}
|
||||
.ag-card{background:#fff;border-radius:14px;box-shadow:0 1px 2px rgba(0,0,0,.03);padding:18px 16px 20px}
|
||||
.ag-lead{font-size:13px;font-weight:400;line-height:1.85;color:#666;margin-bottom:10px}
|
||||
.ag-h{font-size:16px;font-weight:600;line-height:1.5;color:#1A1A1A;margin:22px 0 8px}
|
||||
.ag-h3{font-size:14px;font-weight:600;line-height:1.5;color:#1A1A1A;margin:14px 0 6px}
|
||||
.ag-p{font-size:13px;font-weight:400;line-height:1.85;color:#666;margin-bottom:8px}
|
||||
.ag-toc{list-style:none;padding-left:0}
|
||||
strong{font-weight:600;color:#1A1A1A}
|
||||
ul,ol{margin:4px 0 8px;padding-left:20px}
|
||||
li{font-size:13px;font-weight:400;line-height:1.8;color:#666;margin-bottom:6px}
|
||||
.ag-hr{border:none;border-top:0.5px solid #E5E5E5;margin:16px 0}
|
||||
table{width:100%;border-collapse:collapse;margin:10px 0;font-size:11px;line-height:1.55}
|
||||
th,td{border:0.5px solid #E0E0E0;padding:5px 6px;text-align:left;vertical-align:top;color:#666;word-break:break-word}
|
||||
th{background:#F7F7F7;color:#1A1A1A;font-weight:600}
|
||||
a{color:#1565C0;text-decoration:none;word-break:break-all}
|
||||
.ag-note{font-size:12px;color:#999;line-height:1.7;margin-top:8px}
|
||||
.ag-foot{text-align:center;font-size:12px;font-weight:400;color:#CCC;line-height:1.7;margin:24px 0 8px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="ag-meta">生效日期:【2026 年 06 月 25 日】</div>
|
||||
|
||||
<div class="ag-card">
|
||||
<div class="ag-lead">万德一博(北京)科技有限公司(以下简称“我们”)深知个人信息对您的重要性,并会尽全力保护您的个人信息安全可靠。我们致力于维持您对我们的信任,恪守适用法律和我们对您的承诺,遵循正当、合法、必要、诚信、最小必要的原则处理您的个人信息。</div>
|
||||
<div class="ag-p">请您在使用“傻瓜比价”App(以下简称“本 App”或“本产品”)前,仔细阅读并充分理解本《傻瓜比价隐私政策》(以下简称“本政策”,<strong>我们已将重点内容以加粗形式提示,请您特别关注</strong>),并在确认充分理解并同意后再开始使用。如您对本政策有任何疑问,可通过本政策第八条“如何联系我们”提供的方式与我们联系。</div>
|
||||
|
||||
<div class="ag-p"><strong>【特别提示】</strong>本 App 是一款“比价工具”。我们本身不销售任何商品、不提供外卖/团购等交易服务,也不是您与电商/外卖/团购平台之间交易的相对方。您看到的商品、价格、优惠均来自淘宝、京东、拼多多、抖音、美团等第三方平台,最终下单、支付、履约均在相应第三方平台内完成,受该第三方平台自己的协议与隐私政策约束。</div>
|
||||
|
||||
<div class="ag-p">本政策将帮助您了解以下内容:</div>
|
||||
<ul class="ag-toc">
|
||||
<li>一、我们如何收集和使用您的个人信息</li>
|
||||
<li>二、我们如何使用 Cookie 和同类技术</li>
|
||||
<li>三、我们如何共享、转让、公开披露您的个人信息</li>
|
||||
<li>四、我们如何保存和保护您的个人信息</li>
|
||||
<li>五、您如何管理您的个人信息</li>
|
||||
<li>六、未成年人的个人信息保护</li>
|
||||
<li>七、通知和修订</li>
|
||||
<li>八、如何联系我们</li>
|
||||
<li>九、附录(第三方 SDK 清单、敏感个人信息清单)</li>
|
||||
</ul>
|
||||
|
||||
<div class="ag-hr"></div>
|
||||
<div class="ag-h">一、我们如何收集和使用您的个人信息</div>
|
||||
<div class="ag-p">本 App 的基本功能为“跨平台商品比价”。您同意本政策表示您已了解本 App 提供的基本功能,以及基本功能运行所必需的个人信息,并给予相应的收集使用授权。但这并不代表您同意我们收集、处理非必要个人信息;扩展功能所需的个人信息、以及涉及敏感个人信息、第三方共享、调用系统权限等情形,我们将在您实际使用具体功能时单独征求您的同意。<strong>如您拒绝开启扩展功能或提供非必要个人信息,不会影响您使用基本功能。</strong></div>
|
||||
<div class="ag-p">我们会遵循正当、合法、必要的原则,出于以下目的收集和使用您的个人信息:</div>
|
||||
|
||||
<div class="ag-h3">(一)帮助您注册和登录账号</div>
|
||||
<div class="ag-p">当您注册、登录本 App 时,您需要向我们提供手机号码,我们通过发送短信验证码验证您的身份。您的手机号码用于创建账号、登录、账号安全保护以及向您发送服务通知。</div>
|
||||
<div class="ag-p">为方便您快捷登录,您可以选择“一键登录”功能,我们会使用基础电信运营商提供的快捷登录能力,经您授权后获取您当前设备的本机手机号为您完成注册/登录。如您不希望使用,可通过短信验证码方式登录。</div>
|
||||
<div class="ag-p">在您完成首次比价体验前,<strong>您无需登录即可使用核心比价功能</strong>(详见下文第(三)条);只有在您需要领取金币奖励、提现、查看比价记录等需要账号的功能时,才需要登录。</div>
|
||||
|
||||
<div class="ag-h3">(二)权限与设备信息的获取</div>
|
||||
<div class="ag-p">为实现比价功能、保障账号与运行安全,我们会在您授权后获取以下信息。<strong>所有系统权限我们均不会默认开启,会在您使用到对应功能时向您申请,您可随时在系统设置中关闭:</strong></div>
|
||||
<ol>
|
||||
<li><strong>悬浮窗权限(在其他应用上层显示):</strong>用于在您浏览购物平台时显示“比价”悬浮按钮、比价进度与比价结果。这是本产品“无需打开 App 即可比价”体验的必要权限。</li>
|
||||
<li><strong>无障碍服务权限(Accessibility Service):</strong>用于实现核心比价功能,详见第(三)条专门说明。</li>
|
||||
<li><strong>设备与网络信息:</strong>为保障账号安全、识别风险、适配界面并排查故障,我们会收集您的设备型号、操作系统及版本、应用版本、屏幕分辨率、语言设置、设备标识符(如 OAID、Android ID,安卓系统不再提供 IMEI 时不强制收集)、网络状态、IP 地址、电信运营商等软硬件特征信息。</li>
|
||||
<li><strong>自启动、忽略电池优化等系统设置:</strong>为保证比价与悬浮窗服务在后台稳定运行、避免被系统中断,我们会引导您开启应用自启动、将本 App 加入电池优化白名单(忽略电池优化)。这些设置仅用于维持服务可用性,不收集您的个人信息。您可随时在系统设置中关闭,关闭后可能影响比价服务的稳定性。</li>
|
||||
</ol>
|
||||
|
||||
<div class="ag-h3">(三)核心比价功能所需的系统能力</div>
|
||||
<div class="ag-p">为实现“在购物页面一键比价”以及“省钱记录”,本 App 需要您开启系统的无障碍服务与悬浮窗权限。开启后,<strong>仅在您使用比价相关功能时</strong>,本 App 会:①当您点击“比价”时,识别您当前查看的商品信息(如名称、价格、规格),并代您在其他购物平台搜索同款、读取价格,生成比价结果;②当您通过比价结果跳转并在第三方平台完成购买后,识别下单/支付成功结果,用于为您生成省钱记录。我们就此说明:</div>
|
||||
<ul>
|
||||
<li>商品识别尽量在您的设备本地完成,仅将商品文字关键信息(如名称/关键词、品牌、规格、价格)上传至服务器用于同款匹配,<strong>不会上传商品页面截图或任何屏幕图像</strong>;</li>
|
||||
<li>下单记录:当您完成购买后,本 App 会识别下单/支付成功页面的结果信息(如下单平台、商品、金额、下单时间),用于在您的“比价记录/省钱统计”中展示。<strong>我们仅记录上述用于省钱统计所必需的信息,不会记录您的收货地址、收件人、银行卡号、支付密码、短信验证码或聊天等内容</strong>;</li>
|
||||
<li>本 App 不会代您下单或支付,也不会进行与上述比价、省钱记录无关的操作;</li>
|
||||
<li>比价结果仅供参考,各平台价格与优惠实时变动,最终价格、优惠及交易以第三方平台实际展示和结算为准;</li>
|
||||
<li>您可随时在系统设置中关闭相关权限,关闭后将无法使用自动比价与省钱记录功能,但不影响 App 内其他功能。</li>
|
||||
</ul>
|
||||
|
||||
<div class="ag-h3">(四)为您提供比价记录与“省钱统计”</div>
|
||||
<div class="ag-p">为向您展示历史比价记录与累计为您节省的金额,我们会记录:</div>
|
||||
<ul>
|
||||
<li>比价记录:您在本 App 内发起的比价(如比价时间、目标商品、各平台价格对比结果);</li>
|
||||
<li>下单记录:通过无障碍服务识别您在第三方平台的下单/支付成功结果(下单平台、商品、金额、下单时间),用于统计为您节省的金额并在记录页展示。<strong>我们仅记录用于上述统计所必需的信息,不记录您的收货地址、收件人、银行卡号、支付密码等信息。</strong>识别方式详见第(三)项关于无障碍服务的说明。</li>
|
||||
</ul>
|
||||
<div class="ag-p">此外,返佣/返现结算:我们通过所对接的 CPS 联盟接口(京东联盟、淘宝闪购联盟、美团联盟等)获取相关订单的结算状态,用于发放返现/奖励。</div>
|
||||
|
||||
<div class="ag-h3">(五)金币、奖励与提现功能(含敏感个人信息)</div>
|
||||
<div class="ag-p">本 App 提供金币体系:您可通过签到、记录比价战绩、观看激励视频、邀请好友等任务获取金币,金币可按 App 内公示规则提现(具体兑换比例、提现门槛以 App 内最新公示为准)。为此我们会处理:</div>
|
||||
<ul>
|
||||
<li>任务与金币记录:您的签到、任务完成、金币收支、邀请关系等记录;</li>
|
||||
<li>提现相关信息:当您申请提现时,我们通过微信支付向您的微信账户发放提现金额。<strong>实名核验与收款均由微信支付侧完成,我们不收集、不存储您的身份证件号码、银行卡号等信息</strong>;我们仅处理完成微信提现所必需的信息(如您的微信授权标识/OpenID、提现金额与提现记录)。如您不使用提现功能,则无需提供上述信息。</li>
|
||||
</ul>
|
||||
|
||||
<div class="ag-h3">(六)为您展示内容与改进服务</div>
|
||||
<div class="ag-p">为向您展示首页低价商品、“低价盲盒”、福利任务等内容,并改进我们的产品与服务,我们会收集您的浏览、点击、搜索、比价、收藏等行为信息进行统计分析。<strong>我们不基于上述信息对您进行个性化推荐。</strong></div>
|
||||
|
||||
<div class="ag-h3">(七)广告功能</div>
|
||||
<div class="ag-p">在比价等待期的悬浮窗中、以及福利 Tab“看视频赚金币”任务中,我们会向您展示广告(含激励视频广告)。为实现广告展示与反作弊,接入的广告 SDK 可能收集设备信息等(详见第九条 SDK 清单)。</div>
|
||||
<ul>
|
||||
<li><strong>首次比价不展示任何广告;广告从第二次比价开始展示。</strong></li>
|
||||
<li>您可通过【我的 → 设置 → 关于傻瓜比价 → 个性化广告】管理个性化广告;关闭后您看到的广告相关性会降低,但广告不会消失。</li>
|
||||
</ul>
|
||||
|
||||
<div class="ag-h3">(八)跳转第三方平台与私域社群</div>
|
||||
<ul>
|
||||
<li>跳转购买:您点击比价结果卡片或低价商品时,我们会通过 CPS 联盟推广链接将您跳转至对应第三方平台的商品页面,您在该平台内完成下单与支付。<strong>我们不会获取您在第三方平台输入的账户密码、支付密码。</strong></li>
|
||||
<li>私域社群:如您主动选择加入我们的福利社群,可能跳转至企业微信等第三方工具,相关信息处理适用该第三方的规则。</li>
|
||||
</ul>
|
||||
|
||||
<div class="ag-h3">(九)为您提供客服与安全保障</div>
|
||||
<ul>
|
||||
<li>客服:当您联系客服时,我们会记录沟通记录、并核验您的账号信息,以处理您的问题。</li>
|
||||
<li>安全保障:为保障账号、交易与系统运行安全,预防欺诈、薅羊毛、刷量等行为,我们会收集设备信息、日志信息、IP 地址、应用运行与崩溃信息等用于风险识别与防控。</li>
|
||||
</ul>
|
||||
|
||||
<div class="ag-h3">(十)征得授权同意的例外</div>
|
||||
<div class="ag-p">根据法律法规,在下列情形下我们处理您的个人信息无需征得您的授权同意:与履行法定义务相关、与国家安全/公共安全/公共卫生/重大公共利益直接相关、为订立或履行您作为一方当事人的合同所必需、在合理范围内处理您自行公开或已合法公开的信息、应急情况下为保护自然人生命健康和财产安全所必需,以及法律法规规定的其他情形。</div>
|
||||
|
||||
<div class="ag-hr"></div>
|
||||
<div class="ag-h">二、我们如何使用 Cookie 和同类技术</div>
|
||||
<div class="ag-p">为确保本产品正常运转、为您提供更便捷的体验,我们会在您的设备上存储名为 Cookie、设备标识或同类技术的小型数据文件,用于:记住您的身份与偏好设置、保障登录与数据安全、分析产品使用情况以优化体验。您可在系统/浏览器中清除或管理上述数据,但清除后可能影响您使用部分功能。</div>
|
||||
|
||||
<div class="ag-hr"></div>
|
||||
<div class="ag-h">三、我们如何共享、转让、公开披露您的个人信息</div>
|
||||
<div class="ag-h3">(一)共享</div>
|
||||
<div class="ag-p">我们不会与任何公司、组织和个人共享您的个人信息,但以下情形除外:</div>
|
||||
<ol>
|
||||
<li>事先取得您的明确同意或授权;涉及敏感个人信息或向第三方提供个人信息时,我们将取得您的单独同意;</li>
|
||||
<li>根据法律法规、行政或司法机关的强制性要求;</li>
|
||||
<li>在符合法律法规的前提下,为实现本政策所述目的,与下列合作伙伴在必要范围内共享:
|
||||
<ul>
|
||||
<li>第三方 SDK 服务商(如广告、统计、推送、一键登录、崩溃监控等,详见第九条清单);</li>
|
||||
<li>CPS/CPA 联盟平台:为完成返佣结算、订单追踪、拉新结算,我们会与所对接的电商/外卖联盟在必要范围内交互订单/设备标识等信息;</li>
|
||||
<li>云服务、短信、实名核验、收款/支付通道服务商:为实现注册登录、提现到账、实名核验等。</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
<div class="ag-p">对受托处理个人信息的合作方,我们会与其签订严格的数据保护协议,要求其按照本政策及法律法规处理您的个人信息。</div>
|
||||
<div class="ag-h3">(二)转让</div>
|
||||
<div class="ag-p">我们不会向任何公司、组织和个人转让您的个人信息,但以下情形除外:取得您的明确同意;在涉及合并、分立、收购、资产转让或类似交易时,我们会要求新的持有方继续受本政策约束,否则将要求其重新征得您的授权同意。</div>
|
||||
<div class="ag-h3">(三)公开披露</div>
|
||||
<div class="ag-p">我们仅在取得您单独同意、或基于法律法规、强制性行政/司法要求的情形下公开披露您的个人信息,并采取符合业界标准的安全防护措施。</div>
|
||||
|
||||
<div class="ag-hr"></div>
|
||||
<div class="ag-h">四、我们如何保存和保护您的个人信息</div>
|
||||
<div class="ag-h3">(一)保存地点</div>
|
||||
<div class="ag-p">您的个人信息存储于中华人民共和国境内(我们使用阿里云作为云服务商,数据存储于其境内数据中心)。<strong>我们不会向境外传输您的个人信息。</strong></div>
|
||||
<div class="ag-h3">(二)保存期限</div>
|
||||
<div class="ag-p">我们仅在实现本政策所述目的所必需的最短期限内保存您的个人信息,并结合法律的强制留存要求确定保存期限(例如《电子商务法》要求商品和服务信息、交易信息自交易完成之日起保存不少于三年)。超出保存期限后,我们将对您的个人信息进行删除或匿名化处理。</div>
|
||||
<div class="ag-h3">(三)保护措施</div>
|
||||
<div class="ag-p">我们采用符合业界标准的安全防护措施保护您的个人信息,包括传输与存储加密(如 HTTPS)、访问权限控制、数据脱敏、内部安全管理制度与员工保密义务等,防止信息遭到未经授权的访问、使用、修改或泄露、损毁、丢失。</div>
|
||||
<div class="ag-h3">(四)安全事件处置</div>
|
||||
<div class="ag-p">若不幸发生个人信息安全事件,我们将按法律法规要求及时向您告知:事件基本情况与可能影响、我们已采取或将采取的处置措施、您可自主防范和降低风险的建议、对您的补救措施等,并以推送、短信、邮件、公告等方式告知您,同时按规定向监管部门上报。</div>
|
||||
<div class="ag-h3">(五)产品或服务停止运营时的处置</div>
|
||||
<div class="ag-p">如本 App 停止运营,我们将:①以推送、公告等显著方式通知您;②停止继续收集您的个人信息;③对我们持有的您的个人信息进行删除或匿名化处理,法律法规另有强制留存要求的除外。</div>
|
||||
|
||||
<div class="ag-hr"></div>
|
||||
<div class="ag-h">五、您如何管理您的个人信息</div>
|
||||
<div class="ag-p">您对您的个人信息享有以下权利,可通过【我的 → 设置 → 隐私管理】或本政策第八条的联系方式行使:</div>
|
||||
<ol>
|
||||
<li>访问、复制、更正、补充您的个人信息;</li>
|
||||
<li>删除您的个人信息(在我们违法处理、未经同意处理、或您注销账号等情形下,您可请求删除);</li>
|
||||
<li>改变或撤回授权同意:您可关闭相应系统权限或在设置中撤回授权。请您理解,撤回同意不影响撤回前基于您同意已进行的处理;撤回后我们将无法继续提供对应功能;</li>
|
||||
<li>注销账号:您可通过【我的 → 设置 → 账户与安全 → 注销账号】注销。注销后我们将停止为您提供产品/服务,并依法删除或匿名化您的个人信息;</li>
|
||||
<li>获取个人信息副本;</li>
|
||||
<li>响应您的请求:我们将在收到并核验您身份后的 15 天内予以答复。对合理请求原则上不收取费用;对重复、超出合理限度的请求,我们可能酌情收取成本费用或予以拒绝。</li>
|
||||
</ol>
|
||||
<div class="ag-p">如您对我们的答复不满意,特别是认为我们的处理行为损害了您的合法权益,您可向网信、电信、公安、市场监管等监管部门投诉、举报。</div>
|
||||
|
||||
<div class="ag-hr"></div>
|
||||
<div class="ag-h">六、未成年人的个人信息保护</div>
|
||||
<div class="ag-p">本 App 主要面向成年人。若您是 18 周岁以下的未成年人,请在监护人陪同下阅读本政策,并在监护人同意后再使用本产品及提供个人信息。对于不满 14 周岁儿童的个人信息,我们将依据《儿童个人信息网络保护规定》等要求,在取得其监护人单独同意后方可处理,并采取严格保护措施。如您是未成年人的监护人,对未成年人个人信息有任何疑问,请通过第八条方式联系我们。</div>
|
||||
|
||||
<div class="ag-hr"></div>
|
||||
<div class="ag-h">七、通知和修订</div>
|
||||
<div class="ag-p">为提供更好的服务,本政策可能适时更新。<strong>未经您明确同意,我们不会削减您依据本政策应享有的权利。</strong>政策更新后,我们会通过 App 内公告、弹窗、推送或其他适当方式提示您。对于重大变更(如处理目的、处理信息类型、共享对象、您行使权利的方式发生重大变化,或所有权结构发生重大变化等),我们会提供更显著的通知并在生效前再次征得您的同意(如适用)。</div>
|
||||
|
||||
<div class="ag-hr"></div>
|
||||
<div class="ag-h">八、如何联系我们</div>
|
||||
<div class="ag-p">如您对本政策、您的个人信息处理、或需要投诉、举报、咨询,请通过以下方式与我们联系:</div>
|
||||
<ul>
|
||||
<li>公司全称:万德一博(北京)科技有限公司</li>
|
||||
<li>注册地址:北京市丰台区丰管路甲1号北楼三层302-765室</li>
|
||||
<li>客服 / 个人信息保护事务邮箱:support@wonderable.ai</li>
|
||||
</ul>
|
||||
<div class="ag-p">一般情况下,我们将在 15 天内回复您的请求。</div>
|
||||
|
||||
<div class="ag-hr"></div>
|
||||
<div class="ag-h">九、附录</div>
|
||||
<div class="ag-h3">附录一:第三方 SDK 与合作方清单</div>
|
||||
<div class="ag-p">本清单是应用商店审核与监管检查的重点项。穿山甲为聚合广告平台(GroMore),其下游可能调用快手、腾讯优量汇等第三方广告网络,这些下游网络也会收集设备标识等信息,已在表中一并披露。</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>SDK / 合作方名称</th><th>提供方公司全称</th><th>使用目的</th><th>收集的个人信息</th><th>隐私政策链接</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>穿山甲(GroMore 聚合广告平台,含激励视频广告)</td><td>北京巨量引擎网络技术有限公司</td><td>展示激励视频广告、广告归因与反作弊</td><td>设备标识符(OAID 等)、设备信息、网络信息、广告交互数据</td><td><a href="https://www.csjplatform.com/privacy">https://www.csjplatform.com/privacy</a></td></tr>
|
||||
<tr><td>└ 经穿山甲聚合调用的下游广告网络(快手广告)</td><td>北京快手科技有限公司</td><td>通过聚合平台填充与展示广告</td><td>设备标识符、设备信息、网络信息</td><td><a href="https://www.kuaishou.com/about/policy">https://www.kuaishou.com/about/policy</a></td></tr>
|
||||
<tr><td>└ 经穿山甲聚合调用的下游广告网络(腾讯优量汇)</td><td>深圳市腾讯计算机系统有限公司</td><td>通过聚合平台填充与展示广告</td><td>设备标识符、设备信息、网络信息</td><td><a href="https://e.qq.com/optout.html">https://e.qq.com/optout.html</a></td></tr>
|
||||
<tr><td>极光(JIGUANG,一键登录 / 号码认证 / 短信验证)</td><td>深圳市和讯华谷信息技术有限公司</td><td>一键登录取号、短信验证码下发与号码认证</td><td>本机号码(运营商掩码取号)、设备信息、网络信息</td><td><a href="https://www.jiguang.cn/license/privacy">https://www.jiguang.cn/license/privacy</a></td></tr>
|
||||
<tr><td>美团联盟(API,无 SDK)</td><td>北京三快科技有限公司</td><td>外卖/团购比价的返佣订单追踪与结算</td><td>订单信息、推广标识</td><td>以美团联盟官方规则为准</td></tr>
|
||||
<tr><td>京东联盟(API/链接,无 SDK)</td><td>北京京东叁佰陆拾度电子商务有限公司及其关联公司</td><td>电商比价的返佣订单追踪与结算</td><td>订单信息、推广标识</td><td>以京东联盟官方规则为准</td></tr>
|
||||
<tr><td>淘宝闪购联盟(API/链接,无 SDK)</td><td>阿里巴巴(中国)软件有限公司 / 阿里妈妈</td><td>电商/闪购比价的返佣订单追踪与结算</td><td>订单信息、推广标识</td><td>以对应联盟官方规则为准</td></tr>
|
||||
<tr><td>阿里云</td><td>阿里云计算有限公司</td><td>云服务器、数据存储等基础设施(受托处理)</td><td>受托存储上述各项个人信息</td><td><a href="https://www.aliyun.com/">https://www.aliyun.com/</a></td></tr>
|
||||
<tr><td>微信支付(提现)</td><td>财付通支付科技有限公司</td><td>向用户发放微信提现、实名核验与收款(由微信侧完成)</td><td>微信授权标识/OpenID、提现金额与记录</td><td>以微信支付官方规则为准</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="ag-note">说明:本 App 未接入独立的统计分析、消息推送 SDK,也不会将屏幕图像上传至云端 AI 大模型。</div>
|
||||
|
||||
<div class="ag-h3">附录二:本政策涉及的敏感个人信息清单</div>
|
||||
<div class="ag-p">为便于您识别,下列为本 App 在特定功能下处理的、属于敏感或受单独同意约束的信息:</div>
|
||||
<ul>
|
||||
<li>下单记录:通过无障碍服务识别您的下单/支付成功结果(下单平台、商品、金额、下单时间)用于省钱统计,详见正文第一条第(三)项;</li>
|
||||
<li>提现:实名核验与银行卡/身份证件号码由微信支付侧收集与处理,本 App 不收集、不存储。</li>
|
||||
<li>本 App 不处理人脸、指纹等生物识别信息,不收集身份证件号码、银行卡号,不收集行踪轨迹,不读取通讯录、短信、相册(除您主动上传的反馈截图外)。</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="ag-foot">傻瓜比价 · 隐私政策<br>万德一博(北京)科技有限公司</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,133 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="../../shared/fonts.css">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
body{font-family:'PuHuiTi',-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F5F5;color:#1A1A1A;padding:4px 14px 40px;-webkit-text-size-adjust:100%}
|
||||
.ag-title{font-size:19px;font-weight:700;line-height:1.4;color:#1A1A1A;text-align:center;margin:10px 0 6px}
|
||||
.ag-meta{font-size:12px;font-weight:400;line-height:1.7;color:#999;text-align:center;margin-bottom:14px}
|
||||
.ag-card{background:#fff;border-radius:14px;box-shadow:0 1px 2px rgba(0,0,0,.03);padding:18px 16px 20px}
|
||||
.ag-lead{font-size:13px;font-weight:400;line-height:1.85;color:#666;margin-bottom:10px}
|
||||
.ag-h{font-size:16px;font-weight:600;line-height:1.5;color:#1A1A1A;margin:22px 0 8px}
|
||||
.ag-p{font-size:13px;font-weight:400;line-height:1.85;color:#666;margin-bottom:8px}
|
||||
strong{font-weight:600;color:#1A1A1A}
|
||||
ol{margin:4px 0 8px;padding-left:20px}
|
||||
li{font-size:13px;font-weight:400;line-height:1.8;color:#666;margin-bottom:6px}
|
||||
.ag-hr{border:none;border-top:0.5px solid #E5E5E5;margin:16px 0}
|
||||
a{color:#1565C0;text-decoration:none;word-break:break-all}
|
||||
.ag-foot{text-align:center;font-size:12px;font-weight:400;color:#CCC;line-height:1.7;margin:24px 0 8px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="ag-meta">生效日期:【2026 年 06 月 25 日】</div>
|
||||
|
||||
<div class="ag-card">
|
||||
<div class="ag-lead">欢迎您使用“傻瓜比价”App!本《傻瓜比价用户服务协议》(以下简称“本协议”)是您与万德一博(北京)科技有限公司(注册地址:北京市丰台区丰管路甲1号北楼三层302-765室,以下简称“我们”或“傻瓜比价”)之间就您注册、使用“傻瓜比价”App(以下简称“本 App”或“本服务”)所订立的协议。</div>
|
||||
<div class="ag-p"><strong>请您务必审慎阅读、充分理解本协议各条款,特别是以加粗形式提示您的免除或限制我们责任、需您自行承担风险或责任的条款。</strong>如您未满 18 周岁,请在监护人陪同下阅读并在其同意后使用本服务。</div>
|
||||
<div class="ag-p"><strong>当您勾选同意、或以注册、登录、使用本服务等任何方式表示接受本协议时,即视为您已阅读并同意本协议的全部内容,自愿接受其约束。</strong>如您不同意本协议任何内容,请勿注册或使用本服务。</div>
|
||||
<div class="ag-p">本协议内容同时包括《傻瓜比价隐私政策》及我们在 App 内公示的与本服务相关的各项规则(如金币规则、活动规则等),上述内容为本协议不可分割的组成部分,与本协议正文具有同等效力。</div>
|
||||
|
||||
<div class="ag-hr"></div>
|
||||
<div class="ag-h">一、服务说明(请重点阅读本 App 的性质)</div>
|
||||
<ol>
|
||||
<li><strong>本 App 是一款“比价工具”/信息服务,不是商品或服务的销售方、交易方。</strong>本 App 帮助您在淘宝、京东、拼多多、抖音、美团等第三方平台浏览商品时,自动跨平台搜索同款商品并展示价格对比结果。</li>
|
||||
<li><strong>我们不销售任何商品、不提供外卖/团购/物流等交易及履约服务。</strong>您看到的商品、价格、优惠、店铺均来自第三方平台;您的下单、支付、发货、售后、退换货等全部在相应第三方平台内完成,并受该第三方平台自身的用户协议、规则与隐私政策约束。因商品质量、发货、售后、虚假宣传等产生的争议,应由您与该第三方平台或商家解决,我们不承担销售者/服务提供者责任,但会在合理范围内为您提供必要协助。</li>
|
||||
<li><strong>比价结果仅供参考。</strong>各平台价格、库存、优惠券、满减、返现等实时变动,且受地域、账号、活动、时间等多种因素影响。我们力求比价结果准确及时,但<strong>不对比价结果(包括但不限于“全网最低价”的表述、同款匹配的准确性、价格的实时性)作任何明示或默示的保证;最终价格、优惠及交易以第三方平台实际展示和结算为准。</strong>请您在下单前自行核对。</li>
|
||||
<li><strong>本服务的核心功能依赖系统无障碍服务与悬浮窗权限。</strong>您在使用前需要在系统设置中授予相应权限。关于该等权限读取与处理信息的范围、本地处理原则及您的关闭方式,详见《傻瓜比价隐私政策》第一条第(三)项。</li>
|
||||
</ol>
|
||||
|
||||
<div class="ag-h">二、比价功能的开启与使用</div>
|
||||
<ol>
|
||||
<li>本服务的比价功能需要您开启系统的无障碍服务与悬浮窗权限。开启后,仅在您使用比价相关功能时,本 App 会识别您当前查看的商品并代您在其他购物平台搜索同款、比对价格,并在您完成购买后识别下单结果用于为您生成省钱记录;不会代您下单、支付或修改账户信息,也不会进行与比价、省钱记录无关的操作。关于权限读取与处理信息的范围、本地处理原则及关闭方式,详见《傻瓜比价隐私政策》第一条第(三)项。</li>
|
||||
<li><strong>您理解并同意,是否使用比价功能由您自主选择。</strong>您可随时在系统设置中关闭相关权限,关闭后比价功能将不可用,但不影响您使用 App 内其他功能。</li>
|
||||
</ol>
|
||||
|
||||
<div class="ag-h">三、账号的注册与使用</div>
|
||||
<ol>
|
||||
<li><strong>【注册资料】</strong>您应以诚实信用原则提供真实、准确、合法的注册信息(如手机号码),并在信息变动时及时更新。因您提供的信息不真实、不准确或未及时更新导致的后果,由您自行承担。</li>
|
||||
<li><strong>【实名与提现】</strong>因法律法规、反洗钱及收款渠道要求,您在使用提现等功能时可能需要完成实名核验并提供收款账号信息,详见《傻瓜比价隐私政策》。未完成必要核验的,您可能无法使用相应功能。</li>
|
||||
<li><strong>【账号安全】</strong>您应妥善保管账号及密码,对账号项下的全部行为负责。如发现账号被盗用或存在安全问题,应立即通知我们。因您自身保管不善导致的账号丢失、泄露及由此产生的损失,我们不承担责任(我们存在过错的除外)。</li>
|
||||
<li><strong>【账号管理】</strong>原则上一名用户对应一个账号。如您存在不当注册或不当使用多个账号、利用账号从事违规行为的情形,我们有权对相关账号采取限制、冻结、合并、注销等措施。</li>
|
||||
</ol>
|
||||
|
||||
<div class="ag-h">四、金币、奖励与提现规则</div>
|
||||
<ol>
|
||||
<li><strong>【金币性质】</strong>金币是本 App 内用于激励用户的虚拟权益,不是法定货币、不可在用户间转让、不可用于本 App 约定用途之外的交易。金币的获取、消耗、兑换、提现规则以 App 内公示的最新规则为准。</li>
|
||||
<li><strong>【提现】</strong>金币可按 App 内公示的兑换比例与提现门槛提现(具体数值以 App 内最新公示页面为准)。当前提现通过微信支付发放,实名核验与收款由微信支付侧完成。</li>
|
||||
<li><strong>【反作弊】(请重点阅读)您不得通过作弊、外挂、机器批量操作、虚假注册、刷量、薅羊毛、利用系统漏洞等任何不正当方式获取金币或奖励。一经发现,我们有权扣除相应金币/奖励、驳回提现、冻结或注销账号,并保留追究法律责任的权利。</strong>金币规则及反作弊规则如需调整,我们将提前以合理方式公示;如您对反作弊判定有异议,可通过第五条约定的申诉渠道提出申诉。</li>
|
||||
<li><strong>【活动规则】</strong>各项福利任务、裂变、邀请等活动的具体规则以活动页面公示为准;如活动规则与本协议不一致,就该活动事项以活动规则为准。</li>
|
||||
</ol>
|
||||
|
||||
<div class="ag-h">五、用户行为规范</div>
|
||||
<div class="ag-p">您承诺在使用本服务过程中遵守法律法规,不从事下列行为,否则我们有权视情形采取警告、限制功能、冻结或注销账号等措施,由此产生的责任由您承担:</div>
|
||||
<ol>
|
||||
<li>发布、传播违反宪法确定的基本原则,危害国家安全、社会稳定、违背公序良俗,或法律法规禁止的其他内容;</li>
|
||||
<li>侵犯他人知识产权、隐私权、名誉权等合法权益;</li>
|
||||
<li>实施网络攻击、传播病毒/木马,破解、干扰、破坏本服务或其相关系统;</li>
|
||||
<li>未经我们书面许可,自行或协助第三方对本服务进行非法抓取、反向工程、反编译,或使用外挂、插件、机器人等干扰本服务正常运行;</li>
|
||||
<li>利用本服务从事诈骗、洗钱、刷单炒信、薅羊毛等违法或不正当行为;</li>
|
||||
<li>其他违反法律法规或损害我们、其他用户、第三方合法权益的行为。</li>
|
||||
</ol>
|
||||
<div class="ag-p"><strong>【处罚与申诉】</strong>我们对账号采取限制、冻结、注销等处罚措施时,将根据违规行为的性质与严重程度合理处理,并以适当方式告知您处罚的事由。如您认为处罚有误,可通过 support@wonderable.ai 或 App 内客服渠道提出申诉,我们将在收到申诉后 15 个工作日内核实并答复。我们不会在不提供任何申诉渠道的情况下对账号作出无理由的永久封禁。</div>
|
||||
|
||||
<div class="ag-h">六、知识产权</div>
|
||||
<ol>
|
||||
<li>除另有声明外,本服务所包含的内容(包括但不限于软件、技术、程序、界面、文字、图片、图标、音视频、版面设计、商标、标识等)的知识产权归我们或相关权利人所有,受法律保护。</li>
|
||||
<li>未经我们事先书面许可,您不得以任何形式使用、复制、修改、发布、出售、出租、反向工程、反编译上述内容,或制作衍生作品。</li>
|
||||
<li>您在本服务中上传/发布的内容(如“反馈更低价”提交的链接、截图、文字等),应为您原创或已获合法授权,不侵犯他人合法权益;您授权我们在为提供和改进本服务所必需的范围内对该等内容进行使用。</li>
|
||||
<li><strong>【侵权投诉处理】</strong>如您认为本服务中的内容侵犯了您的知识产权或其他合法权益,可通过 support@wonderable.ai 向我们发起投诉并提供权属证明及相关材料。我们核实后将依法采取删除、屏蔽等必要措施;被投诉方可提交不侵权声明进行申诉。</li>
|
||||
</ol>
|
||||
|
||||
<div class="ag-h">七、第三方平台与第三方服务</div>
|
||||
<ol>
|
||||
<li>本服务包含跳转至第三方平台(电商/外卖/团购平台、CPS 联盟链接、私域社群、广告等)的功能。该等第三方平台与服务由第三方独立提供并独立承担责任,受其自身协议与规则约束。我们对第三方平台的内容、商品、服务、价格及其行为不作保证,亦不承担责任。</li>
|
||||
<li>您通过本服务跳转第三方平台进行的交易,是您与该第三方平台/商家之间的交易,相关权利义务由您与该第三方解决。</li>
|
||||
</ol>
|
||||
|
||||
<div class="ag-h">八、广告</div>
|
||||
<ol>
|
||||
<li>您理解并同意,为维持本服务的免费运营,我们或我们授权的第三方可能在本服务中(如比价等待期悬浮窗、福利任务)向您展示广告(含激励视频广告)。</li>
|
||||
<li><strong>您应对广告内容自行审慎判断,除法律法规明确规定外,您应对依广告信息进行的交易自行负责。</strong>您可按《傻瓜比价隐私政策》的说明管理个性化广告。</li>
|
||||
</ol>
|
||||
|
||||
<div class="ag-h">九、免责声明与责任限制(请重点阅读)</div>
|
||||
<ol>
|
||||
<li><strong>【服务“现状”提供】</strong>在法律允许的范围内,本服务按“现状”和“可得”基础提供。我们不保证本服务不会中断,也不保证其及时性、安全性、准确性、无错误。</li>
|
||||
<li><strong>【比价准确性免责】</strong>如前所述,我们不对比价结果的准确性、完整性、实时性及“最低价”表述作保证,您应在第三方平台下单前自行核对价格与优惠。</li>
|
||||
<li><strong>【第三方原因免责】</strong>对因第三方平台规则变化、接口变动、风控封禁、第三方 SDK/服务故障等非我们直接原因导致的服务异常或损失,在法律允许范围内我们不承担责任。</li>
|
||||
<li><strong>【第三方平台规则风险】</strong>您理解并同意,是否使用本服务由您自主选择。各第三方平台对其平台的访问与使用有其自身规则,若您与第三方平台之间因平台规则产生账号限制等后果,在法律允许范围内由您与该第三方平台依其规则处理,我们不对该等第三方平台的处理结果承担责任;我们会在合理范围内持续优化服务以降低此类情况发生。</li>
|
||||
<li><strong>【不可抗力】</strong>因不可抗力(如自然灾害、网络故障、电力中断、政府行为、法律法规变动等)导致服务中断或无法提供的,在法律允许范围内我们免责,但会尽力减少对您的影响。</li>
|
||||
<li><strong>【责任限额】</strong>在法律允许的最大范围内,对于因使用或无法使用本服务造成的间接、偶然、惩罚性损失(如利润损失、数据损失),我们不承担责任;我们对您承担的累计赔偿责任总额,以法律强制规定为限【如需设置上限,由法务确定具体表述】。本条不排除或限制依法不可排除或限制的责任(如因我们故意或重大过失、或侵害您人身权益依法应承担的责任)。</li>
|
||||
</ol>
|
||||
|
||||
<div class="ag-h">十、协议的变更、中止与终止</div>
|
||||
<ol>
|
||||
<li><strong>【协议变更】</strong>我们可根据法律法规变化或运营需要修订本协议,并通过 App 内公告、弹窗、推送等合理方式提前通知。变更内容将在公示的生效日期起施行(通常不短于公示后 7-8 个自然日)。如您不同意变更内容,应停止使用相关服务;变更生效后您继续使用的,视为同意变更后的协议。</li>
|
||||
<li><strong>【服务中止/终止】</strong>在您违反本协议、法律法规要求、或我们基于合理商业安排经合理通知终止服务等情形下,我们有权中止或终止向您提供部分或全部服务。</li>
|
||||
<li><strong>【账号注销】</strong>您可按 App 内流程注销账号;注销后我们将停止为您提供服务,并依法处理您的个人信息。</li>
|
||||
<li>协议终止不影响在此之前已产生的权利义务,以及知识产权、责任限制等依其性质应继续有效的条款。</li>
|
||||
</ol>
|
||||
|
||||
<div class="ag-h">十一、通知与送达</div>
|
||||
<div class="ag-p">我们可通过以下任一方式向您送达通知:App 内公告/弹窗、站内信、推送、向您注册的手机号发送短信、向您提供的邮箱发送邮件等。上述通知于发送成功或刊登完成时视为送达。请您保证联系方式真实有效并及时更新,因联系方式不准确或未及时更新导致通知无法送达的后果由您承担。</div>
|
||||
|
||||
<div class="ag-h">十二、法律适用与争议解决</div>
|
||||
<ol>
|
||||
<li>本协议的订立、生效、履行、解释及争议解决,适用中华人民共和国法律(不含冲突法及港澳台地区法律)。</li>
|
||||
<li>因本协议或本服务产生的争议,您与我们应友好协商解决;协商不成的,任何一方均可向本协议签订地有管辖权的人民法院提起诉讼。本协议签订地为北京市丰台区。(注:约定公司所在地法院管辖属合理约定;不得约定与双方无实际联系的偏远地区法院,否则该管辖约定可能被认定无效。)</li>
|
||||
</ol>
|
||||
|
||||
<div class="ag-h">十三、其他</div>
|
||||
<ol>
|
||||
<li>本协议各条款标题仅为方便阅读,不影响条款含义的解释。</li>
|
||||
<li>本协议任一条款被认定为无效或不可执行的,不影响其余条款的效力。</li>
|
||||
<li>如您对本协议有任何问题或建议,可通过《傻瓜比价隐私政策》“如何联系我们”中的方式与我们联系。</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="ag-foot">傻瓜比价 · 用户服务协议<br>万德一博(北京)科技有限公司</div>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
@@ -0,0 +1,541 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="../shared/fonts.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||
<title>设置 · 傻瓜比价</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
|
||||
/* 【去框 + 不滚动】页面本身不滚动(固定屏),内部 set-scroll 才滚;不用 min-height:100vh(避免 vh 与 WebView 视口差导致整页能下滑一点) */
|
||||
html, body { height: 100%; overflow: hidden; }
|
||||
body { font-family: 'PuHuiTi', -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; background: #F5F5F5; color: #1A1A1A; }
|
||||
.device { position: relative; width: 100%; height: 100%; background: #F5F5F5; overflow: hidden; }
|
||||
.set-screen { position: absolute; inset: 0; display: flex; flex-direction: column; background: #F5F5F5; }
|
||||
|
||||
/* header */
|
||||
.set-header { height: 48px; flex-shrink: 0; display: flex; align-items: center; padding: 0 8px; position: relative; background: #F5F5F5; }
|
||||
.set-back { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; background: none; border: none; cursor: pointer; padding: 0; }
|
||||
.set-back:active { opacity: .5; }
|
||||
.set-back svg { width: 24px; height: 24px; display: block; }
|
||||
.set-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1A1A1A; }
|
||||
|
||||
/* panels */
|
||||
.set-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
|
||||
.set-body[hidden] { display: none; }
|
||||
.set-scroll { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 12px 14px; display: flex; flex-direction: column; gap: 12px; }
|
||||
.set-scroll::-webkit-scrollbar { display: none; }
|
||||
.set-bottom-group { flex-shrink: 0; padding: 8px 14px 20px; display: flex; flex-direction: column; gap: 6px; }
|
||||
|
||||
/* card + row */
|
||||
.set-card { background: #FFFFFF; border-radius: 14px; padding: 0 16px; box-shadow: 0 1px 2px rgba(0,0,0,.03); }
|
||||
.set-row { display: flex; align-items: center; min-height: 56px; padding: 12px 0; cursor: pointer; }
|
||||
.set-row:active { background: rgba(0,0,0,.02); }
|
||||
.set-row.set-static { cursor: default; }
|
||||
.set-row.set-static:active { background: transparent; }
|
||||
.set-row-label { flex: 1; font-size: 15px; font-weight: 400; color: #1A1A1A; line-height: 1.5; }
|
||||
.set-row-right { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
||||
.set-value { font-size: 15px; color: #999999; max-width: 52vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.set-chevron { display: flex; align-items: center; flex-shrink: 0; }
|
||||
.set-chevron svg { width: 8px; height: 14px; display: block; }
|
||||
.set-divider { height: .5px; background: #E5E5E5; }
|
||||
|
||||
/* 头像缩略(对齐原型 .set-avatar-thumb:渐变圆 + 卡通头像 SVG) */
|
||||
.set-avatar-thumb { width: 40px; height: 40px; border-radius: 50%; overflow: hidden; background: radial-gradient(circle at 42% 32%, #FFE0B2 0%, #FFE066 43%, #FFEB3B 100%); border: 2px solid #fff; display: flex; align-items: center; justify-content: center; flex-shrink: 0; box-shadow: 0 6px 16px rgba(255,137,32,.20); }
|
||||
.set-avatar-thumb svg { width: 38px; height: 38px; display: block; }
|
||||
.set-avatar-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
|
||||
/* 退出 / 注销 */
|
||||
.set-logout-row { justify-content: center; }
|
||||
.set-logout-row .set-row-label { flex: 0 0 auto; font-size: 15px; color: #666666; text-align: center; white-space: nowrap; }
|
||||
.set-delete { font-size: 12px; color: #999999; padding: 6px 12px; border-radius: 6px; cursor: pointer; align-self: center; }
|
||||
.set-delete:active { background: rgba(0,0,0,.04); }
|
||||
|
||||
/* 关于 hero */
|
||||
.set-about-hero { padding: 28px 0 34px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
|
||||
.set-about-brand { display: inline-flex; align-items: center; justify-content: center; gap: 12px; }
|
||||
.set-about-logo { width: 48px; height: 48px; border-radius: 12px; display: block; box-shadow: 0 5px 14px rgba(0,0,0,.08); }
|
||||
.set-about-name { font-size: 30px; font-weight: 900; line-height: 1.05; color: #000000; white-space: nowrap; }
|
||||
.set-about-version { margin-top: 10px; font-size: 13px; font-weight: 400; line-height: 1.35; color: #999999; }
|
||||
|
||||
/* 个性化广告 假开关 */
|
||||
.set-switch-row { display: flex; align-items: flex-start; gap: 12px; padding: 14px 0; }
|
||||
.set-switch-text { flex: 1; min-width: 0; }
|
||||
.set-switch-label { font-size: 15px; color: #1A1A1A; line-height: 22px; }
|
||||
.set-switch-desc { font-size: 12px; color: #999999; line-height: 18px; margin-top: 4px; }
|
||||
.set-switch { width: 50px; height: 30px; border-radius: 15px; background: #E5E5E5; position: relative; flex-shrink: 0; cursor: pointer; transition: background .2s; margin-top: 2px; }
|
||||
.set-switch.on { background: #34C759; }
|
||||
.set-switch-knob { position: absolute; top: 2px; left: 2px; width: 26px; height: 26px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.2); transition: transform .2s; }
|
||||
.set-switch.on .set-switch-knob { transform: translateX(20px); }
|
||||
|
||||
/* ===== 昵称编辑弹窗(对齐原型 .nick-modal:按钮 radius 10 四角圆弧,输入 #FAFAFA,含字数) ===== */
|
||||
.nick-modal { display: none; position: fixed; inset: 0; z-index: 285; background: rgba(0,0,0,.45); align-items: center; justify-content: center; padding: 0 32px; }
|
||||
.nick-modal.open { display: flex; }
|
||||
.nick-modal-card { width: 100%; background: #FFFFFF; border-radius: 14px; padding: 20px 18px 16px; }
|
||||
.nick-modal-title { font-size: 16px; font-weight: 600; line-height: 1.5; color: #1A1A1A; text-align: center; margin-bottom: 14px; }
|
||||
.nick-modal-input { width: 100%; height: 40px; padding: 0 12px; border: none; background: #FAFAFA; border-radius: 10px; font-size: 15px; font-weight: 400; color: #1A1A1A; font-family: inherit; outline: none; margin-bottom: 6px; }
|
||||
.nick-modal-count { text-align: right; font-size: 12px; font-weight: 400; line-height: 1.5; color: #999999; margin: 0 2px 14px; }
|
||||
.nick-modal-actions { display: flex; gap: 12px; }
|
||||
.nick-modal-btn { flex: 1; height: 40px; border-radius: 10px; border: none; font-size: 15px; font-weight: 700; line-height: 1; cursor: pointer; font-family: inherit; }
|
||||
.nick-modal-btn.cancel { background: #FAFAFA; color: #666666; }
|
||||
.nick-modal-btn.confirm { background: #FFD600; color: #1A1A1A; }
|
||||
|
||||
/* ===== 退出 / 注销确认弹窗(对齐原型:radius 18 卡 + 按钮 radius 12 四角圆弧) ===== */
|
||||
.cfm-mask { display: none; position: fixed; inset: 0; z-index: 260; background: rgba(0,0,0,.45); align-items: center; justify-content: center; padding: 40px 32px; }
|
||||
.cfm-mask.open { display: flex; }
|
||||
.cfm-card { background: #fff; border-radius: 18px; max-width: 295px; width: 100%; padding: 24px 24px 16px; text-align: center; }
|
||||
.cfm-warn { font-size: 48px; line-height: 1; margin-bottom: 12px; }
|
||||
.cfm-title { font-size: 18px; font-weight: 700; margin-bottom: 8px; color: #1A1A1A; }
|
||||
.cfm-title.danger { color: #E53935; }
|
||||
.cfm-msg { font-size: 14px; color: #999999; line-height: 22px; margin-bottom: 24px; }
|
||||
.cfm-msg.tight { font-size: 13px; margin-bottom: 8px; white-space: nowrap; }
|
||||
.cfm-msg .danger { color: #E53935; font-weight: 600; }
|
||||
.cfm-databox { text-align: left; background: #FAFAFA; border-radius: 8px; padding: 12px 16px; margin-bottom: 24px; font-size: 13px; color: #666666; line-height: 22px; }
|
||||
.cfm-actions { display: flex; gap: 12px; }
|
||||
.cfm-btn { flex: 1; padding: 12px; border-radius: 12px; font-size: 15px; font-weight: 600; cursor: pointer; font-family: inherit; }
|
||||
.cfm-btn.outline { border: 1px solid #CCCCCC; background: #fff; color: #4D4D4D; }
|
||||
.cfm-btn.cta { border: none; background: linear-gradient(180deg, #FFE066 0%, #FFD600 100%); color: #1A1A1A; box-shadow: inset 0 1px 0 rgba(255,255,255,.7), 0 6px 18px rgba(255,179,0,.35); }
|
||||
|
||||
/* ===== 头像底部 sheet(对齐原型 .avatar-sheet:设置页下方弹出) ===== */
|
||||
.avatar-sheet-mask { display: none; position: fixed; inset: 0; z-index: 290; background: rgba(0,0,0,.45); }
|
||||
.avatar-sheet-mask.open { display: block; }
|
||||
.avatar-sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 291; transform: translateY(100%); transition: transform .26s cubic-bezier(.32,.72,.27,1); padding: 0 8px 8px; pointer-events: none; }
|
||||
.avatar-sheet.open { transform: translateY(0); pointer-events: auto; }
|
||||
.avatar-sheet-group { background: rgba(255,255,255,.98); border-radius: 14px; overflow: hidden; }
|
||||
.avatar-sheet-grip { width: 36px; height: 4px; background: rgba(0,0,0,.18); border-radius: 2px; margin: 8px auto 4px; }
|
||||
.avatar-sheet-btn { width: 100%; height: 56px; border: none; background: transparent; font-size: 17px; font-weight: 400; line-height: 1.5; color: #1A1A1A; cursor: pointer; font-family: inherit; }
|
||||
.avatar-sheet-btn:active { background: rgba(0,0,0,.05); }
|
||||
.avatar-sheet-btn + .avatar-sheet-btn { border-top: .5px solid #E5E5E5; }
|
||||
.avatar-sheet-cancel { margin-top: 8px; background: rgba(255,255,255,.98); border-radius: 14px; font-weight: 700; }
|
||||
|
||||
/* ===== 头像裁剪(移动和缩放) ===== */
|
||||
.crop-screen { display: none; position: fixed; inset: 0; z-index: 300; background: #000; flex-direction: column; }
|
||||
.crop-screen.open { display: flex; }
|
||||
.crop-header { height: 48px; flex-shrink: 0; display: flex; align-items: center; justify-content: space-between; padding: 0 16px; }
|
||||
.crop-header-btn { background: none; border: none; color: #fff; font-size: 16px; font-weight: 400; cursor: pointer; font-family: inherit; padding: 8px 0; }
|
||||
.crop-header-btn.confirm { color: #FFD600; font-weight: 700; }
|
||||
.crop-header-title { color: #fff; font-size: 16px; font-weight: 500; }
|
||||
.crop-stage { flex: 1; position: relative; overflow: hidden; touch-action: none; }
|
||||
.crop-stage img { position: absolute; left: 0; top: 0; transform-origin: 0 0; will-change: transform; -webkit-user-drag: none; user-select: none; pointer-events: none; }
|
||||
.crop-mask { position: absolute; inset: 0; pointer-events: none; }
|
||||
.crop-tips { flex-shrink: 0; text-align: center; color: rgba(255,255,255,.7); font-size: 13px; padding: 14px 0 18px; }
|
||||
|
||||
/* toast */
|
||||
.set-toast { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); background: rgba(0,0,0,.78); color: #FFFFFF; padding: 12px 20px; border-radius: 10px; font-size: 14px; line-height: 1.5; max-width: 70%; text-align: center; z-index: 320; opacity: 0; pointer-events: none; transition: opacity .2s; }
|
||||
.set-toast.show { opacity: 1; }
|
||||
|
||||
/* 忙碌遮罩(上传中) */
|
||||
.busy-mask { display: none; position: fixed; inset: 0; z-index: 310; background: rgba(0,0,0,.2); align-items: center; justify-content: center; }
|
||||
.busy-mask.open { display: flex; }
|
||||
.busy-spin { width: 38px; height: 38px; border: 3px solid rgba(255,255,255,.5); border-top-color: #FFD600; border-radius: 50%; animation: busySpin .8s linear infinite; }
|
||||
@keyframes busySpin { to { transform: rotate(360deg); } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="device">
|
||||
<div class="set-screen">
|
||||
<div class="set-header">
|
||||
<button class="set-back" onclick="onBack()" aria-label="返回">
|
||||
<svg viewBox="0 0 24 24" fill="none"><path d="M15 6L9 12L15 18" stroke="#1A1A1A" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</button>
|
||||
<div class="set-title" id="setTitle">设置</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== 主面板 ===== -->
|
||||
<div class="set-body" id="panel-main">
|
||||
<div class="set-scroll">
|
||||
<div class="set-card">
|
||||
<div class="set-row" onclick="openAvatarSheet()">
|
||||
<span class="set-row-label">头像</span>
|
||||
<div class="set-row-right">
|
||||
<span class="set-avatar-thumb" id="avatarThumb"></span>
|
||||
<span class="set-chevron"><svg viewBox="0 0 8 14" fill="none"><path d="M1 1L7 7L1 13" stroke="#C7C7CC" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="set-divider"></div>
|
||||
<div class="set-row" onclick="openNickname()">
|
||||
<span class="set-row-label">昵称</span>
|
||||
<div class="set-row-right"><span class="set-value" id="nicknameVal"></span><span class="set-chevron"><svg viewBox="0 0 8 14" fill="none"><path d="M1 1L7 7L1 13" stroke="#C7C7CC" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div>
|
||||
</div>
|
||||
<div class="set-divider"></div>
|
||||
<div class="set-row" onclick="showPanel('phone')">
|
||||
<span class="set-row-label">手机号</span>
|
||||
<div class="set-row-right"><span class="set-value" id="phoneVal"></span><span class="set-chevron"><svg viewBox="0 0 8 14" fill="none"><path d="M1 1L7 7L1 13" stroke="#C7C7CC" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="set-card">
|
||||
<div class="set-row" onclick="nav('notificationSettings')">
|
||||
<span class="set-row-label">通知设置</span>
|
||||
<div class="set-row-right"><span class="set-chevron"><svg viewBox="0 0 8 14" fill="none"><path d="M1 1L7 7L1 13" stroke="#C7C7CC" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="set-card">
|
||||
<div class="set-row" onclick="showPanel('about')">
|
||||
<span class="set-row-label">关于傻瓜比价</span>
|
||||
<div class="set-row-right"><span class="set-chevron"><svg viewBox="0 0 8 14" fill="none"><path d="M1 1L7 7L1 13" stroke="#C7C7CC" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="set-bottom-group">
|
||||
<div class="set-card">
|
||||
<div class="set-row set-logout-row" onclick="openLogout()"><span class="set-row-label">退出登录</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== 手机号 ===== -->
|
||||
<div class="set-body" id="panel-phone" hidden>
|
||||
<div class="set-scroll">
|
||||
<div class="set-card">
|
||||
<div class="set-row set-static"><span class="set-row-label">手机号</span><div class="set-row-right"><span class="set-value" id="phoneVal2"></span></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="set-bottom-group"><span class="set-delete" onclick="openDelete()">注销账号</span></div>
|
||||
</div>
|
||||
|
||||
<!-- ===== 关于傻瓜比价 ===== -->
|
||||
<div class="set-body" id="panel-about" hidden>
|
||||
<div class="set-scroll">
|
||||
<div class="set-about-hero">
|
||||
<div class="set-about-brand">
|
||||
<img class="set-about-logo" src="assets/shared/logos/sb-brand.png" alt="傻瓜比价">
|
||||
<span class="set-about-name">傻瓜比价</span>
|
||||
</div>
|
||||
<div class="set-about-version" id="aboutVersion">version</div>
|
||||
</div>
|
||||
<div class="set-card">
|
||||
<div class="set-row" onclick="nav('checkUpdate')"><span class="set-row-label">检查更新</span><div class="set-row-right"><span class="set-value" id="updVersion"></span></div></div>
|
||||
</div>
|
||||
<div class="set-card">
|
||||
<div class="set-row" onclick="showPanel('agreements')"><span class="set-row-label">相关协议</span><div class="set-row-right"><span class="set-chevron"><svg viewBox="0 0 8 14" fill="none"><path d="M1 1L7 7L1 13" stroke="#C7C7CC" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div></div>
|
||||
<div class="set-divider"></div>
|
||||
<div class="set-row" onclick="nav('permissions')"><span class="set-row-label">权限管理</span><div class="set-row-right"><span class="set-chevron"><svg viewBox="0 0 8 14" fill="none"><path d="M1 1L7 7L1 13" stroke="#C7C7CC" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div></div>
|
||||
<div class="set-divider"></div>
|
||||
<div class="set-row" onclick="showPanel('ads')"><span class="set-row-label">个性化广告</span><div class="set-row-right"><span class="set-chevron"><svg viewBox="0 0 8 14" fill="none"><path d="M1 1L7 7L1 13" stroke="#C7C7CC" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div></div>
|
||||
<div class="set-divider"></div>
|
||||
<div class="set-row" onclick="nav('devSettings')"><span class="set-row-label">开发设置</span><div class="set-row-right"><span class="set-chevron"><svg viewBox="0 0 8 14" fill="none"><path d="M1 1L7 7L1 13" stroke="#C7C7CC" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== 相关协议 ===== -->
|
||||
<div class="set-body" id="panel-agreements" hidden>
|
||||
<div class="set-scroll">
|
||||
<div class="set-card">
|
||||
<div class="set-row" onclick="nav('agreement:user')"><span class="set-row-label">用户服务协议</span><div class="set-row-right"><span class="set-chevron"><svg viewBox="0 0 8 14" fill="none"><path d="M1 1L7 7L1 13" stroke="#C7C7CC" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div></div>
|
||||
<div class="set-divider"></div>
|
||||
<div class="set-row" onclick="nav('agreement:privacy')"><span class="set-row-label">隐私政策</span><div class="set-row-right"><span class="set-chevron"><svg viewBox="0 0 8 14" fill="none"><path d="M1 1L7 7L1 13" stroke="#C7C7CC" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== 个性化广告(假开关,纯 H5) ===== -->
|
||||
<div class="set-body" id="panel-ads" hidden>
|
||||
<div class="set-scroll">
|
||||
<div class="set-card">
|
||||
<div class="set-switch-row">
|
||||
<div class="set-switch-text">
|
||||
<div class="set-switch-label">个性化广告推荐</div>
|
||||
<div class="set-switch-desc">关闭个性化推荐不会减少广告数量,但广告与你的相关性可能降低。</div>
|
||||
</div>
|
||||
<div class="set-switch on" id="adsSwitch" onclick="toggleAds()"><span class="set-switch-knob"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 头像底部 sheet -->
|
||||
<div class="avatar-sheet-mask" id="avatarSheetMask" onclick="closeAvatarSheet()"></div>
|
||||
<div class="avatar-sheet" id="avatarSheet">
|
||||
<div class="avatar-sheet-group">
|
||||
<div class="avatar-sheet-grip"></div>
|
||||
<button class="avatar-sheet-btn" onclick="pickAvatar(true)">拍照</button>
|
||||
<button class="avatar-sheet-btn" onclick="pickAvatar(false)">从相册中选择</button>
|
||||
</div>
|
||||
<button class="avatar-sheet-btn avatar-sheet-cancel" onclick="closeAvatarSheet()">取消</button>
|
||||
</div>
|
||||
<input type="file" id="avCam" accept="image/*" capture="environment" style="display:none">
|
||||
<input type="file" id="avAlbum" accept="image/*" style="display:none">
|
||||
|
||||
<!-- 头像裁剪(移动和缩放) -->
|
||||
<div class="crop-screen" id="cropScreen">
|
||||
<div class="crop-header">
|
||||
<button class="crop-header-btn" onclick="closeCrop()">取消</button>
|
||||
<span class="crop-header-title">移动和缩放</span>
|
||||
<button class="crop-header-btn confirm" onclick="confirmCrop()">选取</button>
|
||||
</div>
|
||||
<div class="crop-stage" id="cropStage">
|
||||
<img id="cropImg" alt="">
|
||||
<canvas class="crop-mask" id="cropMask"></canvas>
|
||||
</div>
|
||||
<div class="crop-tips">捏合手势可缩放,拖动可调整位置</div>
|
||||
</div>
|
||||
|
||||
<!-- 昵称编辑弹窗 -->
|
||||
<div class="nick-modal" id="nickModal" onclick="closeNickname(event)">
|
||||
<div class="nick-modal-card" onclick="event.stopPropagation()">
|
||||
<div class="nick-modal-title">修改昵称</div>
|
||||
<input type="text" id="nickInput" class="nick-modal-input" maxlength="20" placeholder="请输入昵称" oninput="updateNickCount()">
|
||||
<div id="nickCount" class="nick-modal-count">0/20</div>
|
||||
<div class="nick-modal-actions">
|
||||
<button class="nick-modal-btn cancel" onclick="closeNickname()">取消</button>
|
||||
<button class="nick-modal-btn confirm" onclick="saveNickname()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 退出确认 -->
|
||||
<div class="cfm-mask" id="logoutModal">
|
||||
<div class="cfm-card">
|
||||
<div class="cfm-title">退出登录</div>
|
||||
<div class="cfm-msg">退出后将无法继续累积金币收益</div>
|
||||
<div class="cfm-actions">
|
||||
<button class="cfm-btn outline" onclick="doLogout()">退出</button>
|
||||
<button class="cfm-btn outline" onclick="closeLogout()">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 注销确认 -->
|
||||
<div class="cfm-mask" id="deleteModal">
|
||||
<div class="cfm-card">
|
||||
<div class="cfm-warn">⚠️</div>
|
||||
<div class="cfm-title danger">确认注销账号?</div>
|
||||
<div class="cfm-msg tight">注销后以下数据将<span class="danger">永久删除且无法恢复</span>:</div>
|
||||
<div class="cfm-databox">· 全部金币余额和现金收益<br>· 比价记录和购买战绩<br>· 邀请好友关系和返佣收益</div>
|
||||
<div class="cfm-actions">
|
||||
<button class="cfm-btn outline" onclick="doDelete()">确认注销</button>
|
||||
<button class="cfm-btn cta" onclick="closeDelete()">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="busy-mask" id="busyMask"><div class="busy-spin"></div></div>
|
||||
<div class="set-toast" id="toast"></div>
|
||||
|
||||
<script src="../shared/bridge.js"></script>
|
||||
<script src="../shared/api.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
var DEFAULT_AVATAR = '<svg viewBox="0 0 80 80" fill="none"><defs><radialGradient id="sgAvBg" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(31 24) rotate(58) scale(52)"><stop offset="0" stop-color="#FFF5B5"/><stop offset=".58" stop-color="#FFD45F"/><stop offset="1" stop-color="#FFB43A"/></radialGradient><linearGradient id="sgAvFace" x1="39" y1="25" x2="39" y2="55" gradientUnits="userSpaceOnUse"><stop stop-color="#FFE0B0"/><stop offset="1" stop-color="#FFC783"/></linearGradient><linearGradient id="sgAvHood" x1="40" y1="45" x2="40" y2="78" gradientUnits="userSpaceOnUse"><stop stop-color="#FFD742"/><stop offset="1" stop-color="#FFA923"/></linearGradient></defs><circle cx="40" cy="40" r="40" fill="url(#sgAvBg)"/><path d="M15 72c2.5-13 12.2-21 25-21s22.5 8 25 21H15z" fill="url(#sgAvHood)"/><path d="M26 62c2.8 4.8 7.4 7.4 14 7.4 6.5 0 11.2-2.6 14-7.4-2.6-7.2-7.2-10.8-14-10.8S28.6 54.8 26 62z" fill="#FFE789" opacity=".8"/><path d="M20.5 37.5c0-13.2 8.3-22.2 20.3-22.2 11.7 0 19.7 8.8 19.7 22.1 0 2.4-.3 4.6-.8 6.8H21.3c-.5-2.2-.8-4.5-.8-6.7z" fill="#3B2416"/><path d="M23.5 36.3c.8-11.4 7.7-18 17.1-18 9.8 0 16.4 6.9 16.8 18.3-3.3-5.2-8.1-7.7-14.4-7.5-3.1.1-5.2 1.6-8 1.6-3.8 0-7.7 1.5-11.5 5.6z" fill="#5B3520"/><path d="M22.8 39.6c-2.9.1-5.2 2.5-5.1 5.7.1 3.1 2.4 5.3 5.5 5.4l.5-11.1h-.9z" fill="#FFC783"/><path d="M57.2 39.6c2.9.1 5.2 2.5 5.1 5.7-.1 3.1-2.4 5.3-5.5 5.4l-.5-11.1h.9z" fill="#FFC783"/><path d="M22.5 38.4c0-10.5 7.2-17.7 17.5-17.7s17.5 7.2 17.5 17.7v5.8c0 10.2-7.2 17.2-17.5 17.2s-17.5-7-17.5-17.2v-5.8z" fill="url(#sgAvFace)"/><path d="M22.7 35.8c2.5-8.7 9.7-13.2 18-13.2 7.7 0 13.7 4.4 16.1 11.9-4.8-.3-8.5-2.5-11-6.5-3.2 4.7-10 7.8-23.1 7.8z" fill="#3B2416"/><circle cx="31.3" cy="42.5" r="2.1" fill="#3A2113"/><circle cx="48.7" cy="42.5" r="2.1" fill="#3A2113"/><circle cx="28.2" cy="48.4" r="3.2" fill="#FF916C" opacity=".54"/><circle cx="51.8" cy="48.4" r="3.2" fill="#FF916C" opacity=".54"/><path d="M35.8 50.8c2.7 2.1 5.7 2.1 8.4 0" stroke="#6B2C19" stroke-width="1.8" stroke-linecap="round"/><path d="M27 34.2c1.8-3.2 3.9-5.7 6.3-7.3-1.7 3.3-2.5 6.6-2.4 9.8-1.2-.8-2.5-1.6-3.9-2.5zM39.5 22c-4.1 1.7-7.2 4.1-9.4 7.3 5.8-.1 10.5-1.6 14-4.5L39.5 22z" fill="#2A170E"/><path d="M33 63.7c3.7 1.8 10.3 1.8 14 0" stroke="#FFF2B3" stroke-width="2.2" stroke-linecap="round" opacity=".75"/></svg>';
|
||||
var toastEl = document.getElementById('toast'), toastTimer = null;
|
||||
function showToast(m) { toastEl.textContent = m; toastEl.classList.add('show'); if (toastTimer) clearTimeout(toastTimer); toastTimer = setTimeout(function () { toastEl.classList.remove('show'); }, 1600); }
|
||||
function escAttr(s) { return String(s == null ? '' : s).replace(/"/g, '"').replace(/</g, '<'); }
|
||||
function bridgeReady() { return window.SGBridge && SGBridge.hasNative && typeof SGBridge.getToken === 'function'; }
|
||||
function busy(on) { document.getElementById('busyMask').classList.toggle('open', !!on); }
|
||||
|
||||
// ===== 面板切换 =====
|
||||
var PARENT = { main: null, phone: 'main', about: 'main', agreements: 'about', ads: 'about' };
|
||||
var TITLE = { main: '设置', phone: '手机号', about: '', agreements: '相关协议', ads: '个性化广告' };
|
||||
var curPanel = 'main';
|
||||
function showPanel(name) {
|
||||
['main', 'phone', 'about', 'agreements', 'ads'].forEach(function (p) { document.getElementById('panel-' + p).hidden = (p !== name); });
|
||||
document.getElementById('setTitle').textContent = TITLE[name] || '';
|
||||
curPanel = name;
|
||||
}
|
||||
window.showPanel = showPanel;
|
||||
// 返回:裁剪>弹窗>面板>退出,逐级
|
||||
window.onBack = function () {
|
||||
if (document.getElementById('cropScreen').classList.contains('open')) { closeCrop(); return; }
|
||||
if (document.getElementById('avatarSheet').classList.contains('open')) { closeAvatarSheet(); return; }
|
||||
var modals = ['nickModal', 'logoutModal', 'deleteModal'];
|
||||
for (var i = 0; i < modals.length; i++) { var m = document.getElementById(modals[i]); if (m && m.classList.contains('open')) { m.classList.remove('open'); return; } }
|
||||
var p = PARENT[curPanel];
|
||||
if (p) { showPanel(p); return; }
|
||||
if (window.SGBridge && SGBridge.closePage) { SGBridge.closePage(); } else if (history.length > 1) { history.back(); }
|
||||
};
|
||||
|
||||
// ===== 跳原生 =====
|
||||
window.nav = function (route) {
|
||||
if (route === 'permissions' || route === 'devSettings' || route.indexOf('agreement:') === 0) {
|
||||
try { localStorage.setItem('sg_set_panel', curPanel); } catch (e) {}
|
||||
}
|
||||
if (window.SGBridge && SGBridge.navigate) { SGBridge.navigate(route); } else { console.log('[nav]', route); }
|
||||
};
|
||||
|
||||
// ===== 用户资料 =====
|
||||
function loadProfile() {
|
||||
var a = (window.SGBridge && SGBridge.getAuthState) ? (SGBridge.getAuthState() || {}) : {};
|
||||
document.getElementById('nicknameVal').textContent = a.nickname || '傻瓜用户';
|
||||
var phone = a.phone || '未绑定';
|
||||
document.getElementById('phoneVal').textContent = phone;
|
||||
document.getElementById('phoneVal2').textContent = phone;
|
||||
setAvatar(a.avatarUrl);
|
||||
var ver = (window.SGBridge && SGBridge.getAppVersion) ? (SGBridge.getAppVersion() || '') : '';
|
||||
ver = ver || '1.0.0';
|
||||
document.getElementById('aboutVersion').textContent = 'version v' + ver;
|
||||
document.getElementById('updVersion').textContent = 'v' + ver;
|
||||
}
|
||||
function setAvatar(url) {
|
||||
var el = document.getElementById('avatarThumb');
|
||||
// 任意非空 url 都用 <img>:http(s) 绝对、/media 同源相对、blob: 本地预览均可
|
||||
if (url) { el.innerHTML = '<img src="' + escAttr(url) + '" alt="头像">'; }
|
||||
else { el.innerHTML = DEFAULT_AVATAR; }
|
||||
}
|
||||
|
||||
// ===== 头像 sheet =====
|
||||
window.openAvatarSheet = function () { document.getElementById('avatarSheetMask').classList.add('open'); document.getElementById('avatarSheet').classList.add('open'); };
|
||||
window.closeAvatarSheet = function () { document.getElementById('avatarSheetMask').classList.remove('open'); document.getElementById('avatarSheet').classList.remove('open'); };
|
||||
window.pickAvatar = function (useCamera) { closeAvatarSheet(); document.getElementById(useCamera ? 'avCam' : 'avAlbum').click(); };
|
||||
['avCam', 'avAlbum'].forEach(function (id) {
|
||||
document.getElementById(id).addEventListener('change', function () {
|
||||
var f = this.files && this.files[0]; this.value = '';
|
||||
if (f && /^image\//.test(f.type)) openCrop(f);
|
||||
});
|
||||
});
|
||||
|
||||
// ===== 裁剪(移动和缩放)=====
|
||||
var crop = { img: null, natW: 0, natH: 0, base: 1, scale: 1, x: 0, y: 0, D: 0, cx: 0, cy: 0, pts: {}, startDist: 0, startScale: 1, midX: 0, midY: 0, file: null };
|
||||
var cropImgEl = document.getElementById('cropImg'), cropStage = document.getElementById('cropStage'), cropMask = document.getElementById('cropMask');
|
||||
function openCrop(file) {
|
||||
crop.file = file;
|
||||
var url = URL.createObjectURL(file);
|
||||
var im = new Image();
|
||||
im.onload = function () {
|
||||
crop.img = im; crop.natW = im.naturalWidth; crop.natH = im.naturalHeight;
|
||||
document.getElementById('cropScreen').classList.add('open');
|
||||
// 等布局生效后按 stage 实际尺寸初始化
|
||||
setTimeout(function () { initCrop(); }, 30);
|
||||
};
|
||||
im.onerror = function () { URL.revokeObjectURL(url); showToast('图片读取失败'); };
|
||||
cropImgEl.src = url; im.src = url;
|
||||
}
|
||||
function initCrop() {
|
||||
var sw = cropStage.clientWidth, sh = cropStage.clientHeight;
|
||||
crop.D = Math.min(sw, sh) * 0.86;
|
||||
crop.cx = (sw - crop.D) / 2; crop.cy = (sh - crop.D) / 2;
|
||||
crop.base = Math.max(crop.D / crop.natW, crop.D / crop.natH); // cover 裁剪框
|
||||
crop.scale = crop.base;
|
||||
crop.x = (sw - crop.natW * crop.scale) / 2;
|
||||
crop.y = (sh - crop.natH * crop.scale) / 2;
|
||||
drawMaskRing(sw, sh);
|
||||
applyCrop();
|
||||
}
|
||||
function drawMaskRing(sw, sh) {
|
||||
var dpr = window.devicePixelRatio || 1;
|
||||
cropMask.width = sw * dpr; cropMask.height = sh * dpr; cropMask.style.width = sw + 'px'; cropMask.style.height = sh + 'px';
|
||||
var ctx = cropMask.getContext('2d'); ctx.setTransform(dpr, 0, 0, dpr, 0, 0); ctx.clearRect(0, 0, sw, sh);
|
||||
ctx.fillStyle = 'rgba(0,0,0,.55)'; ctx.fillRect(0, 0, sw, sh);
|
||||
ctx.globalCompositeOperation = 'destination-out';
|
||||
ctx.beginPath(); ctx.arc(crop.cx + crop.D / 2, crop.cy + crop.D / 2, crop.D / 2, 0, Math.PI * 2); ctx.fill();
|
||||
ctx.globalCompositeOperation = 'source-over';
|
||||
ctx.strokeStyle = 'rgba(255,255,255,.9)'; ctx.lineWidth = 1.5;
|
||||
ctx.beginPath(); ctx.arc(crop.cx + crop.D / 2, crop.cy + crop.D / 2, crop.D / 2, 0, Math.PI * 2); ctx.stroke();
|
||||
}
|
||||
function clampCrop() {
|
||||
var w = crop.natW * crop.scale, h = crop.natH * crop.scale;
|
||||
if (crop.x > crop.cx) crop.x = crop.cx;
|
||||
if (crop.x + w < crop.cx + crop.D) crop.x = crop.cx + crop.D - w;
|
||||
if (crop.y > crop.cy) crop.y = crop.cy;
|
||||
if (crop.y + h < crop.cy + crop.D) crop.y = crop.cy + crop.D - h;
|
||||
}
|
||||
function applyCrop() { clampCrop(); cropImgEl.style.transform = 'translate(' + crop.x + 'px,' + crop.y + 'px) scale(' + crop.scale + ')'; }
|
||||
cropStage.addEventListener('pointerdown', function (e) { cropStage.setPointerCapture(e.pointerId); crop.pts[e.pointerId] = { x: e.clientX, y: e.clientY }; var ids = Object.keys(crop.pts); if (ids.length === 2) { var a = crop.pts[ids[0]], b = crop.pts[ids[1]]; crop.startDist = Math.hypot(a.x - b.x, a.y - b.y); crop.startScale = crop.scale; var r = cropStage.getBoundingClientRect(); crop.midX = (a.x + b.x) / 2 - r.left; crop.midY = (a.y + b.y) / 2 - r.top; } });
|
||||
cropStage.addEventListener('pointermove', function (e) {
|
||||
if (!crop.pts[e.pointerId]) return;
|
||||
var prev = crop.pts[e.pointerId]; crop.pts[e.pointerId] = { x: e.clientX, y: e.clientY };
|
||||
var ids = Object.keys(crop.pts);
|
||||
if (ids.length === 1) { crop.x += e.clientX - prev.x; crop.y += e.clientY - prev.y; applyCrop(); }
|
||||
else if (ids.length === 2) {
|
||||
var a = crop.pts[ids[0]], b = crop.pts[ids[1]]; var dist = Math.hypot(a.x - b.x, a.y - b.y);
|
||||
if (crop.startDist > 0) {
|
||||
var ns = Math.max(crop.base, Math.min(crop.base * 5, crop.startScale * dist / crop.startDist));
|
||||
// 以双指中点为锚缩放
|
||||
var k = ns / crop.scale;
|
||||
crop.x = crop.midX - (crop.midX - crop.x) * k;
|
||||
crop.y = crop.midY - (crop.midY - crop.y) * k;
|
||||
crop.scale = ns; applyCrop();
|
||||
}
|
||||
}
|
||||
});
|
||||
function endPt(e) { delete crop.pts[e.pointerId]; var ids = Object.keys(crop.pts); if (ids.length === 1) { } else if (ids.length === 0) { crop.startDist = 0; } }
|
||||
cropStage.addEventListener('pointerup', endPt);
|
||||
cropStage.addEventListener('pointercancel', endPt);
|
||||
window.closeCrop = function () { document.getElementById('cropScreen').classList.remove('open'); if (crop.img) { try { URL.revokeObjectURL(crop.img.src); } catch (e) {} } crop.img = null; crop.pts = {}; };
|
||||
window.confirmCrop = function () {
|
||||
if (!crop.img) return;
|
||||
var out = 512, cv = document.createElement('canvas'); cv.width = out; cv.height = out;
|
||||
var sx = (crop.cx - crop.x) / crop.scale, sy = (crop.cy - crop.y) / crop.scale, sd = crop.D / crop.scale;
|
||||
try { cv.getContext('2d').drawImage(crop.img, sx, sy, sd, sd, 0, 0, out, out); } catch (e) { showToast('裁剪失败'); return; }
|
||||
cv.toBlob(function (blob) { document.getElementById('cropScreen').classList.remove('open'); uploadAvatar(blob || crop.file); }, 'image/jpeg', 0.9);
|
||||
};
|
||||
|
||||
// ===== 上传头像 =====
|
||||
function uploadAvatar(blob) {
|
||||
var thumb = document.getElementById('avatarThumb');
|
||||
var prevHtml = thumb.innerHTML;
|
||||
setAvatar(URL.createObjectURL(blob)); // 乐观:裁剪完立即显示本地图,不等服务端(修「重进才变」)
|
||||
if (!bridgeReady()) { showToast('(预览)头像已更新'); return; }
|
||||
busy(true);
|
||||
(async function () {
|
||||
try {
|
||||
var fd = new FormData(); fd.append('file', blob, 'avatar.jpg');
|
||||
var res = await fetch('/api/v1/user/avatar', { method: 'POST', headers: { 'Authorization': 'Bearer ' + SGBridge.getToken() }, body: fd });
|
||||
if (res.ok) {
|
||||
showToast('头像已更新'); // 本地图已显示,保持不动(避免再拉服务端图闪一下)
|
||||
if (SGBridge.navigate) SGBridge.navigate('profileChanged'); // 同步原生缓存(我的页一致)
|
||||
} else if (res.status === 401) { thumb.innerHTML = prevHtml; if (SGBridge.requestLogin) SGBridge.requestLogin(); }
|
||||
else { thumb.innerHTML = prevHtml; var d = ''; try { var e = await res.json(); d = (e && e.detail) ? e.detail : ''; } catch (x) {} showToast(d || '头像上传失败,请重试'); }
|
||||
} catch (e) { thumb.innerHTML = prevHtml; showToast('网络异常,请重试'); } finally { busy(false); if (crop.img) { try { URL.revokeObjectURL(crop.img.src); } catch (e) {} crop.img = null; } }
|
||||
})();
|
||||
}
|
||||
|
||||
// ===== 昵称 =====
|
||||
window.openNickname = function () { var v = document.getElementById('nicknameVal').textContent || ''; document.getElementById('nickInput').value = v; updateNickCount(); document.getElementById('nickModal').classList.add('open'); setTimeout(function () { document.getElementById('nickInput').focus(); }, 60); };
|
||||
window.closeNickname = function (ev) { if (ev && ev.target && ev.target.id !== 'nickModal') return; document.getElementById('nickModal').classList.remove('open'); };
|
||||
window.updateNickCount = function () { var v = document.getElementById('nickInput').value || ''; document.getElementById('nickCount').textContent = v.length + '/20'; };
|
||||
window.saveNickname = function () {
|
||||
var name = (document.getElementById('nickInput').value || '').trim();
|
||||
if (!name) { showToast('昵称不能为空'); return; }
|
||||
if (!bridgeReady()) { document.getElementById('nicknameVal').textContent = name; document.getElementById('nickModal').classList.remove('open'); showToast('昵称已更新'); return; }
|
||||
(async function () {
|
||||
try {
|
||||
var res = await fetch('/api/v1/user/profile', { method: 'PATCH', headers: { 'Authorization': 'Bearer ' + SGBridge.getToken(), 'Content-Type': 'application/json' }, body: JSON.stringify({ nickname: name }) });
|
||||
if (res.ok) {
|
||||
var j = null; try { j = await res.json(); } catch (e) {}
|
||||
document.getElementById('nicknameVal').textContent = (j && j.nickname) || name;
|
||||
document.getElementById('nickModal').classList.remove('open');
|
||||
showToast('昵称已更新');
|
||||
if (SGBridge.navigate) SGBridge.navigate('profileChanged');
|
||||
} else if (res.status === 401) { if (SGBridge.requestLogin) SGBridge.requestLogin(); }
|
||||
else { var d = ''; try { var e = await res.json(); d = (e && e.detail) ? e.detail : ''; } catch (x) {} showToast(d || '更新失败,请重试'); }
|
||||
} catch (e) { showToast('网络异常,请重试'); }
|
||||
})();
|
||||
};
|
||||
|
||||
// ===== 退出 / 注销 =====
|
||||
window.openLogout = function () { document.getElementById('logoutModal').classList.add('open'); };
|
||||
window.closeLogout = function () { document.getElementById('logoutModal').classList.remove('open'); };
|
||||
window.doLogout = function () { closeLogout(); if (window.SGBridge && SGBridge.navigate) { SGBridge.navigate('logout'); } else { showToast('(预览)已退出'); } };
|
||||
window.openDelete = function () { document.getElementById('deleteModal').classList.add('open'); };
|
||||
window.closeDelete = function () { document.getElementById('deleteModal').classList.remove('open'); };
|
||||
window.doDelete = function () {
|
||||
if (!bridgeReady()) { closeDelete(); showToast('(预览)已注销'); return; }
|
||||
closeDelete();
|
||||
(async function () {
|
||||
try {
|
||||
var res = await fetch('/api/v1/user', { method: 'DELETE', headers: { 'Authorization': 'Bearer ' + SGBridge.getToken() } });
|
||||
if (res.ok) { if (SGBridge.navigate) SGBridge.navigate('logout'); }
|
||||
else if (res.status === 401) { if (SGBridge.requestLogin) SGBridge.requestLogin(); }
|
||||
else { var d = ''; try { var e = await res.json(); d = (e && e.detail) ? e.detail : ''; } catch (x) {} showToast(d || '注销失败,请重试'); }
|
||||
} catch (e) { showToast('网络异常,请重试'); }
|
||||
})();
|
||||
};
|
||||
|
||||
window.toggleAds = function () { document.getElementById('adsSwitch').classList.toggle('on'); };
|
||||
|
||||
// ===== init =====
|
||||
(function () { var p = 'main'; try { var sp = localStorage.getItem('sg_set_panel'); if (sp) { p = sp; localStorage.removeItem('sg_set_panel'); } } catch (e) {} showPanel(p); })();
|
||||
loadProfile();
|
||||
if (window.SGBridge && SGBridge.on) { SGBridge.on('onResume', loadProfile); SGBridge.on('onAuthChange', loadProfile); }
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user