进行了一些小优化
This commit is contained in:
1 parent
10b3e6dd9f
commit
f5c60cd425
5 files changed
+127
-24
No files matched your search
+13
-13
@@ -36,7 +36,7 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function showToast(text, type) {
|
function notify(text, type) {
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
window.notyf(escapeHtml(text), type || 'info');
|
window.notyf(escapeHtml(text), type || 'info');
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
box.dataset.loading = '0';
|
box.dataset.loading = '0';
|
||||||
box.dataset.loaded = '0';
|
box.dataset.loaded = '0';
|
||||||
box.innerHTML = '<button type="button" data-auth-refresh-qr>二维码加载失败,点击重试</button>';
|
box.innerHTML = '<button type="button" data-auth-refresh-qr>二维码加载失败,点击重试</button>';
|
||||||
showToast(error.message, 'danger');
|
notify(error.message, 'danger');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,14 +78,14 @@
|
|||||||
window.setTimeout(function () {
|
window.setTimeout(function () {
|
||||||
request('check-qrcode-login', { token: token }).then(function (result) {
|
request('check-qrcode-login', { token: token }).then(function (result) {
|
||||||
if (result.logged_in) {
|
if (result.logged_in) {
|
||||||
showToast('登录成功', 'success');
|
notify('登录成功', 'success');
|
||||||
window.location.assign(result.redirect || window.location.href);
|
window.location.assign(result.redirect || window.location.href);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result.status === 'expired') {
|
if (result.status === 'expired') {
|
||||||
box.dataset.loaded = '0';
|
box.dataset.loaded = '0';
|
||||||
box.innerHTML = '<button type="button" data-auth-refresh-qr>二维码已过期,点击刷新</button>';
|
box.innerHTML = '<button type="button" data-auth-refresh-qr>二维码已过期,点击刷新</button>';
|
||||||
showToast('二维码已过期,请刷新后重试', 'warning');
|
notify('二维码已过期,请刷新后重试', 'warning');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pollQr(box, token, count + 1);
|
pollQr(box, token, count + 1);
|
||||||
@@ -98,11 +98,11 @@
|
|||||||
var button = form.querySelector('button[type="submit"]');
|
var button = form.querySelector('button[type="submit"]');
|
||||||
if (button) button.disabled = true;
|
if (button) button.disabled = true;
|
||||||
request('weixingzh-code', data).then(function (result) {
|
request('weixingzh-code', data).then(function (result) {
|
||||||
showToast('登录成功', 'success');
|
notify('登录成功', 'success');
|
||||||
window.location.assign(result.redirect || window.location.href);
|
window.location.assign(result.redirect || window.location.href);
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
if (button) button.disabled = false;
|
if (button) button.disabled = false;
|
||||||
showToast(error.message, 'danger');
|
notify(error.message, 'danger');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@
|
|||||||
var form = button.closest('form');
|
var form = button.closest('form');
|
||||||
var target = form && form.querySelector('[name="target"]');
|
var target = form && form.querySelector('[name="target"]');
|
||||||
if (!target || !target.value.trim()) {
|
if (!target || !target.value.trim()) {
|
||||||
showToast('请先填写邮箱或手机号', 'warning');
|
notify('请先填写邮箱或手机号', 'warning');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
button.disabled = true;
|
button.disabled = true;
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
verifyCaptcha(payload.scene, function (verified) {
|
verifyCaptcha(payload.scene, function (verified) {
|
||||||
if (!verified) {
|
if (!verified) {
|
||||||
button.disabled = false;
|
button.disabled = false;
|
||||||
showToast('请先完成人机验证', 'warning');
|
notify('请先完成人机验证', 'warning');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
payload = formData(form);
|
payload = formData(form);
|
||||||
@@ -175,11 +175,11 @@
|
|||||||
payload.target = target.value.trim();
|
payload.target = target.value.trim();
|
||||||
payload.channel = (form.querySelector('[name="channel"]') || {}).value || '';
|
payload.channel = (form.querySelector('[name="channel"]') || {}).value || '';
|
||||||
request('code', payload).then(function (result) {
|
request('code', payload).then(function (result) {
|
||||||
showToast(result.message || '验证码已发送', 'success');
|
notify(result.message || '验证码已发送', 'success');
|
||||||
startCountdown(button, result.countdown || 60);
|
startCountdown(button, result.countdown || 60);
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
button.disabled = false;
|
button.disabled = false;
|
||||||
showToast(error.message, 'danger');
|
notify(error.message, 'danger');
|
||||||
}).finally(function () {
|
}).finally(function () {
|
||||||
resetCaptcha(payload.scene);
|
resetCaptcha(payload.scene);
|
||||||
});
|
});
|
||||||
@@ -194,10 +194,10 @@
|
|||||||
}
|
}
|
||||||
setBusy(form, true);
|
setBusy(form, true);
|
||||||
request(action, payload).then(function (result) {
|
request(action, payload).then(function (result) {
|
||||||
showToast(result.message || '操作成功', 'success');
|
notify(result.message || '操作成功', 'success');
|
||||||
if (result.redirect) window.setTimeout(function () { window.location.assign(result.redirect); }, 350);
|
if (result.redirect) window.setTimeout(function () { window.location.assign(result.redirect); }, 350);
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
showToast(error.message, 'danger');
|
notify(error.message, 'danger');
|
||||||
setBusy(form, false);
|
setBusy(form, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -255,7 +255,7 @@
|
|||||||
function validateForm(form) {
|
function validateForm(form) {
|
||||||
if (!form.checkValidity || form.checkValidity()) return true;
|
if (!form.checkValidity || form.checkValidity()) return true;
|
||||||
var field = form.querySelector(':invalid');
|
var field = form.querySelector(':invalid');
|
||||||
showToast((field && field.validationMessage) || '请完整填写表单', 'warning');
|
notify((field && field.validationMessage) || '请完整填写表单', 'warning');
|
||||||
if (field && typeof field.focus === 'function') field.focus();
|
if (field && typeof field.focus === 'function') field.focus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,79 @@
|
|||||||
tabs[next].click();
|
tabs[next].click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initSwiperA11y(el) {
|
||||||
|
if (el.dataset.autoplay !== '1' || !once(el, 'SwiperA11y')) return;
|
||||||
|
var i18n = config.i18n || {};
|
||||||
|
var userPaused = reducedMotion;
|
||||||
|
var focusPaused = false;
|
||||||
|
var button = document.createElement('button');
|
||||||
|
button.type = 'button';
|
||||||
|
button.className = 'aksrt-widget-swiper__pause';
|
||||||
|
|
||||||
|
function setControlState() {
|
||||||
|
button.setAttribute('aria-pressed', userPaused ? 'true' : 'false');
|
||||||
|
button.setAttribute('aria-label', userPaused ? (i18n.resume || '继续自动播放') : (i18n.pause || '暂停自动播放'));
|
||||||
|
button.textContent = userPaused ? '▶' : 'Ⅱ';
|
||||||
|
}
|
||||||
|
|
||||||
|
function autoplay() {
|
||||||
|
return el.swiper && el.swiper.autoplay ? el.swiper.autoplay : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopAutoplay() {
|
||||||
|
var runtime = autoplay();
|
||||||
|
if (runtime && typeof runtime.stop === 'function') runtime.stop();
|
||||||
|
setControlState();
|
||||||
|
}
|
||||||
|
|
||||||
|
function pause() {
|
||||||
|
focusPaused = true;
|
||||||
|
stopAutoplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
function resume() {
|
||||||
|
if (reducedMotion || userPaused || focusPaused) {
|
||||||
|
stopAutoplay();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var runtime = autoplay();
|
||||||
|
if (runtime && typeof runtime.start === 'function') runtime.start();
|
||||||
|
setControlState();
|
||||||
|
}
|
||||||
|
|
||||||
|
button.addEventListener('click', function () {
|
||||||
|
if (userPaused && !reducedMotion) {
|
||||||
|
userPaused = false;
|
||||||
|
resume();
|
||||||
|
} else {
|
||||||
|
userPaused = true;
|
||||||
|
stopAutoplay();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
el.addEventListener('focusin', pause);
|
||||||
|
el.addEventListener('focusout', function () {
|
||||||
|
window.setTimeout(function () {
|
||||||
|
if (el.contains(document.activeElement)) return;
|
||||||
|
focusPaused = false;
|
||||||
|
resume();
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
setControlState();
|
||||||
|
el.appendChild(button);
|
||||||
|
|
||||||
|
var attempts = 0;
|
||||||
|
function connectToSwiper() {
|
||||||
|
if (autoplay()) {
|
||||||
|
if (reducedMotion || userPaused || focusPaused) stopAutoplay();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
attempts += 1;
|
||||||
|
if (attempts < 120) window.requestAnimationFrame(connectToSwiper);
|
||||||
|
}
|
||||||
|
connectToSwiper();
|
||||||
|
}
|
||||||
|
|
||||||
function videoType(url) {
|
function videoType(url) {
|
||||||
if (/\.m3u8(?:\?|$)/i.test(url)) return 'hls';
|
if (/\.m3u8(?:\?|$)/i.test(url)) return 'hls';
|
||||||
if (/\.flv(?:\?|$)/i.test(url)) return 'flv';
|
if (/\.flv(?:\?|$)/i.test(url)) return 'flv';
|
||||||
@@ -257,6 +330,8 @@
|
|||||||
|
|
||||||
function scan(root) {
|
function scan(root) {
|
||||||
var scope = root || document;
|
var scope = root || document;
|
||||||
|
if (scope.matches && scope.matches('.aksrt-widget-swiper')) initSwiperA11y(scope);
|
||||||
|
scope.querySelectorAll('.aksrt-widget-swiper').forEach(initSwiperA11y);
|
||||||
scope.querySelectorAll('.aksrt-widget-video[data-video-url]').forEach(initVideo);
|
scope.querySelectorAll('.aksrt-widget-video[data-video-url]').forEach(initVideo);
|
||||||
scope.querySelectorAll('.aksrt-widget-toc').forEach(initToc);
|
scope.querySelectorAll('.aksrt-widget-toc').forEach(initToc);
|
||||||
scope.querySelectorAll('.aksrt-widget-quote').forEach(initQuote);
|
scope.querySelectorAll('.aksrt-widget-quote').forEach(initQuote);
|
||||||
|
|||||||
@@ -373,17 +373,42 @@ trait BalanceServiceRest {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
$order_number = 'PX' . strtoupper(substr(hash('sha256', $operation_key), 0, 30));
|
if (!class_exists('\\AKSRT\\Payment\\OrderRepository')) {
|
||||||
$business_mutation = static function (int $transaction_id) use ($user_id, $amount, $points, $operation_key, $order_number) {
|
return new \WP_Error('aksrt_order_unavailable', __('订单服务不可用', 'aksrt'), ['status' => 500]);
|
||||||
if (!class_exists('\\AKSRT\\Payment\\OrderRepository')) {
|
}
|
||||||
return new \WP_Error('aksrt_order_unavailable', __('订单服务不可用', 'aksrt'), ['status' => 500]);
|
$note = wp_json_encode([
|
||||||
|
'points_exchange' => 1,
|
||||||
|
'points' => $points,
|
||||||
|
'product_title' => sprintf(__('购买 %d 积分', 'aksrt'), $points),
|
||||||
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
$repo = \AKSRT\Payment\OrderRepository::get_instance();
|
||||||
|
$existing_order = $repo->get_by_request_key($operation_key);
|
||||||
|
$is_new_order = !is_array($existing_order);
|
||||||
|
if (is_array($existing_order)) {
|
||||||
|
$existing_meta = json_decode((string) ($existing_order['note'] ?? ''), true);
|
||||||
|
$existing_meta = is_array($existing_meta) ? $existing_meta : [];
|
||||||
|
if ((int) ($existing_order['user_id'] ?? 0) !== $user_id
|
||||||
|
|| sanitize_key((string) ($existing_order['product_type'] ?? '')) !== \AKSRT\Core\DomainModel::ORDER_PRODUCT_POINTS
|
||||||
|
|| (int) ($existing_order['product_id'] ?? 0) !== 0
|
||||||
|
|| (string) ($existing_order['amount'] ?? '') !== $amount->decimal()
|
||||||
|
|| sanitize_key((string) ($existing_order['currency'] ?? '')) !== 'cny'
|
||||||
|
|| sanitize_key((string) ($existing_order['payment_method'] ?? '')) !== 'balance'
|
||||||
|
|| (int) ($existing_meta['points'] ?? 0) !== $points
|
||||||
|
) {
|
||||||
|
return new \WP_Error('aksrt_ledger_idempotency_conflict', __('相同操作标识已用于其他积分购买请求', 'aksrt'), ['status' => 409]);
|
||||||
}
|
}
|
||||||
$note = wp_json_encode([
|
$order_number = (string) ($existing_order['order_number'] ?? '');
|
||||||
'points_exchange' => 1,
|
} else {
|
||||||
'points' => $points,
|
$order_number = $repo->allocate_order_number();
|
||||||
'product_title' => sprintf(__('购买 %d 积分', 'aksrt'), $points),
|
}
|
||||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
if ($order_number === '') {
|
||||||
$created = \AKSRT\Payment\OrderRepository::get_instance()->create([
|
return new \WP_Error('aksrt_order_create_failed', __('积分订单创建失败', 'aksrt'), ['status' => 500]);
|
||||||
|
}
|
||||||
|
$business_mutation = static function (int $transaction_id) use ($is_new_order, $repo, $user_id, $amount, $points, $operation_key, $order_number, $note) {
|
||||||
|
if (!$is_new_order) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$created = $repo->create([
|
||||||
'order_number' => $order_number,
|
'order_number' => $order_number,
|
||||||
'user_id' => $user_id,
|
'user_id' => $user_id,
|
||||||
'product_type' => \AKSRT\Core\DomainModel::ORDER_PRODUCT_POINTS,
|
'product_type' => \AKSRT\Core\DomainModel::ORDER_PRODUCT_POINTS,
|
||||||
|
|||||||
@@ -234,6 +234,9 @@ test('asset purchases share the order center and refresh every wallet surface',
|
|||||||
|
|
||||||
assert.match(balanceRest, /register_rest_route\('aksrt\/v1', '\/pay\/assets'/)
|
assert.match(balanceRest, /register_rest_route\('aksrt\/v1', '\/pay\/assets'/)
|
||||||
assert.match(balanceRest, /'product_type'\s*=>\s*\\AKSRT\\Core\\DomainModel::ORDER_PRODUCT_POINTS/)
|
assert.match(balanceRest, /'product_type'\s*=>\s*\\AKSRT\\Core\\DomainModel::ORDER_PRODUCT_POINTS/)
|
||||||
|
assert.match(balanceRest, /\$existing_order\s*=\s*\$repo->get_by_request_key\(\$operation_key\)/)
|
||||||
|
assert.match(balanceRest, /\$order_number\s*=\s*\$repo->allocate_order_number\(\)/)
|
||||||
|
assert.doesNotMatch(balanceRest, /['"]PX['"]\s*\.|hash\('sha256',\s*\$operation_key\)/)
|
||||||
assert.match(balanceRest, /\['type'\s*=>\s*'order',\s*'key'\s*=>\s*\$order_number\]/)
|
assert.match(balanceRest, /\['type'\s*=>\s*'order',\s*'key'\s*=>\s*\$order_number\]/)
|
||||||
assert.match(balanceRest, /'order_number'\s*=>\s*\$order_number/)
|
assert.match(balanceRest, /'order_number'\s*=>\s*\$order_number/)
|
||||||
assert.match(chargeCard, /self::TYPE_CREDITS[\s\S]*?ORDER_PRODUCT_POINTS/)
|
assert.match(chargeCard, /self::TYPE_CREDITS[\s\S]*?ORDER_PRODUCT_POINTS/)
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ test('shared renderer contracts every configured authentication state', () => {
|
|||||||
assert.match(client, /data-password-show/);
|
assert.match(client, /data-password-show/);
|
||||||
assert.match(client, /pollQr/);
|
assert.match(client, /pollQr/);
|
||||||
assert.match(client, /window\.notyf\(escapeHtml\(text\), type \|\| 'info'\)/);
|
assert.match(client, /window\.notyf\(escapeHtml\(text\), type \|\| 'info'\)/);
|
||||||
assert.match(client, /showToast\('请先完成人机验证', 'warning'\)/);
|
assert.match(client, /notify\('请先完成人机验证', 'warning'\)/);
|
||||||
assert.match(client, /form\.noValidate = true/);
|
assert.match(client, /form\.noValidate = true/);
|
||||||
assert.match(client, /form\.checkValidity\(\)[\s\S]*?field\.validationMessage/);
|
assert.match(client, /form\.checkValidity\(\)[\s\S]*?field\.validationMessage/);
|
||||||
assert.match(client, /window\.location\.assign\(authPageUrl/);
|
assert.match(client, /window\.location\.assign\(authPageUrl/);
|
||||||
|
|||||||
Reference in new issue
Block a user