feat(checkin): open reference-parity details modal from signed buttons
- Rebuild checkin details modal HTML 1:1 with reference theme: colorful header c-blue, user card (points/level), daily reward card and 7-day continuous mini cards - Signed entry buttons (header dropdown, user-card badge, user center) become clickable checkin-details-link modal triggers instead of disabled buttons - Swap data-signin-btn to details link in place after successful signin (reference .initiate-checkin replacement behavior) - Add aksrt-checkin-details-modal runtime shell (modal-mini 400px) - Remove dead code: legacy lite modal, admin-ajax details handler, /signin/history route, signin calendar; rebuild public bundles - Update contract tests to the new checkin modal contract
This commit is contained in:
+19
-39
@@ -3046,10 +3046,8 @@ main.container,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 已签到态对齐参考主题:保留原配色(参考主题签到后仍为同一彩色按钮),
|
/* 已签到态对齐参考主题:保留原配色(参考主题签到后仍为同一彩色按钮),
|
||||||
* 仅禁用指针交互;此前的灰底灰字覆盖是与参考主题的偏差。 */
|
* 且按钮可点击(打开签到详情弹窗);仅请求进行中的禁用态降不透明度。 */
|
||||||
.aksrt-header-checkin.is-done,
|
|
||||||
.aksrt-header-checkin:disabled,
|
.aksrt-header-checkin:disabled,
|
||||||
.aksrt-header-checkin.is-done:hover,
|
|
||||||
.aksrt-header-checkin:disabled:hover {
|
.aksrt-header-checkin:disabled:hover {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
opacity: .85;
|
opacity: .85;
|
||||||
@@ -6269,42 +6267,7 @@ body.aksrt-body-scroll .aksrt-show-on-scroll {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
* 18. 签到日历可视化
|
* 18. VIP 等级标识
|
||||||
* ============================================================ */
|
|
||||||
.aksrt-signin-calendar__grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(7, 1fr);
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aksrt-signin-calendar__day {
|
|
||||||
aspect-ratio: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 6px;
|
|
||||||
background: var(--surface-2, #F4F5F7);
|
|
||||||
font-size: 12px;
|
|
||||||
color: var(--color-ink-3);
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aksrt-signin-calendar__day.is-signed {
|
|
||||||
background: var(--color-success, #10B981);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aksrt-signin-calendar__day.is-today {
|
|
||||||
border: 2px solid var(--color-primary, var(--color-primary));
|
|
||||||
}
|
|
||||||
|
|
||||||
.aksrt-signin-calendar__day.is-signed.is-today {
|
|
||||||
background: var(--color-primary, var(--color-primary));
|
|
||||||
border-color: var(--color-primary, var(--color-primary));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================
|
|
||||||
* 19. VIP 等级标识
|
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
.aksrt-vip-badge {
|
.aksrt-vip-badge {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@@ -7180,6 +7143,23 @@ body.aksrt-modal-runtime-open {
|
|||||||
color: var(--color-on-primary, #fff);
|
color: var(--color-on-primary, #fff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- 签到详情弹窗(参考主题 refresh_modal modal-mini 同构壳) ----
|
||||||
|
内容为服务端 HTML(modal-colorful-header + modal-body),与参考主题
|
||||||
|
.modal-dialog.modal-mini 几何 1:1:宽 400px、圆角 var(--main-radius)。 */
|
||||||
|
.aksrt-modal-runtime.aksrt-checkin-details-modal:not(.aksrt-modal-runtime--bottom) .aksrt-modal-runtime__dialog {
|
||||||
|
width: min(400px, calc(100vw - 32px));
|
||||||
|
border-radius: var(--main-radius, 8px);
|
||||||
|
background: var(--main-bg-color, #fff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.aksrt-modal-runtime.aksrt-checkin-details-modal .aksrt-modal-runtime__content {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aksrt-modal-runtime.aksrt-checkin-details-modal .aksrt-modal-runtime__skeleton {
|
||||||
|
padding: 24px 18px;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- ajax list ---- */
|
/* ---- ajax list ---- */
|
||||||
.ajaxpager.is-ajax-loading {
|
.ajaxpager.is-ajax-loading {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -356,42 +356,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
* 18. 签到日历可视化
|
* 18. VIP 等级标识
|
||||||
* ============================================================ */
|
|
||||||
.aksrt-signin-calendar__grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(7, 1fr);
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aksrt-signin-calendar__day {
|
|
||||||
aspect-ratio: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 6px;
|
|
||||||
background: var(--surface-2, #F4F5F7);
|
|
||||||
font-size: 12px;
|
|
||||||
color: var(--color-ink-3);
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aksrt-signin-calendar__day.is-signed {
|
|
||||||
background: var(--color-success, #10B981);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aksrt-signin-calendar__day.is-today {
|
|
||||||
border: 2px solid var(--color-primary, var(--color-primary));
|
|
||||||
}
|
|
||||||
|
|
||||||
.aksrt-signin-calendar__day.is-signed.is-today {
|
|
||||||
background: var(--color-primary, var(--color-primary));
|
|
||||||
border-color: var(--color-primary, var(--color-primary));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================
|
|
||||||
* 19. VIP 等级标识
|
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
.aksrt-vip-badge {
|
.aksrt-vip-badge {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|||||||
@@ -327,10 +327,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 已签到态对齐参考主题:保留原配色(参考主题签到后仍为同一彩色按钮),
|
/* 已签到态对齐参考主题:保留原配色(参考主题签到后仍为同一彩色按钮),
|
||||||
* 仅禁用指针交互;此前的灰底灰字覆盖是与参考主题的偏差。 */
|
* 且按钮可点击(打开签到详情弹窗);仅请求进行中的禁用态降不透明度。 */
|
||||||
.aksrt-header-checkin.is-done,
|
|
||||||
.aksrt-header-checkin:disabled,
|
.aksrt-header-checkin:disabled,
|
||||||
.aksrt-header-checkin.is-done:hover,
|
|
||||||
.aksrt-header-checkin:disabled:hover {
|
.aksrt-header-checkin:disabled:hover {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
opacity: .85;
|
opacity: .85;
|
||||||
|
|||||||
@@ -223,6 +223,23 @@ body.aksrt-modal-runtime-open {
|
|||||||
color: var(--color-on-primary, #fff);
|
color: var(--color-on-primary, #fff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- 签到详情弹窗(参考主题 refresh_modal modal-mini 同构壳) ----
|
||||||
|
内容为服务端 HTML(modal-colorful-header + modal-body),与参考主题
|
||||||
|
.modal-dialog.modal-mini 几何 1:1:宽 400px、圆角 var(--main-radius)。 */
|
||||||
|
.aksrt-modal-runtime.aksrt-checkin-details-modal:not(.aksrt-modal-runtime--bottom) .aksrt-modal-runtime__dialog {
|
||||||
|
width: min(400px, calc(100vw - 32px));
|
||||||
|
border-radius: var(--main-radius, 8px);
|
||||||
|
background: var(--main-bg-color, #fff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.aksrt-modal-runtime.aksrt-checkin-details-modal .aksrt-modal-runtime__content {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aksrt-modal-runtime.aksrt-checkin-details-modal .aksrt-modal-runtime__skeleton {
|
||||||
|
padding: 24px 18px;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- ajax list ---- */
|
/* ---- ajax list ---- */
|
||||||
.ajaxpager.is-ajax-loading {
|
.ajaxpager.is-ajax-loading {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@@ -241,41 +241,6 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================
|
|
||||||
* 8. 签到日历可视化
|
|
||||||
* ============================================================ */
|
|
||||||
function initSigninCalendar() {
|
|
||||||
var calendar = document.querySelector('[data-aksrt-signin-calendar]');
|
|
||||||
if (!calendar) return;
|
|
||||||
|
|
||||||
var data = [];
|
|
||||||
try {
|
|
||||||
data = JSON.parse(calendar.dataset.aksrtSigninCalendar || '[]');
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
// 生成最近 30 天的格子
|
|
||||||
var today = new Date();
|
|
||||||
var html = '<div class="aksrt-signin-calendar__grid">';
|
|
||||||
|
|
||||||
for (var i = 29; i >= 0; i--) {
|
|
||||||
var d = new Date(today);
|
|
||||||
d.setDate(d.getDate() - i);
|
|
||||||
var dateStr = d.toISOString().split('T')[0];
|
|
||||||
var isSigned = data.indexOf(dateStr) !== -1;
|
|
||||||
var isToday = i === 0;
|
|
||||||
|
|
||||||
html += '<div class="aksrt-signin-calendar__day' +
|
|
||||||
(isSigned ? ' is-signed' : '') +
|
|
||||||
(isToday ? ' is-today' : '') +
|
|
||||||
'" title="' + dateStr + (isSigned ? ' ✓' : '') + '">' +
|
|
||||||
'<span>' + d.getDate() + '</span>' +
|
|
||||||
'</div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '</div>';
|
|
||||||
calendar.innerHTML = html;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
* 初始化入口 — 先执行一次,随后监听 auto_fun 重扫(各 init 幂等)
|
* 初始化入口 — 先执行一次,随后监听 auto_fun 重扫(各 init 幂等)
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
@@ -286,7 +251,6 @@
|
|||||||
initSticky();
|
initSticky();
|
||||||
initParallax();
|
initParallax();
|
||||||
initFloatLabels();
|
initFloatLabels();
|
||||||
initSigninCalendar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.readyState === 'loading') {
|
if (document.readyState === 'loading') {
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -72,6 +72,26 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 签到成功后,入口按钮就地替换为「已签到」详情弹窗触发链接
|
||||||
|
// (参考主题:.initiate-checkin → details_link 的替换行为)。
|
||||||
|
function swapButtonsToDetailsLink() {
|
||||||
|
var url = window.aksrtData && window.aksrtData.signinDetailsUrl;
|
||||||
|
if (!url) return;
|
||||||
|
currentButtons().forEach(function (button) {
|
||||||
|
var link = document.createElement('a');
|
||||||
|
link.href = 'javascript:;';
|
||||||
|
link.className = (button.className || '') + ' checkin-details-link';
|
||||||
|
link.setAttribute('data-aksrt-modal', 'remote');
|
||||||
|
link.setAttribute('data-aksrt-modal-url', url);
|
||||||
|
link.setAttribute('data-aksrt-modal-class', 'aksrt-checkin-details-modal modal-mini');
|
||||||
|
link.setAttribute('data-aksrt-modal-height', '240');
|
||||||
|
link.setAttribute('data-aksrt-modal-mobile-bottom', 'true');
|
||||||
|
link.setAttribute('data-aksrt-modal-cache', 'false');
|
||||||
|
link.innerHTML = button.innerHTML;
|
||||||
|
button.replaceWith(link);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
api('/signin/today').then(function (result) {
|
api('/signin/today').then(function (result) {
|
||||||
if (!result.ok) {
|
if (!result.ok) {
|
||||||
@@ -90,6 +110,7 @@
|
|||||||
if (data.signed) {
|
if (data.signed) {
|
||||||
setStatusHtml('已签到 <strong>' + data.streak + '</strong> 天 +' + data.reward_today);
|
setStatusHtml('已签到 <strong>' + data.streak + '</strong> 天 +' + data.reward_today);
|
||||||
setButtonState('done');
|
setButtonState('done');
|
||||||
|
swapButtonsToDetailsLink();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setStatusHtml('连续 <strong>' + data.streak + '</strong> 天,+' + data.reward_if_signin);
|
setStatusHtml('连续 <strong>' + data.streak + '</strong> 天,+' + data.reward_if_signin);
|
||||||
@@ -120,6 +141,7 @@
|
|||||||
element.title = element.textContent;
|
element.title = element.textContent;
|
||||||
});
|
});
|
||||||
setButtonState('done');
|
setButtonState('done');
|
||||||
|
swapButtonsToDetailsLink();
|
||||||
refresh();
|
refresh();
|
||||||
}).finally(function () {
|
}).finally(function () {
|
||||||
if (window.AKSRTCaptcha) window.AKSRTCaptcha.reset('signin', captchaMount());
|
if (window.AKSRTCaptcha) window.AKSRTCaptcha.reset('signin', captchaMount());
|
||||||
|
|||||||
@@ -7,6 +7,29 @@
|
|||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
if (!function_exists('aksrt_get_user_checkin_details_link')) :
|
||||||
|
/**
|
||||||
|
* 已签到详情弹窗触发链接(参考主题 zib_get_user_checkin_details_link 1:1):
|
||||||
|
* 打开刷新式 mini 弹窗(高 240,移动端底部弹出,每次都重新拉取)。
|
||||||
|
*
|
||||||
|
* @param string $class 沿用入口按钮的类。
|
||||||
|
* @param string $text 链接内文(含图标)。
|
||||||
|
*/
|
||||||
|
function aksrt_get_user_checkin_details_link(string $class = '', string $text = ''): string {
|
||||||
|
$class = trim($class . ' checkin-details-link');
|
||||||
|
|
||||||
|
return '<a class="' . esc_attr($class) . '" href="javascript:;"'
|
||||||
|
. ' data-aksrt-modal="remote"'
|
||||||
|
. ' data-aksrt-modal-url="' . esc_url(rest_url('aksrt/v1/signin/details')) . '"'
|
||||||
|
. ' data-aksrt-modal-class="aksrt-checkin-details-modal modal-mini"'
|
||||||
|
. ' data-aksrt-modal-height="240"'
|
||||||
|
. ' data-aksrt-modal-mobile-bottom="true"'
|
||||||
|
. ' data-aksrt-modal-cache="false">'
|
||||||
|
. $text
|
||||||
|
. '</a>';
|
||||||
|
}
|
||||||
|
endif;
|
||||||
|
|
||||||
if (!function_exists('aksrt_header_user_checkin_btn')) :
|
if (!function_exists('aksrt_header_user_checkin_btn')) :
|
||||||
/**
|
/**
|
||||||
* Check-in CTA for header dropdown and compact card placements.
|
* Check-in CTA for header dropdown and compact card placements.
|
||||||
@@ -31,27 +54,36 @@ if (!function_exists('aksrt_header_user_checkin_btn')) :
|
|||||||
|
|
||||||
$signed = \AKSRT\Credits\Signin::get_instance()->is_signed_today($user_id);
|
$signed = \AKSRT\Credits\Signin::get_instance()->is_signed_today($user_id);
|
||||||
|
|
||||||
|
// 已签到:与参考主题一致,入口按钮变为签到详情弹窗触发链接(可点击)。
|
||||||
|
if ($signed) {
|
||||||
|
$icon = '<i class="fa fas fa-calendar-check ml3 mr6" aria-hidden="true"></i>';
|
||||||
|
if ($class !== null) {
|
||||||
|
// 用户卡片签到书签:保留书签类与 is-done 视觉,仅将行为切换为打开详情弹窗。
|
||||||
|
return aksrt_get_user_checkin_details_link(
|
||||||
|
$class . ' is-done',
|
||||||
|
$icon . '<span>' . esc_html__('已签到', 'aksrt') . '</span>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return aksrt_get_user_checkin_details_link(
|
||||||
|
'but block c-yellow aksrt-header-checkin is-done',
|
||||||
|
'<i class="fa fas fa-calendar-check" aria-hidden="true"></i> ' . esc_html($compact ? __('已签到', 'aksrt') : __('今日已签到', 'aksrt'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$classes = $class ?? ('but block c-yellow aksrt-header-checkin' . ($compact ? ' aksrt-header-checkin--compact' : ''));
|
$classes = $class ?? ('but block c-yellow aksrt-header-checkin' . ($compact ? ' aksrt-header-checkin--compact' : ''));
|
||||||
|
|
||||||
// Card badge variant (explicit $class, e.g. the user-card 签到 badge):
|
// Card badge variant (explicit $class, e.g. the user-card 签到 badge):
|
||||||
// reference parity renders an <a> so the badge inherits the card font
|
// reference parity renders an <a> so the badge inherits the card font
|
||||||
// instead of the UA button stylesheet (font/UI 1:1 with the reference).
|
// instead of the UA button stylesheet (font/UI 1:1 with the reference).
|
||||||
if ($class !== null) {
|
if ($class !== null) {
|
||||||
return '<a class="' . esc_attr($classes . ($signed ? ' is-done' : '')) . '" href="javascript:;" data-signin-btn'
|
return '<a class="' . esc_attr($classes) . '" href="javascript:;" data-signin-btn'
|
||||||
. ' data-signin-idle-label="' . esc_attr__('签到', 'aksrt') . '"'
|
. ' data-signin-idle-label="' . esc_attr__('签到', 'aksrt') . '"'
|
||||||
. ' data-signin-done-label="' . esc_attr__('已签到', 'aksrt') . '">'
|
. ' data-signin-done-label="' . esc_attr__('已签到', 'aksrt') . '">'
|
||||||
. '<i class="fa fas fa-calendar-check ml3 mr6" aria-hidden="true"></i>'
|
. '<i class="fa fas fa-calendar-check ml3 mr6" aria-hidden="true"></i>'
|
||||||
. '<span data-signin-label>' . esc_html($signed ? __('已签到', 'aksrt') : __('签到', 'aksrt')) . '</span>'
|
. '<span data-signin-label>' . esc_html__('签到', 'aksrt') . '</span>'
|
||||||
. '</a>';
|
. '</a>';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($signed) {
|
|
||||||
return '<button type="button" class="' . esc_attr($classes . ' is-done') . '" data-signin-btn data-signin-idle-label="' . esc_attr__('签到', 'aksrt') . '" data-signin-done-label="' . esc_attr__('已签到', 'aksrt') . '" disabled>'
|
|
||||||
. '<i class="fa fas fa-calendar-check" aria-hidden="true"></i>'
|
|
||||||
. '<span data-signin-label>' . esc_html($compact ? __('已签到', 'aksrt') : __('今日已签到', 'aksrt')) . '</span>'
|
|
||||||
. '</button>';
|
|
||||||
}
|
|
||||||
|
|
||||||
return '<button type="button" class="' . esc_attr($classes) . '" data-signin-btn data-signin-idle-label="' . esc_attr__('签到', 'aksrt') . '" data-signin-done-label="' . esc_attr__('已签到', 'aksrt') . '">'
|
return '<button type="button" class="' . esc_attr($classes) . '" data-signin-btn data-signin-idle-label="' . esc_attr__('签到', 'aksrt') . '" data-signin-done-label="' . esc_attr__('已签到', 'aksrt') . '">'
|
||||||
. '<i class="fa fas fa-calendar-check" aria-hidden="true"></i>'
|
. '<i class="fa fas fa-calendar-check" aria-hidden="true"></i>'
|
||||||
. '<span data-signin-label>' . esc_html($compact ? __('签到', 'aksrt') : __('签到领取今日奖励', 'aksrt')) . '</span>'
|
. '<span data-signin-label>' . esc_html($compact ? __('签到', 'aksrt') : __('签到领取今日奖励', 'aksrt')) . '</span>'
|
||||||
|
|||||||
@@ -32,9 +32,13 @@ $currency = (string) ($currency_name ?? __('积分', 'aksrt'));
|
|||||||
</div>
|
</div>
|
||||||
<?php if (!empty($signin_enabled)) : ?>
|
<?php if (!empty($signin_enabled)) : ?>
|
||||||
<span class="uc-asset-card__head-action muted-color px12" data-aksrt-signin>
|
<span class="uc-asset-card__head-action muted-color px12" data-aksrt-signin>
|
||||||
|
<?php if (!empty($signin_signed_today)) : ?>
|
||||||
|
<?php echo aksrt_get_user_checkin_details_link('uc-asset-card__signin muted-color px12', '<span>' . esc_html__('已签到', 'aksrt') . '</span><i class="fa fas fa-angle-right em12 ml3" aria-hidden="true"></i>'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||||
|
<?php else : ?>
|
||||||
<button type="button" class="uc-asset-card__signin muted-color px12" data-signin-btn data-signin-idle-label="<?php esc_attr_e('签到领积分', 'aksrt'); ?>" data-signin-done-label="<?php esc_attr_e('已签到', 'aksrt'); ?>" disabled>
|
<button type="button" class="uc-asset-card__signin muted-color px12" data-signin-btn data-signin-idle-label="<?php esc_attr_e('签到领积分', 'aksrt'); ?>" data-signin-done-label="<?php esc_attr_e('已签到', 'aksrt'); ?>" disabled>
|
||||||
<span data-signin-label><?php esc_html_e('签到领积分', 'aksrt'); ?></span><i class="fa fas fa-angle-right em12 ml3" aria-hidden="true"></i>
|
<span data-signin-label><?php esc_html_e('签到领积分', 'aksrt'); ?></span><i class="fa fas fa-angle-right em12 ml3" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<?php endif; ?>
|
||||||
<span class="uc-asset-card__signin-status" data-signin-status></span>
|
<span class="uc-asset-card__signin-status" data-signin-status></span>
|
||||||
</span>
|
</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
@@ -69,21 +69,24 @@ extract($context, EXTR_SKIP); // phpcs:ignore WordPress.PHP.DontExtract.extract_
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="uc-header__actions">
|
<div class="uc-header__actions">
|
||||||
<?php if (!empty($signin_enabled)) : ?>
|
<?php if (!empty($signin_enabled)) : ?>
|
||||||
<span data-aksrt-signin>
|
<span data-aksrt-signin>
|
||||||
<button
|
<?php if (!empty($signin_signed_today)) : ?>
|
||||||
type="button"
|
<?php echo aksrt_get_user_checkin_details_link('btn btn-sm uc-header__signin-btn is-done', '<i class="fa fas fa-calendar-check" aria-hidden="true"></i><span>' . esc_html__('已签到', 'aksrt') . '</span>'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||||
class="btn btn-sm uc-header__signin-btn<?php echo !empty($signin_signed_today) ? ' is-done' : ''; ?>"
|
<?php else : ?>
|
||||||
data-signin-btn
|
<button
|
||||||
data-signin-idle-label="<?php esc_attr_e('签到', 'aksrt'); ?>"
|
type="button"
|
||||||
data-signin-done-label="<?php esc_attr_e('已签到', 'aksrt'); ?>"
|
class="btn btn-sm uc-header__signin-btn"
|
||||||
<?php disabled(!empty($signin_signed_today)); ?>
|
data-signin-btn
|
||||||
>
|
data-signin-idle-label="<?php esc_attr_e('签到', 'aksrt'); ?>"
|
||||||
<i class="fa fas fa-calendar-check" aria-hidden="true"></i>
|
data-signin-done-label="<?php esc_attr_e('已签到', 'aksrt'); ?>"
|
||||||
<span data-signin-label><?php echo !empty($signin_signed_today) ? esc_html__('已签到', 'aksrt') : esc_html__('签到', 'aksrt'); ?></span>
|
>
|
||||||
</button>
|
<i class="fa fas fa-calendar-check" aria-hidden="true"></i>
|
||||||
</span>
|
<span data-signin-label><?php esc_html_e('签到', 'aksrt'); ?></span>
|
||||||
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
<?php if (!empty($messages_url)) : ?>
|
<?php if (!empty($messages_url)) : ?>
|
||||||
<a href="<?php echo esc_url($messages_url); ?>" class="btn-ghost btn-sm btn-icon uc-header__message-btn" aria-label="<?php esc_attr_e('消息通知', 'aksrt'); ?>" title="<?php esc_attr_e('消息通知', 'aksrt'); ?>">
|
<a href="<?php echo esc_url($messages_url); ?>" class="btn-ghost btn-sm btn-icon uc-header__message-btn" aria-label="<?php esc_attr_e('消息通知', 'aksrt'); ?>" title="<?php esc_attr_e('消息通知', 'aksrt'); ?>">
|
||||||
<i class="fa fas fa-bell" aria-hidden="true"></i>
|
<i class="fa fas fa-bell" aria-hidden="true"></i>
|
||||||
|
|||||||
@@ -461,6 +461,8 @@ trait ScriptsPart1c {
|
|||||||
'nonce' => wp_create_nonce('aksrt_public_nonce'),
|
'nonce' => wp_create_nonce('aksrt_public_nonce'),
|
||||||
'restNonce' => wp_create_nonce('wp_rest'),
|
'restNonce' => wp_create_nonce('wp_rest'),
|
||||||
'captchaSignin' => function_exists('aksrt_is_captcha_enabled_for') && aksrt_is_captcha_enabled_for('signin'),
|
'captchaSignin' => function_exists('aksrt_is_captcha_enabled_for') && aksrt_is_captcha_enabled_for('signin'),
|
||||||
|
// 已签到详情弹窗(签到成功后就地替换入口按钮用)。
|
||||||
|
'signinDetailsUrl' => esc_url_raw(rest_url('aksrt/v1/signin/details')),
|
||||||
'visibilityNonce' => wp_create_nonce('aksrt_visibility'),
|
'visibilityNonce' => wp_create_nonce('aksrt_visibility'),
|
||||||
'siteUrl' => home_url('/'),
|
'siteUrl' => home_url('/'),
|
||||||
'themeUrl' => AKSRT_URI,
|
'themeUrl' => AKSRT_URI,
|
||||||
|
|||||||
+78
-123
@@ -20,7 +20,6 @@ class Signin {
|
|||||||
|
|
||||||
public function init(): void {
|
public function init(): void {
|
||||||
add_action('rest_api_init', [$this, 'register_routes']);
|
add_action('rest_api_init', [$this, 'register_routes']);
|
||||||
add_action('wp_ajax_aksrt_checkin_details_modal', [$this, 'ajax_details_modal']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function register_routes(): void {
|
public function register_routes(): void {
|
||||||
@@ -34,11 +33,6 @@ class Signin {
|
|||||||
'callback' => [$this, 'rest_signin'],
|
'callback' => [$this, 'rest_signin'],
|
||||||
'permission_callback' => [$this, 'check_rest_permission'],
|
'permission_callback' => [$this, 'check_rest_permission'],
|
||||||
]);
|
]);
|
||||||
register_rest_route('aksrt/v1', '/signin/history', [
|
|
||||||
'methods' => 'GET',
|
|
||||||
'callback' => [$this, 'rest_history'],
|
|
||||||
'permission_callback' => [$this, 'check_rest_permission'],
|
|
||||||
]);
|
|
||||||
register_rest_route('aksrt/v1', '/signin/details', [
|
register_rest_route('aksrt/v1', '/signin/details', [
|
||||||
'methods' => 'GET',
|
'methods' => 'GET',
|
||||||
'callback' => [$this, 'rest_details_html'],
|
'callback' => [$this, 'rest_details_html'],
|
||||||
@@ -237,42 +231,12 @@ class Signin {
|
|||||||
do_action('aksrt_checkin_done', $user_id);
|
do_action('aksrt_checkin_done', $user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** GET /signin/history — last N days for calendar/modals. */
|
|
||||||
public function rest_history(\WP_REST_Request $request) {
|
|
||||||
$user_id = get_current_user_id();
|
|
||||||
$days = max(7, min(90, (int) ($request->get_param('days') ?: 30)));
|
|
||||||
$rows = $this->get_recent_signins($user_id, $days);
|
|
||||||
$dates = [];
|
|
||||||
foreach ($rows as $row) {
|
|
||||||
if (!empty($row['signin_date'])) {
|
|
||||||
$dates[] = (string) $row['signin_date'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$today = $this->today_date();
|
|
||||||
return new \WP_REST_Response([
|
|
||||||
'dates' => $dates,
|
|
||||||
'streak' => $this->compute_current_streak($user_id, $today),
|
|
||||||
'total' => $this->get_total_days($user_id),
|
|
||||||
'signed' => (bool) $this->get_record($user_id, $today),
|
|
||||||
'all_day' => (int) get_user_meta($user_id, 'aksrt_checkin_all_day', true) ?: $this->get_total_days($user_id),
|
|
||||||
], 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** GET /signin/details — HTML fragment for remote modal. */
|
/** GET /signin/details — HTML fragment for remote modal. */
|
||||||
public function rest_details_html(\WP_REST_Request $request) {
|
public function rest_details_html(\WP_REST_Request $request) {
|
||||||
$html = $this->render_details_modal_html(get_current_user_id());
|
$html = $this->render_details_modal_html(get_current_user_id());
|
||||||
return new \WP_REST_Response(['success' => true, 'html' => $html], 200);
|
return new \WP_REST_Response(['success' => true, 'html' => $html], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** admin-ajax HTML (remote modal fetch often hits admin-ajax). */
|
|
||||||
public function ajax_details_modal(): void {
|
|
||||||
if (!is_user_logged_in()) {
|
|
||||||
wp_send_json_error(['message' => __('请先登录', 'aksrt')], 401);
|
|
||||||
}
|
|
||||||
$html = $this->render_details_modal_html(get_current_user_id());
|
|
||||||
wp_send_json_success(['html' => $html]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function is_signed_today(int $user_id = 0): bool {
|
public function is_signed_today(int $user_id = 0): bool {
|
||||||
$user_id = $user_id > 0 ? $user_id : get_current_user_id();
|
$user_id = $user_id > 0 ? $user_id : get_current_user_id();
|
||||||
if ($user_id <= 0) {
|
if ($user_id <= 0) {
|
||||||
@@ -299,12 +263,13 @@ class Signin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* legacy checkin_details_modal lite HTML.
|
* 签到详情弹窗 HTML(参考主题 zib_get_user_checkin_details_modal 1:1):
|
||||||
|
* 炫彩头部 + 用户卡片(我的积分/我的等级)+ 每日签到奖励卡 + 连续签到奖励 7 天迷你卡。
|
||||||
*/
|
*/
|
||||||
public function render_details_modal_html(int $user_id): string {
|
public function render_details_modal_html(int $user_id): string {
|
||||||
$user = get_userdata($user_id);
|
$user = get_userdata($user_id);
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
return '<div class="aksrt-checkin-modal"><p>' . esc_html__('用户不存在', 'aksrt') . '</p></div>';
|
return '<div class="modal-body"><p class="muted-color padding-10 text-center">' . esc_html__('用户不存在', 'aksrt') . '</p></div>';
|
||||||
}
|
}
|
||||||
$cfg = class_exists('\AKSRT\Settings\Settings')
|
$cfg = class_exists('\AKSRT\Settings\Settings')
|
||||||
? \AKSRT\Settings\Settings::get_signin_reward_settings()
|
? \AKSRT\Settings\Settings::get_signin_reward_settings()
|
||||||
@@ -313,87 +278,100 @@ class Signin {
|
|||||||
$rec = $this->get_record($user_id, $today);
|
$rec = $this->get_record($user_id, $today);
|
||||||
$streak = $this->compute_current_streak($user_id, $today);
|
$streak = $this->compute_current_streak($user_id, $today);
|
||||||
$total = $this->get_total_days($user_id);
|
$total = $this->get_total_days($user_id);
|
||||||
$balance = \AKSRT\Ledger\LedgerService::get_instance()->balance($user_id, \AKSRT\Ledger\AssetType::POINTS);
|
$base = (int) ($cfg['base'] ?? 0);
|
||||||
$currency = class_exists('\AKSRT\Settings\Settings')
|
$currency = class_exists('\AKSRT\Settings\Settings')
|
||||||
? \AKSRT\Settings\Settings::get_currency_name()
|
? \AKSRT\Settings\Settings::get_currency_name()
|
||||||
: __('积分', 'aksrt');
|
: __('积分', 'aksrt');
|
||||||
$base = (int) ($cfg['base'] ?? 0);
|
$points_svg = static fn(string $class = 'icon'): string =>
|
||||||
$avatar = function_exists('aksrt_get_avatar_url')
|
'<svg class="' . esc_attr($class) . '" aria-hidden="true"><use xlink:href="#icon-points"></use></svg>';
|
||||||
? aksrt_get_avatar_url($user_id, ['size' => 64])
|
$gift_svg = static fn(string $class = 'icon'): string =>
|
||||||
: get_avatar_url($user_id, ['size' => 64]);
|
'<svg class="' . esc_attr($class) . '" aria-hidden="true"><use xlink:href="#icon-gift-color"></use></svg>';
|
||||||
$center = function_exists('aksrt_get_user_center_url')
|
$signed_today = (bool) $rec;
|
||||||
? aksrt_get_user_center_url('assets')
|
|
||||||
: home_url('/');
|
|
||||||
|
|
||||||
$html = '<div class="aksrt-checkin-modal">';
|
// 炫彩头部
|
||||||
$html .= '<div class="aksrt-checkin-modal__head">';
|
$html = '<div class="modal-body">';
|
||||||
$html .= '<i class="fa fas fa-calendar-check" aria-hidden="true"></i>';
|
$html .= '<div class="modal-colorful-header colorful-bg c-blue">';
|
||||||
$html .= '<strong>' . esc_html__('签到领奖励', 'aksrt') . '</strong>';
|
$html .= '<button class="close" data-aksrt-modal-close aria-label="' . esc_attr__('关闭', 'aksrt') . '"><svg class="ic-close" aria-hidden="true"><use xlink:href="#icon-close"></use></svg></button>';
|
||||||
$html .= '<button type="button" class="aksrt-modal-runtime__close" data-aksrt-modal-close aria-label="' . esc_attr__('关闭', 'aksrt') . '">×</button>';
|
$html .= '<div class="colorful-make"></div>';
|
||||||
$html .= '</div>';
|
$html .= '<div class="text-center">';
|
||||||
|
$html .= '<div class="em2x"><i class="fa fas fa-calendar-check" aria-hidden="true"></i></div>';
|
||||||
$html .= '<div class="aksrt-checkin-modal__user">';
|
$html .= '<div class="mt10 em12 padding-w10">' . esc_html__('签到领奖励', 'aksrt') . '</div>';
|
||||||
$html .= '<img class="aksrt-checkin-modal__avatar" src="' . esc_url($avatar) . '" alt="" width="40" height="40" />';
|
|
||||||
$html .= '<div class="aksrt-checkin-modal__user-meta">';
|
|
||||||
$html .= '<div class="aksrt-checkin-modal__name">' . esc_html($user->display_name) . '</div>';
|
|
||||||
$html .= '<div class="aksrt-checkin-modal__sub">' . esc_html(sprintf(__('累计签到 %d 天', 'aksrt'), $total)) . '</div>';
|
|
||||||
$html .= '</div></div>';
|
$html .= '</div></div>';
|
||||||
|
|
||||||
$html .= '<div class="aksrt-checkin-modal__wallet">';
|
// 用户卡片(头像/昵称 + 我的积分 + 我的等级)
|
||||||
$html .= '<a class="aksrt-checkin-modal__wallet-item" href="' . esc_url($center) . '">';
|
$points_svg_mini = $points_svg('px12 mr6 muted-2-color');
|
||||||
$html .= '<span class="muted">' . esc_html($currency) . '</span>';
|
$user_card = '<a rel="nofollow" class="block flex1 muted-box padding-10" href="' . esc_url(aksrt_get_user_center_url('credits')) . '">
|
||||||
$html .= '<b>' . esc_html(number_format_i18n($balance)) . '</b>';
|
<div class="muted-2-color em09 mb6">' . esc_html__('我的积分', 'aksrt') . '</div>
|
||||||
$html .= '</a></div>';
|
<div class="em12">' . $points_svg_mini . esc_html(number_format_i18n(aksrt_user_points($user_id))) . '<i class="muted-2-color px12 fa fas fa-angle-right ml6" aria-hidden="true"></i></div>
|
||||||
|
</a>';
|
||||||
|
|
||||||
$html .= '<div class="aksrt-checkin-modal__card">';
|
$level_s = class_exists('\AKSRT\User\Level')
|
||||||
$html .= '<div class="aksrt-checkin-modal__card-main">';
|
&& \AKSRT\User\Level::settings()['enabled']
|
||||||
$html .= '<div class="aksrt-checkin-modal__card-title"><i class="fa fas fa-gift" aria-hidden="true"></i> ' . esc_html__('每日签到奖励', 'aksrt') . '</div>';
|
&& \AKSRT\User\Level::settings()['public_display'];
|
||||||
$html .= '<div class="aksrt-checkin-modal__badge">' . esc_html($currency) . ' +' . esc_html((string) $base) . '</div>';
|
if ($level_s) {
|
||||||
$html .= '</div>';
|
$level_badge = \AKSRT\User\Level::get_badge_html($user_id, 'em12 mr10');
|
||||||
if ($rec) {
|
$user_card .= '<a rel="nofollow" class="block flex1 muted-box padding-10 ml6" href="' . esc_url(aksrt_get_user_center_url('level')) . '">
|
||||||
$html .= '<div class="aksrt-checkin-modal__done"><i class="fa fas fa-calendar-check" aria-hidden="true"></i> ' . esc_html__('今日已签到', 'aksrt');
|
<div class="muted-2-color em09 mb6 flex jsb ac"><div>' . esc_html__('我的等级', 'aksrt') . '</div>' . $level_badge . '</div>
|
||||||
$html .= '<div class="em09">+' . esc_html((string) (int) ($rec['reward'] ?? 0)) . '</div></div>';
|
<div class="em12">' . esc_html(number_format_i18n(\AKSRT\User\Level::get_integral($user_id))) . '<span class="px12 ml6 muted-2-color">' . esc_html__('经验值', 'aksrt') . '<i class="fa fas fa-angle-right ml6" aria-hidden="true"></i></span></div>
|
||||||
|
</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$checkin_all_day = $total ? '<div class="mb6 em09">' . sprintf(__('累计签到%s天', 'aksrt'), '<badge class="c-blue">' . esc_html((string) $total) . '</badge>') . '</div>' : '';
|
||||||
|
$avatar_img = aksrt_get_avatar_box($user_id, 'avatar-img avatar-mini mr6', false, true);
|
||||||
|
$html .= '<div class="mb20"><div class="flex ac jsb"><div class="mb10">' . $avatar_img . esc_html($user->display_name) . '</div>' . $checkin_all_day . '</div><div class="flex ab jsb">' . $user_card . '</div></div>';
|
||||||
|
|
||||||
|
// 每日签到奖励卡片
|
||||||
|
$reward_badge = $base ? '<badge class=" p2-10 mr6 c-green" data-toggle="tooltip" title="' . esc_attr(sprintf(__('积分奖励%s', 'aksrt'), $base)) . '">' . $points_svg('icon') . '+' . esc_html((string) $base) . '</badge>' : '';
|
||||||
|
|
||||||
|
if ($signed_today) {
|
||||||
|
$checkin_btn = '<div class="em09 c-blue">
|
||||||
|
<div class="mb10"><i class="fa fas fa-calendar-check mr6" aria-hidden="true"></i>' . esc_html__('今日已签到', 'aksrt') . '</div>
|
||||||
|
<div class="px12">' . sprintf(__('积分', 'aksrt') . '+%d', (int) ($rec['reward'] ?? 0)) . '</div>
|
||||||
|
</div>';
|
||||||
} else {
|
} else {
|
||||||
$html .= '<button type="button" class="but c-blue aksrt-checkin-modal__btn" data-signin-btn data-signin-idle-label="' . esc_attr__('立即签到', 'aksrt') . '" data-signin-done-label="' . esc_attr__('已签到', 'aksrt') . '"><span data-signin-label>' . esc_html__('立即签到', 'aksrt') . '</span></button>';
|
$checkin_btn = '<button type="button" class="but c-blue ml10 p2-10 radius" data-signin-btn'
|
||||||
|
. ' data-signin-idle-label="' . esc_attr__('立即签到', 'aksrt') . '"'
|
||||||
|
. ' data-signin-done-label="' . esc_attr__('今日已签到', 'aksrt') . '">'
|
||||||
|
. '<span data-signin-label>' . esc_html__('立即签到', 'aksrt') . '</span></button>';
|
||||||
}
|
}
|
||||||
$html .= '</div>';
|
|
||||||
|
|
||||||
|
$card_1 = '<div class="zib-widget flex ac jsb">
|
||||||
|
<div class="mr10">
|
||||||
|
<div class="em09 mb10">' . $gift_svg('mr6 em12') . esc_html__('每日签到奖励', 'aksrt') . '</div>
|
||||||
|
<div class="flex ac jsb">' . $reward_badge . '</div>
|
||||||
|
</div>
|
||||||
|
' . $checkin_btn . '
|
||||||
|
</div>';
|
||||||
|
|
||||||
|
// 连续签到奖励卡片(参考主题固定 7 天)
|
||||||
$streak_table = is_array($cfg['streak'] ?? null) ? $cfg['streak'] : [];
|
$streak_table = is_array($cfg['streak'] ?? null) ? $cfg['streak'] : [];
|
||||||
$max = 7;
|
$reward_continuous_day_html = $streak > 1 ? '<div class="mb6 em09">' . sprintf(__('已连续签到%s天', 'aksrt'), '<badge class="c-blue">' . esc_html((string) $streak) . '</badge>') . '</div>' : '';
|
||||||
foreach (array_keys($streak_table) as $k) {
|
$continuous_lists = '';
|
||||||
$max = max($max, (int) $k);
|
$max_day = 7;
|
||||||
}
|
for ($d = 1; $d <= $max_day; $d++) {
|
||||||
$max = min(14, max(2, $max));
|
|
||||||
$html .= '<div class="aksrt-checkin-modal__streak">';
|
|
||||||
$html .= '<div class="aksrt-checkin-modal__streak-head"><span>' . esc_html__('连续签到奖励', 'aksrt') . '</span>';
|
|
||||||
if ($streak > 1) {
|
|
||||||
$html .= '<badge class="c-blue">' . esc_html(sprintf(__('已连续 %d 天', 'aksrt'), $streak)) . '</badge>';
|
|
||||||
}
|
|
||||||
$html .= '</div><div class="aksrt-checkin-modal__ladder">';
|
|
||||||
for ($d = 1; $d <= $max; $d++) {
|
|
||||||
$extra = 0;
|
$extra = 0;
|
||||||
foreach ($streak_table as $k => $v) {
|
foreach ($streak_table as $k => $v) {
|
||||||
if ((int) $k === $d) {
|
if ((int) $k === $d) {
|
||||||
$extra = (int) $v;
|
$extra = (int) $v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$pts = $base + $extra;
|
$_points = $base + $extra;
|
||||||
$is_done = $streak >= $d;
|
$is_ed = $signed_today && $streak >= $d;
|
||||||
$html .= '<div class="aksrt-checkin-modal__day' . ($is_done ? ' is-done' : '') . '">';
|
$_mini_card = $_points ? '<div class="badg badg-sm ' . ($is_ed ? 'b' : 'c') . '-green" data-toggle="tooltip" title="' . esc_attr(sprintf(__('积分奖励%s', 'aksrt'), $_points)) . '">' . $points_svg('icon') . '<br/>+' . esc_html((string) $_points) . '</div>' : '';
|
||||||
$html .= '<div class="aksrt-checkin-modal__day-n">D' . (int) $d . '</div>';
|
|
||||||
$html .= '<div class="aksrt-checkin-modal__day-p">+' . esc_html((string) $pts) . '</div>';
|
|
||||||
$html .= '</div>';
|
|
||||||
}
|
|
||||||
$html .= '</div></div>';
|
|
||||||
|
|
||||||
$dates = [];
|
$continuous_lists .= '<div class="flex1 text-center" style="flex: 1;">
|
||||||
foreach ($this->get_recent_signins($user_id, 30) as $row) {
|
<div class="mb6 checkin-mini-box">' . $_mini_card . '</div>
|
||||||
if (!empty($row['signin_date'])) {
|
<div class="muted-2-color smail' . ($is_ed ? ' c-blue' : '') . '">' . ($is_ed ? '<i class="fa fas fa-check-circle" aria-hidden="true"></i>' : '') . sprintf(__('第%d天', 'aksrt'), $d) . '</div>
|
||||||
$dates[] = (string) $row['signin_date'];
|
</div>';
|
||||||
}
|
|
||||||
}
|
}
|
||||||
$html .= '<div class="aksrt-checkin-modal__cal-title">' . esc_html__('最近 30 天', 'aksrt') . '</div>';
|
|
||||||
$html .= '<div data-aksrt-signin-calendar=\'' . esc_attr(wp_json_encode(array_values($dates))) . '\'></div>';
|
$card_2 = '<div class="mt10">
|
||||||
|
<div class="flex ac jsb"><div class="em09 mb10">' . $gift_svg('mr6 em12') . esc_html__('连续签到奖励', 'aksrt') . '</div>' . $reward_continuous_day_html . '</div>
|
||||||
|
<div class="flex ac jsb">' . $continuous_lists . '</div>
|
||||||
|
</div>';
|
||||||
|
|
||||||
|
$html .= $card_1;
|
||||||
|
$html .= $card_2;
|
||||||
$html .= '</div>';
|
$html .= '</div>';
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
@@ -418,29 +396,6 @@ class Signin {
|
|||||||
return $row ?: null;
|
return $row ?: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取最近 N 天的签到记录
|
|
||||||
*
|
|
||||||
* @param int $user_id
|
|
||||||
* @param int $days
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function get_recent_signins(int $user_id, int $days = 30): array {
|
|
||||||
global $wpdb;
|
|
||||||
$table = \AKSRT\Core\DBMigrator::table('signin_log');
|
|
||||||
if (!$table) return [];
|
|
||||||
|
|
||||||
$from_date = (new \DateTimeImmutable("-{$days} days", wp_timezone()))->format('Y-m-d');
|
|
||||||
|
|
||||||
$rows = $wpdb->get_results($wpdb->prepare(
|
|
||||||
"SELECT signin_date FROM {$table} WHERE user_id = %d AND signin_date >= %s ORDER BY signin_date ASC",
|
|
||||||
$user_id,
|
|
||||||
$from_date
|
|
||||||
), ARRAY_A);
|
|
||||||
|
|
||||||
return $rows ?: [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 算"今天之前"的连续签到天数。
|
* 算"今天之前"的连续签到天数。
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -460,11 +460,14 @@ test('profile routes load versioned leaf styles and keep dialogs hidden initiall
|
|||||||
assert.match(userCenterCreditsCss, /#panel-credits\.dashboard-panel\s*\{[^}]*background:\s*transparent;[^}]*box-shadow:\s*none;/);
|
assert.match(userCenterCreditsCss, /#panel-credits\.dashboard-panel\s*\{[^}]*background:\s*transparent;[^}]*box-shadow:\s*none;/);
|
||||||
assert.match(userCenterCreditsCss, /\.uc-asset-tabs\s*\{[^}]*background:\s*var\(--surface-1,\s*#fff\);[^}]*border:[^;}]+;[^}]*box-shadow:[^;}]+;/);
|
assert.match(userCenterCreditsCss, /\.uc-asset-tabs\s*\{[^}]*background:\s*var\(--surface-1,\s*#fff\);[^}]*border:[^;}]+;[^}]*box-shadow:[^;}]+;/);
|
||||||
assert.doesNotMatch(profileCredits, /credits-signin\.php|data-aksrt-signin-calendar/);
|
assert.doesNotMatch(profileCredits, /credits-signin\.php|data-aksrt-signin-calendar/);
|
||||||
// 签到日历只存在于签到弹窗(src/Credits/Signin.php + enhancements2.js),
|
// 签到详情弹窗为参考主题 1:1 结构(src/Credits/Signin.php),日历已随
|
||||||
// 用户中心里的孤儿渲染器已整包移除。
|
// 旧版 lite 弹窗一并移除;用户中心里的孤儿渲染器也已整包移除。
|
||||||
assert.equal(fs.existsSync(path.join(root, 'inc/helpers/user-center-renderers/credits-signin.php')), false);
|
assert.equal(fs.existsSync(path.join(root, 'inc/helpers/user-center-renderers/credits-signin.php')), false);
|
||||||
assert.doesNotMatch(userCenterCreditsCss + read('assets/css/frontend/enhancements/components/custom-amount.css'), /uc-signin-calendar/);
|
assert.doesNotMatch(userCenterCreditsCss + read('assets/css/frontend/enhancements/components/custom-amount.css'), /uc-signin-calendar/);
|
||||||
assert.match(read('src/Credits/Signin.php'), /data-aksrt-signin-calendar/);
|
const signinModalHtml = read('src/Credits/Signin.php');
|
||||||
|
assert.match(signinModalHtml, /modal-colorful-header colorful-bg c-blue/);
|
||||||
|
assert.match(signinModalHtml, /checkin-mini-box/);
|
||||||
|
assert.doesNotMatch(signinModalHtml, /data-aksrt-signin-calendar/);
|
||||||
assert.match(profileOrders, /data-aksrt-orders-filter-panel hidden/);
|
assert.match(profileOrders, /data-aksrt-orders-filter-panel hidden/);
|
||||||
assert.doesNotMatch(profileOrders, /\$_GET|add_query_arg|name="order_(?:status|type|number|page)"/);
|
assert.doesNotMatch(profileOrders, /\$_GET|add_query_arg|name="order_(?:status|type|number|page)"/);
|
||||||
assert.match(profileOrders, /data-aksrt-orders-filter-panel hidden[\s\S]*?aksrt-orders-page__status-filters[\s\S]*?aksrt-orders-page__type-filters/);
|
assert.match(profileOrders, /data-aksrt-orders-filter-panel hidden[\s\S]*?aksrt-orders-page__status-filters[\s\S]*?aksrt-orders-page__type-filters/);
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ test('balance center actions use direct fixed-id notyf flows', () => {
|
|||||||
assert.match(headerUserbox, /data-signin-btn[\s\S]*?data-signin-label/);
|
assert.match(headerUserbox, /data-signin-btn[\s\S]*?data-signin-label/);
|
||||||
assert.match(headerUserbox, /add_action\('wp_footer', 'aksrt_render_signin_captcha'\)/);
|
assert.match(headerUserbox, /add_action\('wp_footer', 'aksrt_render_signin_captcha'\)/);
|
||||||
assert.match(headerUserbox, /data-signin-captcha[\s\S]*?aksrt_render_captcha\('signin'\)/);
|
assert.match(headerUserbox, /data-signin-captcha[\s\S]*?aksrt_render_captcha\('signin'\)/);
|
||||||
assert.match(signinService, /aksrt-checkin-modal__btn[^>]+data-signin-btn/);
|
assert.match(signinService, /but c-blue ml10 p2-10 radius" data-signin-btn/);
|
||||||
assert.doesNotMatch(headerUserbox + signinService, /data-aksrt-checkin/);
|
assert.doesNotMatch(headerUserbox + signinService, /data-aksrt-checkin/);
|
||||||
assert.match(context, /'signin_enabled'\s*=>\s*\$signin_enabled/);
|
assert.match(context, /'signin_enabled'\s*=>\s*\$signin_enabled/);
|
||||||
assert.match(context, /'signin_signed_today'\s*=>\s*\$signin_signed_today/);
|
assert.match(context, /'signin_signed_today'\s*=>\s*\$signin_signed_today/);
|
||||||
|
|||||||
Reference in New Issue
Block a user