登录注册体系的源码级硬切换
This commit is contained in:
1 parent
73fcd4ed72
commit
af52f9e94d
72 files changed
+1666
-6576
No files matched your search
@@ -3,7 +3,6 @@ export const toolsApiMethods = {
|
||||
* 扩展&增强 / 备份&导入 (Extensions & Tools)
|
||||
* ================================================================ */
|
||||
|
||||
getHealthEmailVerification() { return this.request('/health/email-verification') },
|
||||
getUpdateInfo() { return this.request('/tools/update-info') },
|
||||
detectUpdate() { return this.request('/tools/update-check', { method: 'POST', body: JSON.stringify({}) }) },
|
||||
dismissUpdate(version) { return this.request('/tools/update-dismiss', { method: 'POST', body: JSON.stringify({ version }) }) },
|
||||
|
||||
@@ -41,7 +41,7 @@ export const toolsSection = {
|
||||
label: '健康检查',
|
||||
route: '/tools/health',
|
||||
title: '健康检查',
|
||||
desc: '查看主题环境、数据表、邮箱验证迁移和系统诊断状态。',
|
||||
desc: '查看主题环境、数据表和系统诊断状态。',
|
||||
component: 'ToolsHealth',
|
||||
}),
|
||||
customPage({
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="aksrt-page-container">
|
||||
<PageHeader
|
||||
title="健康检查"
|
||||
desc="集中查看运行环境、数据库表、邮箱验证迁移和系统诊断状态。"
|
||||
desc="集中查看运行环境、数据库表和系统诊断状态。"
|
||||
>
|
||||
<template #actions>
|
||||
<n-space>
|
||||
@@ -13,23 +13,6 @@
|
||||
</PageHeader>
|
||||
|
||||
<n-spin :show="loading" style="width: 100%; min-height: 200px;">
|
||||
<n-card class="aksrt-section-card">
|
||||
<div class="aksrt-section-header">
|
||||
<h3>邮箱验证状态</h3>
|
||||
</div>
|
||||
<n-space>
|
||||
<n-tag round :type="emailHealth.feature_enabled ? 'success' : 'default'">
|
||||
功能开关:{{ emailHealth.feature_enabled ? '已启用' : '未启用' }}
|
||||
</n-tag>
|
||||
<n-tag round :type="emailHealth.rest_blocking_active ? 'warning' : 'default'">
|
||||
REST 阻断:{{ emailHealth.rest_blocking_active ? '已开启' : '仅记录/关闭' }}
|
||||
</n-tag>
|
||||
<n-tag round type="info">
|
||||
待验证用户:{{ emailHealth.pending_users }}
|
||||
</n-tag>
|
||||
</n-space>
|
||||
</n-card>
|
||||
|
||||
<div class="aksrt-health-grid">
|
||||
<n-card v-for="check in checkItems" :key="check.key" class="aksrt-section-card">
|
||||
<div class="aksrt-section-header">
|
||||
@@ -55,11 +38,6 @@ const message = useMessage()
|
||||
|
||||
const loading = ref(true)
|
||||
const healthData = ref({})
|
||||
const emailHealth = ref({
|
||||
feature_enabled: false,
|
||||
pending_users: 0,
|
||||
rest_blocking_active: false,
|
||||
})
|
||||
|
||||
const checkItems = computed(() => {
|
||||
return Object.entries(healthData.value || {}).map(([key, value]) => ({
|
||||
@@ -86,12 +64,8 @@ function statusToTag(status) {
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const [healthRes, emailRes] = await Promise.all([
|
||||
api.getHealthCheck(),
|
||||
api.getHealthEmailVerification(),
|
||||
])
|
||||
const healthRes = await api.getHealthCheck()
|
||||
healthData.value = extractData(healthRes).checks || {}
|
||||
emailHealth.value = extractData(emailRes)
|
||||
} catch (error) {
|
||||
message.error(error.message || '加载健康检查失败')
|
||||
} finally {
|
||||
|
||||
@@ -23,9 +23,6 @@
|
||||
<n-tag round :type="form.referral_reward_enabled ? 'success' : 'default'">
|
||||
推广奖励:{{ form.referral_reward_enabled ? '已启用' : '已关闭' }}
|
||||
</n-tag>
|
||||
<n-tag round :type="form.referral_registration_enabled ? 'info' : 'default'">
|
||||
推广码注册:{{ form.referral_registration_enabled ? '开启' : '关闭' }}
|
||||
</n-tag>
|
||||
<n-tag round :type="captchaSummary.register ? 'info' : 'default'">
|
||||
注册验证码:{{ captchaSummary.register ? '启用' : '未启用' }}
|
||||
</n-tag>
|
||||
@@ -82,43 +79,6 @@
|
||||
<n-switch v-model:value="form.referral_reward_enabled" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="Ref 码长度">
|
||||
<n-input-number v-model:value="form.referral_code_length" :min="4" :max="12" style="width: 180px;" />
|
||||
<template #feedback>
|
||||
<span class="aksrt-hint-text">只影响新生成或管理员重新生成的推广码,已有 Ref 不会失效。</span>
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="首次触达窗口(天)">
|
||||
<n-input-number v-model:value="form.referral_window_days" :min="1" :max="365" style="width: 180px;" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="开放推广码注册">
|
||||
<n-switch v-model:value="form.referral_registration_enabled" />
|
||||
<template #feedback>
|
||||
<span class="aksrt-hint-text">此开关只控制注册页推广码字段;现金返佣和积分奖励仍可独立使用同一 Ref 关系。</span>
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<template v-if="form.referral_registration_enabled">
|
||||
<n-form-item label="注册页推广码字段">
|
||||
<n-radio-group v-model:value="form.referral_register_field">
|
||||
<n-space size="large">
|
||||
<n-radio value="hidden">隐藏</n-radio>
|
||||
<n-radio value="optional">选填</n-radio>
|
||||
<n-radio value="required">必填</n-radio>
|
||||
</n-space>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="无效推广码处理" v-if="form.referral_register_field === 'required'">
|
||||
<n-switch v-model:value="form.referral_reject_invalid" />
|
||||
<template #feedback>
|
||||
<span class="aksrt-hint-text">开启后,必填模式下无效推广码会直接拒绝注册。首次触达 Ref 始终优先于手填码。</span>
|
||||
</template>
|
||||
</n-form-item>
|
||||
</template>
|
||||
|
||||
<template v-if="form.referral_reward_enabled">
|
||||
<n-form-item label="推广人奖励">
|
||||
<n-input-number v-model:value="form.promoter_amount" :min="0" :max="100000" style="width: 180px;" />
|
||||
@@ -160,7 +120,6 @@ const message = useMessage()
|
||||
const loading = ref(true)
|
||||
const saving = ref(false)
|
||||
const creditSnapshot = ref({})
|
||||
const authSnapshot = ref({})
|
||||
|
||||
const captchaSummary = reactive({
|
||||
register: false,
|
||||
@@ -179,11 +138,6 @@ const form = reactive({
|
||||
level_points: 0,
|
||||
require_verify: true,
|
||||
ip_daily_cap: 3,
|
||||
referral_registration_enabled: true,
|
||||
referral_code_length: 12,
|
||||
referral_window_days: 30,
|
||||
referral_register_field: 'optional',
|
||||
referral_reject_invalid: true,
|
||||
})
|
||||
|
||||
const currencyLabel = computed(() => form.currency_name || '积分')
|
||||
@@ -229,14 +183,12 @@ function parseStreakText(value) {
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const [creditRes, authRes, captchaRes] = await Promise.all([
|
||||
const [creditRes, captchaRes] = await Promise.all([
|
||||
api.getCreditSettings(),
|
||||
api.getAuthSettings(),
|
||||
api.getPermissionsLoginSettings(),
|
||||
])
|
||||
|
||||
const creditData = extractData(creditRes)
|
||||
const authData = extractData(authRes)
|
||||
const captchaData = extractData(captchaRes)
|
||||
const dailySignin = creditData.daily_signin || {}
|
||||
const referralReward = creditData.referral_reward || {}
|
||||
@@ -246,7 +198,6 @@ async function load() {
|
||||
const sceneOn = (key) => enabledScenarios.includes(key)
|
||||
|
||||
creditSnapshot.value = creditData
|
||||
authSnapshot.value = authData
|
||||
|
||||
form.credits_enabled = creditData.enabled !== false
|
||||
form.currency_name = creditData.currency_name || ''
|
||||
@@ -259,11 +210,6 @@ async function load() {
|
||||
form.level_points = Number(referralReward.level_points || 0)
|
||||
form.require_verify = referralReward.require_verify !== false
|
||||
form.ip_daily_cap = Number(referralReward.ip_daily_cap || 0)
|
||||
form.referral_registration_enabled = authData.referral_registration_enabled !== false
|
||||
form.referral_code_length = Number(authData.referral_code_length || 12)
|
||||
form.referral_window_days = Number(authData.referral_window_days || 30)
|
||||
form.referral_register_field = authData.referral_register_field || 'optional'
|
||||
form.referral_reject_invalid = authData.referral_reject_invalid !== false
|
||||
|
||||
captchaSummary.register = !!captchaData.enabled && !!captchaData.active_provider && sceneOn('register')
|
||||
captchaSummary.signin = !!captchaData.enabled && !!captchaData.active_provider && sceneOn('signin')
|
||||
@@ -296,22 +242,9 @@ async function handleSave() {
|
||||
},
|
||||
}
|
||||
|
||||
const nextAuth = {
|
||||
...authSnapshot.value,
|
||||
referral_registration_enabled: form.referral_registration_enabled,
|
||||
referral_code_length: Number(form.referral_code_length || 12),
|
||||
referral_window_days: Number(form.referral_window_days || 30),
|
||||
referral_register_field: form.referral_register_field,
|
||||
referral_reject_invalid: form.referral_reject_invalid,
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
api.saveCreditSettings(nextCredit),
|
||||
api.saveAuthSettings(nextAuth),
|
||||
])
|
||||
await api.saveCreditSettings(nextCredit)
|
||||
|
||||
creditSnapshot.value = nextCredit
|
||||
authSnapshot.value = nextAuth
|
||||
message.success('签到奖励配置已保存')
|
||||
} catch (error) {
|
||||
message.error(error.message || '保存失败')
|
||||
|
||||
@@ -18,7 +18,7 @@ export const permissionsSchemas = {
|
||||
mode: 'always',
|
||||
enabled_scenarios: [
|
||||
'comment', 'login', 'register', 'bind', 'bind_phone',
|
||||
'lostpassword', 'change_password', 'change_email', 'verify_email', 'download', 'signin',
|
||||
'lostpassword', 'change_password', 'change_email', 'download', 'signin',
|
||||
],
|
||||
tencent: {},
|
||||
aliyun: {},
|
||||
@@ -71,7 +71,6 @@ export const permissionsSchemas = {
|
||||
{ label: '找回密码', value: 'lostpassword' },
|
||||
{ label: '修改密码', value: 'change_password' },
|
||||
{ label: '更改邮箱', value: 'change_email' },
|
||||
{ label: '邮箱验证', value: 'verify_email' },
|
||||
{ label: '资源下载', value: 'download' },
|
||||
{ label: '每日签到', value: 'signin' },
|
||||
{ label: '前台投稿', value: 'front_submit' },
|
||||
|
||||
@@ -1,107 +1,118 @@
|
||||
const verificationOptions = [
|
||||
{ label: '邮箱验证', value: 'email' },
|
||||
{ label: '手机验证', value: 'phone' },
|
||||
{ label: '邮箱或手机验证', value: 'email_phone' },
|
||||
];
|
||||
|
||||
export const authSchema = {
|
||||
key: 'users.auth',
|
||||
title: '注册登录',
|
||||
icon: 'fa fas fa-sign-in-alt',
|
||||
description: '注册方式、登录限制、密码策略配置。',
|
||||
description: '登录注册入口、验证规则、协议与认证界面配置。',
|
||||
defaults: {
|
||||
close_sign: false,
|
||||
user_close_signup: false,
|
||||
close_signup: false,
|
||||
close_signin: false,
|
||||
user_agreement_s: true,
|
||||
user_agreement_page: '',
|
||||
user_privacy_s: true,
|
||||
user_privacy_page: '',
|
||||
user_agreement_check: true,
|
||||
no_repetition_name: false,
|
||||
user_nickname_out: '赌博,博彩,代发,代理,刷单,六合彩,admin,test,管理员,客服',
|
||||
user_email_limit_type: 'black',
|
||||
user_email_out: '@tempmail.com\n@throwaway.email\n@guerrillamail.com',
|
||||
user_close_login: false,
|
||||
user_sign_type: 'page',
|
||||
user_sign_type: 'modal',
|
||||
sign_modal_auto_s: false,
|
||||
sign_modal_auto_waiting_time: 5,
|
||||
sign_modal_auto_expires: 1,
|
||||
replace_wp_login: true,
|
||||
admin_sign_key: '',
|
||||
invit_code_s: 'close',
|
||||
invit_code_open_desc: '如您受到邀请,可填写推广码。部分推广码会有额外积分赠送',
|
||||
invit_code_must_desc: '<div>本站需使用推广码注册</div><div>获取推广码请与客服联系</div>',
|
||||
user_signin_phone_s: false,
|
||||
user_signin_nopas_s: false,
|
||||
user_signin_nopas_type: 'email',
|
||||
user_signin_nopas_active: 'nopas_first',
|
||||
user_signup_captch: true,
|
||||
user_signin_nopas_active: 'nopas',
|
||||
user_signup_captch: false,
|
||||
captch_type: 'email',
|
||||
user_signup_no_repas: true,
|
||||
user_repas_captch_type: 'email',
|
||||
user_agreement_s: false,
|
||||
user_agreement_page: '',
|
||||
user_privacy_s: false,
|
||||
user_privacy_page: '',
|
||||
user_agreement_check: false,
|
||||
no_repetition_name: true,
|
||||
user_nickname_out: '赌博,博彩,彩票,性爱,色情,做爱,爱爱,淫秽,傻b,妈的,妈b,admin,test',
|
||||
user_email_limit_type: 'not',
|
||||
user_email_out: '',
|
||||
bind_phone: false,
|
||||
bind_reminder: 'close',
|
||||
bind_reminder_text: '请绑定手机号以正常使用',
|
||||
bind_reminder_text: '为了您的账户安全,请务必完成账户绑定',
|
||||
bind_reminder_expires: 24,
|
||||
mandatory_bind: 'close',
|
||||
mandatory_bind_text: '为了您的账户安全,请先完成账户绑定',
|
||||
email_set_captch: true,
|
||||
referral_registration_enabled: true,
|
||||
referral_register_field: 'optional',
|
||||
referral_reject_invalid: true,
|
||||
referral_code_length: 12,
|
||||
referral_window_days: 30,
|
||||
referral_open_desc: '推广码为选填,没有推广码也可以注册',
|
||||
referral_required_desc: '请输入推广码',
|
||||
sign_page_background: [],
|
||||
sign_theme_mode: 'default',
|
||||
sign_theme_mode: 'no',
|
||||
sign_show_header: true,
|
||||
sign_card_position: 'center',
|
||||
sign_show_logo: true,
|
||||
sign_card_position: 'right',
|
||||
sign_show_logo: false,
|
||||
sign_page_footer: '',
|
||||
sign_modal_background: [],
|
||||
sign_modal_show_logo: true,
|
||||
sign_modal_show_logo: false,
|
||||
user_logo: [],
|
||||
user_logo_dark: [],
|
||||
},
|
||||
groups: [
|
||||
{
|
||||
key: 'register',
|
||||
title: '注册设置',
|
||||
icon: 'fa fas fa-user-plus',
|
||||
fields: [
|
||||
{ key: 'close_sign', label: '一键禁用登录注册', type: 'switch', default: false, help: '开启后前台禁用全部注册/登录入口(含社交登录),不影响后台登录' },
|
||||
{ key: 'user_close_signup', label: '关闭注册', type: 'switch', default: false },
|
||||
{ key: 'close_signin', label: '禁用账密登录', type: 'switch', default: false, help: '仅允许社交账号登录' },
|
||||
{ key: 'user_agreement_s', label: '用户协议', type: 'switch', default: true },
|
||||
{ key: 'user_agreement_page', label: '协议页面', type: 'input', default: '' },
|
||||
{ key: 'user_privacy_s', label: '隐私政策', type: 'switch', default: true },
|
||||
{ key: 'user_privacy_page', label: '隐私页面', type: 'input', default: '' },
|
||||
{ key: 'user_agreement_check', label: '强制勾选协议', type: 'switch', default: true },
|
||||
{ key: 'no_repetition_name', label: '禁止重复昵称', type: 'switch', default: false },
|
||||
{ key: 'user_nickname_out', label: '昵称黑名单关键词', type: 'textarea', default: '赌博,博彩,代发,代理,刷单,六合彩,admin,test,管理员,客服', help: '一行一个关键词,注册昵称包含关键词将被拒绝' },
|
||||
{ key: 'user_email_limit_type', label: '邮箱限制类型', type: 'radio', default: 'black', options: [{ label: '黑名单(拒绝以下后缀)', value: 'black' }, { label: '白名单(仅允许以下后缀)', value: 'white' }] },
|
||||
{ key: 'user_email_out', label: '邮箱限制后缀', type: 'textarea', default: '@tempmail.com\n@throwaway.email\n@guerrillamail.com', help: '一行一个邮箱后缀,如 @tempmail.com' },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'login',
|
||||
title: '登录设置',
|
||||
key: 'entry',
|
||||
title: '登录注册',
|
||||
icon: 'fa fas fa-sign-in-alt',
|
||||
fields: [
|
||||
{ key: 'user_close_login', label: '关闭登录', type: 'switch', default: false },
|
||||
{ key: 'user_sign_type', label: '登录注册样式', type: 'radio', default: 'page', options: [{ label: '弹窗', value: 'modal' }, { label: '跳转页面', value: 'page' }] },
|
||||
{ key: 'sign_modal_auto_s', label: '自动弹出登录窗', type: 'switch', default: false, help: '仅在 user_sign_type=modal 时生效' },
|
||||
{ key: 'sign_modal_auto_waiting_time', label: '弹窗等待秒数', type: 'number', default: 5, min: 0, max: 60, dependsOn: { key: 'sign_modal_auto_s', value: true } },
|
||||
{ key: 'sign_modal_auto_expires', label: '弹窗周期(小时)', type: 'number', default: 1, min: 0, max: 720, dependsOn: { key: 'sign_modal_auto_s', value: true } },
|
||||
{ key: 'replace_wp_login', label: '替换WP登录页', type: 'switch', default: true },
|
||||
{ key: 'admin_sign_key', label: '应急登录 Key', type: 'input', default: '', help: '留空为禁用。管理员可通过 /wp-login.php?aksrt_bypass=<key> 绕过前台替换' },
|
||||
{ key: 'user_signin_phone_s', label: '手机号登录', type: 'switch', default: false, help: '允许用手机号作为用户名登录' },
|
||||
{ key: 'user_signin_nopas_s', label: '免密登录', type: 'switch', default: false },
|
||||
{ key: 'user_signin_nopas_type', label: '免密登录方式', type: 'radio', default: 'email', options: [{ label: '邮箱验证码', value: 'email' }, { label: '手机验证码', value: 'phone' }, { label: '邮箱或手机', value: 'email_phone' }], dependsOn: { key: 'user_signin_nopas_s', value: true } },
|
||||
{ key: 'user_signin_nopas_active', label: '免密显示模式', type: 'radio', default: 'nopas_first', options: [{ label: '优先免密', value: 'nopas_first' }, { label: '优先密码', value: 'password_first' }, { label: '仅免密', value: 'nopas_only' }], dependsOn: { key: 'user_signin_nopas_s', value: true } },
|
||||
{ key: 'close_sign', label: '禁用登录注册', type: 'switch', default: false, help: '关闭前台全部认证入口,不影响管理员后台应急登录' },
|
||||
{ key: 'close_signup', label: '禁用新用户注册', type: 'switch', default: false, dependsOn: { key: 'close_sign', value: false } },
|
||||
{ key: 'close_signin', label: '禁用账号登录/注册', type: 'switch', default: false, dependsOn: { key: 'close_sign', value: false }, help: '关闭账号密码和验证码登录注册,仅保留已启用的 OAuth 登录' },
|
||||
{ key: 'user_sign_type', label: '默认登录注册样式', type: 'radio', default: 'modal', options: [{ label: '弹窗显示', value: 'modal' }, { label: '独立页面', value: 'page' }] },
|
||||
{ key: 'sign_modal_auto_s', label: '自动弹出登录窗口', type: 'switch', default: false, dependsOn: { key: 'user_sign_type', value: 'modal' } },
|
||||
{ key: 'sign_modal_auto_waiting_time', label: '等待时间(秒)', type: 'number', default: 5, min: 1, max: 100, dependsOn: { key: 'sign_modal_auto_s', value: true } },
|
||||
{ key: 'sign_modal_auto_expires', label: '自动弹窗周期(小时)', type: 'number', default: 1, min: 0, max: 2000, dependsOn: { key: 'sign_modal_auto_s', value: true } },
|
||||
{ key: 'replace_wp_login', label: '代替 WP 自带登录页面', type: 'switch', default: true },
|
||||
{ key: 'admin_sign_key', label: '应急登录 Key', type: 'input', default: '', dependsOn: { key: 'replace_wp_login', value: true }, help: '通过 /wp-login.php?aksrt_bypass=<key> 使用 WP 登录页' },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'signup_captcha',
|
||||
title: '注册验证',
|
||||
icon: 'fa fas fa-user',
|
||||
key: 'invitation',
|
||||
title: '推广码注册',
|
||||
icon: 'fa fas fa-ticket-alt',
|
||||
fields: [
|
||||
{ key: 'user_signup_captch', label: '注册需验证', type: 'switch', default: true, help: '注册时需完成邮箱或手机验证' },
|
||||
{ key: 'captch_type', label: '验证方式', type: 'radio', default: 'email', options: [{ label: '邮箱', value: 'email' }, { label: '手机', value: 'phone' }, { label: '邮箱或手机', value: 'email_phone' }], dependsOn: { key: 'user_signup_captch', value: true } },
|
||||
{ key: 'user_signup_no_repas', label: '无需重复密码', type: 'switch', default: true, help: '注册时不要求二次确认密码' },
|
||||
{ key: 'user_repas_captch_type', label: '找回密码验证方式', type: 'radio', default: 'email', options: [{ label: '邮箱', value: 'email' }, { label: '手机', value: 'phone' }, { label: '邮箱或手机', value: 'email_phone' }] },
|
||||
{ key: 'invit_code_s', label: '推广码注册', type: 'radio', default: 'close', options: [{ label: '关闭', value: 'close' }, { label: '选填推广码', value: 'open' }, { label: '必须填写推广码', value: 'must' }] },
|
||||
{ key: 'invit_code_open_desc', label: '选填提示文案', type: 'input', default: '如您受到邀请,可填写推广码。部分推广码会有额外积分赠送', dependsOn: { key: 'invit_code_s', value: 'open' } },
|
||||
{ key: 'invit_code_must_desc', label: '必填提示文案', type: 'textarea', default: '<div>本站需使用推广码注册</div><div>获取推广码请与客服联系</div>', dependsOn: { key: 'invit_code_s', value: 'must' }, help: '支持安全 HTML' },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'verification',
|
||||
title: '登录与验证',
|
||||
icon: 'fa fas fa-shield-alt',
|
||||
fields: [
|
||||
{ key: 'user_signin_phone_s', label: '手机号登录', type: 'switch', default: false },
|
||||
{ key: 'user_signin_nopas_s', label: '免密登录', type: 'switch', default: false },
|
||||
{ key: 'user_signin_nopas_type', label: '免密登录方式', type: 'radio', default: 'email', options: verificationOptions, dependsOn: { key: 'user_signin_nopas_s', value: true } },
|
||||
{ key: 'user_signin_nopas_active', label: '登录方式显示模式', type: 'radio', default: 'nopas', options: [{ label: '优先免密登录', value: 'nopas' }, { label: '优先账号密码', value: 'pas' }, { label: '仅显示免密登录', value: 'only_nopas' }], dependsOn: { key: 'user_signin_nopas_s', value: true } },
|
||||
{ key: 'user_signup_captch', label: '注册需验证', type: 'switch', default: false },
|
||||
{ key: 'captch_type', label: '注册验证方式', type: 'radio', default: 'email', options: verificationOptions, dependsOn: { key: 'user_signup_captch', value: true } },
|
||||
{ key: 'user_signup_no_repas', label: '注册无需重复密码', type: 'switch', default: true, dependsOn: { key: 'user_signup_captch', value: true } },
|
||||
{ key: 'user_repas_captch_type', label: '找回密码验证方式', type: 'radio', default: 'email', options: verificationOptions },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'agreements',
|
||||
title: '协议与账号限制',
|
||||
icon: 'fa fas fa-file-contract',
|
||||
fields: [
|
||||
{ key: 'user_agreement_s', label: '显示用户协议', type: 'switch', default: false },
|
||||
{ key: 'user_agreement_page', label: '用户协议页面', type: 'input', default: '', dependsOn: { key: 'user_agreement_s', value: true } },
|
||||
{ key: 'user_privacy_s', label: '显示隐私协议', type: 'switch', default: false },
|
||||
{ key: 'user_privacy_page', label: '隐私协议页面', type: 'input', default: '', dependsOn: { key: 'user_privacy_s', value: true } },
|
||||
{ key: 'user_agreement_check', label: '协议必须手动勾选', type: 'switch', default: false },
|
||||
{ key: 'no_repetition_name', label: '禁止重复昵称', type: 'switch', default: true },
|
||||
{ key: 'user_nickname_out', label: '禁止的昵称关键词', type: 'textarea', default: '赌博,博彩,彩票,性爱,色情,做爱,爱爱,淫秽,傻b,妈的,妈b,admin,test' },
|
||||
{ key: 'user_email_limit_type', label: '邮箱限制方式', type: 'radio', default: 'not', options: [{ label: '黑名单', value: 'not' }, { label: '白名单', value: 'allow' }] },
|
||||
{ key: 'user_email_out', label: '邮箱限制关键词', type: 'textarea', default: '' },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -109,39 +120,13 @@ export const authSchema = {
|
||||
title: '绑定设置',
|
||||
icon: 'fa fas fa-link',
|
||||
fields: [
|
||||
{ key: 'bind_phone', label: '绑定手机', type: 'switch', default: false },
|
||||
{ key: 'bind_reminder', label: '绑定提醒', type: 'radio', default: 'close', options: [{ label: '提醒绑定邮箱', value: 'email' }, { label: '提醒绑定手机', value: 'phone' }, { label: '提醒绑定邮箱和手机', value: 'email_phone' }, { label: '关闭', value: 'close' }] },
|
||||
{ key: 'bind_reminder_text', label: '提醒文案', type: 'input', default: '请绑定手机号以正常使用' },
|
||||
{ key: 'bind_reminder_expires', label: '提醒周期(小时)', type: 'number', default: 24, min: 1, max: 720, help: '用户关闭提醒后多少小时内不再提醒' },
|
||||
{ key: 'mandatory_bind', label: '强制绑定', type: 'radio', default: 'close', options: [{ label: '强制绑定邮箱', value: 'email' }, { label: '强制绑定手机', value: 'phone' }, { label: '强制绑定邮箱和手机', value: 'email_phone' }, { label: '关闭', value: 'close' }] },
|
||||
{ key: 'email_set_captch', label: '绑定邮箱需验证', type: 'switch', default: true, help: '绑定邮箱时需发送验证码确认' },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'referral_inline',
|
||||
title: '推广码注册',
|
||||
icon: 'fa fas fa-ticket-alt',
|
||||
fields: [
|
||||
{ key: 'referral_registration_enabled', label: '开放推广码注册', type: 'switch', default: true },
|
||||
{ key: 'referral_register_field', label: '注册页推广码字段', type: 'select', default: 'optional', options: [{ label: '隐藏', value: 'hidden' }, { label: '选填', value: 'optional' }, { label: '必填', value: 'required' }], dependsOn: { key: 'referral_registration_enabled', value: true } },
|
||||
{ key: 'referral_reject_invalid', label: '拒绝无效推广码', type: 'switch', default: true, dependsOn: { key: 'referral_registration_enabled', value: true } },
|
||||
{ key: 'referral_code_length', label: 'Ref 码长度', type: 'number', default: 12, min: 4, max: 12 },
|
||||
{ key: 'referral_window_days', label: '首次触达窗口(天)', type: 'number', default: 30, min: 1, max: 365 },
|
||||
{ key: 'referral_open_desc', label: '选填提示', type: 'input', default: '推广码为选填,没有推广码也可以注册', dependsOn: { key: 'referral_registration_enabled', value: true } },
|
||||
{ key: 'referral_required_desc', label: '必填提示', type: 'input', default: '请输入推广码', dependsOn: { key: 'referral_registration_enabled', value: true } },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'sign_page_ui',
|
||||
title: '页面 UI 配置',
|
||||
icon: 'fa fas fa-paint-brush',
|
||||
fields: [
|
||||
{ key: 'sign_page_background', label: '页面背景图', type: 'gallery', default: [], help: '登录注册页背景图,多图随机' },
|
||||
{ key: 'sign_theme_mode', label: '主题模式', type: 'radio', default: 'default', options: [{ label: '默认', value: 'default' }, { label: '亮色', value: 'light' }, { label: '暗色', value: 'dark' }] },
|
||||
{ key: 'sign_show_header', label: '显示顶部导航', type: 'switch', default: true },
|
||||
{ key: 'sign_card_position', label: '卡片位置', type: 'radio', default: 'center', options: [{ label: '靠左', value: 'left' }, { label: '居中', value: 'center' }, { label: '靠右', value: 'right' }] },
|
||||
{ key: 'sign_show_logo', label: '显示 LOGO', type: 'switch', default: true },
|
||||
{ key: 'sign_page_footer', label: '页脚 HTML', type: 'textarea', default: '', help: '登录注册页自定义页脚内容,支持 HTML' },
|
||||
{ key: 'bind_phone', label: '手机绑定', type: 'switch', default: false },
|
||||
{ key: 'bind_reminder', label: '绑定提醒', type: 'radio', default: 'close', options: [{ label: '提醒绑定邮箱', value: 'email' }, { label: '提醒绑定手机', value: 'phone' }, { label: '提醒邮箱和手机', value: 'email_phone' }, { label: '关闭', value: 'close' }] },
|
||||
{ key: 'bind_reminder_text', label: '绑定提醒文案', type: 'textarea', default: '为了您的账户安全,请务必完成账户绑定' },
|
||||
{ key: 'bind_reminder_expires', label: '提醒周期(小时)', type: 'number', default: 24, min: 0, max: 2000 },
|
||||
{ key: 'mandatory_bind', label: '强制绑定', type: 'radio', default: 'close', options: [{ label: '必须绑定邮箱', value: 'email' }, { label: '必须绑定手机', value: 'phone' }, { label: '必须绑定邮箱和手机', value: 'email_phone' }, { label: '关闭', value: 'close' }] },
|
||||
{ key: 'mandatory_bind_text', label: '强制绑定文案', type: 'textarea', default: '为了您的账户安全,请先完成账户绑定' },
|
||||
{ key: 'email_set_captch', label: '绑定邮箱需验证', type: 'switch', default: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -149,8 +134,21 @@ export const authSchema = {
|
||||
title: '弹窗 UI 配置',
|
||||
icon: 'fa fas fa-window-restore',
|
||||
fields: [
|
||||
{ key: 'sign_modal_background', label: '弹窗背景图', type: 'gallery', default: [], help: '弹窗左侧背景图,多图随机' },
|
||||
{ key: 'sign_modal_show_logo', label: '弹窗显示 LOGO', type: 'switch', default: true },
|
||||
{ key: 'sign_modal_background', label: '左侧图片', type: 'gallery', default: [], help: '多图时随机显示;移动端隐藏' },
|
||||
{ key: 'sign_modal_show_logo', label: '显示 LOGO', type: 'switch', default: false },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'sign_page_ui',
|
||||
title: '页面 UI 配置',
|
||||
icon: 'fa fas fa-paint-brush',
|
||||
fields: [
|
||||
{ key: 'sign_page_background', label: '页面背景图', type: 'gallery', default: [] },
|
||||
{ key: 'sign_theme_mode', label: '自定义主题', type: 'radio', default: 'no', options: [{ label: '保持默认', value: 'no' }, { label: '日间亮色', value: 'white-theme' }, { label: '夜间深色', value: 'dark-theme' }] },
|
||||
{ key: 'sign_show_header', label: '显示顶部导航', type: 'switch', default: true },
|
||||
{ key: 'sign_card_position', label: '卡片位置', type: 'radio', default: 'right', options: [{ label: '靠左', value: 'left' }, { label: '居中', value: 'center' }, { label: '靠右', value: 'right' }] },
|
||||
{ key: 'sign_show_logo', label: '显示卡片 LOGO', type: 'switch', default: false },
|
||||
{ key: 'sign_page_footer', label: '页脚内容', type: 'textarea', default: '', help: '支持安全 HTML' },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -158,9 +156,9 @@ export const authSchema = {
|
||||
title: '登录框 LOGO',
|
||||
icon: 'fa fas fa-image',
|
||||
fields: [
|
||||
{ key: 'user_logo', label: '日间 LOGO', type: 'gallery', default: [], help: '登录框专用日间 LOGO,留空使用站点全局 LOGO' },
|
||||
{ key: 'user_logo_dark', label: '夜间 LOGO', type: 'gallery', default: [], help: '登录框专用夜间 LOGO,留空使用站点全局夜间 LOGO' },
|
||||
{ key: 'user_logo', label: '日间 LOGO', type: 'gallery', default: [] },
|
||||
{ key: 'user_logo_dark', label: '夜间 LOGO', type: 'gallery', default: [] },
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
};
|
||||
@@ -1,3 +1,2 @@
|
||||
@import url("enhancements/core-ui.css");
|
||||
@import url("enhancements/components.css");
|
||||
@import url("enhancements/modal-motion.css");
|
||||
@@ -5,27 +5,6 @@
|
||||
* 所有选择器使用 aksrt- 前缀避免冲突
|
||||
*/
|
||||
|
||||
.aksrt-modal-auth__error.is-success {
|
||||
background: rgba(16, 185, 129, 0.08);
|
||||
border-color: rgba(16, 185, 129, 0.22);
|
||||
color: #047857;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__checkbox {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
font-size: 13px;
|
||||
color: var(--muted-color, #777);
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__hint {
|
||||
margin: -4px 0 0;
|
||||
font-size: 13px;
|
||||
color: var(--muted-color, #777);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
@keyframes aksrt-spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
@import url("modal-motion/base.css");
|
||||
@import url("modal-motion/tabs.css");
|
||||
@import url("modal-motion/panels.css");
|
||||
@import url("modal-motion/form.css");
|
||||
@import url("modal-motion/divider.css");
|
||||
@import url("modal-motion/oauth.css");
|
||||
@import url("modal-motion/footer.css");
|
||||
@import url("modal-motion/dark-mode.css");
|
||||
@import url("modal-motion/responsive.css");
|
||||
@import url("modal-motion/dark-mode-2.css");
|
||||
@@ -1,210 +0,0 @@
|
||||
/* ============================================================
|
||||
* 21. 弹窗登录/注册 — 1:1 legacy modal
|
||||
* ============================================================ */
|
||||
.aksrt-modal-auth {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 99999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.3s, visibility 0.3s;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth.is-open {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
backdrop-filter: none;
|
||||
-webkit-backdrop-filter: none;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__card {
|
||||
position: relative;
|
||||
background: var(--main-bg-color, var(--surface-1, #fff));
|
||||
border-radius: var(--main-radius, 8px);
|
||||
border: none;
|
||||
padding: 0;
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
max-height: calc(100vh - 20px);
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08));
|
||||
z-index: 1;
|
||||
transform: scale(0.9);
|
||||
transition: transform 0.5s cubic-bezier(0.32, 0.85, 0.45, 1.18), width 0.3s;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth.is-open .aksrt-modal-auth__card {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__header {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
padding: 28px 24px 16px;
|
||||
min-height: 120px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: var(--main-radius, 8px) var(--main-radius, 8px) 0 0;
|
||||
overflow: hidden;
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-active, #c9206d) 100%);
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__header::before,
|
||||
.aksrt-modal-auth__header::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
border-radius: 100%;
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__header::before {
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
right: -60px;
|
||||
top: -80px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__header::after {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
left: -40px;
|
||||
bottom: -70px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__close {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
min-width: 28px;
|
||||
min-height: 28px;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
color: #fff;
|
||||
opacity: 0.6;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: opacity 0.2s;
|
||||
font-size: 18px;
|
||||
z-index: 9;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__close:hover {
|
||||
opacity: 1;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__logo {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.18);
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 10px;
|
||||
border: 2px solid rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__title {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__tabs,
|
||||
.aksrt-modal-auth__panel,
|
||||
.aksrt-modal-auth__body {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__panel {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth.bottom {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth.bottom .aksrt-modal-auth__card {
|
||||
max-width: calc(100% - 20px);
|
||||
margin-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
|
||||
transform: translateY(110%);
|
||||
transition: transform 0.4s;
|
||||
border-radius: var(--main-radius, 8px);
|
||||
box-shadow: 0 -10px 50px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.aksrt-modal-auth.bottom.is-open .aksrt-modal-auth__card {
|
||||
transform: translateY(0);
|
||||
transition: transform 0.6s cubic-bezier(0.28, 0.9, 0.34, 0.99);
|
||||
}
|
||||
|
||||
.modal-content,
|
||||
.aksrt-modal__content {
|
||||
border-radius: var(--main-radius, 8px);
|
||||
background: var(--main-bg-color, var(--surface-1));
|
||||
border: none;
|
||||
box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08));
|
||||
}
|
||||
|
||||
.modal-colorful-header {
|
||||
border-radius: var(--main-radius, 8px) var(--main-radius, 8px) 0 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--this-color, #fff);
|
||||
background: var(--this-bg, var(--focus-color, var(--color-primary)));
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modal-colorful-header + * {
|
||||
margin-top: 120px;
|
||||
}
|
||||
|
||||
.modal-colorful-header > .close {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
color: var(--this-color, #fff);
|
||||
opacity: 0.6;
|
||||
font-size: 18px;
|
||||
z-index: 9;
|
||||
}
|
||||
@@ -1,449 +0,0 @@
|
||||
|
||||
/* ============================================================
|
||||
* 响应式
|
||||
* ============================================================ */
|
||||
@media (max-width: 640px) {
|
||||
.aksrt-lightbox__nav {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.single-cover-slider__img {
|
||||
height: 240px;
|
||||
}
|
||||
|
||||
.single-cover-slider__title {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.reward-modal__card {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.reward-modal__qr {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
}
|
||||
|
||||
.aksrt-cover-cards {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.aksrt-cover-card {
|
||||
min-height: 140px;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 13. 无障碍:prefers-reduced-motion
|
||||
* 用户系统设置"减少动画"时,禁用所有非必要动效
|
||||
* ============================================================ */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
|
||||
.aksrt-skeleton {
|
||||
animation: none !important;
|
||||
}
|
||||
|
||||
[data-aksrt-animate] {
|
||||
opacity: 1 !important;
|
||||
transform: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* legacy lazySizes state and animation contract. */
|
||||
.lazyloaded {
|
||||
transition: 0.3s;
|
||||
--lazy-animation: lazy_blur;
|
||||
}
|
||||
|
||||
.lazyloaded.img-icon {
|
||||
--lazy-animation: lazy_fade;
|
||||
}
|
||||
|
||||
img.lazyloaded:not(.lazyloadafter) {
|
||||
-webkit-animation: var(--lazy-animation) 0.6s;
|
||||
animation: var(--lazy-animation) 0.6s;
|
||||
}
|
||||
|
||||
@keyframes lazy_blur {
|
||||
0% { filter: blur(5px); }
|
||||
100% { filter: blur(0); }
|
||||
}
|
||||
|
||||
@keyframes lazy_fade {
|
||||
0% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes lazy_scale {
|
||||
0% { transform: scale(1.1); }
|
||||
80% { transform: unset; }
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 15. 错误反馈 shake 动画
|
||||
* 表单验证失败时的水平抖动效果
|
||||
* ============================================================ */
|
||||
@keyframes aksrtShake {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
10%, 30%, 50%, 70%, 90% { transform: translateX(-4px); }
|
||||
20%, 40%, 60%, 80% { transform: translateX(4px); }
|
||||
}
|
||||
|
||||
.aksrt-shake {
|
||||
animation: aksrtShake 0.4s ease-in-out;
|
||||
}
|
||||
|
||||
/* 应用于 Naive UI 表单验证 */
|
||||
.n-form-item--error .n-input,
|
||||
.n-form-item--error .n-select,
|
||||
.n-form-item--error .n-input-number {
|
||||
animation: aksrtShake 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 16. FPS 加速模式:低端设备禁用 backdrop-filter
|
||||
* 模仿 legacy 的 body.fps-accelerat 模式
|
||||
* ============================================================ */
|
||||
body.fps-accelerat .site-nav,
|
||||
body.fps-accelerat .footer-tabbar,
|
||||
body.fps-accelerat .float-right .float-btn,
|
||||
body.fps-accelerat .aksrt-blur-bg {
|
||||
backdrop-filter: none !important;
|
||||
-webkit-backdrop-filter: none !important;
|
||||
}
|
||||
|
||||
/* 模态框内禁用 backdrop-filter 避免渲染冲突 */
|
||||
body.modal-open .site-nav,
|
||||
body.dialog-open .site-nav {
|
||||
backdrop-filter: none !important;
|
||||
-webkit-backdrop-filter: none !important;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 17. .blur-bg 通用工具类
|
||||
* 模仿 legacy 的 .blur-bg,可在任意元素上应用毛玻璃效果
|
||||
* ============================================================ */
|
||||
.aksrt-blur-bg {
|
||||
background: var(--blur-bg);
|
||||
backdrop-filter: saturate(5) blur(20px);
|
||||
-webkit-backdrop-filter: saturate(5) blur(20px);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 18. 滚动触发动画延迟支持
|
||||
* data-aksrt-delay 属性控制入场延迟
|
||||
* ============================================================ */
|
||||
[data-aksrt-animate][data-aksrt-delay="1"] { transition-delay: 0.1s; }
|
||||
[data-aksrt-animate][data-aksrt-delay="2"] { transition-delay: 0.2s; }
|
||||
[data-aksrt-animate][data-aksrt-delay="3"] { transition-delay: 0.3s; }
|
||||
[data-aksrt-animate][data-aksrt-delay="4"] { transition-delay: 0.4s; }
|
||||
[data-aksrt-animate][data-aksrt-delay="5"] { transition-delay: 0.5s; }
|
||||
|
||||
/* ============================================================
|
||||
* 19. 全站动效节奏统一
|
||||
* 模仿 legacy 的统一 hover / slide / blur / drawer 语言
|
||||
* ============================================================ */
|
||||
|
||||
/* --- 全局过渡基线 --- */
|
||||
a, button, input, select, textarea {
|
||||
transition: border-color var(--dur-fast) var(--ease),
|
||||
box-shadow var(--dur-fast) var(--ease),
|
||||
background-color var(--dur-fast) var(--ease),
|
||||
color var(--dur-fast) var(--ease);
|
||||
}
|
||||
|
||||
/* --- 卡片 hover 统一 --- */
|
||||
.post-card, .widget, .aksrt-theme-box, .theme-box,
|
||||
.comment-body, .friend-card, .special-card,
|
||||
.resource-download-box {
|
||||
transition: box-shadow var(--dur) var(--ease),
|
||||
border-color var(--dur) var(--ease),
|
||||
transform var(--dur) var(--ease);
|
||||
}
|
||||
|
||||
.post-card:hover, .widget:hover, .friend-card:hover, .special-card:hover {
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* --- 按钮 hover 统一 --- */
|
||||
.btn-primary, .btn-outline, .btn-lg, .btn-sm,
|
||||
.n-button, .aksrt-button {
|
||||
transition: all var(--dur-fast) var(--ease);
|
||||
}
|
||||
|
||||
.btn-primary:hover, .n-button--primary-type:hover {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.btn-primary:active, .n-button--primary-type:active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* --- 输入框 focus 统一 --- */
|
||||
input:focus, textarea:focus, select:focus,
|
||||
.n-input--focus, .n-select--focus {
|
||||
box-shadow: var(--focus-ring);
|
||||
transition: box-shadow var(--dur-fast) var(--ease);
|
||||
}
|
||||
|
||||
/* --- 抽屉/模态框动效统一 --- */
|
||||
.n-drawer, .n-modal, .n-dialog {
|
||||
transition: all var(--dur) var(--ease-out);
|
||||
}
|
||||
|
||||
.n-drawer-mask, .n-modal-mask, .n-dialog-mask {
|
||||
transition: opacity var(--dur) var(--ease);
|
||||
}
|
||||
|
||||
/* --- Tab 切换动效 --- */
|
||||
.n-tabs-tab, .nav-tab, .aksrt-tab {
|
||||
transition: color var(--dur-fast) var(--ease),
|
||||
border-color var(--dur-fast) var(--ease),
|
||||
background-color var(--dur-fast) var(--ease);
|
||||
}
|
||||
|
||||
/* --- 下拉菜单动效 --- */
|
||||
.n-dropdown-menu, .aksrt-dropdown {
|
||||
transition: opacity var(--dur-fast) var(--ease),
|
||||
transform var(--dur-fast) var(--ease-out);
|
||||
transform-origin: top;
|
||||
}
|
||||
|
||||
/* --- 骨架屏动效 --- */
|
||||
.aksrt-skeleton {
|
||||
animation: aksrtSkeletonShimmer 1.5s infinite linear;
|
||||
background: linear-gradient(90deg, var(--skeleton-base) 25%, var(--skeleton-shine) 50%, var(--skeleton-base) 75%);
|
||||
background-size: 200% 100%;
|
||||
}
|
||||
|
||||
/* --- 页面切换动效 --- */
|
||||
.fade-slide-enter-active,
|
||||
.fade-slide-leave-active {
|
||||
transition: opacity var(--dur) var(--ease),
|
||||
transform var(--dur) var(--ease);
|
||||
}
|
||||
|
||||
.fade-slide-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
|
||||
.fade-slide-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
|
||||
/* --- 导航栏滚动动效 --- */
|
||||
.site-nav {
|
||||
transition: transform var(--dur) var(--ease),
|
||||
background-color var(--dur) var(--ease),
|
||||
box-shadow var(--dur) var(--ease);
|
||||
}
|
||||
|
||||
.site-nav.aksrt-nav--hidden {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
/* --- 浮层弹出动效 --- */
|
||||
@keyframes aksrtPopIn {
|
||||
0% { opacity: 0; transform: scale(0.95) translateY(-4px); }
|
||||
100% { opacity: 1; transform: scale(1) translateY(0); }
|
||||
}
|
||||
|
||||
@keyframes aksrtPopOut {
|
||||
0% { opacity: 1; transform: scale(1) translateY(0); }
|
||||
100% { opacity: 0; transform: scale(0.95) translateY(-4px); }
|
||||
}
|
||||
|
||||
.aksrt-popover, .aksrt-tooltip, .aksrt-dropdown-panel {
|
||||
animation: aksrtPopIn var(--dur-fast) var(--ease-out) forwards;
|
||||
}
|
||||
|
||||
/* --- 滚动进度条动效 --- */
|
||||
.reading-progress-bar {
|
||||
transition: width 0.1s linear;
|
||||
}
|
||||
|
||||
/* --- 移动端抽屉动效 --- */
|
||||
@media (max-width: 767px) {
|
||||
.n-drawer {
|
||||
transition: transform var(--dur) var(--ease-out);
|
||||
}
|
||||
|
||||
.site-nav .n-drawer-body {
|
||||
transition: transform var(--dur) var(--ease-out);
|
||||
}
|
||||
}
|
||||
|
||||
/* --- 暗色模式切换动效 --- */
|
||||
html.dark {
|
||||
transition: background-color 0.3s var(--ease),
|
||||
color 0.3s var(--ease);
|
||||
}
|
||||
|
||||
html.dark * {
|
||||
transition: background-color 0.3s var(--ease),
|
||||
border-color 0.3s var(--ease),
|
||||
color 0.3s var(--ease),
|
||||
box-shadow 0.3s var(--ease);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 18. 合作伙伴无缝滚动 (marquee)
|
||||
* ============================================================ */
|
||||
.aksrt-marquee {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.aksrt-marquee__inner {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
white-space: nowrap;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.aksrt-marquee__inner > * {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.aksrt-marquee__inner {
|
||||
animation: none !important;
|
||||
transform: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 19. 视频剧集切换按钮
|
||||
* ============================================================ */
|
||||
.switch-video,
|
||||
.switch-iframe {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 6px 14px;
|
||||
border: 1px solid var(--color-line, rgba(50, 50, 50, 0.1));
|
||||
border-radius: var(--radius, 8px);
|
||||
background: var(--surface-1, #fff);
|
||||
color: var(--color-ink-2, #4e5358);
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.switch-video:hover,
|
||||
.switch-iframe:hover {
|
||||
border-color: var(--color-primary);
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.switch-video.is-active,
|
||||
.switch-iframe.is-active {
|
||||
background: var(--color-primary);
|
||||
border-color: var(--color-primary);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 20. 一言轮播组件
|
||||
* ============================================================ */
|
||||
.aksrt-yiyan {
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.aksrt-yiyan__content {
|
||||
min-height: 60px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.aksrt-yiyan__icon {
|
||||
font-size: 20px;
|
||||
color: var(--color-primary);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.aksrt-yiyan__text {
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
color: var(--color-ink-2, #4e5358);
|
||||
margin: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.aksrt-yiyan__from {
|
||||
font-size: 12px;
|
||||
color: var(--color-ink-4, #999);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.aksrt-yiyan__dots {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.aksrt-yiyan__dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-line, rgba(50, 50, 50, 0.1));
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.aksrt-yiyan__dot.is-active {
|
||||
background: var(--color-primary);
|
||||
width: 16px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 底部弹出 Sheet — 对齐 legacy .modal.bottom
|
||||
* ============================================================ */
|
||||
.aksrt-modal--bottom .aksrt-modal-auth__card,
|
||||
.modal.bottom .modal-dialog {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
border-radius: var(--main-radius, 8px) var(--main-radius, 8px) 0 0;
|
||||
transform: translateY(110%);
|
||||
transition: transform 0.4s;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.aksrt-modal--bottom.is-open .aksrt-modal-auth__card,
|
||||
.modal.bottom.in .modal-dialog {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.aksrt-modal--bottom .aksrt-modal-auth__card,
|
||||
.modal.bottom .modal-dialog .modal-content {
|
||||
box-shadow: 0 -10px 50px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
/* Dark mode */
|
||||
.theme-dark .aksrt-modal-auth__card,
|
||||
html.dark .aksrt-modal-auth__card {
|
||||
background: #1e1e2e;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.theme-dark .aksrt-modal-auth__field input,
|
||||
html.dark .aksrt-modal-auth__field input {
|
||||
background: #2a2a3a;
|
||||
border-color: rgba(255, 255, 255, 0.15);
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
.theme-dark .aksrt-modal-auth__close,
|
||||
html.dark .aksrt-modal-auth__close {
|
||||
background: #2a2a3a;
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/* Divider */
|
||||
.aksrt-modal-auth__divider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin: 20px 0;
|
||||
color: var(--color-ink-4, #8A8F98);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__divider::before,
|
||||
.aksrt-modal-auth__divider::after {
|
||||
content: '';
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background: var(--color-line);
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
/* Footer */
|
||||
.aksrt-modal-auth__footer {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
font-size: 13px;
|
||||
color: var(--color-ink-3);
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__switch {
|
||||
border: none;
|
||||
background: none;
|
||||
color: var(--color-primary, var(--color-primary));
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__switch:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
/* Form */
|
||||
.aksrt-modal-auth__form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__error {
|
||||
padding: 10px 14px;
|
||||
border-radius: 8px;
|
||||
background: rgba(239, 68, 68, 0.08);
|
||||
color: var(--color-error, #EF4444);
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__error a {
|
||||
color: var(--color-primary, var(--color-primary));
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__field label {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
color: var(--color-ink-2);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__field input {
|
||||
width: 100%;
|
||||
padding: 10px 14px;
|
||||
border: 1px solid var(--color-line);
|
||||
border-radius: var(--main-radius, 8px);
|
||||
font-size: 14px;
|
||||
color: var(--color-ink);
|
||||
background: var(--surface-1, #fff);
|
||||
transition: border-color 0.2s;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__field input:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary, var(--color-primary));
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__field input::placeholder {
|
||||
color: var(--color-ink-4, #8A8F98);
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__pass-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__pass-wrap input {
|
||||
padding-right: 44px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__pass-toggle {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: none;
|
||||
background: none;
|
||||
color: var(--color-ink-4, #8A8F98);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__pass-toggle:hover {
|
||||
background: var(--surface-2, #F4F5F7);
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__link {
|
||||
font-size: 13px;
|
||||
color: var(--color-primary, var(--color-primary));
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__submit {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: none;
|
||||
border-radius: var(--main-radius, 8px);
|
||||
background: var(--color-primary, var(--color-primary));
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__submit:hover {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__submit:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/* OAuth */
|
||||
.aksrt-modal-auth__oauth {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__oauth-btn {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border: 1px solid var(--color-line);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--color-ink-2);
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__oauth-btn:hover {
|
||||
border-color: var(--color-primary, var(--color-primary));
|
||||
color: var(--color-primary, var(--color-primary));
|
||||
background: var(--color-primary-soft, rgba(240, 68, 148, 0.1));
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
/* Panels */
|
||||
.aksrt-modal-auth__panel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__panel.is-active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/* Responsive */
|
||||
@media (max-width: 480px) {
|
||||
.aksrt-modal-auth__card {
|
||||
padding: 24px 20px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__logo {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__title {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/* Tabs — under colorful header */
|
||||
.aksrt-modal-auth__tabs {
|
||||
display: flex;
|
||||
border-bottom: 1px solid var(--main-border-color, var(--color-line));
|
||||
margin: 8px 0 16px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__tab {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
background: none;
|
||||
font-size: 15px;
|
||||
font-weight: normal;
|
||||
color: var(--muted-color, var(--color-ink-3));
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
transition: color 0.15s, opacity 0.15s;
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__tab:hover {
|
||||
opacity: 0.8;
|
||||
color: var(--focus-color, var(--color-primary));
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__tab.is-active {
|
||||
color: var(--focus-color, var(--color-primary));
|
||||
}
|
||||
|
||||
.aksrt-modal-auth__tab.is-active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: 20%;
|
||||
right: 20%;
|
||||
height: 2px;
|
||||
background: var(--focus-color, var(--color-primary));
|
||||
border-radius: 2px;
|
||||
}
|
||||
@@ -1,359 +0,0 @@
|
||||
/**
|
||||
* AKSRT Auth Pages — 认证页面样式
|
||||
*
|
||||
* 类名对齐实际模板:auth-shell, auth-card, auth-form, form-field, input-wrap
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
/* 认证页面容器 */
|
||||
.auth-shell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: calc(100vh - 200px);
|
||||
padding: 40px 16px;
|
||||
}
|
||||
|
||||
/* 认证卡片 */
|
||||
.auth-card {
|
||||
width: 100%;
|
||||
max-width: 440px;
|
||||
background: var(--surface-1);
|
||||
border: none;
|
||||
border-radius: var(--radius-2xl, 16px);
|
||||
padding: 32px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.auth-card__logo {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 12px;
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.auth-card__title {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
margin: 0 0 8px;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
.auth-card__subtitle {
|
||||
font-size: 14px;
|
||||
color: var(--color-ink-3);
|
||||
margin: 0 0 24px;
|
||||
}
|
||||
|
||||
/* 表单 */
|
||||
.auth-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
/* 表单字段 */
|
||||
.form-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.form-field label {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--color-ink-2);
|
||||
}
|
||||
|
||||
/* 输入框包装 */
|
||||
.input-wrap {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.input-wrap input {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
padding: 0 14px 0 40px;
|
||||
font-size: 14px;
|
||||
color: var(--color-ink);
|
||||
background: var(--surface-4);
|
||||
border: 1px solid var(--color-line);
|
||||
border-radius: 12px;
|
||||
transition: border-color 0.15s, box-shadow 0.15s;
|
||||
}
|
||||
|
||||
.input-wrap input:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 0 2px 3px rgba(253, 83, 161, 0.4);
|
||||
}
|
||||
|
||||
.input-wrap input::placeholder {
|
||||
color: var(--color-ink-4);
|
||||
}
|
||||
|
||||
.input-icon {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--color-ink-4);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* 密码切换按钮 */
|
||||
.toggle-pwd {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--color-ink-4);
|
||||
cursor: pointer;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.toggle-pwd:hover {
|
||||
color: var(--color-ink-2);
|
||||
}
|
||||
|
||||
/* 密码字段输入框右侧留空 */
|
||||
.form-field--pwd .input-wrap input {
|
||||
padding-right: 40px;
|
||||
}
|
||||
|
||||
/* 记住我 + 忘记密码 */
|
||||
.form-row-between {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.form-row-between a {
|
||||
color: var(--color-primary);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.form-row-between a:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* 错误提示 */
|
||||
.alert {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
padding: 12px;
|
||||
border-radius: var(--radius);
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.alert svg {
|
||||
flex-shrink: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.alert--error {
|
||||
background: #fff2f0;
|
||||
border: 1px solid #ffccc7;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.alert--error a {
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* 底部链接 */
|
||||
.auth-footer-link {
|
||||
text-align: center;
|
||||
margin-top: 16px;
|
||||
font-size: 14px;
|
||||
color: var(--color-ink-3);
|
||||
}
|
||||
|
||||
.auth-footer-link a {
|
||||
color: var(--color-primary);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.auth-footer-link a:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* OAuth 社交登录区域 */
|
||||
.aksrt-oauth-section {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.aksrt-oauth-divider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 13px;
|
||||
color: var(--color-ink-4);
|
||||
}
|
||||
|
||||
.aksrt-oauth-divider::before,
|
||||
.aksrt-oauth-divider::after {
|
||||
content: '';
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background: var(--color-line);
|
||||
}
|
||||
|
||||
.aksrt-oauth-buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.aksrt-oauth-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
background: var(--surface-4);
|
||||
box-shadow: var(--shadow-sm);
|
||||
color: var(--color-ink);
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
transition: border-color 0.2s, color 0.2s, box-shadow 0.2s, background 0.2s;
|
||||
}
|
||||
|
||||
.aksrt-oauth-btn:hover {
|
||||
border-color: var(--color-primary);
|
||||
color: var(--color-primary);
|
||||
background: var(--color-primary-soft);
|
||||
}
|
||||
|
||||
/* 成功提示 */
|
||||
.alert--success {
|
||||
background: #f6ffed;
|
||||
border: 1px solid #b7eb8f;
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
/* 认证 Tab 切换 */
|
||||
.aksrt-auth-tabs {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid var(--color-line-soft);
|
||||
}
|
||||
|
||||
.aksrt-auth-tab {
|
||||
flex: 1;
|
||||
padding: 10px 0;
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
background: transparent;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
color: var(--color-ink-3);
|
||||
border-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.aksrt-auth-tab.is-active {
|
||||
color: var(--color-primary);
|
||||
background: var(--color-primary-soft);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.aksrt-auth-tab:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
/* 表单提示文本 */
|
||||
.form-field-hint {
|
||||
display: block;
|
||||
margin-top: 6px;
|
||||
font-size: 12px;
|
||||
color: var(--color-ink-3);
|
||||
}
|
||||
|
||||
/* 必填/选填标记 */
|
||||
.aksrt-required-mark {
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.aksrt-optional-hint {
|
||||
color: var(--color-ink-3);
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* 同意条款复选框 */
|
||||
.aksrt-terms-check {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
font-size: 13px;
|
||||
margin-bottom: 16px;
|
||||
cursor: pointer;
|
||||
color: var(--color-ink-3);
|
||||
}
|
||||
|
||||
.aksrt-terms-check input {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* 提交按钮全宽 */
|
||||
.auth-form .btn-primary.btn-lg,
|
||||
.auth-form input[type="submit"].btn-primary.btn-lg {
|
||||
width: 100%;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 验证码输入行 */
|
||||
.aksrt-code-row {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.aksrt-code-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.aksrt-sms-trigger {
|
||||
white-space: nowrap;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
/* 响应式 */
|
||||
@media (max-width: 767px) {
|
||||
.auth-shell {
|
||||
padding: 24px 16px;
|
||||
min-height: calc(100vh - 150px);
|
||||
}
|
||||
|
||||
.auth-card {
|
||||
padding: 24px 20px;
|
||||
}
|
||||
|
||||
.aksrt-auth-tab {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
+109
-288
@@ -1,295 +1,116 @@
|
||||
/**
|
||||
* AKSRT full-page sign shell (login / register / reset / bind).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
.page-template-user-sign {
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.sign-page {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
padding: 70px 16px 40px;
|
||||
}
|
||||
|
||||
.sign-bg {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.sign-topbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 20px;
|
||||
background: color-mix(in srgb, var(--main-bg-color, #fff) 86%, transparent);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.sign-topbar a {
|
||||
color: var(--main-color, #4e5358);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sign-card {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
background: var(--main-bg-color, #fff);
|
||||
border-radius: var(--main-radius, 8px);
|
||||
box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08));
|
||||
padding: 30px 35px;
|
||||
}
|
||||
|
||||
.sign-card--left { margin-right: auto; }
|
||||
.sign-card--right { margin-left: auto; }
|
||||
.sign-card--center { margin: 0 auto; }
|
||||
|
||||
.sign-logo {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sign-logo img {
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.sign-logo__text {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 12px;
|
||||
background: var(--focus-color, #f04494);
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sign-tabs {
|
||||
display: flex;
|
||||
border-bottom: 2px solid var(--main-border-color, rgba(50, 50, 50, 0.06));
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sign-tab {
|
||||
flex: 1;
|
||||
padding: 10px 0;
|
||||
border: none;
|
||||
background: none;
|
||||
font-size: 15px;
|
||||
cursor: pointer;
|
||||
color: var(--muted-color, #777);
|
||||
border-bottom: 2px solid transparent;
|
||||
margin-bottom: -2px;
|
||||
transition: all .2s;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.sign-tab.is-active {
|
||||
color: var(--focus-color, #f04494);
|
||||
border-bottom-color: var(--focus-color, #f04494);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sign-tab:hover { color: var(--focus-color, #f04494); }
|
||||
|
||||
.sign-panel { display: none; }
|
||||
.sign-panel.is-active { display: block; }
|
||||
|
||||
.sign-error {
|
||||
background: rgba(239, 68, 68, 0.08);
|
||||
border: 1px solid rgba(239, 68, 68, 0.2);
|
||||
border-radius: var(--main-radius, 8px);
|
||||
padding: 10px 14px;
|
||||
font-size: 13px;
|
||||
color: #ef4444;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.sign-success {
|
||||
background: rgba(16, 185, 129, 0.08);
|
||||
border: 1px solid rgba(16, 185, 129, 0.2);
|
||||
border-radius: var(--main-radius, 8px);
|
||||
padding: 10px 14px;
|
||||
font-size: 13px;
|
||||
color: #10b981;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.sign-notice {
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
color: var(--muted-2-color, #666);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sign-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.sign-form .form-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.sign-form label {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
/* Shared Zibll-source authentication contract: modal and /sign/. */
|
||||
.sign {
|
||||
max-width: 330px;
|
||||
margin: auto;
|
||||
padding: 30px 0;
|
||||
color: var(--main-color, #4e5358);
|
||||
}
|
||||
|
||||
.sign-form .input-wrap { position: relative; }
|
||||
.sign [hidden] { display: none !important; }
|
||||
.sign button { font: inherit; }
|
||||
.sign-logo { margin-bottom: 24px; text-align: center; }
|
||||
.sign-logo img { max-width: 180px; max-height: 70px; }
|
||||
.sign-logo .sign-logo-dark { display: none; }
|
||||
.dark-theme .sign-logo .sign-logo-light { display: none; }
|
||||
.dark-theme .sign-logo .sign-logo-dark { display: inline-block; }
|
||||
.sign-logo__text { font-size: 22px; font-weight: 700; color: inherit; }
|
||||
.sign-panel { animation: auth-panel-in .24s ease both; }
|
||||
|
||||
.sign-form .input-wrap input {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
padding: 0 14px;
|
||||
border: 1px solid transparent;
|
||||
background: var(--body-bg-color, #f5f6f7);
|
||||
border-radius: var(--main-radius, 8px);
|
||||
font-size: 14px;
|
||||
color: var(--key-color, #333);
|
||||
transition: border-color .15s;
|
||||
@keyframes auth-panel-in {
|
||||
from { opacity: 0; transform: translateY(5px); }
|
||||
to { opacity: 1; transform: none; }
|
||||
}
|
||||
|
||||
.sign-form .input-wrap input:focus {
|
||||
outline: none;
|
||||
border-color: var(--focus-color, #f04494);
|
||||
box-shadow: 0 0 2px 3px var(--focus-shadow-color, rgba(253, 83, 161, 0.4));
|
||||
}
|
||||
|
||||
.sign-form .toggle-pwd {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: var(--muted-2-color, #999);
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.sign-form .form-row-between {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.sign-form .form-row-between a { color: var(--focus-color, #f04494); }
|
||||
|
||||
.sign-form .form-row-between label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
color: var(--muted-color, #777);
|
||||
}
|
||||
|
||||
.sign-form .btn-submit {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
border: none;
|
||||
border-radius: var(--main-radius, 8px);
|
||||
background: var(--focus-color, #f04494);
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: opacity .15s;
|
||||
}
|
||||
|
||||
.sign-form .btn-submit:hover { opacity: .85; }
|
||||
.sign-form .btn-submit:disabled { opacity: .5; cursor: not-allowed; }
|
||||
|
||||
.sign-hint {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
color: var(--muted-color, #777);
|
||||
}
|
||||
|
||||
.sign-terms {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
color: var(--muted-color, #777);
|
||||
}
|
||||
|
||||
.sign-terms a {
|
||||
color: var(--focus-color, #f04494);
|
||||
}
|
||||
|
||||
.sign-footer {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
font-size: 14px;
|
||||
color: var(--muted-color, #777);
|
||||
}
|
||||
|
||||
.sign-footer a { color: var(--focus-color, #f04494); }
|
||||
|
||||
.sign-footer-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
color: var(--muted-2-color, #999);
|
||||
z-index: 1;
|
||||
background: color-mix(in srgb, var(--main-bg-color, #fff) 80%, transparent);
|
||||
}
|
||||
|
||||
.sign-oauth {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.sign-oauth__divider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 14px;
|
||||
font-size: 12px;
|
||||
color: var(--muted-2-color, #999);
|
||||
}
|
||||
|
||||
.sign-oauth__divider::before,
|
||||
.sign-oauth__divider::after {
|
||||
content: "";
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background: var(--main-border-color, rgba(50, 50, 50, 0.08));
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.sign-card { padding: 24px 20px; }
|
||||
.sign-page { padding-top: 56px; }
|
||||
.sign-header { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 23px; }
|
||||
.sign-header h2 { margin: 0; font-size: 22px; line-height: 1.4; color: var(--key-color, #333); }
|
||||
.sign-header span { font-size: 12px; color: var(--muted-2-color, #999); }
|
||||
.sign-header button,
|
||||
.sign-options button,
|
||||
.sign-mode-switch { padding: 0; border: 0; background: none; color: var(--focus-color, #f04494); cursor: pointer; }
|
||||
.sign-form { display: grid; gap: 17px; }
|
||||
|
||||
.floating-input { position: relative; min-height: 42px; border-bottom: 1px solid var(--main-border-color, rgba(50, 50, 50, .12)); }
|
||||
.floating-input::after { content: ""; position: absolute; right: 0; bottom: -1px; left: 0; height: 2px; background: var(--focus-color, #f04494); transform: scaleX(0); transition: transform .25s; }
|
||||
.floating-input:focus-within::after { transform: scaleX(1); }
|
||||
.floating-input input { width: 100%; height: 42px; padding: 13px 4px 2px; border: 0; outline: 0; background: transparent; color: inherit; font-size: 14px; box-shadow: none !important; }
|
||||
.floating-input label { position: absolute; top: 12px; left: 4px; color: var(--muted-color, #777); font-size: 14px; font-weight: 400; pointer-events: none; transition: all .18s; }
|
||||
.floating-input input:focus + label,
|
||||
.floating-input input:not(:placeholder-shown) + label,
|
||||
.floating-input.is-filled label { top: 0; font-size: 10px; color: var(--focus-color, #f04494); }
|
||||
.floating-input.has-action input { padding-right: 94px; }
|
||||
.floating-input .password-show,
|
||||
.floating-input .send-code { position: absolute; right: 0; bottom: 6px; z-index: 2; border: 0; background: none; color: var(--muted-2-color, #999); cursor: pointer; }
|
||||
.floating-input .send-code { color: var(--focus-color, #f04494); font-size: 12px; }
|
||||
.floating-input .send-code:disabled { color: var(--muted-2-color, #999); cursor: default; }
|
||||
|
||||
.sign-options { display: flex; align-items: center; justify-content: space-between; color: var(--muted-2-color, #999); font-size: 12px; }
|
||||
.sign-options label { margin: 0; font-weight: 400; }
|
||||
.sign-submit { width: 100%; min-height: 42px; padding: 10px 16px; border: 0; border-radius: 5px; color: #fff; cursor: pointer; transition: opacity .2s, transform .2s; }
|
||||
.sign-submit:hover { opacity: .88; transform: translateY(-1px); }
|
||||
.sign-submit:disabled { opacity: .55; cursor: wait; transform: none; }
|
||||
.sign-submit.jb-blue { background: linear-gradient(135deg, #59c3ff, #2b70ff); }
|
||||
.sign-submit.jb-green { background: linear-gradient(135deg, #50e3a4, #16a085); }
|
||||
.sign-mode-switch { justify-self: center; font-size: 12px; }
|
||||
.sign-message,
|
||||
.sign-notice { margin-bottom: 16px; padding: 10px 12px; border-radius: 5px; background: rgba(255, 86, 86, .08); color: #e55353; font-size: 12px; }
|
||||
.sign-message.is-success { background: rgba(45, 194, 117, .1); color: #1e9d5d; }
|
||||
.sign-hint { margin-top: -10px; color: var(--muted-2-color, #999); font-size: 11px; }
|
||||
.sign-agreement { display: flex; align-items: flex-start; gap: 6px; margin: 0; color: var(--muted-2-color, #999); font-size: 11px; font-weight: 400; }
|
||||
.sign-agreement a { color: var(--focus-color, #f04494); }
|
||||
.sign-agreement-implicit { justify-content: center; text-align: center; }
|
||||
|
||||
.social-login { margin-top: 24px; text-align: center; }
|
||||
.social-login > span { display: flex; align-items: center; gap: 10px; color: var(--muted-2-color, #999); font-size: 11px; }
|
||||
.social-login > span::before,
|
||||
.social-login > span::after { content: ""; flex: 1; height: 1px; background: var(--main-border-color, rgba(50, 50, 50, .08)); }
|
||||
.social-login-buttons { display: flex; flex-wrap: wrap; justify-content: center; gap: 13px; margin-top: 14px; }
|
||||
.social-login-item { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50px; background: var(--body-bg-color, #f5f6f7); color: #fff; text-decoration: none; cursor: pointer; }
|
||||
.social-login-item:hover { transform: translateY(-2px); color: var(--focus-color, #f04494); }
|
||||
.oauth-button-lg .social-login-item { width: auto; padding: 0 14px; }
|
||||
.oauth-button-lg .social-login-item i,
|
||||
.oauth-button-lg .social-login-item svg { margin-right: 6px; font-size: 1.2em; }
|
||||
.social-login-item.weibo { background: #ea5d5c; }
|
||||
.social-login-item.weixingzh,
|
||||
.social-login-item.weixin { background: #24b76a; }
|
||||
.social-login-item.qq,
|
||||
.social-login-item.alipay { background: #1296db; }
|
||||
.social-login-item.baidu { background: #4e6ef2; }
|
||||
.social-login-item.github { background: #505050; }
|
||||
.social-login-item.gitee { background: #c2292f; }
|
||||
.social-login-item.google { background: var(--main-shadow, rgba(116, 116, 116, .08)); color: var(--main-color, #4e5358); }
|
||||
.auth-qrcode { display: grid; place-items: center; width: 180px; min-height: 180px; margin: 20px auto; background: #fff; color: #38b766; text-align: center; }
|
||||
.auth-qrcode i { font-size: 46px; }
|
||||
.auth-qrcode span { color: #777; font-size: 12px; }
|
||||
|
||||
.aksrt-auth-modal { position: fixed; inset: 0; z-index: 100050; display: none; place-items: center; padding: 18px; }
|
||||
.aksrt-auth-modal.is-open { display: grid; }
|
||||
.auth-modal-backdrop { position: absolute; inset: 0; background: rgba(14, 18, 24, .62); backdrop-filter: blur(2px); }
|
||||
#u_sign .modal-dialog { position: relative; z-index: 1; width: 400px; max-width: calc(100vw - 30px); margin: 0; }
|
||||
#u_sign.has-sign-img .modal-dialog { width: 800px; }
|
||||
#u_sign .modal-content { position: relative; min-height: 300px; max-height: calc(100vh - 36px); overflow-x: hidden; overflow-y: auto; border: 0; border-radius: 8px; background: var(--main-bg-color, #fff); box-shadow: 0 12px 50px rgba(0, 0, 0, .22); }
|
||||
.auth-modal-close { position: absolute; top: 13px; right: 15px; z-index: 4; width: 30px; height: 30px; border: 0; border-radius: 50%; background: rgba(0, 0, 0, .04); color: var(--muted-color, #777); cursor: pointer; }
|
||||
.sign-img { position: absolute; inset: 0 55% 0 0; background-position: center; background-size: cover; }
|
||||
.sign-img + .sign { max-width: unset; margin-left: 55%; padding: 34px 44px; }
|
||||
|
||||
.page-template-user-sign { min-height: 100vh; background: var(--body-bg-color, #f5f6f7); }
|
||||
.sign-page-background { position: fixed; inset: 0; z-index: 0; background-position: center; background-size: cover; }
|
||||
.sign-topbar { position: fixed; top: 0; right: 0; left: 0; z-index: 3; display: flex; justify-content: space-between; padding: 15px 24px; background: rgba(255, 255, 255, .75); backdrop-filter: blur(12px); }
|
||||
.sign-page { position: relative; z-index: 1; display: flex; align-items: center; min-height: 100vh; padding: 76px max(5vw, 20px) 56px; }
|
||||
.sign-page.sign-card-position-left { justify-content: flex-start; }
|
||||
.sign-page.sign-card-position-center { justify-content: center; }
|
||||
.sign-page.sign-card-position-right { justify-content: flex-end; }
|
||||
.sign-page-card { width: 400px; max-width: 100%; padding: 0 35px; border-radius: 8px; background: var(--main-bg-color, #fff); box-shadow: 0 10px 40px rgba(0, 0, 0, .12); }
|
||||
.sign-page-footer { position: fixed; right: 0; bottom: 12px; left: 0; z-index: 2; text-align: center; color: var(--muted-2-color, #999); font-size: 12px; }
|
||||
.white-theme { --main-bg-color: #fff; --body-bg-color: #f5f6f7; --main-color: #4e5358; --key-color: #333; }
|
||||
.dark-theme { --main-bg-color: #24272b; --body-bg-color: #17191c; --main-color: #d7d9dc; --key-color: #fff; --main-border-color: rgba(255, 255, 255, .12); }
|
||||
body.auth-modal-open { overflow: hidden; }
|
||||
|
||||
@media (max-width: 767px) {
|
||||
#u_sign .modal-dialog,
|
||||
#u_sign.has-sign-img .modal-dialog { width: 400px; }
|
||||
.sign-img { display: none; }
|
||||
.sign-img + .sign { max-width: 340px; margin-left: auto; padding: 30px 0; }
|
||||
#u_sign .modal-content { padding: 0 24px; }
|
||||
.sign-page { justify-content: center !important; padding-right: 14px; padding-left: 14px; }
|
||||
.sign-page-card { padding: 0 24px; }
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
/** Shared authentication state machine for modal and /sign/. */
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var config = window.aksrtData || {};
|
||||
var apiRoot = String(config.apiUrl || config.restUrl || '/wp-json/aksrt/v1').replace(/\/$/, '');
|
||||
var nonce = config.restNonce || '';
|
||||
|
||||
function request(path, data) {
|
||||
return fetch(apiRoot + '/auth/' + path, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': nonce },
|
||||
body: JSON.stringify(data),
|
||||
}).then(function (response) {
|
||||
return response.json().catch(function () { return {}; }).then(function (body) {
|
||||
if (!response.ok || body.success === false) {
|
||||
throw new Error(body.message || (body.data && body.data.message) || '请求失败,请稍后再试');
|
||||
}
|
||||
return body.data || body;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function formData(form) {
|
||||
var data = {};
|
||||
new FormData(form).forEach(function (value, key) {
|
||||
data[key] = value;
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
function showMessage(root, text, success) {
|
||||
var active = root.querySelector('[data-auth-panel]:not([hidden])');
|
||||
var box = active && active.querySelector('[data-auth-message]');
|
||||
if (!box) return;
|
||||
box.textContent = text || '';
|
||||
box.hidden = !text;
|
||||
box.classList.toggle('is-success', !!success);
|
||||
}
|
||||
|
||||
function activate(root, tab, updateUrl) {
|
||||
var panel = root.querySelector('[data-auth-panel="' + tab + '"]');
|
||||
if (!panel) return;
|
||||
root.querySelectorAll('[data-auth-panel]').forEach(function (item) { item.hidden = item !== panel; });
|
||||
root.dataset.activeTab = tab;
|
||||
showMessage(root, '', false);
|
||||
if (updateUrl && root.dataset.surface === 'page' && window.history && window.URL) {
|
||||
var url = new URL(window.location.href);
|
||||
url.searchParams.set('tab', tab);
|
||||
window.history.replaceState({}, '', url.toString());
|
||||
}
|
||||
var focus = panel.querySelector('input:not([type="hidden"])');
|
||||
if (focus) window.setTimeout(function () { focus.focus(); }, 30);
|
||||
if (tab === 'oauth') loadQr(root);
|
||||
}
|
||||
|
||||
function loadQr(root) {
|
||||
var box = root.querySelector('[data-auth-qrcode]');
|
||||
if (!box || box.dataset.loading === '1' || box.dataset.loaded === '1') return;
|
||||
box.dataset.loading = '1';
|
||||
request('qrcode-login', {}).then(function (result) {
|
||||
box.dataset.loading = '0';
|
||||
box.dataset.loaded = '1';
|
||||
box.innerHTML = result.qr_html || '';
|
||||
if (result.mode === 'scan' && result.token) pollQr(root, box, result.token, 0);
|
||||
}).catch(function (error) {
|
||||
box.dataset.loading = '0';
|
||||
box.innerHTML = '<span>' + String(error.message).replace(/[&<>"']/g, '') + '</span>';
|
||||
});
|
||||
}
|
||||
|
||||
function pollQr(root, box, token, count) {
|
||||
if (!document.documentElement.contains(box) || count >= 100) return;
|
||||
window.setTimeout(function () {
|
||||
request('check-qrcode-login', { token: token }).then(function (result) {
|
||||
if (result.logged_in) {
|
||||
showMessage(root, '登录成功', true);
|
||||
window.location.assign(result.redirect || window.location.href);
|
||||
return;
|
||||
}
|
||||
if (result.status === 'expired') {
|
||||
box.dataset.loaded = '0';
|
||||
box.innerHTML = '<button type="button" data-auth-refresh-qr>二维码已过期,点击刷新</button>';
|
||||
return;
|
||||
}
|
||||
pollQr(root, box, token, count + 1);
|
||||
}).catch(function () { pollQr(root, box, token, count + 1); });
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function submitQrCode(root, form) {
|
||||
var data = formData(form);
|
||||
var button = form.querySelector('button[type="submit"]');
|
||||
if (button) button.disabled = true;
|
||||
request('weixingzh-code', data).then(function (result) {
|
||||
showMessage(root, '登录成功', true);
|
||||
window.location.assign(result.redirect || window.location.href);
|
||||
}).catch(function (error) {
|
||||
if (button) button.disabled = false;
|
||||
showMessage(root, error.message, false);
|
||||
});
|
||||
}
|
||||
|
||||
function setBusy(form, busy) {
|
||||
var button = form.querySelector('.sign-submit');
|
||||
if (!button) return;
|
||||
button.disabled = busy;
|
||||
var spinner = button.querySelector('.fa-spinner');
|
||||
if (spinner) spinner.hidden = !busy;
|
||||
}
|
||||
|
||||
function startCountdown(button, seconds) {
|
||||
var original = button.dataset.label || button.textContent;
|
||||
button.dataset.label = original;
|
||||
button.disabled = true;
|
||||
var left = Math.max(1, Number(seconds) || 60);
|
||||
button.textContent = left + 's';
|
||||
var timer = window.setInterval(function () {
|
||||
left -= 1;
|
||||
if (left <= 0) {
|
||||
window.clearInterval(timer);
|
||||
button.disabled = false;
|
||||
button.textContent = original;
|
||||
} else {
|
||||
button.textContent = left + 's';
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function captchaScene(scene) {
|
||||
return scene === 'resetpassword' ? 'lostpassword' : scene;
|
||||
}
|
||||
|
||||
function verifyCaptcha(scene, callback) {
|
||||
var state = window.AKSRTCaptchaState;
|
||||
var captcha = state && state.scenes ? state.scenes[captchaScene(scene)] : null;
|
||||
if (!captcha || typeof captcha.verify !== 'function') {
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
captcha.verify(function (verified) { callback(verified !== false); });
|
||||
}
|
||||
|
||||
function resetCaptcha(scene) {
|
||||
var state = window.AKSRTCaptchaState;
|
||||
var captcha = state && state.scenes ? state.scenes[captchaScene(scene)] : null;
|
||||
if (captcha && typeof captcha.reset === 'function') captcha.reset();
|
||||
}
|
||||
|
||||
function sendCode(root, button) {
|
||||
var form = button.closest('form');
|
||||
var target = form && form.querySelector('[name="target"]');
|
||||
if (!target || !target.value.trim()) {
|
||||
showMessage(root, '请先填写邮箱或手机号', false);
|
||||
return;
|
||||
}
|
||||
button.disabled = true;
|
||||
var payload = formData(form);
|
||||
payload.scene = button.dataset.sendCode;
|
||||
payload.target = target.value.trim();
|
||||
payload.channel = (form.querySelector('[name="channel"]') || {}).value || '';
|
||||
verifyCaptcha(payload.scene, function (verified) {
|
||||
if (!verified) {
|
||||
button.disabled = false;
|
||||
return;
|
||||
}
|
||||
payload = formData(form);
|
||||
payload.scene = button.dataset.sendCode;
|
||||
payload.target = target.value.trim();
|
||||
payload.channel = (form.querySelector('[name="channel"]') || {}).value || '';
|
||||
request('code', payload).then(function (result) {
|
||||
showMessage(root, result.message || '验证码已发送', true);
|
||||
startCountdown(button, result.countdown || 60);
|
||||
}).catch(function (error) {
|
||||
button.disabled = false;
|
||||
showMessage(root, error.message, false);
|
||||
}).finally(function () {
|
||||
resetCaptcha(payload.scene);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function submit(root, form) {
|
||||
var action = form.dataset.authForm;
|
||||
var payload = formData(form);
|
||||
if (action === 'register' && payload.channel !== 'phone') {
|
||||
payload.user_email = payload.target;
|
||||
}
|
||||
setBusy(form, true);
|
||||
showMessage(root, '', false);
|
||||
request(action, payload).then(function (result) {
|
||||
showMessage(root, result.message || '操作成功', true);
|
||||
if (result.redirect) window.setTimeout(function () { window.location.assign(result.redirect); }, 350);
|
||||
}).catch(function (error) {
|
||||
showMessage(root, error.message, false);
|
||||
setBusy(form, false);
|
||||
});
|
||||
}
|
||||
|
||||
function toggleLoginMode(root, button) {
|
||||
var password = root.querySelector('[data-auth-password-fields]');
|
||||
var code = root.querySelector('[data-auth-code-fields]');
|
||||
if (!password || !code) return;
|
||||
var showCode = code.hidden;
|
||||
code.hidden = !showCode;
|
||||
password.hidden = showCode;
|
||||
button.textContent = showCode ? '使用账号密码登录' : '使用验证码登录';
|
||||
}
|
||||
|
||||
function initRoot(root) {
|
||||
root.querySelectorAll('input').forEach(function (input) {
|
||||
if (!input.hasAttribute('placeholder')) input.setAttribute('placeholder', ' ');
|
||||
});
|
||||
var initial = root.dataset.initialTab || 'signin';
|
||||
if (initial === 'oauth' && window.matchMedia && window.matchMedia('(max-width: 767px)').matches) initial = 'signin';
|
||||
activate(root, initial, false);
|
||||
root.addEventListener('click', function (event) {
|
||||
var tab = event.target.closest('[data-auth-tab]');
|
||||
if (tab) { event.preventDefault(); activate(root, tab.dataset.authTab, true); return; }
|
||||
var password = event.target.closest('[data-password-show]');
|
||||
if (password) {
|
||||
var input = password.closest('.floating-input').querySelector('input');
|
||||
input.type = input.type === 'password' ? 'text' : 'password';
|
||||
password.querySelector('i').className = input.type === 'password' ? 'fa fas fa-eye' : 'fa fas fa-eye-slash';
|
||||
return;
|
||||
}
|
||||
var send = event.target.closest('[data-send-code]');
|
||||
if (send) { event.preventDefault(); sendCode(root, send); return; }
|
||||
var mode = event.target.closest('[data-login-mode]');
|
||||
if (mode) { event.preventDefault(); toggleLoginMode(root, mode); }
|
||||
var refreshQr = event.target.closest('[data-auth-refresh-qr]');
|
||||
if (refreshQr) { event.preventDefault(); loadQr(root); }
|
||||
});
|
||||
root.addEventListener('submit', function (event) {
|
||||
var qrForm = event.target.closest('[data-aksrt-weixingzh-code]');
|
||||
if (qrForm) {
|
||||
event.preventDefault();
|
||||
if (!qrForm.reportValidity || qrForm.reportValidity()) submitQrCode(root, qrForm);
|
||||
return;
|
||||
}
|
||||
var form = event.target.closest('[data-auth-form]');
|
||||
if (!form) return;
|
||||
event.preventDefault();
|
||||
if (form.reportValidity && !form.reportValidity()) return;
|
||||
submit(root, form);
|
||||
});
|
||||
}
|
||||
|
||||
var modal;
|
||||
function authPageUrl(tab, redirect) {
|
||||
var routes = config.routes || {};
|
||||
var base = tab === 'signup' ? routes.register : routes.login;
|
||||
var url = new URL(base || '/sign/', window.location.href);
|
||||
url.searchParams.set('tab', tab || 'signin');
|
||||
if (redirect) url.searchParams.set('redirect_to', redirect);
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
function openModal(tab, redirect) {
|
||||
if (!modal) {
|
||||
window.location.assign(authPageUrl(tab, redirect));
|
||||
return;
|
||||
}
|
||||
modal.classList.add('is-open');
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
document.body.classList.add('auth-modal-open');
|
||||
var root = modal.querySelector('[data-aksrt-auth]');
|
||||
if (root) {
|
||||
activate(root, tab || 'signin', false);
|
||||
var redirectInput = root.querySelector('[name="redirect_to"]');
|
||||
if (redirectInput && redirect) redirectInput.value = redirect;
|
||||
}
|
||||
}
|
||||
|
||||
function closeModal(storeDismissal) {
|
||||
if (!modal) return;
|
||||
modal.classList.remove('is-open');
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
document.body.classList.remove('auth-modal-open');
|
||||
if (storeDismissal && Number(modal.dataset.autoExpires) > 0) {
|
||||
var until = Date.now() + Number(modal.dataset.autoExpires) * 3600000;
|
||||
window.localStorage.setItem('aksrtAuthAutoUntil', String(until));
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
document.querySelectorAll('[data-aksrt-auth]').forEach(initRoot);
|
||||
modal = document.querySelector('[data-auth-modal]');
|
||||
document.addEventListener('click', function (event) {
|
||||
var trigger = event.target.closest('[data-aksrt-auth-required], .aksrt-login-trigger, #nav-login-btn, .signin-loader, .signup-loader, .qrcode-signin');
|
||||
if (!trigger) return;
|
||||
event.preventDefault();
|
||||
var tab = trigger.classList.contains('signup-loader') ? 'signup' : (trigger.classList.contains('qrcode-signin') ? 'oauth' : 'signin');
|
||||
openModal(tab, trigger.dataset.authRedirect || '');
|
||||
});
|
||||
if (modal) {
|
||||
modal.addEventListener('click', function (event) {
|
||||
if (event.target.closest('[data-auth-close]')) closeModal(true);
|
||||
});
|
||||
document.addEventListener('keydown', function (event) { if (event.key === 'Escape') closeModal(true); });
|
||||
if (modal.dataset.auto === '1' && Number(window.localStorage.getItem('aksrtAuthAutoUntil') || 0) < Date.now()) {
|
||||
window.setTimeout(function () { openModal(modal.querySelector('[data-aksrt-auth]').dataset.initialTab || 'signin'); }, Math.max(1, Number(modal.dataset.autoWait) || 5) * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
|
||||
else init();
|
||||
}());
|
||||
@@ -1,610 +0,0 @@
|
||||
/**
|
||||
* AKSRT modal auth interactions.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Resolve REST root for aksrt/v1.
|
||||
* Prefer aksrtData.restUrl (works with plain permalinks: index.php?rest_route=/aksrt/v1).
|
||||
* Do not hardcode /wp-json when rewrite rules are off — that 404s on Apache.
|
||||
*/
|
||||
function resolveApiRoot() {
|
||||
var d = window.aksrtData || {};
|
||||
var raw = d.apiUrl || d.restUrl || d.rest_url || '';
|
||||
if (!raw) {
|
||||
raw = '/index.php?rest_route=/aksrt/v1';
|
||||
}
|
||||
raw = String(raw).trim();
|
||||
// restUrl may be site root rest_url() without namespace in some localizes — ensure aksrt/v1.
|
||||
if (/rest_route=\/?$/.test(raw) || /\/wp-json\/?$/.test(raw)) {
|
||||
if (raw.indexOf('rest_route=') !== -1) {
|
||||
raw = raw.replace(/rest_route=\/?$/, 'rest_route=/aksrt/v1');
|
||||
} else {
|
||||
raw = raw.replace(/\/?$/, '/') + 'aksrt/v1';
|
||||
}
|
||||
}
|
||||
return raw.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
var API_ROOT = resolveApiRoot();
|
||||
var NONCE = (window.aksrtData && window.aksrtData.restNonce) || '';
|
||||
|
||||
var modal = null;
|
||||
var currentTab = 'login';
|
||||
|
||||
function init() {
|
||||
modal = document.getElementById('aksrt-modal-auth');
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
var closeBtn = modal.querySelector('.aksrt-modal-auth__close');
|
||||
var overlay = modal.querySelector('.aksrt-modal-auth__overlay');
|
||||
if (closeBtn) {
|
||||
closeBtn.addEventListener('click', close);
|
||||
}
|
||||
if (overlay) {
|
||||
overlay.addEventListener('click', close);
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', function (event) {
|
||||
if (event.key === 'Escape' && modal.classList.contains('is-open')) {
|
||||
close();
|
||||
}
|
||||
});
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__tab').forEach(function (tab) {
|
||||
tab.addEventListener('click', function () {
|
||||
switchTab(this.dataset.tab || 'login');
|
||||
});
|
||||
});
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__switch').forEach(function (button) {
|
||||
button.addEventListener('click', function () {
|
||||
switchTab(this.dataset.switch || 'login');
|
||||
});
|
||||
});
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__pass-toggle').forEach(function (button) {
|
||||
button.addEventListener('click', function () {
|
||||
var input = this.parentElement.querySelector('input');
|
||||
var icon = this.querySelector('i');
|
||||
if (!input || !icon) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (input.type === 'password') {
|
||||
input.type = 'text';
|
||||
icon.className = 'fa fas fa-eye-slash';
|
||||
} else {
|
||||
input.type = 'password';
|
||||
icon.className = 'fa fas fa-eye';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var loginForm = document.getElementById('aksrt-modal-login-form');
|
||||
if (loginForm) {
|
||||
loginForm.addEventListener('submit', function (event) {
|
||||
event.preventDefault();
|
||||
handleLogin(loginForm);
|
||||
});
|
||||
}
|
||||
|
||||
var registerForm = document.getElementById('aksrt-modal-register-form');
|
||||
if (registerForm) {
|
||||
registerForm.addEventListener('submit', function (event) {
|
||||
event.preventDefault();
|
||||
handleRegister(registerForm);
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
var trigger = event.target.closest('[data-aksrt-auth-required], .aksrt-login-trigger, #nav-login-btn, .signin-loader, .signup-loader, .qrcode-signin');
|
||||
if (!trigger) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (trigger.classList.contains('signup-loader')) {
|
||||
open(trigger.dataset.authRedirect || '');
|
||||
switchTab('register');
|
||||
return;
|
||||
}
|
||||
if (trigger.classList.contains('qrcode-signin')) {
|
||||
open(trigger.dataset.authRedirect || '');
|
||||
switchTab('qrcode');
|
||||
return;
|
||||
}
|
||||
|
||||
open(trigger.dataset.authRedirect || '');
|
||||
});
|
||||
|
||||
initQrLogin();
|
||||
initAgreementShake();
|
||||
initSocialPriority();
|
||||
}
|
||||
|
||||
function open(redirectUrl) {
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
modal.classList.add('is-open');
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
if (redirectUrl) {
|
||||
modal.dataset.redirect = redirectUrl;
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
var firstInput = modal.querySelector('.aksrt-modal-auth__panel.is-active input:not([type="hidden"])');
|
||||
if (firstInput) {
|
||||
firstInput.focus();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
var qrLoginTimer = null;
|
||||
|
||||
function close() {
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
modal.classList.remove('is-open');
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
document.body.style.overflow = '';
|
||||
clearMessages();
|
||||
stopQrPolling();
|
||||
}
|
||||
|
||||
function switchTab(tab) {
|
||||
currentTab = tab;
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__tab').forEach(function (button) {
|
||||
var isActive = button.dataset.tab === tab;
|
||||
button.classList.toggle('is-active', isActive);
|
||||
button.setAttribute('aria-selected', isActive ? 'true' : 'false');
|
||||
});
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__panel').forEach(function (panel) {
|
||||
panel.classList.toggle('is-active', panel.dataset.panel === tab);
|
||||
});
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__footer-text').forEach(function (row) {
|
||||
row.hidden = row.dataset.for !== tab;
|
||||
});
|
||||
|
||||
modal.setAttribute('aria-label', tab === 'register' ? '注册' : '登录');
|
||||
clearMessages();
|
||||
}
|
||||
|
||||
function withCaptcha(scene, form, next) {
|
||||
var store = window.AKSRTCaptchaState && window.AKSRTCaptchaState.scenes
|
||||
? window.AKSRTCaptchaState.scenes
|
||||
: null;
|
||||
var instance = store && store[scene] ? store[scene] : null;
|
||||
if (instance && typeof instance.verify === 'function') {
|
||||
instance.verify(function () {
|
||||
next(serializeForm(form));
|
||||
});
|
||||
return;
|
||||
}
|
||||
next(serializeForm(form));
|
||||
}
|
||||
|
||||
function resetCaptcha(scene) {
|
||||
try {
|
||||
var store = window.AKSRTCaptchaState && window.AKSRTCaptchaState.scenes
|
||||
? window.AKSRTCaptchaState.scenes
|
||||
: null;
|
||||
if (store && store[scene] && typeof store[scene].reset === 'function') {
|
||||
store[scene].reset();
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
function handleLogin(form) {
|
||||
if (!form.querySelector('[name="log"]') || !form.querySelector('[name="pwd"]')) {
|
||||
showMessage('login', '请输入用户名和密码', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(form, true);
|
||||
clearMessages();
|
||||
|
||||
withCaptcha('login', form, function (payload) {
|
||||
if (!payload.log || !payload.pwd) {
|
||||
setLoading(form, false);
|
||||
showMessage('login', '请输入用户名和密码', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
request('/auth/modal-login', payload)
|
||||
.then(function (result) {
|
||||
if (result.ok && result.data.success) {
|
||||
onAuthSuccess(result.data);
|
||||
return;
|
||||
}
|
||||
|
||||
resetCaptcha('login');
|
||||
var message = result.data.message || '登录失败';
|
||||
if (result.data.verify_url) {
|
||||
message += ' <a href="' + escapeAttribute(result.data.verify_url) + '">前往验证</a>';
|
||||
}
|
||||
showMessage('login', message, 'error');
|
||||
})
|
||||
.catch(function () {
|
||||
resetCaptcha('login');
|
||||
showMessage('login', '网络错误,请稍后重试', 'error');
|
||||
})
|
||||
.finally(function () {
|
||||
setLoading(form, false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handleRegister(form) {
|
||||
setLoading(form, true);
|
||||
clearMessages();
|
||||
|
||||
withCaptcha('register', form, function (payload) {
|
||||
if (!payload.user_login || !payload.user_email || !payload.user_pass || !payload.user_pass_confirm) {
|
||||
setLoading(form, false);
|
||||
showMessage('register', '请完整填写注册信息', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload.user_pass !== payload.user_pass_confirm) {
|
||||
setLoading(form, false);
|
||||
showMessage('register', '两次输入的密码不一致', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
request('/auth/modal-register', payload)
|
||||
.then(function (result) {
|
||||
if (!result.ok || !result.data.success) {
|
||||
resetCaptcha('register');
|
||||
showMessage('register', result.data.message || '注册失败', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.data.user) {
|
||||
onAuthSuccess(result.data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.data.verification_required) {
|
||||
var verifyMessage = result.data.message || '注册成功,请完成邮箱验证';
|
||||
if (result.data.notice) verifyMessage += '<br>' + escapeAttribute(result.data.notice);
|
||||
if (result.data.verify_url) {
|
||||
verifyMessage += ' <a href="' + escapeAttribute(result.data.verify_url) + '">前往验证</a>';
|
||||
}
|
||||
showMessage('register', verifyMessage, 'success');
|
||||
form.reset();
|
||||
resetCaptcha('register');
|
||||
return;
|
||||
}
|
||||
|
||||
var loginMessage = result.data.message || '注册成功,请登录';
|
||||
if (result.data.notice) loginMessage += ' ' + result.data.notice;
|
||||
switchTab('login');
|
||||
prefillLogin(result.data.user_login || result.data.user_email || '');
|
||||
showMessage('login', loginMessage, 'success');
|
||||
form.reset();
|
||||
resetCaptcha('register');
|
||||
})
|
||||
.catch(function () {
|
||||
resetCaptcha('register');
|
||||
showMessage('register', '网络错误,请稍后重试', 'error');
|
||||
})
|
||||
.finally(function () {
|
||||
setLoading(form, false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function serializeForm(form) {
|
||||
var payload = {};
|
||||
var formData = new FormData(form);
|
||||
|
||||
formData.forEach(function (value, key) {
|
||||
if (payload[key] !== undefined) {
|
||||
if (!Array.isArray(payload[key])) {
|
||||
payload[key] = [payload[key]];
|
||||
}
|
||||
payload[key].push(value);
|
||||
} else {
|
||||
payload[key] = value;
|
||||
}
|
||||
});
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
function request(path, payload) {
|
||||
var headers = { 'Content-Type': 'application/json' };
|
||||
if (NONCE) {
|
||||
headers['X-WP-Nonce'] = NONCE;
|
||||
}
|
||||
|
||||
var url = joinRestPath(API_ROOT, path);
|
||||
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify(payload),
|
||||
}).then(function (response) {
|
||||
return response.json().then(function (data) {
|
||||
return { ok: response.ok, data: data };
|
||||
}).catch(function () {
|
||||
return { ok: false, data: { message: '响应解析失败' } };
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Join REST root + path for both pretty (/wp-json/aksrt/v1/x)
|
||||
* and plain (?rest_route=/aksrt/v1/x) permalinks.
|
||||
*/
|
||||
function joinRestPath(root, path) {
|
||||
path = String(path || '');
|
||||
if (path.charAt(0) !== '/') {
|
||||
path = '/' + path;
|
||||
}
|
||||
root = String(root || '').replace(/\/$/, '');
|
||||
if (root.indexOf('rest_route=') !== -1) {
|
||||
// e.g. https://host/index.php?rest_route=/aksrt/v1 + /auth/modal-login
|
||||
return root + path;
|
||||
}
|
||||
return root + path;
|
||||
}
|
||||
|
||||
function prefillLogin(value) {
|
||||
var loginInput = document.getElementById('modal-login-user');
|
||||
if (loginInput && value) {
|
||||
loginInput.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
function onAuthSuccess(data) {
|
||||
close();
|
||||
|
||||
if (data.user) {
|
||||
updateNavUser(data.user);
|
||||
}
|
||||
|
||||
notyf(data.message || '登录成功', 'success');
|
||||
|
||||
var redirect = modal.dataset.redirect || data.redirect;
|
||||
if (redirect && redirect !== window.location.href) {
|
||||
setTimeout(function () {
|
||||
window.location.href = redirect;
|
||||
}, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function updateNavUser(user) {
|
||||
document.querySelectorAll('.nav-user__avatar img, .nav-user__toggle img').forEach(function (image) {
|
||||
if (user.avatar_url) {
|
||||
image.src = user.avatar_url;
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelectorAll('.nav-user__name').forEach(function (el) {
|
||||
if (user.display_name) {
|
||||
el.textContent = user.display_name;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showMessage(panel, message, type) {
|
||||
var box = document.getElementById('aksrt-modal-' + panel + '-error');
|
||||
if (!box) {
|
||||
return;
|
||||
}
|
||||
|
||||
box.innerHTML = message;
|
||||
box.hidden = false;
|
||||
box.classList.toggle('is-success', type === 'success');
|
||||
}
|
||||
|
||||
function clearMessages() {
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__error').forEach(function (box) {
|
||||
box.hidden = true;
|
||||
box.innerHTML = '';
|
||||
box.classList.remove('is-success');
|
||||
});
|
||||
}
|
||||
|
||||
function setLoading(form, loading) {
|
||||
var submit = form.querySelector('.aksrt-modal-auth__submit');
|
||||
if (!submit) {
|
||||
return;
|
||||
}
|
||||
|
||||
var label = submit.querySelector('span');
|
||||
var spinner = submit.querySelector('i');
|
||||
submit.disabled = loading;
|
||||
|
||||
if (label) {
|
||||
label.hidden = loading;
|
||||
}
|
||||
if (spinner) {
|
||||
spinner.hidden = !loading;
|
||||
}
|
||||
}
|
||||
|
||||
function escapeAttribute(value) {
|
||||
return String(value || '')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
}
|
||||
|
||||
// ── QR Code Login (§10.7) ──
|
||||
|
||||
|
||||
function bindWeixingzhCodeForm(container) {
|
||||
if (!container) return;
|
||||
var form = container.querySelector('[data-aksrt-weixingzh-code]');
|
||||
if (!form || form._bound) return;
|
||||
form._bound = true;
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var input = form.querySelector('[name="code"]');
|
||||
var code = input ? String(input.value || '').trim() : '';
|
||||
if (!code) return;
|
||||
var btn = form.querySelector('button[type="submit"]');
|
||||
if (btn) btn.disabled = true;
|
||||
request('/auth/weixingzh-code', { code: code })
|
||||
.then(function (result) {
|
||||
var data = (result && result.data) || result || {};
|
||||
if ((result && result.ok) || (result && result.success) || data.logged_in) {
|
||||
onAuthSuccess(data.data || data);
|
||||
return;
|
||||
}
|
||||
throw new Error((result && (result.message || result.msg)) || '验证码错误');
|
||||
})
|
||||
.catch(function (err) {
|
||||
alert(err.message || '登录失败');
|
||||
})
|
||||
.finally(function () {
|
||||
if (btn) btn.disabled = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initQrLogin() {
|
||||
var qrPanel = modal.querySelector('[data-panel="qrcode"]');
|
||||
if (!qrPanel) return;
|
||||
|
||||
var qrContainer = qrPanel.querySelector('.aksrt-modal-auth__qr-code');
|
||||
if (!qrContainer) return;
|
||||
|
||||
// When qrcode tab is activated, fetch QR and start polling
|
||||
var observer = new MutationObserver(function () {
|
||||
if (qrPanel.classList.contains('is-active')) {
|
||||
fetchQrCode(qrContainer);
|
||||
} else {
|
||||
stopQrPolling();
|
||||
}
|
||||
});
|
||||
observer.observe(qrPanel, { attributes: true, attributeFilter: ['class'] });
|
||||
}
|
||||
|
||||
function fetchQrCode(container) {
|
||||
container.innerHTML = '<div class="aksrt-modal-auth__qr-loading"><i class="fa fas fa-spinner fa-spin"></i></div>';
|
||||
|
||||
request('/auth/qrcode-login', {})
|
||||
.then(function (result) {
|
||||
var payload = (result && result.data) || result || {};
|
||||
var qrHtml = payload.qr_html || (payload.data && payload.data.qr_html) || '';
|
||||
var checkUrl = payload.check_url || (payload.data && payload.data.check_url) || '/auth/check-qrcode-login';
|
||||
var token = payload.token || (payload.data && payload.data.token) || '';
|
||||
if (qrHtml) {
|
||||
container.innerHTML = qrHtml;
|
||||
bindWeixingzhCodeForm(container);
|
||||
if (checkUrl && token) {
|
||||
startQrPolling(checkUrl, token);
|
||||
}
|
||||
} else {
|
||||
container.innerHTML = '<p class="aksrt-modal-auth__qr-error">扫码登录暂不可用</p>';
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
container.innerHTML = '<p class="aksrt-modal-auth__qr-error">网络错误</p>';
|
||||
});
|
||||
}
|
||||
|
||||
function startQrPolling(checkUrl, token) {
|
||||
stopQrPolling();
|
||||
qrLoginTimer = setInterval(function () {
|
||||
request(checkUrl, { token: token })
|
||||
.then(function (result) {
|
||||
var data = (result && result.data) || result || {};
|
||||
var body = data.data || data;
|
||||
if ((result && result.ok) || data.success || body.logged_in) {
|
||||
if (body.logged_in || (data.data && data.data.logged_in)) {
|
||||
stopQrPolling();
|
||||
onAuthSuccess(body.data || body);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function () { /* keep polling */ });
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function stopQrPolling() {
|
||||
if (qrLoginTimer) {
|
||||
clearInterval(qrLoginTimer);
|
||||
qrLoginTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Social Login Priority (§10.7) ──
|
||||
|
||||
function initSocialPriority() {
|
||||
var wxPriority = window.aksrtData && aksrtData.signinWxPriority;
|
||||
if (wxPriority && modal) {
|
||||
var wxBtn = modal.querySelector('.social-login-item.weixingzh, .social-login-item[data-provider="wechat"]');
|
||||
if (wxBtn) {
|
||||
setTimeout(function () { wxBtn.click(); }, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Agreement Check: shake instead of disable (§10.7) ──
|
||||
|
||||
function initAgreementShake() {
|
||||
if (!modal) return;
|
||||
modal.querySelectorAll('.aksrt-modal-auth__submit').forEach(function (btn) {
|
||||
btn.addEventListener('click', function (e) {
|
||||
var form = btn.closest('form');
|
||||
if (!form) return;
|
||||
var agree = form.querySelector('[name="agree_terms"], [name="user_agreement"]');
|
||||
if (agree && !agree.checked) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
agree.closest('label, .aksrt-modal-auth__agreement').classList.add('ani', 'shake');
|
||||
notyf('请先同意用户协议', 'warning');
|
||||
setTimeout(function () {
|
||||
agree.closest('label, .aksrt-modal-auth__agreement').classList.remove('ani', 'shake');
|
||||
}, 400);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ── Password Visibility: unified (§10.7) ──
|
||||
// Already handled above; added unification note.
|
||||
|
||||
window.AksrtAuth = {
|
||||
open: open,
|
||||
close: close,
|
||||
};
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -901,6 +901,26 @@
|
||||
if (!form) return;
|
||||
if (form.dataset.aksrtSettingsInitialized === 'true') return;
|
||||
form.dataset.aksrtSettingsInitialized = 'true';
|
||||
var sendButton = form.querySelector('[data-aksrt-sms-trigger]');
|
||||
if (sendButton) sendButton.addEventListener('click', function () {
|
||||
var phone = String((form.querySelector('[name="phone"]') || {}).value || '').trim();
|
||||
if (!/^1[3-9]\d{9}$/.test(phone)) { notyf('请输入正确的手机号', 'warning'); return; }
|
||||
var toastId = 'aksrt-settings-phone-code-toast';
|
||||
var restRoot = (window.aksrtData && aksrtData.apiUrl) || '/wp-json/aksrt/v1';
|
||||
var nonce = (window.aksrtData && aksrtData.restNonce) || '';
|
||||
sendButton.disabled = true;
|
||||
notyf('正在发送验证码…', 'load', '', toastId);
|
||||
fetch(String(restRoot).replace(/\/$/, '') + '/user/phone-code', {
|
||||
method: 'POST', credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': nonce },
|
||||
body: JSON.stringify({ phone: phone })
|
||||
}).then(function (r) { return r.json().then(function (j) { return { ok: r.ok, json: j }; }); }).then(function (res) {
|
||||
if (!res.ok || !res.json.success) throw new Error(res.json.message || '发送失败');
|
||||
notyf(res.json.message || '验证码已发送', 'success', 5, toastId);
|
||||
var left = Number((res.json.data && res.json.data.countdown) || 60);
|
||||
var timer = setInterval(function () { left -= 1; sendButton.textContent = left + 's'; if (left <= 0) { clearInterval(timer); sendButton.disabled = false; sendButton.textContent = '获取验证码'; } }, 1000);
|
||||
}).catch(function (error) { sendButton.disabled = false; notyf(error.message || '发送失败', 'danger', 5, toastId); });
|
||||
});
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var phoneEl = form.querySelector('[name="phone"]');
|
||||
@@ -946,7 +966,7 @@
|
||||
var captcha = collectCaptcha(form);
|
||||
var restRoot = (window.aksrtData && aksrtData.apiUrl) || '/wp-json/aksrt/v1';
|
||||
var nonce = (window.aksrtData && aksrtData.restNonce) || '';
|
||||
fetch(String(restRoot).replace(/\/$/, '') + '/auth/bind-phone', {
|
||||
fetch(String(restRoot).replace(/\/$/, '') + '/user/phone', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
|
||||
@@ -64,7 +64,6 @@ tbquire.config({
|
||||
'main' : 'main.min',
|
||||
'poster-share' : 'poster-share.min',
|
||||
'slidercaptcha' : 'slidercaptcha.min',
|
||||
'sign-register' : 'sign-register',
|
||||
'comment' : 'comment.min',
|
||||
'page-template' : 'page-template.min',
|
||||
'page-edit' : 'page-edit.min',
|
||||
|
||||
@@ -2460,9 +2460,6 @@ function z_auto_fun() {
|
||||
container: 'body',
|
||||
});
|
||||
|
||||
//登录注册
|
||||
$('.signsubmit-loader').length && tbquire(['sign-register']);
|
||||
|
||||
//复制内容
|
||||
$('[data-clipboard-text]').length && tbquire(['clipboard']);
|
||||
|
||||
@@ -3025,114 +3022,6 @@ _win.bd.on('click', '[ajax-action]', function () {
|
||||
});
|
||||
});
|
||||
|
||||
//登录注册
|
||||
_win.bd.on('click', '.signin-loader', function () {
|
||||
if (_win.sign_type == 'page') {
|
||||
window.location.href = _win.signin_url;
|
||||
window.location.reload;
|
||||
} else {
|
||||
$('.modal:not(#u_sign)').modal('hide');
|
||||
$('#u_sign').modal('show');
|
||||
|
||||
if (_win.signin_wx_priority) {
|
||||
$('a[href="#tab-qrcode-signin"]').tab('show');
|
||||
$('.social-login-item.weixingzh:first').click();
|
||||
} else {
|
||||
$('a[href="#tab-sign-in"]').tab('show');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
_win.bd.on('click', '.signup-loader', function () {
|
||||
if (_win.sign_type == 'page') {
|
||||
window.location.href = _win.signup_url;
|
||||
window.location.reload;
|
||||
} else {
|
||||
$('.modal:not(#u_sign)').modal('hide');
|
||||
$('#u_sign').modal('show');
|
||||
$('a[href="#tab-sign-up"]').tab('show');
|
||||
}
|
||||
});
|
||||
|
||||
//扫码登录、绑定
|
||||
_win.bd.on('click', '.qrcode-signin', function () {
|
||||
$('.modal:not(#u_sign)').modal('hide');
|
||||
$('#u_sign').modal('show');
|
||||
$('a[href="#tab-qrcode-signin"]').tab('show');
|
||||
|
||||
var _this = $(this);
|
||||
var url = _this.attr('href');
|
||||
var container = $('.qrcode-signin-container');
|
||||
if (container.find('[get-only-one]').length) {
|
||||
container.find('[name="code"]').val('').trigger('change');
|
||||
return !1;
|
||||
}
|
||||
|
||||
container.html('<p class="placeholder" style="height:180px;width:180px;margin:auto;"></p><p class="placeholder" style="height:27px;width:200px;margin:15px auto 0;"></p>');
|
||||
|
||||
$.post(
|
||||
url,
|
||||
null,
|
||||
function (n) {
|
||||
n || notyf(aksrt__('qrcode_failed'), 'danger');
|
||||
var ys = n.ys ? n.ys : n.error ? 'danger' : '';
|
||||
n.msg && notyf(n.msg, ys);
|
||||
if (n && n.html) {
|
||||
container.html(n.html);
|
||||
_win.qrcode_signin = {
|
||||
url: n.url,
|
||||
state: n.state,
|
||||
};
|
||||
checkLogin();
|
||||
}
|
||||
},
|
||||
'json'
|
||||
);
|
||||
return !1;
|
||||
});
|
||||
|
||||
function checkLogin() {
|
||||
if (_win.checkLoginTimer) return;
|
||||
|
||||
//循环执行调整到ajax外部,避免移动端截图扫码,停止查询登录
|
||||
// 2秒后再次查询
|
||||
_win.checkLoginTimer = setInterval(checkLoginAjax, 2000);
|
||||
}
|
||||
|
||||
function checkLoginAjax() {
|
||||
var url = _win.qrcode_signin.url;
|
||||
var state = _win.qrcode_signin.state;
|
||||
if (!url || !state) {
|
||||
clearInterval(_win.checkLoginTimer);
|
||||
_win.checkLoginTimer = false;
|
||||
return;
|
||||
}
|
||||
$.post(
|
||||
url,
|
||||
{
|
||||
state: state,
|
||||
oauth_rurl: window.location.href,
|
||||
action: 'check_callback',
|
||||
},
|
||||
function (n) {
|
||||
//做逻辑判断,登录跳转
|
||||
if (n && n.goto) {
|
||||
window.location.href = n.goto;
|
||||
window.location.reload;
|
||||
}
|
||||
},
|
||||
'json'
|
||||
);
|
||||
}
|
||||
|
||||
//模态框关闭停止查询登录
|
||||
_win.bd.on('hide.bs.modal', '.modal#u_sign', function () {
|
||||
_win.qrcode_signin = {
|
||||
url: false,
|
||||
state: false,
|
||||
};
|
||||
});
|
||||
|
||||
//防抖函数
|
||||
function throttle(fn, delay) {
|
||||
let valid = true;
|
||||
|
||||
Vendored
+1
-3
@@ -1,3 +1 @@
|
||||
function aksrt__(t){var e=window._win&&window._win.i18n;return e&&Object.prototype.hasOwnProperty.call(e,t)?e[t]:t}function aksrt_is_fatal_error_response(t){return t&&(t.indexOf("Fatal error")>-1||t.indexOf("致命错误")>-1)}function aksrt_sprintf(t){var e=Array.prototype.slice.call(arguments,1),a=aksrt__(t),i=0;return a.replace(/%(\d+\$)?s/g,function(t,a){var n=a?parseInt(a,10)-1:i++;return void 0!==e[n]&&null!==e[n]?e[n]:t})}function only_drop(t){var e=$(t.target).closest(".dropup,.dropdown");$(".dropup.open,.dropdown.open").not(e).removeClass("open")}function new_dplayer(){var t=".new-dplayer:not(.dplayer-initialized),[data-dplayer]:not(.dplayer-initialized)";$(t).length&&$(t).each(function(){var t=$(this);get_new_dplayer(t,function(e){t.addClass("dplayer-initialized").siblings(".dplayer-featured").find(".switch-video").each(function(){var t=$(this),a=t.attr("video-url"),i=t.attr("video-pic");t.data({"video-url":a,"video-pic":i}),t.attr({"dplayer-id":e.container.id}),setTimeout(function(){t.removeAttr("video-url").removeAttr("video-pic")},50)})})})}function get_new_dplayer(t,e){var a={},i=t.attr("video-url")||t.data("video-url"),n=t.attr("data-volume"),o=parseInt((Math.random()+1)*Math.pow(10,4));if(!t.find(".dplayer-video-wrap").length&&i){t.attr("id","dplayer-"+o),a.container=document.getElementById("dplayer-"+o),a.theme="#f04494",a.video={url:i,pic:t.attr("video-pic")||"",type:t.attr("video-type")||"auto"},t.attr("data-loop")&&(a.loop=!0),t.attr("data-autoplay")&&(a.autoplay=!0),n&&n<1&&(a.volume=n),"none"===n&&(a.volume=0);var r=t.attr("video-option");if(r){try{r=JSON.parse(r)}catch(t){console.log(t)}$.extend(a,r)}var s=i.toLowerCase();return-1!=s.indexOf(".m3u")&&_win.dplayer.tbquire.push("hls"),-1!=s.indexOf(".mpd")&&_win.dplayer.tbquire.push("dash"),-1!=s.indexOf(".flv")&&_win.dplayer.tbquire.push("flv"),$("link#dplayer").length||$("dplayer").append('<link type="text/css" id="dplayer" rel="stylesheet" href="'+_win.uri+"/css/dplayer.min.css?ver="+_win.ver+'">'),_win.dplayer.tbquire.push("dplayer"),tbquire(_win.dplayer.tbquire,function(){try{var i=new DPlayer(a);i.on("play",function(){_win.dplayer.play=i}),t.data("dplayer",i),_win.dplayer.obj[o]=i,t.attr({"video-url":"","video-pic":""}),$.isFunction(e)&&e(i)}catch(t){console.error(t)}}),o}}function thumb_dplayer(t,e){function a(t,e,a){e.find(".dplayer-thumb").removeClass(c),_win.dplayer.thumb_play=a,e.find(".progress").show(),t.addClass(d)}function i(t,e,a){a.pause(),e.find(".dplayer-thumb").addClass(c),_win.dplayer.thumb_play=!1,e.find(".progress").hide(),t.removeClass(d)}function n(){if(_win.dplayer.thumb_play){var a=$(_win.dplayer.thumb_play.container).closest(e),n=a.closest(t);i(n,a,_win.dplayer.thumb_play)}}function o(){function t(t){t.on("loadeddata",function(){setTimeout(function(){n.find(".progress-bar").css({width:"100%",opacity:"0",transition:"width .2s, opacity .3s .3s"})},100),setTimeout(function(){n.find(".progress").remove()},800)}),setTimeout(function(){a(i,n,t),t.play()},200)}var i=$(this),n=i.find(e);if(n.length){var o=n.find(".dplayer-thumb").data("dplayer");if(o)return a(i,n,o),o.play();if(!n.find(".dplayer-thumb").length){var r=n.attr("video-url"),s=n.attr("data-volume")||"none",l="",d=~~n.attr("scale-height"),c='<div class="progress progress-striped active progress-abs-bottom"><div class="progress-bar progress-bar-success"></div></div>',u=$('<div class="dplayer-thumb-hide new-dplayer dplayer-thumb controller-hide'+(d?" dplayer-scale-height":"")+'"'+(d?' style="--scale-height:'+d+'%;"':"")+' data-loop="true" data-volume="'+s+'" data-hide="true" video-url="'+r+'" video-pic="'+l+'" video-type="auto"></div>');n.find(".video-thumb").html(u).after(c),setTimeout(function(){n.find(".progress-bar").css({transition:"width 6s",width:"80%"})},50),n.attr("video-url",""),get_new_dplayer(u,t)}}}var r=$("body"),s="thumb_dplayer_data",l=r.data(s)||{};if(!l[t+e]){var d="thumb-dplayer-playing",c="dplayer-thumb-hide";r.on("mouseenter touchstart",t,o),r.on("mouseleave",t,n);var u="thumb_dplayer_init";r.data(u)||r.on("touchstart",function(t){var e=$(t.target);!e.parents("."+d).length&&_win.dplayer.thumb_play&&n()}).data(u,!0),l[t+e]=!0,r.data(s,l)}}function new_swiper(){$(".swiper-scroll:not(.swiper-container-initialized),.new-swiper:not(.swiper-container-initialized),.swiper-tab:not(.swiper-container-initialized)").length&&($("link#swiper").length||$("head").append('<link type="text/css" id="swiper" rel="stylesheet" href="'+_win.uri+"/css/swiper.min.css?ver="+_win.ver+'">'),tbquire(["swiper"],function(){$(".swiper-scroll").each(function(t){if(!$(this).hasClass("swiper-container-initialized")){var e={},a=$(this),i="swiper-scroll-eq-"+t,n=a.attr("data-slideClass")||!1;if(n&&(e.slideClass=n),!a.attr("scroll-nogroup")){var o=a.width(),r=a.find(".swiper-wrapper>*:eq(0)").outerWidth(),s=~~(o/r);e.slidesPerGroup=s||1}e.autoplay=!!a.attr("data-autoplay")&&{delay:~~a.attr("data-interval")||4e3,disableOnInteraction:!1},e.loop=a.attr("data-loop"),e.slidesPeLine truncated
|
||||
;(!o&&f||!a||!t[tt]("src")&&!t.srcset||t.complete||dt(t,n.errorClass)||!dt(t,n.lazyClass))&&(e=ft(t,"lazyunveilread").detail,o&&xt.updateElem(t,!0,t.offsetWidth),t._lazyRace=!0,A++,P(t,e,o,i,a))}},R=_t(function(){n.loadMode=3,L()}),B=function(){3==n.loadMode&&(n.loadMode=2),R()},U=function(){f||(a.now()-v<999?at(U,999):(f=!0,n.loadMode=3,L(),et("scroll",B,!0)))},{_:function(){v=a.now(),i.elements=e.getElementsByClassName(n.lazyClass),h=e.getElementsByClassName(n.lazyClass+" "+n.preloadClass),et("scroll",L,!0),et("resize",L,!0),et("pageshow",function(t){if(t.persisted){var a=e.querySelectorAll("."+n.loadingClass);a.length&&a.forEach&&it(function(){a.forEach(function(t){t.complete&&N(t)})})}}),t.MutationObserver?new MutationObserver(L).observe(Q,{childList:!0,subtree:!0,attributes:!0}):(Q[K]("DOMNodeInserted",L,!0),Q[K]("DOMAttrModified",L,!0),setInterval(L,999)),et("hashchange",L,!0),["focus","mouseover","click","load","transitionend","animationend"].forEach(function(t){e[K](t,L,!0)}),/d$|^c/.test(e.readyState)?U():(et("load",U),e[K]("DOMContentLoaded",L),at(U,2e4)),i.elements.length?(M(),gt._lsFlush()):L()},checkElems:L,unveil:N,_aLSL:B}),xt=(X=wt(function(t,e,a,i){var n,o,r;if(t._lazysizesWidth=i,i+="px",t.setAttribute("sizes",i),ot.test(e.nodeName||""))for(n=e.getElementsByTagName("source"),o=0,r=n.length;o<r;o++)n[o].setAttribute("sizes",i);a.detail.dataAttr||pt(t,a.detail)}),Y=function(t,e,a){var i,n=t.parentNode;n&&(a=vt(t,n,a),i=ft(t,"lazybeforesizes",{width:a,dataAttr:!!e}),i.defaultPrevented||(a=i.detail.width,a&&a!==t._lazysizesWidth&&X(t,n,i,a)))},G=function(){var t,e=V.length;if(e)for(t=0;t<e;t++)Y(V[t])},J=_t(G),{_:function(){V=e.getElementsByClassName(n.autosizesClass),et("resize",J)},checkElems:J,updateElem:Y}),$t=function(){!$t.i&&e.getElementsByClassName&&($t.i=!0,xt._(),yt._())};return at(function(){n.init&&$t()}),i={cfg:n,autoSizer:xt,loader:yt,init:$t,uP:pt,aC:ct,rC:ut,hC:dt,fire:ft,gW:vt,rAF:gt},i}),$.fn.minitouch=function(t){var e="minitouch-isload",a=$(this);if(!a.data(e)){t=$.extend({direction:"bottom",selector:"",start_selector:"",depreciation:50,stop:!1,onStart:!1,onIng:!1,onEnd:!1,inEnd:!1},t);var i=!1,n=t.depreciation,o=0,r=0,s=0,l=0,d=0,c=0,u=0,h=!1,f=function(t,e,a,i,n){var o,r,s;i&&(e+="px",a+="px",o="translate3D("+e+","+a+" , 0)",r={},s=p(),r[s+"transform"]=o,r[s+"transition"]=s+"transform 0s linear",r.cursor=n,"null"==i&&(r[s+"transform"]="",r[s+"transition"]=""),t.css(r))},p=function(){var t=document.body||document.documentElement;return t=t.style,""==t.WebkitTransition?"-webkit-":""==t.MozTransition?"-moz-":""==t.OTransition?"-o-":""==t.transition?"":void 0},m=t.start_selector||t.selector;a.on("touchstart pointerdown MSPointerDown",m,function(t){o=r=s=l=d=c=u=0,o=t.originalEvent.pageX||t.originalEvent.touches[0].pageX,r=t.originalEvent.pageY||t.originalEvent.touches[0].pageY,h=!0,$(t.target).parentsUntil(m,".swiper-container,.scroll-x").length&&(h=!1)}).on("touchmove pointermove MSPointerMove",m,function(e){var n=t.start_selector?t.selector?a.find(t.selector):a.find(t.start_selector):$(this);$.isFunction(t.stop)&&(i=t.stop(a,n,o,r)),h&&!i&&(s=e.originalEvent.pageX||e.originalEvent.touches[0].pageX,l=e.originalEvent.pageY||e.originalEvent.touches[0].pageY,c=s-o,u=l-r,d=180*Math.atan2(u,c)/Math.PI,"right"==t.direction&&(u=0,c=d>-40&&d<40&&c>0?c:0),"left"==t.direction&&(u=0,c=(d>150||d<-150)&&0>c?c:0),"top"==t.direction&&(c=0,u=d>-130&&d<-50&&0>u?u:0),"bottom"==t.direction&&(c=0,u=d>50&&d<130&&u>0?u:0),0===c&&0===u||(e.preventDefault?e.preventDefault():e.returnValue=!1,f(n,c,u,h,"grab"),$.isFunction(t.onIng)&&t.onIng(a,n,c,u)))}).on("touchend touchcancel pointerup MSPointerUp",m,function(){var e=t.start_selector?t.selector?a.find(t.selector):a.find(t.start_selector):$(this);h&&!i&&(f(e,0,0,"null",""),$.isFunction(t.inEnd)&&t.inEnd(a,e,c,u),(Math.abs(c)>n||Math.abs(u)>n)&&$.isFunction(t.onEnd)&&t.onEnd(a,e,c,u),o=r=s=l=d=c=u=0,h=!1)}).data(e,!0)}},_win.bd=$("body"),_win.window=$(window),_win.is_signin=!!_win.bd.hasClass("logged-in");var _wid=_win.window.width(),_hei=_win.window.height();if(_win.bd.on("click","[data-close]",function(){var t=$(this).attr("data-close");return $(t).removeClass("show in"),!1}),_win.bd.on("click","[data-toggle-class]",function(){var t=$(this).attr("data-toggle-class")||"show",e=$(this).attr("data-target")||this;return $(e).toggleClass(t).trigger("toggleClass"),!1}),_win.bd.on("click",only_drop),_win.bd.on("toggleClass",".dropup,.dropdown",only_drop),_win.bd.on("click",".alert-dismissible > .close",function(){$(this).parent().slideUp()}),_win.bd.on("click","[data-onclick]",function(){var t=$(this).attr("data-onclick");return $(t).click()}),$.fn.OnlyOn=function(t,e,a,i){var n=/\S+/g,o=!1;t=t.match(n)[0];var r=$._data(this[0],"events");r&&void 0!==r.type&&$.each(r[t],function(t,i){if(i.selector==e&&i.data==a)return o=!0,!1}),o?console.log("事件重复绑定{type:"+t+",selector:"+e+",data:"+a+"}"):this.on(t,e,a,i)},$.fn.aksrt_ajax=function(t,e,a,i){rLine truncated
|
||||
;e.val().length<1?r.html("").hide():n>i?(t=e.attr("warning-max")||aksrt__("input_max"),r.html(t.replace("1$",i)).fadeIn(150)):n<a?(t=e.attr("warning-min")||aksrt__("input_min"),r.html(t.replace("1$",a)).fadeIn(150)):r.fadeOut(150)},500)),$.fn.AutoSearch=function(){return this.each(function(){function t(){var t={},e=a.serializeObject();$.each(e,function(e,a){t[e]=a}),a.find("input[name]").each(function(){var e=$(this),a=e.val()||"";t[e.attr("name")]=a}),a.addClass(s),u.html(v),h.html(m),c.css({height:c.outerHeight(),overflow:"hidden"}),$.post(i,t,function(t){var e=t.data;e&&c.html('<div class="'+d+'">'+e+"</div>").animate({height:c.children("."+d).outerHeight()},200,"swing",function(){c.css({height:"",overflow:"",transition:""})}),a.removeClass(s),u.html(t.remind||""),h.html(f),auto_fun()},"json")}function e(e){e.val().length>=n?t():u.html(p)}var a=$(this),i=a.attr("ajax-url")||_win.ajax_url,n=2,o="search-",r="."+o,s=o+"loading",l=r+"input",d=o+"centent",c=a.find(r+"container"),u=a.find(r+"remind"),h=a.find(r+"icon"),f=h.html(),p=aksrt_sprintf("search_min_chars",n),m='<i class="loading em12"></i>',v=m+'<span class="ml6">'+aksrt__("search_loading")+"</span>",g="is-on";a.data(g)||a.data(g,!0).find(l).on("input",debounce(function(){e($(this))},500)).on("keydown",function(t){13==t.keyCode&&(t.preventDefault(),e($(this)))})})},_win.bd.on("click",".main-search [data-for]",function(){var t=$(".main-search").find(".scale-placeholder");t.length&&t.text(t.attr("default"))}),_win.bd.on("submit",".main-search form",function(){var t=$(this),e=t.serializeObject();$.each(e,function(e,a){a&&"null"!=a||"s"==e||t.find('input[name="'+e+'"]').remove()})}),_win.bd.on("click",".main-search-btn",function(){var t=$(this),e=$(".main-search form");if($(".main-search").addClass("show"),e.length){var a="search-",i={type:t.attr(a+"type"),user:t.attr(a+"user"),trem:t.attr(a+"trem")};$.each(i,function(a,i){if(i){var n=e.find('input[name="'+a+'"]').val(i),o=e.find('[data-for="'+a+'"][data-value="'+i+'"]').click();if(!o.length&&"trem"==a){var r=t.attr("trem-name"),s=e.find(".cat-drop");r&&s.length&&(s.append('<li data-for="trem" data-value="'+i+'"><a href="javascript:;">'+r+"</a></li>"),s.find('[data-value="'+i+'"]').click())}n.length||e.append('<input type="hidden" name="'+a+'" value="'+i+'">')}});var n=t.attr(a+"placeholder")||e.find(".scale-placeholder").attr("default");e.find(".scale-placeholder").text(n),setTimeout(function(){e.find('[name="s"]').focus()},100)}}),$(".search-page-ajaxpager").length&&(_win.bd.on("click",".page-search-box a.search_keywords",function(){var t=$(this).clone();return t.addClass("ajax-next").attr("ajax-replace","true").attr("route","true"),$(".search-page-ajaxpager").append(t),t.click().remove(),!1}),_win.bd.on("submit",".page-search-box .search-form",function(){var t=$(this),e=t.serializeObject(),a=new URL(t.attr("action"));a.search=new URLSearchParams(e).toString();var i=$('<a class="ajax-next" ajax-replace="1" route="1" href="'+a.href+'"></a>');return $(".search-page-ajaxpager").append(i),i.click().remove(),!1})),window.debounce_notyf=debounce(notyf,100,!0),_win.bd.on("click",".noty1",function(){notyf_close($(this))}),_win.passw=1,_win.bd.on("click",".passw",function(){var t=$(this);1==_win.passw?(t.find(".fa").addClass("fa-eye-slash"),t.siblings("input").attr("type","text"),_win.passw=2):(t.find(".fa").removeClass("fa-eye-slash"),t.siblings("input").attr("type","password"),_win.passw=1)}),_win.bd.on("input change focus",".line-form-input",debounce(function(){placeholder_scale($(this))},100)),$.fn.serializeObject=function(){var t={},e=this.serializeArray();return $.each(e,function(){void 0!==t[this.name]?(t[this.name].push||(t[this.name]=[t[this.name]]),t[this.name].push(this.value||"")):t[this.name]=this.value||""}),t},_win.bd.on("click",".trash-history-search",function(){1==confirm(aksrt__("confirm_clear_search"))&&($(".history-search").slideUp().delay(1e3,function(){$(this).remove()}),$.cookie("history_search",""))}),_win.bd.on("click",".initiate-checkin",function(){aksrt_ajax($(this),0,function(t){t.details_link&&$(".initiate-checkin").each(function(){var e=$(t.details_link),a=$(this),i=a.attr("class"),n=a.attr("ed-text");e.addClass(i).removeClass("initiate-checkin").html(n),a.prop("outerHTML",e.prop("outerHTML"))})},aksrt__("checkin_loading"))}),_win.bd.on("click",".single-pay-tabbar",function(){scrollTo("#posts-pay",-50),$("#posts-pay .cashier-link").click()}),_win.bd.on("submit","[ajax-submit]",function(){var t=$(this),e=t.attr("ajax-submit")||'.wp-ajax-submit,[zibajax="submit"]';return t.find(e).click(),!1}),_win.bd.on("click",'.wp-ajax-submit,[zibajax="submit"]',function(){var t=$(this),e=t.attr("data-confirm");return!(e&&!confirm(e))&&(aksrt_ajax($(this)),!1)}),_win.bd.on("aksrt_ajax.success","[next-tab]",function(t,e){var a=$(this).attr("next-tab");a&&e&&!e.error&&$('a[href="#'+a+'"]').tab("show")}),$(".erphp-login-must").each(function(){$(this).addClass("signin-loader")}),_win.window.resize(debLine truncated
|
||||
jQuery.cookie=function(t,e,a){if(e===void 0){var i=null;if(document.cookie&&document.cookie!="")for(var n=document.cookie.split(";"),r=0;r<n.length;r++){var o=jQuery.trim(n[r]);if(o.substring(0,t.length+1)==t+"="){i=decodeURIComponent(o.substring(t.length+1));break}}return i}a=a||{},e===null&&(e="",a.expires=-1);var s="";if(a.expires&&(typeof a.expires=="number"||a.expires.toUTCString)){var d;typeof a.expires=="number"?(d=new Date,d.setTime(d.getTime()+24*a.expires*60*60*1e3)):d=a.expires,s="; expires="+d.toUTCString()}var c=a.path?"; path="+a.path:"",u=a.domain?"; domain="+a.domain:"",l=a.secure?"; secure":"";document.cookie=[t,"=",encodeURIComponent(e),s,c,u,l].join("")};var lcs={get:function(t){return window.localStorage?localStorage.getItem(t):$.cookie(t)},set:function(t,e){window.localStorage?localStorage[t]=e:$.cookie(t,e)},remove:function(t){window.localStorage?localStorage.removeItem(t):$.cookie(t,"")}};function aksrt__(t){var e=window._win&&window._win.i18n;return e&&Object.prototype.hasOwnProperty.call(e,t)?e[t]:t}function aksrt_is_fatal_error_response(t){return t&&(t.indexOf("Fatal error")>-1||t.indexOf("\u81F4\u547D\u9519\u8BEF")>-1)}function aksrt_sprintf(t){var e=Array.prototype.slice.call(arguments,1),a=aksrt__(t),i=0;return a.replace(/%(\d+\$)?s/g,function(n,r){var o=r?parseInt(r,10)-1:i++;return e[o]!==void 0&&e[o]!==null?e[o]:n})}(function(t,e){var a=e(t,t.document,Date);t.lazySizes=a,typeof module=="object"&&module.exports&&(module.exports=a)})(typeof window<"u"?window:{},function(e,a,i){"use strict";var n,r;if((function(){var w,g={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",loadafterClass:"lazyloadafter",errorClass:"lazyerror",autosizesClass:"lazyautosizes",srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};r=e.lazySizesConfig||e.lazysizesConfig||{};for(w in g)w in r||(r[w]=g[w])})(),!a||!a.getElementsByClassName)return{init:function(){},cfg:r,noSupport:!0};var o=a.documentElement,s=e.HTMLPictureElement,d="addEventListener",c="getAttribute",u=e[d].bind(e),l=e.setTimeout,f=e.requestAnimationFrame||l,h=e.requestIdleCallback,p=/^picture$/i,_=["load","error","lazyincluded","_lazyloaded"],v={},y=Array.prototype.forEach,b=function(w,g){return v[g]||(v[g]=new RegExp("(\\s|^)"+g+"(\\s|$)")),v[g].test(w[c]("class")||"")&&v[g]},C=function(w,g){b(w,g)||w.setAttribute("class",(w[c]("class")||"").trim()+" "+g)},k=function(w,g){var j;(j=b(w,g))&&w.setAttribute("class",(w[c]("class")||"").replace(j," "))},z=function(w,g,j){var L=j?d:"removeEventListener";j&&z(w,g),_.forEach(function(O){w[L](O,g)})},S=function(w,g,j,L,O){var T=a.createEvent("Event");return j||(j={}),j.instance=n,T.initEvent(g,!L,!O),T.detail=j,w.dispatchEvent(T),T},W=function(w,g){var j;!s&&(j=e.picturefill||r.pf)?(g&&g.src&&!w[c]("srcset")&&w.setAttribute("srcset",g.src),j({reevaluate:!0,elements:[w]})):g&&g.src&&(w.src=g.src)},G=function(w,g){return(getComputedStyle(w,null)||{})[g]},tt=function(w,g,j){for(j=j||w.offsetWidth;j<r.minSize&&g&&!w._lazysizesWidth;)j=g.offsetWidth,g=g.parentNode;return j},J=(function(){var w,g,j=[],L=[],O=j,T=function(){var E=O;for(O=j.length?L:j,w=!0,g=!1;E.length;)E.shift()();w=!1},M=function(E,q){w&&!q?E.apply(this,arguments):(O.push(E),g||(g=!0,(a.hidden?l:f)(T)))};return M._lsFlush=T,M})(),Q=function(w,g){return g?function(){J(w)}:function(){var j=this,L=arguments;J(function(){w.apply(j,L)})}},mt=function(w){var g,j=0,L=r.throttleDelay,O=r.ricTimeout,T=function(){g=!1,j=i.now(),w()},M=h&&O>49?function(){h(T,{timeout:O}),O!==r.ricTimeout&&(O=r.ricTimeout)}:Q(function(){l(T)},!0);return function(E){var q;(E=E===!0)&&(O=33),!g&&(g=!0,q=L-(i.now()-j),q<0&&(q=0),E||q<9?M():l(M,q))}},lt=function(w){var g,j,L=99,O=function(){g=null,w()},T=function(){var M=i.now()-j;M<L?l(T,L-M):(h||O)(O)};return function(){j=i.now(),g||(g=l(T,L))}},dt=(function(){var w,g,j,L,O,T,M,E,q,P,D,K,gt=/^img$/i,_t=/^iframe$/i,wt="onscroll"in e&&!/(gle|ing)bot/.test(navigator.userAgent),bt=0,it=0,B=0,at=-1,ct=function(m){B--,(!m||B<0||!m.target)&&(B=0)},ut=function(m){return K==null&&(K=G(a.body,"visibility")=="hidden"),K||!(G(m.parentNode,"visibility")=="hidden"&&G(m,"visibility")=="hidden")},yt=function(m,x){var A,H=m,I=ut(m);for(E-=x,D+=x,q-=x,P+=x;I&&(H=H.offsetParent)&&H!=a.body&&H!=o;)I=(G(H,"opacity")||1)>0,I&&G(H,"overflow")!="visible"&&(A=H.getBoundingClientRect(),I=P>A.left&&q<A.right&&D>A.top-1&&E<A.bottom+1);return I},ft=function(){var m,x,A,H,I,F,U,V,Y,X,Z,et,R=n.elements;if((L=r.loadMode)&&B<8&&(m=R.length)){for(x=0,at++;x<m;x++)if(!(!R[x]||R[x]._lazyRace)){if(!wt||n.prematureUnveil&&n.prematureUnveil(R[x])){rt(R[x]);continue}if((!(V=R[x][c]("data-expand"))||!(F=V*1))&&(F=it),X||(X=!r.expand||r.expand<1?o.clientHeight>500&&o.clientWidth>500?500:370:r.expand,n._defEx=X,Z=X*r.expFactor,et=r.hFac,K=null,it<Z&&B<1&&at>2&&L>2&&!a.hidden?(it=Z,aLine truncated
|
||||
@@ -1,90 +0,0 @@
|
||||
$('.sign form').keydown(function (e) {
|
||||
var e = e || event,
|
||||
keycode = e.which || e.keyCode;
|
||||
if (keycode == 13) {
|
||||
$(this).find('.signsubmit-loader').trigger('click');
|
||||
}
|
||||
});
|
||||
|
||||
//输入检测
|
||||
_win.bd.on('input porpertychange', 'input[change-show]', function () {
|
||||
var _this = $(this);
|
||||
var val = _this.val();
|
||||
if (val.length > 5) {
|
||||
var e = _this.attr('change-show') || '.change-show';
|
||||
_this.parents('form').find(e).slideDown();
|
||||
}
|
||||
});
|
||||
|
||||
/**发送验证码 */
|
||||
_win.bd.on('click', '.captchsubmit', function () {
|
||||
_this = $(this);
|
||||
_win.captchsubmit_wait = 60;
|
||||
var _text = _this.html();
|
||||
var captchsubmit = function () {
|
||||
aksrt_ajax(_this, 0, function (n) {
|
||||
n.error || captchdown();
|
||||
if (n.remaining_time) {
|
||||
_win.captchsubmit_wait = n.remaining_time;
|
||||
captchdown();
|
||||
}
|
||||
});
|
||||
return !1;
|
||||
};
|
||||
|
||||
var captchdown = function () {
|
||||
var _captchsubmit = $('.captchsubmit');
|
||||
if (_win.captchsubmit_wait > 0) {
|
||||
_captchsubmit.html(aksrt_sprintf('captcha_resend_in', _win.captchsubmit_wait)).attr('disabled', !0);
|
||||
_win.captchsubmit_wait--;
|
||||
setTimeout(captchdown, 1000);
|
||||
} else {
|
||||
_captchsubmit.html(_text).attr('disabled', !1);
|
||||
_win.captchsubmit_wait = 60;
|
||||
}
|
||||
};
|
||||
|
||||
captchsubmit();
|
||||
});
|
||||
|
||||
//提交
|
||||
_win.bd.on('click', '.signsubmit-loader', function () {
|
||||
var _this = $(this);
|
||||
var _user_agreement = _this.parent().find('[name="user_agreement"]');
|
||||
|
||||
if (_user_agreement.length && !_user_agreement.is(':checked')) {
|
||||
var _user_agreement_box = _user_agreement.parent();
|
||||
_user_agreement_box.addClass('ani shake');
|
||||
setTimeout(function () {
|
||||
_user_agreement_box.removeClass('ani shake');
|
||||
}, 400);
|
||||
return notyf(aksrt__('agree_terms_first'), 'danger'), !1;
|
||||
}
|
||||
|
||||
aksrt_ajax($(this), 0, function (n) {
|
||||
n.error || window.location.reload();
|
||||
});
|
||||
return !1;
|
||||
});
|
||||
|
||||
//更换绑定的手机号或者邮箱
|
||||
_win.bd.on('click', '.user-verify-submit', function () {
|
||||
var _this = $(this);
|
||||
var _next = _this.parents('.tab-pane').next('.tab-pane').attr('id');
|
||||
|
||||
aksrt_ajax(_this, 0, function (n) {
|
||||
if (!n.error) {
|
||||
$('a[href="#' + _next + '"]').tab('show');
|
||||
if (_win.captchsubmit_wait) {
|
||||
_win.captchsubmit_wait -= 40;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//邀请码注册
|
||||
_win.bd.on('aksrt_ajax.success', '.invit-code-verify', function (e, n) {
|
||||
if (n && n.code) {
|
||||
$('#tab-signup-signup form').append('<input type="hidden" name="invit_code" value="' + n.code + '">');
|
||||
}
|
||||
});
|
||||
-1
@@ -1 +0,0 @@
|
||||
$(".sign form").keydown(function(i){i=i||event;var t=i.which||i.keyCode;13==t&&$(this).find(".signsubmit-loader").trigger("click")}),_win.bd.on("input porpertychange","input[change-show]",function(){var i=$(this),t=i.val();if(t.length>5){var n=i.attr("change-show")||".change-show";i.parents("form").find(n).slideDown()}}),_win.bd.on("click",".captchsubmit",function(){_this=$(this),_win.captchsubmit_wait=60;var i=_this.html(),t=function(){return aksrt_ajax(_this,0,function(i){i.error||n(),i.remaining_time&&(_win.captchsubmit_wait=i.remaining_time,n())}),!1},n=function(){var t=$(".captchsubmit");_win.captchsubmit_wait>0?(t.html(aksrt_sprintf("captcha_resend_in",_win.captchsubmit_wait)).attr("disabled",!0),_win.captchsubmit_wait--,setTimeout(n,1e3)):(t.html(i).attr("disabled",!1),_win.captchsubmit_wait=60)};t()}),_win.bd.on("click",".signsubmit-loader",function(){var i=$(this),t=i.parent().find('[name="user_agreement"]');if(t.length&&!t.is(":checked")){var n=t.parent();return n.addClass("ani shake"),setTimeout(function(){n.removeClass("ani shake")},400),notyf(aksrt__("agree_terms_first"),"danger"),!1}return aksrt_ajax($(this),0,function(i){i.error||window.location.reload()}),!1}),_win.bd.on("click",".user-verify-submit",function(){var i=$(this),t=i.parents(".tab-pane").next(".tab-pane").attr("id");aksrt_ajax(i,0,function(i){i.error||($('a[href="#'+t+'"]').tab("show"),_win.captchsubmit_wait&&(_win.captchsubmit_wait-=40))})}),_win.bd.on("aksrt_ajax.success",".invit-code-verify",function(i,t){t&&t.code&&$("#tab-signup-signup form").append('<input type="hidden" name="invit_code" value="'+t.code+'">')});
|
||||
@@ -1,427 +0,0 @@
|
||||
/**
|
||||
* AKSRT Sign/Register — 统一认证交互脚本
|
||||
*
|
||||
* 对齐 legacy 的 sign-register.js:
|
||||
* - 短信验证码倒计时(60 秒 + 服务端 remaining_time)
|
||||
* - 手机号注册/登录表单交互
|
||||
* - 人机验证联动
|
||||
* - 密码可见性切换
|
||||
* - 协议勾选校验
|
||||
*/
|
||||
;(() => {
|
||||
'use strict'
|
||||
|
||||
const COUNTDOWN_KEY = 'aksrt_sms_cooldown'
|
||||
const DEFAULT_COOLDOWN = 60
|
||||
const REST_BASE = '/wp-json/aksrt/v1'
|
||||
|
||||
/**
|
||||
* 初始化所有认证页面
|
||||
*/
|
||||
function initAuthPages() {
|
||||
initSmsButtons()
|
||||
initPasswordToggles()
|
||||
initAgreementChecks()
|
||||
initFormValidation()
|
||||
initPhoneAuthTabs()
|
||||
}
|
||||
|
||||
/* =================================================================
|
||||
* SMS 验证码发送 + 倒计时
|
||||
* ================================================================= */
|
||||
|
||||
function initSmsButtons(root) {
|
||||
root = root || document
|
||||
root.querySelectorAll('[data-aksrt-sms-trigger]').forEach(btn => {
|
||||
if (btn.dataset.aksrtSmsInitialized === 'true') return
|
||||
btn.dataset.aksrtSmsInitialized = 'true'
|
||||
const cooldown = parseInt(btn.dataset.cooldown || DEFAULT_COOLDOWN, 10)
|
||||
|
||||
// 恢复页面刷新后的倒计时
|
||||
const stored = sessionStorage.getItem(COUNTDOWN_KEY)
|
||||
if (stored) {
|
||||
const remaining = Math.ceil((parseInt(stored, 10) - Date.now()) / 1000)
|
||||
if (remaining > 0) {
|
||||
startCountdown(btn, remaining)
|
||||
}
|
||||
}
|
||||
|
||||
btn.addEventListener('click', e => {
|
||||
e.preventDefault()
|
||||
if (btn.disabled) return
|
||||
sendSmsCode(btn, cooldown)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function sendSmsCode(btn, cooldown) {
|
||||
const phoneInput = document.querySelector(btn.dataset.aksrtSmsPhone || '[data-aksrt-phone-input]')
|
||||
const phone = phoneInput ? phoneInput.value.trim() : ''
|
||||
|
||||
if (!/^1[3-9]\d{9}$/.test(phone)) {
|
||||
notyf('请输入正确的手机号', 'warning')
|
||||
if (phoneInput) phoneInput.focus()
|
||||
return
|
||||
}
|
||||
|
||||
// 人机验证联动
|
||||
const captchaState = window.AKSRTCaptchaState
|
||||
const scene = btn.dataset.aksrtSmsScene || 'register'
|
||||
if (captchaState && captchaState.scenes && captchaState.scenes[scene]) {
|
||||
captchaState.scenes[scene].verify(() => {
|
||||
doSendSms(btn, phone, cooldown)
|
||||
})
|
||||
} else {
|
||||
doSendSms(btn, phone, cooldown)
|
||||
}
|
||||
}
|
||||
|
||||
function doSendSms(btn, phone, cooldown) {
|
||||
btn.disabled = true
|
||||
const original = btn.textContent
|
||||
btn.textContent = '发送中...'
|
||||
|
||||
const scene = btn.dataset.aksrtSmsScene || 'register'
|
||||
const toastId = scene === 'bind_phone'
|
||||
? 'aksrt-settings-phone-code-toast'
|
||||
: 'aksrt-auth-sms-code-toast'
|
||||
notyf('正在发送验证码…', 'load', '', toastId)
|
||||
|
||||
// 收集人机验证字段
|
||||
const form = btn.closest('form')
|
||||
const captchaData = collectCaptchaFields(form)
|
||||
|
||||
fetch(REST_BASE + '/auth/send-sms-code', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ phone, scene, ...captchaData }),
|
||||
})
|
||||
.then(r => r.json().then(data => ({ ok: r.ok, data })))
|
||||
.then(({ ok, data }) => {
|
||||
if (ok && data.success) {
|
||||
notyf(data.message || '验证码已发送', 'success', 5, toastId)
|
||||
const seconds = (data.data && data.data.remaining_time) || cooldown
|
||||
sessionStorage.setItem(COUNTDOWN_KEY, String(Date.now() + seconds * 1000))
|
||||
startCountdown(btn, seconds)
|
||||
} else {
|
||||
const msg = (data.data && data.data.message) || data.message || '发送失败'
|
||||
notyf(msg, 'danger', 5, toastId)
|
||||
try {
|
||||
const captchaState = window.AKSRTCaptchaState
|
||||
if (captchaState && captchaState.scenes && captchaState.scenes[scene]) {
|
||||
captchaState.scenes[scene].reset()
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
const remaining = data.data && data.data.remaining_time
|
||||
if (remaining && remaining > 0) {
|
||||
sessionStorage.setItem(COUNTDOWN_KEY, String(Date.now() + remaining * 1000))
|
||||
startCountdown(btn, remaining)
|
||||
} else {
|
||||
btn.disabled = false
|
||||
btn.textContent = original
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
notyf('网络错误,请重试', 'danger', 5, toastId)
|
||||
btn.disabled = false
|
||||
btn.textContent = original
|
||||
})
|
||||
}
|
||||
|
||||
function startCountdown(btn, seconds) {
|
||||
let remaining = Math.max(1, Math.floor(seconds))
|
||||
btn.disabled = true
|
||||
btn.textContent = remaining + 's'
|
||||
const timer = setInterval(() => {
|
||||
remaining--
|
||||
if (remaining <= 0) {
|
||||
clearInterval(timer)
|
||||
btn.disabled = false
|
||||
btn.textContent = '获取验证码'
|
||||
sessionStorage.removeItem(COUNTDOWN_KEY)
|
||||
} else {
|
||||
btn.textContent = remaining + 's'
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
/* =================================================================
|
||||
* 手机号注册/登录表单
|
||||
* ================================================================= */
|
||||
|
||||
function initPhoneAuthTabs() {
|
||||
document.querySelectorAll('[data-aksrt-auth-tab]').forEach(tab => {
|
||||
tab.addEventListener('click', e => {
|
||||
e.preventDefault()
|
||||
const target = tab.dataset.aksrtAuthTab
|
||||
switchAuthTab(target)
|
||||
})
|
||||
})
|
||||
|
||||
// 手机号注册表单
|
||||
const phoneRegForm = document.getElementById('aksrt-phone-register-form')
|
||||
if (phoneRegForm) {
|
||||
phoneRegForm.addEventListener('submit', e => {
|
||||
e.preventDefault()
|
||||
handlePhoneRegister(phoneRegForm)
|
||||
})
|
||||
}
|
||||
|
||||
// 手机号登录表单
|
||||
const phoneLoginForm = document.getElementById('aksrt-phone-login-form')
|
||||
if (phoneLoginForm) {
|
||||
phoneLoginForm.addEventListener('submit', e => {
|
||||
e.preventDefault()
|
||||
handlePhoneLogin(phoneLoginForm)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function switchAuthTab(tabName) {
|
||||
document.querySelectorAll('[data-auth-panel]').forEach(panel => {
|
||||
panel.style.display = panel.dataset.authPanel === tabName ? '' : 'none'
|
||||
})
|
||||
document.querySelectorAll('[data-aksrt-auth-tab]').forEach(tab => {
|
||||
tab.classList.toggle('is-active', tab.dataset.aksrtAuthTab === tabName)
|
||||
})
|
||||
}
|
||||
|
||||
function handlePhoneRegister(form) {
|
||||
const phone = form.querySelector('[name="phone"]')?.value?.trim()
|
||||
const code = form.querySelector('[name="code"]')?.value?.trim()
|
||||
const password = form.querySelector('[name="password"]')?.value
|
||||
const confirm = form.querySelector('[name="password_confirm"]')?.value
|
||||
const ref = form.querySelector('[name="ref"]')?.value?.trim()
|
||||
|
||||
if (!phone || !code || !password) {
|
||||
notyf('请填写完整信息', 'warning')
|
||||
return
|
||||
}
|
||||
if (password !== confirm) {
|
||||
notyf('两次密码不一致', 'warning')
|
||||
return
|
||||
}
|
||||
if (password.length < 6) {
|
||||
notyf('密码至少 6 位', 'warning')
|
||||
return
|
||||
}
|
||||
|
||||
const submitBtn = form.querySelector('[type="submit"]')
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = true
|
||||
submitBtn.textContent = '注册中...'
|
||||
}
|
||||
|
||||
const captchaState = window.AKSRTCaptchaState
|
||||
const doRegister = () => {
|
||||
const captchaData = collectCaptchaFields(form)
|
||||
fetch(REST_BASE + '/auth/phone-register', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ phone, code, password, ref, ...captchaData }),
|
||||
})
|
||||
.then(r => r.json().then(data => ({ ok: r.ok, data })))
|
||||
.then(({ ok, data }) => {
|
||||
if (ok && data.success) {
|
||||
notyf(data.message || '注册成功', 'success')
|
||||
if (data.notice) notyf(data.notice, 'warning')
|
||||
setTimeout(() => {
|
||||
window.location.href = data.redirect || '/'
|
||||
}, 500)
|
||||
} else {
|
||||
notyf(data.message || '注册失败', 'danger')
|
||||
try {
|
||||
if (captchaState && captchaState.scenes && captchaState.scenes.register) {
|
||||
captchaState.scenes.register.reset()
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = false
|
||||
submitBtn.textContent = '注册'
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
notyf('网络错误', 'danger')
|
||||
try {
|
||||
if (captchaState && captchaState.scenes && captchaState.scenes.register) {
|
||||
captchaState.scenes.register.reset()
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = false
|
||||
submitBtn.textContent = '注册'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (captchaState && captchaState.scenes && captchaState.scenes.register) {
|
||||
captchaState.scenes.register.verify(doRegister)
|
||||
} else {
|
||||
doRegister()
|
||||
}
|
||||
}
|
||||
|
||||
function handlePhoneLogin(form) {
|
||||
const phone = form.querySelector('[name="phone"]')?.value?.trim()
|
||||
const password = form.querySelector('[name="password"]')?.value
|
||||
const loginMode = form.querySelector('[name="login_mode"]')?.value || 'password'
|
||||
|
||||
if (!phone) {
|
||||
notyf('请输入手机号', 'warning')
|
||||
return
|
||||
}
|
||||
|
||||
const submitBtn = form.querySelector('[type="submit"]')
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = true
|
||||
submitBtn.textContent = '登录中...'
|
||||
}
|
||||
|
||||
let endpoint, body
|
||||
if (loginMode === 'code') {
|
||||
const code = form.querySelector('[name="code"]')?.value?.trim()
|
||||
if (!code) {
|
||||
notyf('请输入验证码', 'warning')
|
||||
if (submitBtn) { submitBtn.disabled = false; submitBtn.textContent = '登录' }
|
||||
return
|
||||
}
|
||||
endpoint = '/auth/phone-code-login'
|
||||
body = { phone, code }
|
||||
} else {
|
||||
if (!password) {
|
||||
notyf('请输入密码', 'warning')
|
||||
if (submitBtn) { submitBtn.disabled = false; submitBtn.textContent = '登录' }
|
||||
return
|
||||
}
|
||||
endpoint = '/auth/phone-login'
|
||||
body = { phone, password }
|
||||
}
|
||||
|
||||
const captchaState = window.AKSRTCaptchaState
|
||||
const doLogin = () => {
|
||||
const captchaData = collectCaptchaFields(form)
|
||||
fetch(REST_BASE + endpoint, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ ...body, ...captchaData }),
|
||||
})
|
||||
.then(r => r.json().then(data => ({ ok: r.ok, data })))
|
||||
.then(({ ok, data }) => {
|
||||
if (ok && data.success) {
|
||||
notyf('登录成功', 'success')
|
||||
setTimeout(() => {
|
||||
window.location.href = data.data?.redirect || '/'
|
||||
}, 500)
|
||||
} else {
|
||||
notyf(data.message || '登录失败', 'danger')
|
||||
if (captchaState && captchaState.scenes && captchaState.scenes.login) {
|
||||
captchaState.scenes.login.reset()
|
||||
}
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = false
|
||||
submitBtn.textContent = '登录'
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
notyf('网络错误', 'danger')
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = false
|
||||
submitBtn.textContent = '登录'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (captchaState && captchaState.scenes && captchaState.scenes.login) {
|
||||
captchaState.scenes.login.verify(doLogin)
|
||||
} else {
|
||||
doLogin()
|
||||
}
|
||||
}
|
||||
|
||||
/* =================================================================
|
||||
* 辅助功能
|
||||
* ================================================================= */
|
||||
|
||||
function collectCaptchaFields(form) {
|
||||
if (!form) return {}
|
||||
const fields = {}
|
||||
const names = [
|
||||
'captcha_verified', 'tencent_ticket', 'tencent_randstr', 'tencent_sid',
|
||||
'cf_turnstile_response', 'geetest_lot_number', 'geetest_captcha_output',
|
||||
'geetest_pass_token', 'geetest_gen_time', 'aliyun_captcha_verify_param'
|
||||
]
|
||||
names.forEach(name => {
|
||||
const el = form.querySelector('[name="' + name + '"]')
|
||||
if (el && el.value) fields[name] = el.value
|
||||
})
|
||||
return fields
|
||||
}
|
||||
|
||||
function initPasswordToggles() {
|
||||
document.querySelectorAll('[data-aksrt-password-toggle]').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const input = btn.closest('.input-wrap')?.querySelector('input')
|
||||
if (!input) return
|
||||
const isPassword = input.type === 'password'
|
||||
input.type = isPassword ? 'text' : 'password'
|
||||
const icon = btn.querySelector('i, svg')
|
||||
if (icon) {
|
||||
if (icon.tagName === 'I') {
|
||||
icon.className = isPassword ? 'fa fas fa-eye-slash' : 'fa fas fa-eye'
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function initAgreementChecks() {
|
||||
document.querySelectorAll('form[data-aksrt-auth-form]').forEach(form => {
|
||||
const checkbox = form.querySelector('[data-aksrt-agreement]')
|
||||
const submitBtn = form.querySelector('[type="submit"]')
|
||||
if (checkbox && submitBtn) {
|
||||
const update = () => { submitBtn.disabled = !checkbox.checked }
|
||||
checkbox.addEventListener('change', update)
|
||||
update()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function initFormValidation() {
|
||||
document.querySelectorAll('form[data-aksrt-auth-form]').forEach(form => {
|
||||
form.addEventListener('submit', e => {
|
||||
const password = form.querySelector('[name="password"]')
|
||||
const confirm = form.querySelector('[name="password_confirm"]')
|
||||
if (password && confirm && password.value !== confirm.value) {
|
||||
e.preventDefault()
|
||||
notyf('两次密码不一致', 'warning')
|
||||
confirm.focus()
|
||||
return
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 初始化
|
||||
if (window.AksrtFrontend && typeof window.AksrtFrontend.register === 'function') {
|
||||
window.AksrtFrontend.register('aksrt-sms-buttons', function(root) {
|
||||
initSmsButtons(root)
|
||||
})
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initAuthPages)
|
||||
} else {
|
||||
initAuthPages()
|
||||
}
|
||||
|
||||
// 暴露给外部
|
||||
window.AKSRTSignRegister = {
|
||||
init: initAuthPages,
|
||||
sendSmsCode,
|
||||
switchAuthTab,
|
||||
}
|
||||
})()
|
||||
Reference in new issue
Block a user