diff --git a/assets/css/frontend/widget-batch3.css b/assets/css/frontend/widget-batch3.css new file mode 100644 index 00000000..5479da84 --- /dev/null +++ b/assets/css/frontend/widget-batch3.css @@ -0,0 +1,739 @@ +/** + * Batch3 widgets: partners scroll, iframe, combo info, text title, user lists, plate widgets. + * @package AKSRT + */ + +/* ---- Partners scroll ---- */ +.aksrt-partners-scroll-wrap { + margin-bottom: 20px; +} +.aksrt-partners-scroll-wrap.is-bare { + background: transparent; + box-shadow: none; + padding: 0; +} +.aksrt-partners-scroll { + overflow: hidden; + position: relative; + --aksrt-ps-w: 220px; + --aksrt-ps-h: 90px; + --aksrt-ps-radius: 10px; + --aksrt-ps-speed: 3; +} +.aksrt-ps-end-fade::before, +.aksrt-ps-end-fade::after { + content: ""; + position: absolute; + top: 0; + bottom: 0; + width: 48px; + z-index: 2; + pointer-events: none; +} +.aksrt-ps-end-fade::before { + left: 0; + background: linear-gradient(90deg, var(--surface-1, #fff), transparent); +} +.aksrt-ps-end-fade::after { + right: 0; + background: linear-gradient(270deg, var(--surface-1, #fff), transparent); +} +.aksrt-ps-row { + overflow: hidden; + margin-bottom: 10px; +} +.aksrt-ps-row:last-child { + margin-bottom: 0; +} +.aksrt-ps-track { + display: flex; + width: max-content; + animation: aksrt-ps-marquee calc(40s / var(--aksrt-ps-speed)) linear infinite; +} +.aksrt-ps-dir-right .aksrt-ps-track { + animation-name: aksrt-ps-marquee-rev; +} +.aksrt-ps-pause-hover:hover .aksrt-ps-track { + animation-play-state: paused; +} +.aksrt-ps-group { + display: flex; + flex-shrink: 0; + align-items: center; +} +.aksrt-ps-item { + display: flex; + align-items: center; + flex-shrink: 0; + width: var(--aksrt-ps-w); + height: var(--aksrt-ps-h); + margin-right: 12px; + border-radius: var(--aksrt-ps-radius); + overflow: hidden; + text-decoration: none; + color: inherit; + box-sizing: border-box; + padding: 8px 12px; +} +.aksrt-ps-card-bg .aksrt-ps-item { + background: var(--surface-2, #f3f4f6); +} +.aksrt-ps-img { + max-width: 100%; + max-height: 100%; + object-fit: contain; + display: block; +} +.aksrt-ps-style-logo .aksrt-ps-item { + justify-content: center; + padding: 10px; +} +.aksrt-ps-card-icon { + width: 42px; + height: 42px; + flex-shrink: 0; + margin-right: 10px; + display: flex; + align-items: center; + justify-content: center; +} +.aksrt-ps-card-icon .aksrt-ps-img { + max-height: 42px; +} +.aksrt-ps-card-text { + min-width: 0; + flex: 1; + display: flex; + flex-direction: column; +} +.aksrt-ps-card-title { + font-weight: 700; + font-size: 13px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.aksrt-ps-card-desc { + font-size: 12px; + color: var(--muted-2-color, #999); + margin-top: 3px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.aksrt-ps-style-chip .aksrt-ps-item { + width: auto; + height: auto; + min-height: 36px; + border-radius: 999px; + padding: 6px 14px; + gap: 6px; +} +.aksrt-ps-chip-icon { + width: 22px; + height: 22px; + display: flex; + align-items: center; + margin-right: 6px; +} +.aksrt-ps-chip-title { + font-size: 13px; + white-space: nowrap; +} +@keyframes aksrt-ps-marquee { + from { transform: translateX(0); } + to { transform: translateX(-50%); } +} +@keyframes aksrt-ps-marquee-rev { + from { transform: translateX(-50%); } + to { transform: translateX(0); } +} + +/* ---- Iframe embed ---- */ +.aksrt-iframe-embed { + margin-bottom: 16px; +} +.aksrt-iframe-ratio { + position: relative; + width: 100%; + height: 0; + border-radius: 8px; + overflow: hidden; + background: var(--surface-2, #f3f4f6); +} +.aksrt-iframe-ratio iframe, +.aksrt-iframe-el { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + border: 0; +} + +/* ---- Combo info cards ---- */ +.aksrt-combo-info { + display: grid; + grid-template-columns: repeat(var(--aksrt-zci-pc, 4), minmax(0, 1fr)); + gap: 14px; + margin-bottom: 16px; + --aksrt-zci-radius: 12px; + --aksrt-zci-band-h: 70px; +} +@media (max-width: 991.98px) { + .aksrt-combo-info { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} +@media (max-width: 575.98px) { + .aksrt-combo-info { + grid-template-columns: repeat(var(--aksrt-zci-m, 1), minmax(0, 1fr)); + } +} +.aksrt-zci-card { + position: relative; + display: flex; + flex-direction: column; + border-radius: var(--aksrt-zci-radius); + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #e5e7eb); + padding: 18px 16px 16px; + overflow: hidden; + min-height: 100%; +} +.aksrt-combo-info.has-band .aksrt-zci-card::before { + content: ""; + position: absolute; + left: 0; + right: 0; + top: 0; + height: 4px; + background: var(--color-primary, #3b82f6); +} +.aksrt-zci-band-blue::before { background: #3b82f6; } +.aksrt-zci-band-cyan::before { background: #06b6d4; } +.aksrt-zci-band-green::before { background: #22c55e; } +.aksrt-zci-band-yellow::before { background: #eab308; } +.aksrt-zci-band-pink::before { background: #ec4899; } +.aksrt-zci-band-purple::before { background: #a855f7; } +.aksrt-zci-icon { + width: 48px; + height: 48px; + margin-bottom: 14px; + display: flex; + align-items: center; + justify-content: center; + font-size: 28px; + color: var(--color-primary, #3b82f6); +} +.aksrt-zci-icon img { + max-width: 48px; + max-height: 48px; + object-fit: contain; +} +.aksrt-zci-title { + font-weight: 700; + font-size: 16px; + margin-bottom: 8px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.aksrt-zci-tags { + display: flex; + flex-wrap: wrap; + gap: 6px; + margin-bottom: 8px; +} +.aksrt-zci-tag { + display: inline-block; + font-size: 12px; + padding: 2px 10px; + border-radius: 999px; + background: var(--surface-2, #f3f4f6); + color: var(--color-ink-3, #666); +} +.aksrt-zci-desc { + font-size: 13px; + color: var(--muted-2-color, #888); + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + flex: 1; +} +.aksrt-zci-cta { + margin-top: 14px; + display: inline-flex; + align-items: center; + gap: 6px; + font-size: 13px; + font-weight: 600; + color: var(--color-primary, #3b82f6); + text-decoration: none; +} +.aksrt-zci-cta:hover i { + transform: translateX(3px); +} +.aksrt-zci-cta i { + transition: transform .2s ease; + font-size: 12px; +} + +/* ---- Text title ---- */ +.aksrt-text-title { + margin: 8px 0 18px; + --aksrt-tt-title-size: 22px; + --aksrt-tt-desc-size: 14px; +} +.aksrt-text-title.align-center { text-align: center; } +.aksrt-text-title.align-left { text-align: left; } +.aksrt-text-title.align-right { text-align: right; } +.aksrt-text-title__main { + display: inline-flex; + align-items: center; + gap: 8px; + font-size: var(--aksrt-tt-title-size); + font-weight: 700; + color: var(--aksrt-tt-title-color, inherit); + line-height: 1.3; +} +.aksrt-text-title.align-center .aksrt-text-title__main { + justify-content: center; +} +.aksrt-text-title__desc { + margin-top: 8px; + font-size: var(--aksrt-tt-desc-size); + color: var(--aksrt-tt-desc-color, var(--muted-2-color, #888)); + line-height: 1.5; +} +.aksrt-text-title__icon { + display: inline-flex; + opacity: .85; +} + +/* ---- User lists ---- */ +.aksrt-user-lists { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 12px 8px; + text-align: center; + padding: 4px 0 8px; +} +.aksrt-user-lists.is-bare { + padding: 0; +} +@media (max-width: 575.98px) { + .aksrt-user-lists { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } +} +.aksrt-user-lists__item { + display: flex; + flex-direction: column; + align-items: center; + gap: 6px; + text-decoration: none; + color: inherit; + min-width: 0; +} +.aksrt-user-lists__avatar { + width: 48px; + height: 48px; + border-radius: 50%; + object-fit: cover; + background: var(--surface-2, #eee); +} +.aksrt-user-lists__name { + font-size: 12px; + max-width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* ---- Forum plate lists ---- */ +.aksrt-plate-lists { + display: flex; + flex-direction: column; + gap: 10px; +} +.aksrt-plate-item { + display: flex; + gap: 12px; + align-items: flex-start; + text-decoration: none; + color: inherit; + padding: 6px 0; + border-bottom: 1px dashed var(--color-line, #e5e7eb); +} +.aksrt-plate-item:last-child { + border-bottom: 0; +} +.aksrt-plate-item__thumb { + width: 48px; + height: 48px; + border-radius: 10px; + overflow: hidden; + flex-shrink: 0; + background: var(--surface-2, #f3f4f6); + display: flex; + align-items: center; + justify-content: center; + color: var(--color-primary, #3b82f6); + font-size: 18px; +} +.aksrt-plate-item__thumb img { + width: 100%; + height: 100%; + object-fit: cover; +} +.aksrt-plate-item__body { + min-width: 0; + flex: 1; +} +.aksrt-plate-item__title { + font-weight: 700; + font-size: 14px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.aksrt-plate-item__desc { + font-size: 12px; + color: var(--muted-2-color, #888); + margin-top: 3px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.aksrt-plate-item__meta { + font-size: 11px; + color: var(--color-ink-4, #999); + margin-top: 4px; +} +.aksrt-plate-cards { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 12px; +} +@media (max-width: 575.98px) { + .aksrt-plate-cards { + grid-template-columns: 1fr; + } +} +.aksrt-plate-card { + display: block; + text-decoration: none; + color: inherit; + border-radius: 10px; + overflow: hidden; + border: 1px solid var(--color-line, #e5e7eb); + background: var(--surface-1, #fff); +} +.aksrt-plate-card__cover { + height: 88px; + background: var(--surface-2, #f3f4f6) center/cover no-repeat; +} +.aksrt-plate-card__title { + font-weight: 700; + font-size: 13px; + padding: 10px 10px 4px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.aksrt-plate-card__meta { + display: flex; + justify-content: space-between; + font-size: 11px; + color: var(--muted-2-color, #888); + padding: 0 10px 10px; +} + +/* ---- Plate info ---- */ +.aksrt-plate-info { + border-radius: 10px; + overflow: hidden; + border: 1px solid var(--color-line, #e5e7eb); + background: var(--surface-1, #fff); + margin-bottom: 12px; +} +.aksrt-plate-info__cover { + height: 90px; + background: var(--surface-2, #f3f4f6) center/cover no-repeat; +} +.aksrt-plate-info__body { + padding: 12px 14px 14px; +} +.aksrt-plate-info__title { + display: block; + font-weight: 700; + font-size: 16px; + color: inherit; + text-decoration: none; + margin-bottom: 6px; +} +.aksrt-plate-info__desc { + font-size: 12px; + color: var(--muted-2-color, #888); + line-height: 1.5; + margin-bottom: 10px; +} +.aksrt-plate-info__stats { + display: flex; + gap: 14px; + font-size: 12px; + color: var(--color-ink-3, #666); +} +.aksrt-plate-info__stats i { + margin-right: 4px; + opacity: .75; +} + +/* ---- Plate moderators ---- */ +.aksrt-plate-mods { + margin-bottom: 12px; +} +.aksrt-plate-mods__head { + margin-bottom: 10px; +} +.aksrt-plate-mods__list { + display: flex; + flex-direction: column; + gap: 8px; +} +.aksrt-plate-mods__item { + display: flex; + align-items: center; + gap: 10px; + text-decoration: none; + color: inherit; +} +.aksrt-plate-mods__avatar { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; +} +.aksrt-plate-mods__name { + flex: 1; + min-width: 0; + font-size: 13px; + font-weight: 600; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.aksrt-plate-mods__role { + font-size: 11px; + color: var(--color-primary, #3b82f6); + flex-shrink: 0; +} + + +/* ---- Pricing plans ---- */ +.aksrt-pricing { margin-bottom: 16px; } +.aksrt-pricing__cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 16px; +} +.aksrt-pricing__card { + position: relative; + border: 1px solid var(--color-line, #e5e7eb); + border-radius: 14px; + padding: 22px 18px 18px; + background: var(--surface-1, #fff); + display: flex; + flex-direction: column; + min-height: 100%; +} +.aksrt-pricing__card.is-featured { + box-shadow: 0 10px 28px rgba(0,0,0,.08); + border-color: transparent; + border-top: 3px solid var(--plan-accent, #3b82f6); +} +.aksrt-pricing__card.accent-pink { --plan-accent: #ec4899; } +.aksrt-pricing__card.accent-purple { --plan-accent: #a855f7; } +.aksrt-pricing__card.accent-blue { --plan-accent: #3b82f6; } +.aksrt-pricing__card.accent-green { --plan-accent: #22c55e; } +.aksrt-pricing__card.accent-yellow { --plan-accent: #eab308; } +.aksrt-pricing__card.accent-cyan { --plan-accent: #06b6d4; } +.aksrt-pricing__badge { + position: absolute; + top: 12px; + right: 12px; + font-size: 11px; + padding: 2px 8px; + border-radius: 999px; + background: var(--plan-accent, #3b82f6); + color: #fff; +} +.aksrt-pricing__name { font-size: 18px; font-weight: 700; margin: 0 0 6px; } +.aksrt-pricing__desc { font-size: 13px; color: var(--muted-2-color, #888); margin: 0 0 12px; } +.aksrt-pricing__price { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; } +.aksrt-pricing__main { font-size: 32px; font-weight: 800; color: var(--plan-accent, #3b82f6); line-height: 1; } +.aksrt-pricing__mark { font-size: .55em; margin-right: 2px; } +.aksrt-pricing__original { font-size: 13px; color: #999; text-decoration: line-through; } +.aksrt-pricing__features { list-style: none; margin: 0 0 16px; padding: 0; flex: 1; } +.aksrt-pricing__features li { display: flex; gap: 8px; font-size: 13px; padding: 5px 0; } +.aksrt-pricing__features i { color: var(--plan-accent, #3b82f6); margin-top: 2px; } +.aksrt-pricing__btn { + display: block; + text-align: center; + padding: 10px 14px; + border-radius: 999px; + background: var(--plan-accent, #3b82f6); + color: #fff !important; + text-decoration: none; + font-weight: 600; +} +.aksrt-pricing__trust { + display: flex; + flex-wrap: wrap; + gap: 14px 22px; + margin-top: 18px; + justify-content: center; +} +.aksrt-pricing__trust-item { display: flex; gap: 8px; align-items: flex-start; font-size: 13px; } +.aksrt-pricing__trust-item i { color: var(--color-primary, #3b82f6); margin-top: 2px; } +.aksrt-pricing__trust-item strong { display: block; } +.aksrt-pricing__trust-item span { color: var(--muted-2-color, #888); font-size: 12px; } + +/* ---- FAQ ---- */ +.aksrt-faq { margin-bottom: 16px; } +.aksrt-faq__search { display: flex; gap: 8px; margin-bottom: 14px; } +.aksrt-faq__search-input { + flex: 1; + border: 1px solid var(--color-line, #e5e7eb); + border-radius: 8px; + padding: 8px 12px; +} +.aksrt-faq__search-btn { + border: 0; + border-radius: 8px; + padding: 8px 14px; + background: var(--color-primary, #3b82f6); + color: #fff; + cursor: pointer; +} +.aksrt-faq__item { + border: 1px solid var(--color-line, #e5e7eb); + border-radius: 10px; + padding: 0; + margin-bottom: 10px; + background: var(--surface-1, #fff); +} +.aksrt-faq__q { + list-style: none; + display: flex; + align-items: center; + gap: 10px; + padding: 12px 14px; + cursor: pointer; + font-weight: 600; +} +.aksrt-faq__q::-webkit-details-marker { display: none; } +.aksrt-faq__num { + width: 28px; + height: 28px; + border-radius: 8px; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 12px; + background: var(--surface-2, #f3f4f6); + color: var(--color-primary, #3b82f6); + flex-shrink: 0; +} +.aksrt-faq__a { + padding: 0 14px 14px 52px; + font-size: 13px; + color: var(--muted-2-color, #666); + line-height: 1.6; +} +.aksrt-faq__aside { display: grid; gap: 12px; margin-top: 14px; } +.aksrt-faq__doc, .aksrt-faq__help { + border-radius: 10px; + border: 1px solid var(--color-line, #e5e7eb); + padding: 14px; + background: var(--surface-2, #f8fafc); +} +.aksrt-faq__help-btn { + display: inline-block; + margin-top: 8px; + padding: 6px 12px; + border-radius: 999px; + background: var(--color-primary, #3b82f6); + color: #fff !important; + text-decoration: none; + font-size: 13px; +} + +/* ---- Stats ---- */ +.aksrt-stats { margin-bottom: 16px; } +.aksrt-stats__intro { margin-bottom: 14px; } +.aksrt-stats__intro-title { font-size: 22px; margin: 0 0 6px; } +.aksrt-stats__intro-sub { color: var(--muted-2-color, #888); margin: 0; font-size: 13px; } +.aksrt-stats__grid { + display: grid; + grid-template-columns: repeat(var(--aksrt-stats-pc, 4), minmax(0, 1fr)); + gap: 12px; +} +@media (max-width: 767.98px) { + .aksrt-stats__grid { + grid-template-columns: repeat(var(--aksrt-stats-m, 2), minmax(0, 1fr)); + } +} +.aksrt-stats__item { + border-radius: 12px; + padding: 16px 14px; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #e5e7eb); + text-align: center; +} +.aksrt-stats__item.color-pink { --stat-c: #ec4899; } +.aksrt-stats__item.color-purple { --stat-c: #a855f7; } +.aksrt-stats__item.color-orange { --stat-c: #f97316; } +.aksrt-stats__item.color-blue { --stat-c: #3b82f6; } +.aksrt-stats__item.color-green { --stat-c: #22c55e; } +.aksrt-stats__icon { font-size: 20px; color: var(--stat-c, #3b82f6); margin-bottom: 8px; } +.aksrt-stats__value { font-size: 28px; font-weight: 800; color: var(--stat-c, #3b82f6); line-height: 1.1; } +.aksrt-stats__prefix, .aksrt-stats__unit { font-size: .55em; font-weight: 600; } +.aksrt-stats__label { margin-top: 6px; font-size: 12px; color: var(--muted-2-color, #888); } + +/* ---- Forum topic lists ---- */ +.aksrt-ftopic-list { list-style: none; margin: 0; padding: 0; } +.aksrt-ftopic-list__item { + display: flex; + align-items: flex-start; + gap: 8px; + padding: 8px 0; + border-bottom: 1px dashed var(--color-line, #e5e7eb); +} +.aksrt-ftopic-list__item:last-child { border-bottom: 0; } +.aksrt-ftopic-list__link { + flex: 1; + min-width: 0; + color: inherit; + text-decoration: none; + font-size: 13px; + line-height: 1.45; +} +.aksrt-ftopic-list__views { + flex-shrink: 0; + font-size: 11px; + color: var(--muted-2-color, #999); +} +.aksrt-ftopic-list.is-detail .aksrt-ftopic-list__item { flex-direction: column; gap: 4px; } +.aksrt-ftopic-list__meta { + display: flex; + gap: 10px; + font-size: 11px; + color: var(--muted-2-color, #999); +} + +/* Forum widget sidebar shell */ +.aksrt-forum-widget-zone { margin-top: 12px; } +.aksrt-forum-widget-zone .zib-widget { margin-bottom: 14px; } diff --git a/assets/css/frontend/widget-batch3c.css b/assets/css/frontend/widget-batch3c.css new file mode 100644 index 00000000..4614fd89 --- /dev/null +++ b/assets/css/frontend/widget-batch3c.css @@ -0,0 +1,110 @@ +/** + * Batch3c: reviews + highlights. + */ + +.aksrt-reviews { + margin-bottom: 16px; + --aksrt-rev-pc: 3; + --aksrt-rev-m: 1.2; +} +.aksrt-reviews__track { + display: grid; + grid-auto-flow: column; + grid-auto-columns: calc((100% - (var(--aksrt-rev-pc) - 1) * 12px) / var(--aksrt-rev-pc)); + gap: 12px; + overflow-x: auto; + scroll-snap-type: x mandatory; + padding-bottom: 6px; + -webkit-overflow-scrolling: touch; +} +@media (max-width: 767.98px) { + .aksrt-reviews__track { + grid-auto-columns: calc((100% - (var(--aksrt-rev-m) - 1) * 12px) / var(--aksrt-rev-m)); + } +} +.aksrt-reviews__slide { scroll-snap-align: start; min-width: 0; } +.aksrt-reviews__card { + position: relative; + border: 1px solid var(--color-line, #e5e7eb); + border-radius: 12px; + padding: 16px; + background: var(--surface-1, #fff); + min-height: 100%; +} +.aksrt-reviews__head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; } +.aksrt-reviews__avatar { + width: 44px; + height: 44px; + border-radius: 50%; + object-fit: cover; + background: var(--surface-2, #eee); + display: inline-flex; + align-items: center; + justify-content: center; + color: #999; + flex-shrink: 0; +} +.aksrt-reviews__name { font-weight: 700; font-size: 14px; } +.aksrt-reviews__name a { color: inherit; text-decoration: none; } +.aksrt-reviews__role { font-size: 12px; color: var(--muted-2-color, #888); } +.aksrt-reviews__stars { margin-bottom: 8px; font-size: 12px; } +.aksrt-reviews__stars .is-on { color: #f5a623; } +.aksrt-reviews__stars .is-off { color: #ddd; } +.aksrt-reviews__content { + font-size: 13px; + line-height: 1.55; + color: var(--color-ink-2, #444); + margin: 0; +} +.aksrt-reviews__quote { + position: absolute; + right: 14px; + bottom: 10px; + opacity: .12; + font-size: 28px; +} + +.aksrt-highlights { margin-bottom: 16px; display: flex; flex-direction: column; gap: 12px; } +.aksrt-highlights__row { + display: grid; + gap: 12px; +} +.aksrt-highlights__row.is-large { grid-template-columns: 1fr; } +.aksrt-highlights__row.is-medium { grid-template-columns: repeat(2, minmax(0, 1fr)); } +.aksrt-highlights__row.is-small { grid-template-columns: repeat(3, minmax(0, 1fr)); } +@media (max-width: 767.98px) { + .aksrt-highlights__row.is-medium, + .aksrt-highlights__row.is-small { grid-template-columns: 1fr; } +} +.aksrt-hl-card { + display: flex; + gap: 12px; + border-radius: 12px; + border: 1px solid var(--color-line, #e5e7eb); + background: var(--surface-1, #fff); + padding: 14px; + text-decoration: none; + color: inherit; + overflow: hidden; + min-height: 100%; +} +.aksrt-hl-card.color-blue { --hl: #3b82f6; } +.aksrt-hl-card.color-pink { --hl: #ec4899; } +.aksrt-hl-card.color-purple { --hl: #a855f7; } +.aksrt-hl-card.color-green { --hl: #22c55e; } +.aksrt-hl-card.color-orange { --hl: #f97316; } +.aksrt-hl-card.color-cyan { --hl: #06b6d4; } +.aksrt-hl-card.size-large { min-height: 140px; } +.aksrt-hl-card__media { + width: 96px; + flex-shrink: 0; + border-radius: 10px; + overflow: hidden; + background: var(--surface-2, #f3f4f6); +} +.aksrt-hl-card.size-large .aksrt-hl-card__media { width: 160px; } +.aksrt-hl-card__media img { width: 100%; height: 100%; object-fit: cover; display: block; min-height: 80px; } +.aksrt-hl-card__body { min-width: 0; flex: 1; display: flex; flex-direction: column; } +.aksrt-hl-card__icon { color: var(--hl, #3b82f6); font-size: 22px; margin-bottom: 8px; } +.aksrt-hl-card__title { font-weight: 700; font-size: 15px; margin-bottom: 4px; } +.aksrt-hl-card__desc { font-size: 12px; color: var(--muted-2-color, #888); line-height: 1.5; } diff --git a/assets/css/frontend/widget-batch3d.css b/assets/css/frontend/widget-batch3d.css new file mode 100644 index 00000000..d9fe3fcd --- /dev/null +++ b/assets/css/frontend/widget-batch3d.css @@ -0,0 +1,163 @@ +/** + * Batch3d: feature intro, term cards, paid posts. + */ + +.aksrt-fi { + display: grid; + grid-template-columns: 1fr 1.1fr; + gap: 28px; + align-items: center; + margin-bottom: 20px; +} +.aksrt-fi.media-left { grid-template-columns: 1.1fr 1fr; } +.aksrt-fi.media-left .aksrt-fi__text { order: 2; } +.aksrt-fi.media-left .aksrt-fi__media { order: 1; } +@media (max-width: 991.98px) { + .aksrt-fi, + .aksrt-fi.media-left { + grid-template-columns: 1fr; + } + .aksrt-fi.media-left .aksrt-fi__text, + .aksrt-fi.media-left .aksrt-fi__media { order: initial; } +} +.aksrt-fi__title { + font-size: 28px; + line-height: 1.25; + margin: 0 0 12px; +} +.aksrt-fi__desc { + font-size: 14px; + color: var(--muted-2-color, #666); + line-height: 1.7; + margin-bottom: 14px; +} +.aksrt-fi__stat { + display: flex; + align-items: baseline; + gap: 6px; + margin-bottom: 14px; +} +.aksrt-fi__stat-num { + font-size: 36px; + font-weight: 800; + color: var(--color-primary, #3b82f6); + line-height: 1; +} +.aksrt-fi__stat-plus { font-size: 22px; font-weight: 700; color: var(--color-primary, #3b82f6); } +.aksrt-fi__stat-label { font-size: 13px; color: var(--muted-2-color, #888); margin-left: 4px; } +.aksrt-fi__tabs { display: flex; flex-wrap: wrap; gap: 8px; } +.aksrt-fi__tab { + border: 1px solid var(--color-line, #e5e7eb); + background: var(--surface-1, #fff); + border-radius: 999px; + padding: 6px 14px; + font-size: 13px; + cursor: pointer; +} +.aksrt-fi__tab.is-active { + background: var(--color-primary, #3b82f6); + border-color: transparent; + color: #fff; +} +.aksrt-fi__panel { display: none; } +.aksrt-fi__panel.is-active { display: block; } +.aksrt-fi__browser { + border-radius: 12px; + overflow: hidden; + border: 1px solid var(--color-line, #e5e7eb); + background: var(--surface-2, #f3f4f6); + box-shadow: 0 12px 32px rgba(0,0,0,.08); +} +.aksrt-fi__browser.is-plain { box-shadow: none; } +.aksrt-fi__browser-bar { + height: 28px; + background: #eef1f5; + display: flex; + align-items: center; + gap: 6px; + padding: 0 12px; +} +.aksrt-fi__browser-bar span { + width: 8px; + height: 8px; + border-radius: 50%; + background: #d0d5dd; +} +.aksrt-fi__browser-bar span:nth-child(1) { background: #ff5f57; } +.aksrt-fi__browser-bar span:nth-child(2) { background: #febc2e; } +.aksrt-fi__browser-bar span:nth-child(3) { background: #28c840; } +.aksrt-fi__browser-body { + position: relative; + width: 100%; + height: 0; + background: #111; +} +.aksrt-fi__img, +.aksrt-fi__video { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +.aksrt-term-cards { + display: grid; + grid-template-columns: repeat(var(--aksrt-tc-cols, 2), minmax(0, 1fr)); + gap: 12px; + margin-bottom: 12px; +} +.aksrt-term-card { + display: block; + border-radius: 12px; + overflow: hidden; + border: 1px solid var(--color-line, #e5e7eb); + text-decoration: none; + color: inherit; + background: var(--surface-1, #fff); +} +.aksrt-term-card__cover { + height: 88px; + background: var(--surface-2, #f3f4f6) center/cover no-repeat; +} +.aksrt-term-card__cover.is-empty { + background: linear-gradient(135deg, #dbeafe, #eff6ff); +} +.aksrt-term-card__body { padding: 10px 12px 12px; } +.aksrt-term-card__name { font-weight: 700; font-size: 14px; } +.aksrt-term-card__count { font-size: 12px; color: var(--muted-2-color, #888); margin-top: 2px; } + +.aksrt-paid-posts { list-style: none; margin: 0; padding: 0; } +.aksrt-paid-posts__item { + display: flex; + gap: 10px; + padding: 8px 0; + border-bottom: 1px dashed var(--color-line, #e5e7eb); +} +.aksrt-paid-posts__item:last-child { border-bottom: 0; } +.aksrt-paid-posts__thumb { + width: 56px; + height: 56px; + border-radius: 8px; + overflow: hidden; + flex-shrink: 0; + background: var(--surface-2, #eee); +} +.aksrt-paid-posts__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; } +.aksrt-paid-posts__body { min-width: 0; flex: 1; } +.aksrt-paid-posts__title { + display: block; + color: inherit; + text-decoration: none; + font-size: 13px; + font-weight: 600; + line-height: 1.4; +} +.aksrt-paid-posts__price { + display: inline-block; + margin-top: 4px; + font-size: 12px; + color: #e11d48; + font-weight: 700; +} diff --git a/assets/css/frontend/widgets.css b/assets/css/frontend/widgets.css index ed3d1caf..88c6fa77 100644 --- a/assets/css/frontend/widgets.css +++ b/assets/css/frontend/widgets.css @@ -3,3 +3,6 @@ @import url("widgets/part-3.css"); @import url("widgets/part-4.css"); @import url("widget-slider.css"); +@import url("widget-batch3.css"); +@import url("widget-batch3c.css"); +@import url("widget-batch3d.css"); diff --git a/inc/modules/widgets-register.php b/inc/modules/widgets-register.php index 65fbb549..7d7690df 100644 --- a/inc/modules/widgets-register.php +++ b/inc/modules/widgets-register.php @@ -56,6 +56,23 @@ function aksrt_register_widgets() { // 幻灯片 register_widget('\AKSRT\Widgets\WidgetSlider'); + // zibll more widgets batch + register_widget('\AKSRT\Widgets\WidgetPartnersScroll'); + register_widget('\AKSRT\Widgets\WidgetIframe'); + register_widget('\AKSRT\Widgets\WidgetComboInfo'); + register_widget('\AKSRT\Widgets\WidgetTextTitle'); + register_widget('\AKSRT\Widgets\WidgetUserLists'); + + register_widget('\AKSRT\Widgets\WidgetPricingPlans'); + register_widget('\AKSRT\Widgets\WidgetFaq'); + register_widget('\AKSRT\Widgets\WidgetStats'); + register_widget('\AKSRT\Widgets\WidgetReviews'); + register_widget('\AKSRT\Widgets\WidgetHighlights'); + register_widget('\AKSRT\Widgets\WidgetFeatureIntro'); + register_widget('\AKSRT\Widgets\WidgetTermCards'); + register_widget('\AKSRT\Widgets\WidgetPaidPosts'); + + // Forum widgets if (class_exists('\AKSRT\Widgets\WidgetForumBoardList')) { register_widget('\AKSRT\Widgets\WidgetForumBoardList'); @@ -66,6 +83,18 @@ function aksrt_register_widgets() { if (class_exists('\AKSRT\Widgets\WidgetForumRecentTopics')) { register_widget('\AKSRT\Widgets\WidgetForumRecentTopics'); } + if (class_exists('\AKSRT\Widgets\WidgetForumPlateLists')) { + register_widget('\AKSRT\Widgets\WidgetForumPlateLists'); + } + if (class_exists('\AKSRT\Widgets\WidgetForumPlateInfo')) { + register_widget('\AKSRT\Widgets\WidgetForumPlateInfo'); + } + if (class_exists('\AKSRT\Widgets\WidgetForumPlateModerator')) { + register_widget('\AKSRT\Widgets\WidgetForumPlateModerator'); + } + if (class_exists('\AKSRT\Widgets\WidgetForumTopicLists')) { + register_widget('\AKSRT\Widgets\WidgetForumTopicLists'); + } // Shop product widgets (§6.9) register_widget('\AKSRT\Widgets\WidgetProductList'); diff --git a/src/AKSRT/Core/SetupPart1.php b/src/AKSRT/Core/SetupPart1.php index 61345257..26634b99 100644 --- a/src/AKSRT/Core/SetupPart1.php +++ b/src/AKSRT/Core/SetupPart1.php @@ -382,6 +382,29 @@ trait SetupPart1 { 'after_title' => $title_after, ]); + // ── Forum / BBS widget areas (zibll bbs_* parity lite) ── + $forum_widgets = [ + 'bbs_home_sidebar' => [__('论坛首页 · 侧栏', 'aksrt'), __('论坛首页侧栏区域。', 'aksrt')], + 'bbs_home_top_fluid' => [__('论坛首页 · 顶部全宽', 'aksrt'), __('论坛首页顶部全宽。', 'aksrt')], + 'bbs_plate_sidebar' => [__('论坛版块 · 侧栏', 'aksrt'), __('版块页侧栏。', 'aksrt')], + 'bbs_plate_top_fluid' => [__('论坛版块 · 顶部全宽', 'aksrt'), __('版块页顶部全宽。', 'aksrt')], + 'bbs_posts_sidebar' => [__('论坛帖子 · 侧栏', 'aksrt'), __('帖子页侧栏挂件区。', 'aksrt')], + 'bbs_posts_top_fluid' => [__('论坛帖子 · 顶部全宽', 'aksrt'), __('帖子页顶部全宽。', 'aksrt')], + 'bbs_new_posts_sidebar_top' => [__('论坛发帖 · 侧栏顶部', 'aksrt'), __('发帖页侧栏顶部。', 'aksrt')], + 'bbs_new_posts_sidebar_bottom' => [__('论坛发帖 · 侧栏底部', 'aksrt'), __('发帖页侧栏底部。', 'aksrt')], + ]; + foreach ($forum_widgets as $sid => $meta) { + register_sidebar([ + 'id' => $sid, + 'name' => $meta[0], + 'description' => $meta[1], + 'before_widget' => $card_wrapper_before, + 'after_widget' => '', + 'before_title' => $title_before, + 'after_title' => $title_after, + ]); + } + // ── Shop widget areas (§6.9) ── $shop_widgets = [ 'shop_product_top_fluid' => ['商品详情页 · 顶部通栏', '商品详情页顶部全宽区域。'], diff --git a/src/AKSRT/Widgets/WidgetComboInfo.php b/src/AKSRT/Widgets/WidgetComboInfo.php new file mode 100644 index 00000000..61e6514e --- /dev/null +++ b/src/AKSRT/Widgets/WidgetComboInfo.php @@ -0,0 +1,238 @@ + esc_html__('图标 + 标题 + 标签 + 描述 + CTA 的多列信息卡。', 'aksrt'), + 'classname' => 'widget_aksrt_combo_info', + ] + ); + } + + public function widget($args, $instance): void { + $cards = $this->normalize_cards($instance['cards'] ?? []); + if (!$cards) { + return; + } + + $pc_row = max(1, min(6, (int) ($instance['pc_row'] ?? 4))); + $m_row = max(1, min(3, (int) ($instance['m_row'] ?? 1))); + $radius = max(0, min(40, (int) ($instance['card_radius'] ?? 12))); + $top_band = !empty($instance['top_band']) || !isset($instance['top_band']); + $band_h = max(20, min(160, (int) ($instance['top_band_height'] ?? 70))); + $cta_default = (string) ($instance['cta_text'] ?? __('立即体验', 'aksrt')); + $go_link = !empty($instance['go_link']); + + echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + $title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base); + if ($title !== '') { + echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } + + $style = sprintf('--aksrt-zci-radius:%dpx;--aksrt-zci-band-h:%dpx;--aksrt-zci-pc:%d;--aksrt-zci-m:%d;', $radius, $band_h, $pc_row, $m_row); + $wrap = 'aksrt-combo-info' . ($top_band ? ' has-band' : ''); + + echo '
+ +
++ +
++ + +
++ +
+
+
+
+
' . esc_html($doc_desc) . '
'; + } + echo '' . esc_html($sub) . '
'; + } + if ($help_btn !== '' && $help_url !== '') { + echo '' . esc_html($help_btn) . ''; + } + echo '+ +
++ +
++ +
++ +
++ +
++ +
++ +
++ +
+ sanitize_text_field((string) ($new_instance['title'] ?? '')), + 'faqs' => $this->normalize_faqs($new_instance['faqs'] ?? []), + 'search_s' => !empty($new_instance['search_s']) ? 1 : 0, + 'search_placeholder' => sanitize_text_field((string) ($new_instance['search_placeholder'] ?? '')), + 'search_btn_text' => sanitize_text_field((string) ($new_instance['search_btn_text'] ?? '')), + 'doc_title' => sanitize_text_field((string) ($new_instance['doc_title'] ?? '')), + 'doc_desc' => sanitize_text_field((string) ($new_instance['doc_desc'] ?? '')), + 'help_title' => sanitize_text_field((string) ($new_instance['help_title'] ?? '')), + 'help_subtitle' => sanitize_text_field((string) ($new_instance['help_subtitle'] ?? '')), + 'help_btn_text' => sanitize_text_field((string) ($new_instance['help_btn_text'] ?? '')), + 'help_btn_url' => esc_url_raw(trim((string) ($new_instance['help_btn_url'] ?? ''))), + ]; + } +} diff --git a/src/AKSRT/Widgets/WidgetFeatureIntro.php b/src/AKSRT/Widgets/WidgetFeatureIntro.php new file mode 100644 index 00000000..3435deb1 --- /dev/null +++ b/src/AKSRT/Widgets/WidgetFeatureIntro.php @@ -0,0 +1,227 @@ + esc_html__('左文右图/视频的 TAB 功能介绍模块。', 'aksrt'), + 'classname' => 'widget_aksrt_feature_intro', + ] + ); + } + + public function widget($args, $instance): void { + $slides = $this->normalize_slides($instance['slides'] ?? []); + if (!$slides) { + return; + } + $heading = trim((string) ($instance['heading'] ?? '')); + $desc = trim((string) ($instance['description'] ?? '')); + $media_pos = (($instance['media_position'] ?? 'right') === 'left') ? 'left' : 'right'; + $chrome = !empty($instance['browser_chrome']) || !isset($instance['browser_chrome']); + $ratio = max(30, min(100, (int) ($instance['media_ratio'] ?? 66))); + $show_stat = !empty($instance['show_stat']); + + echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + $uid = 'aksrt-fi-' . esc_attr($this->id); + + echo '+ +
++ +
++ +
++ +
++ +
+
+
+
+
+ +
++ +
++ +
+ sanitize_text_field((string) ($new_instance['heading'] ?? '')), + 'description' => wp_kses_post((string) ($new_instance['description'] ?? '')), + 'slides' => $this->normalize_slides($new_instance['slides'] ?? []), + 'media_position' => ($new_instance['media_position'] ?? '') === 'left' ? 'left' : 'right', + 'media_ratio' => max(30, min(100, (int) ($new_instance['media_ratio'] ?? 66))), + 'browser_chrome' => !empty($new_instance['browser_chrome']) ? 1 : 0, + 'show_stat' => !empty($new_instance['show_stat']) ? 1 : 0, + 'stat_number' => sanitize_text_field((string) ($new_instance['stat_number'] ?? '')), + 'stat_suffix' => sanitize_text_field((string) ($new_instance['stat_suffix'] ?? '')), + 'stat_label' => sanitize_text_field((string) ($new_instance['stat_label'] ?? '')), + ]; + } +} diff --git a/src/AKSRT/Widgets/WidgetForumBoardList.php b/src/AKSRT/Widgets/WidgetForumBoardList.php index 5ee4dc9d..5cd9d5d0 100644 --- a/src/AKSRT/Widgets/WidgetForumBoardList.php +++ b/src/AKSRT/Widgets/WidgetForumBoardList.php @@ -26,31 +26,60 @@ class WidgetForumBoardList extends \WP_Widget { echo $args['before_widget']; echo $args['before_title'] . esc_html($title) . $args['after_title']; - $boards = get_terms([ - 'taxonomy' => 'aksrt_forum_board', - 'hide_empty' => true, - 'orderby' => 'meta_value_num', - 'meta_key' => '_aksrt_sort_order', - 'order' => 'ASC', - ]); - - if (!is_wp_error($boards) && !empty($boards)) { - echo ''; + } + } + if (!$rendered) { + $boards = get_terms([ + 'taxonomy' => 'aksrt_forum_board', + 'hide_empty' => true, + 'orderby' => 'meta_value_num', + 'meta_key' => '_aksrt_sort_order', + 'order' => 'ASC', + ]); + if (!is_wp_error($boards) && !empty($boards)) { + echo ''; + } else { + echo ''; } - echo ''; - } else { - echo ''; } echo $args['after_widget']; diff --git a/src/AKSRT/Widgets/WidgetForumPlateInfo.php b/src/AKSRT/Widgets/WidgetForumPlateInfo.php new file mode 100644 index 00000000..b0bf8b8b --- /dev/null +++ b/src/AKSRT/Widgets/WidgetForumPlateInfo.php @@ -0,0 +1,94 @@ + esc_html__('在版块/帖子页侧栏显示当前 plate 信息。', 'aksrt'), + 'classname' => 'widget_aksrt_forum_plate_info', + ] + ); + } + + public function widget($args, $instance): void { + $plate = $this->resolve_current_plate(); + if (!$plate) { + return; + } + + echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + + $id = (int) $plate->ID; + $url = get_permalink($id); + $thumb = get_the_post_thumbnail_url($id, 'medium'); + $posts = (int) get_post_meta($id, '_aksrt_posts_count', true); + $reply = (int) get_post_meta($id, '_aksrt_reply_count', true); + $follow = (int) get_post_meta($id, '_aksrt_follow_count', true); + $desc = $plate->post_excerpt !== '' ? $plate->post_excerpt : wp_trim_words(wp_strip_all_tags($plate->post_content), 30); + + echo '' . esc_html__('无需配置。仅在版块页或帖子页显示对应版块信息。', 'aksrt') . '
'; + } + + public function update($new_instance, $old_instance): array { + return []; + } +} diff --git a/src/AKSRT/Widgets/WidgetForumPlateLists.php b/src/AKSRT/Widgets/WidgetForumPlateLists.php new file mode 100644 index 00000000..0dbe1afd --- /dev/null +++ b/src/AKSRT/Widgets/WidgetForumPlateLists.php @@ -0,0 +1,216 @@ + esc_html__('展示论坛 plate 版块列表,支持排序与卡片样式。', 'aksrt'), + 'classname' => 'widget_aksrt_forum_plate_lists', + ] + ); + } + + public function widget($args, $instance): void { + if (!post_type_exists('aksrt_forum_plate')) { + return; + } + + $limit = max(1, min(30, (int) ($instance['showposts'] ?? 8))); + $orderby = sanitize_key((string) ($instance['orderby'] ?? 'menu_order')); + $style = sanitize_key((string) ($instance['style'] ?? 'default')); + $filter = sanitize_key((string) ($instance['filter'] ?? '')); + $cat_raw = (string) ($instance['cat'] ?? ''); + $cat_ids = array_values(array_filter(array_map('intval', preg_split('/[\s,]+/', $cat_raw) ?: []))); + + $query_args = [ + 'post_type' => 'aksrt_forum_plate', + 'post_status' => 'publish', + 'posts_per_page' => $limit, + 'order' => 'ASC', + ]; + + switch ($orderby) { + case 'date': + $query_args['orderby'] = 'date'; + $query_args['order'] = 'DESC'; + break; + case 'posts': + $query_args['meta_key'] = '_aksrt_posts_count'; + $query_args['orderby'] = 'meta_value_num'; + $query_args['order'] = 'DESC'; + break; + case 'views': + $query_args['meta_key'] = '_aksrt_views'; + $query_args['orderby'] = 'meta_value_num'; + $query_args['order'] = 'DESC'; + break; + case 'follow': + $query_args['meta_key'] = '_aksrt_follow_count'; + $query_args['orderby'] = 'meta_value_num'; + $query_args['order'] = 'DESC'; + break; + default: + $query_args['orderby'] = 'menu_order title'; + } + + if ($cat_ids) { + $query_args['tax_query'] = [[ + 'taxonomy' => 'aksrt_plate_cat', + 'field' => 'term_id', + 'terms' => $cat_ids, + ]]; + } + + if ($filter === 'is_hot') { + $query_args['meta_query'] = [[ + 'key' => '_aksrt_is_hot', + 'value' => '1', + 'compare' => '=', + ]]; + } + + $plates = get_posts($query_args); + if (!$plates) { + return; + } + + echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + $title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base); + if ($title !== '') { + echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } + + if ($style === 'card') { + echo '+ +
++ +
++ +
++ +
++ +
++ +
+ sanitize_text_field((string) ($new_instance['title'] ?? '')), + 'showposts' => max(1, min(30, (int) ($new_instance['showposts'] ?? 8))), + 'orderby' => $orderby, + 'style' => ($new_instance['style'] ?? '') === 'card' ? 'card' : 'default', + 'filter' => ($new_instance['filter'] ?? '') === 'is_hot' ? 'is_hot' : '', + 'cat' => sanitize_text_field((string) ($new_instance['cat'] ?? '')), + ]; + } +} diff --git a/src/AKSRT/Widgets/WidgetForumPlateModerator.php b/src/AKSRT/Widgets/WidgetForumPlateModerator.php new file mode 100644 index 00000000..d2fe667d --- /dev/null +++ b/src/AKSRT/Widgets/WidgetForumPlateModerator.php @@ -0,0 +1,131 @@ + esc_html__('显示当前版块的版主与超级版主。', 'aksrt'), + 'classname' => 'widget_aksrt_forum_plate_moderator', + ] + ); + } + + public function widget($args, $instance): void { + $plate = $this->resolve_current_plate(); + if (!$plate) { + return; + } + + $id = (int) $plate->ID; + $author_id = (int) $plate->post_author; + $mods = get_post_meta($id, '_aksrt_moderators', true); + if (!is_array($mods)) { + $mods = []; + } + $mods = array_values(array_unique(array_filter(array_map('intval', $mods)))); + + $people = []; + if ($author_id > 0) { + $people[] = ['id' => $author_id, 'role' => 'author']; + } + foreach ($mods as $mid) { + if ($mid === $author_id) { + continue; + } + $people[] = ['id' => $mid, 'role' => 'moderator']; + } + if (!$people) { + return; + } + + $title_text = (string) ($instance['title_text'] ?? __('版主', 'aksrt')); + + echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + + echo '+ +
+ + sanitize_text_field((string) ($new_instance['title_text'] ?? '')), + ]; + } +} diff --git a/src/AKSRT/Widgets/WidgetForumTopicLists.php b/src/AKSRT/Widgets/WidgetForumTopicLists.php new file mode 100644 index 00000000..72d559e1 --- /dev/null +++ b/src/AKSRT/Widgets/WidgetForumTopicLists.php @@ -0,0 +1,176 @@ + esc_html__('按排序/版块筛选展示论坛帖子。', 'aksrt'), + 'classname' => 'widget_aksrt_forum_topic_lists', + ] + ); + } + + public function widget($args, $instance): void { + if (!post_type_exists('aksrt_forum_topic')) { + return; + } + + $count = max(1, min(30, (int) ($instance['count'] ?? 8))); + $orderby = sanitize_key((string) ($instance['orderby'] ?? 'date')); + $style = sanitize_key((string) ($instance['style'] ?? 'mini')); + $plate_id = (int) ($instance['plate_id'] ?? 0); + $current_plate = !empty($instance['current_plate']); + + if ($current_plate) { + $resolved = $this->resolve_current_plate_id(); + if ($resolved <= 0) { + return; + } + $plate_id = $resolved; + } + + $query = [ + 'post_type' => 'aksrt_forum_topic', + 'post_status' => 'publish', + 'posts_per_page' => $count, + 'order' => 'DESC', + ]; + + switch ($orderby) { + case 'views': + $query['meta_key'] = '_aksrt_views'; + $query['orderby'] = 'meta_value_num'; + break; + case 'comments': + $query['orderby'] = 'comment_count'; + break; + case 'modified': + $query['orderby'] = 'modified'; + break; + default: + $query['orderby'] = 'date'; + } + + if ($plate_id > 0) { + $query['meta_query'] = [[ + 'key' => '_aksrt_plate_id', + 'value' => $plate_id, + ]]; + } + + $q = new \WP_Query($query); + if (!$q->have_posts()) { + wp_reset_postdata(); + return; + } + + echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + $title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base); + if ($title !== '') { + echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } + + $list_class = $style === 'detail' ? 'aksrt-ftopic-list is-detail' : 'aksrt-ftopic-list is-mini'; + echo '+ +
++ +
++ +
++ +
++ +
++ +
+ sanitize_text_field((string) ($new_instance['title'] ?? '')), + 'count' => max(1, min(30, (int) ($new_instance['count'] ?? 8))), + 'orderby' => $orderby, + 'style' => ($new_instance['style'] ?? '') === 'detail' ? 'detail' : 'mini', + 'plate_id' => max(0, (int) ($new_instance['plate_id'] ?? 0)), + 'current_plate' => !empty($new_instance['current_plate']) ? 1 : 0, + ]; + } +} diff --git a/src/AKSRT/Widgets/WidgetHighlights.php b/src/AKSRT/Widgets/WidgetHighlights.php new file mode 100644 index 00000000..f9f1d12f --- /dev/null +++ b/src/AKSRT/Widgets/WidgetHighlights.php @@ -0,0 +1,177 @@ + esc_html__('大中小尺寸亮点/卖点卡片栅格。', 'aksrt'), + 'classname' => 'widget_aksrt_highlights', + ] + ); + } + + public function widget($args, $instance): void { + $cards = $this->normalize($instance['cards'] ?? []); + if (!$cards) { + return; + } + $go_link = !empty($instance['go_link']); + + echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + $title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base); + if ($title !== '') { + echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } + + $large = array_values(array_filter($cards, static fn($c) => ($c['size'] ?? 'medium') === 'large')); + $medium = array_values(array_filter($cards, static fn($c) => ($c['size'] ?? 'medium') === 'medium')); + $small = array_values(array_filter($cards, static fn($c) => ($c['size'] ?? 'medium') === 'small')); + // Fallback: if no size tags, treat all as medium. + if (!$large && !$medium && !$small) { + $medium = $cards; + } + + echo '+ +
++ + +
++ +
+ sanitize_text_field((string) ($new_instance['title'] ?? '')), + 'cards' => $this->normalize($new_instance['cards'] ?? []), + 'go_link' => !empty($new_instance['go_link']) ? 1 : 0, + ]; + } +} diff --git a/src/AKSRT/Widgets/WidgetIframe.php b/src/AKSRT/Widgets/WidgetIframe.php new file mode 100644 index 00000000..eaeeb2cc --- /dev/null +++ b/src/AKSRT/Widgets/WidgetIframe.php @@ -0,0 +1,113 @@ + esc_html__('嵌入在线视频/音乐播放器或任意 iframe 内容。', 'aksrt'), + 'classname' => 'widget_aksrt_iframe', + ] + ); + } + + public function widget($args, $instance): void { + $raw = trim((string) ($instance['url'] ?? '')); + if ($raw === '') { + return; + } + $aspect = max(20, min(300, (int) ($instance['aspect'] ?? 55))); + $allow_fs = !empty($instance['allowfullscreen']); + + echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + $title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base); + if ($title !== '') { + echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } + + $iframe_html = ''; + if (stripos($raw, '