diff --git a/assets/css/frontend/nav/header-userbox.css b/assets/css/frontend/nav/header-userbox.css
new file mode 100644
index 00000000..9db422c2
--- /dev/null
+++ b/assets/css/frontend/nav/header-userbox.css
@@ -0,0 +1,96 @@
+/**
+ * Header user-box density (check-in / wallet / payvip / signout modal).
+ *
+ * @package AKSRT
+ */
+
+.aksrt-header-wallet {
+ display: flex;
+ gap: 10px;
+ justify-content: space-between;
+ padding: 8px 10px;
+ border-radius: 8px;
+ background: var(--surface-2, rgba(0, 0, 0, 0.04));
+ color: inherit;
+ text-decoration: none;
+ font-size: 12px;
+}
+
+.aksrt-header-wallet__item b {
+ margin-left: 2px;
+}
+
+.aksrt-header-checkin {
+ width: 100%;
+ border: 0;
+ border-radius: 6px;
+ padding: 8px 10px;
+ cursor: pointer;
+ background: rgba(255, 193, 7, 0.18);
+ color: #b78103;
+}
+
+.aksrt-header-checkin.is-done {
+ opacity: 0.75;
+ cursor: default;
+}
+
+.aksrt-header-payvip .payvip-icon,
+.aksrt-header-payvip .but {
+ display: block;
+ text-align: center;
+ text-decoration: none;
+ padding: 8px 10px;
+ border-radius: 6px;
+ background: linear-gradient(90deg, #ff6b6b, #f04494);
+ color: #fff;
+}
+
+.aksrt-header-badges {
+ flex-wrap: wrap;
+ gap: 4px;
+}
+
+#modal_signout.modal {
+ position: fixed;
+ inset: 0;
+ z-index: 1100;
+ display: none;
+ align-items: center;
+ justify-content: center;
+ background: rgba(0, 0, 0, 0.45);
+ padding: 16px;
+}
+
+#modal_signout.modal.is-open,
+#modal_signout.modal.show {
+ display: flex;
+}
+
+#modal_signout .modal-content {
+ background: var(--main-bg-color, #fff);
+ border-radius: 10px;
+ min-width: 280px;
+ max-width: 92vw;
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.18);
+}
+
+#modal_signout .but.c-red {
+ background: #e74c3c;
+ color: #fff;
+ text-decoration: none;
+ padding: 8px 14px;
+ border-radius: 6px;
+}
+
+#modal_signout .but {
+ border: 0;
+ background: var(--surface-2, #f0f0f0);
+ padding: 8px 14px;
+ border-radius: 6px;
+ cursor: pointer;
+}
+
+.user-dropdown .social_loginbar {
+ padding: 0 10px 12px;
+}
diff --git a/assets/css/routes/links.css b/assets/css/routes/links.css
new file mode 100644
index 00000000..573129e2
--- /dev/null
+++ b/assets/css/routes/links.css
@@ -0,0 +1,459 @@
+/**
+ * AKSRT 网址导航 — zibll links page shell/styles.
+ *
+ * @package AKSRT
+ */
+
+/* ---- cards ---- */
+.links-cat-header {
+ padding: 0 15px 10px;
+}
+
+.links-box:not(.zib-widget):not(.links-style-simple):not(.links-style-image) {
+ margin: -5px;
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.links-box .links-card {
+ padding: 10px 4px 10px 8px;
+ min-width: 0;
+ margin: 5px;
+ width: calc(50% - 10px);
+ box-sizing: border-box;
+}
+
+.links-style-bigcard {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.links-box .links-card.big-card {
+ padding: 20px 10px 15px;
+ text-align: center;
+}
+
+.links-box:not(.zib-widget) .links-card {
+ background: var(--main-bg-color, var(--surface-1, #fff));
+}
+
+.author-minicard.links-card {
+ border-radius: 8px;
+ overflow: hidden;
+ box-shadow: 0 1px 4px var(--main-shadow, rgba(0, 0, 0, 0.06));
+ transition: transform 0.15s ease, box-shadow 0.15s ease;
+}
+
+.author-minicard.links-card:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 14px var(--main-shadow, rgba(0, 0, 0, 0.1));
+}
+
+.links-card a {
+ display: block;
+ color: inherit;
+ text-decoration: none;
+}
+
+.links-card .list-inline {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.links-card .list-inline > li {
+ margin: 0;
+}
+
+.link-img {
+ --this-size: 42px;
+ width: var(--this-size);
+ height: var(--this-size);
+ flex-shrink: 0;
+}
+
+.link-img img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ border-radius: 4px;
+ display: block;
+}
+
+.links-card.big-card .link-img {
+ --this-size: 58px;
+ margin: 0 auto;
+}
+
+.links-card.big-card .link-img img {
+ border-radius: 100px;
+}
+
+.links-style-image {
+ --link-img-size: 60px;
+ --this-margin: 10px;
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.links-style-image .link-img.link-only-img {
+ margin: var(--this-margin);
+ --this-size: var(--link-img-size);
+}
+
+.links-style-image .link-img.link-only-img img {
+ border-radius: 8px;
+}
+
+/* ---- fixed category nav ---- */
+.fixed-wrap .fixed-wrap-nav.zib-widget,
+.link-nav-box .zib-widget {
+ padding: 8px 15px;
+}
+
+.fixed-wrap-nav .tab-nav-theme {
+ border-bottom: none;
+ padding: 0;
+ list-style: none;
+ margin: 0;
+}
+
+.link-nav-box .nav > li > a {
+ display: block;
+ padding: 6px;
+ color: var(--muted-2-color, #888);
+ text-decoration: none;
+}
+
+.link-nav-box .nav > li > a:hover,
+.link-nav-box .nav > .active > a {
+ color: var(--focus-color, var(--color-primary, #f04494));
+}
+
+.link-nav-submit,
+.link-cat-submit {
+ margin-top: 10px;
+}
+
+.link-cat-submit {
+ display: none;
+}
+
+.links-page-container .title-theme {
+ font-weight: 600;
+ font-size: 1.15em;
+ margin-bottom: 6px;
+}
+
+/* ---- search cover ---- */
+.link-page-search-cover.page-cover {
+ position: relative;
+ overflow: hidden;
+ padding-bottom: calc(25% + 100px);
+ margin-bottom: 20px;
+}
+
+.link-page-search-cover .fit-cover {
+ position: absolute;
+ inset: 0;
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.link-page-search-cover .header-slider-search {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ width: min(560px, 92%);
+ z-index: 2;
+}
+
+.link-page-search-cover .tab-nav-theme {
+ display: flex;
+ gap: 4px;
+ list-style: none;
+ padding: 0;
+ margin: 0 0 8px;
+ justify-content: center;
+}
+
+.link-page-search-cover .tab-nav-theme li a {
+ opacity: 0.7;
+ padding: 0 10px;
+ color: #fff;
+ text-decoration: none;
+ cursor: pointer;
+}
+
+.link-page-search-cover .tab-nav-theme li a:hover,
+.link-page-search-cover .tab-nav-theme li.active a {
+ color: #fff;
+ opacity: 1;
+ font-weight: 600;
+}
+
+.link-page-search-cover .tab-pane {
+ display: none;
+}
+
+.link-page-search-cover .tab-pane.active,
+.link-page-search-cover .tab-pane.in.active {
+ display: block;
+}
+
+.link-page-search-cover .line-form {
+ position: relative;
+ background: rgba(255, 255, 255, 0.92);
+ border-radius: 8px;
+ padding: 8px 12px;
+}
+
+.link-page-search-cover .line-form-input {
+ width: 100%;
+ border: 0;
+ background: transparent;
+ outline: none;
+ font-size: 15px;
+ padding: 8px 36px 8px 4px;
+}
+
+.link-page-search-cover .abs-right {
+ position: absolute;
+ right: 10px;
+ top: 50%;
+ transform: translateY(-50%);
+}
+
+.link-page-search-cover .abs-right button {
+ border: 0;
+ background: transparent;
+ cursor: pointer;
+ color: var(--muted-2-color, #666);
+}
+
+.link-page-search-cover .header-slider-search-more {
+ color: #fff;
+ text-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
+ margin-bottom: 8px;
+}
+
+/* ---- submit modal ---- */
+#submit-links-modal.modal {
+ position: fixed;
+ inset: 0;
+ z-index: 1050;
+ display: none;
+ align-items: center;
+ justify-content: center;
+ background: rgba(0, 0, 0, 0.45);
+ padding: 16px;
+}
+
+#submit-links-modal.modal.is-open,
+#submit-links-modal.modal.show {
+ display: flex;
+}
+
+#submit-links-modal .modal-dialog {
+ width: min(520px, 100%);
+ max-height: 90vh;
+ overflow: auto;
+}
+
+#submit-links-modal .modal-content {
+ background: var(--main-bg-color, #fff);
+ border-radius: 10px;
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.18);
+}
+
+#submit-links-modal .modal-body {
+ padding: 20px;
+}
+
+#submit-links-modal .close {
+ float: right;
+ border: 0;
+ background: transparent;
+ cursor: pointer;
+ font-size: 18px;
+}
+
+#submit-links-modal .preview-square {
+ width: 72px;
+ height: 72px;
+ border: 1px dashed var(--main-border-color, #ddd);
+ border-radius: 8px;
+ overflow: hidden;
+ display: inline-block;
+}
+
+#submit-links-modal .preview-square img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+#submit-links-modal .hide {
+ display: none !important;
+}
+
+#submit-links-modal .form-control {
+ width: 100%;
+ padding: 8px 10px;
+ border: 1px solid var(--main-border-color, #ddd);
+ border-radius: 6px;
+ box-sizing: border-box;
+}
+
+#submit-links-modal .row.gutters-5 {
+ display: flex;
+ flex-wrap: wrap;
+ margin: 0 -5px;
+}
+
+#submit-links-modal .col-sm-6,
+#submit-links-modal .col-sm-12 {
+ padding: 0 5px;
+ box-sizing: border-box;
+ width: 100%;
+}
+
+@media (min-width: 576px) {
+ #submit-links-modal .col-sm-6 {
+ width: 50%;
+ }
+}
+
+/* ---- responsive grid ---- */
+@media (min-width: 992px) {
+ .links-box .links-card {
+ width: calc(25% - 10px);
+ }
+
+ .site-layout-1 .links-box .links-card,
+ .fluid-widget-wrap .links-box .links-card {
+ width: calc(20% - 10px);
+ }
+
+ .fluid-widget-wrap .links-box.links-style-bigcard .links-card,
+ .site-layout-1 .links-box.links-style-bigcard .links-card {
+ width: calc(16.6665% - 10px);
+ }
+
+ .sidebar .links-box .links-card {
+ width: calc(50% - 10px);
+ }
+
+ .fixed-wrap {
+ position: relative;
+ --fixed-width: 120px;
+ }
+
+ .fixed-wrap > .fixed-wrap-nav {
+ position: absolute;
+ width: var(--fixed-width);
+ }
+
+ .fixed-wrap > .fixed-wrap-nav + .fixed-wrap-content {
+ margin-left: calc(var(--fixed-width) + 15px);
+ }
+
+ .fixed-wrap-nav.affix {
+ position: sticky;
+ top: 80px;
+ }
+
+ .fixed-wrap .tab-nav-theme.mini-scrollbar {
+ display: flex;
+ flex-direction: column;
+ overflow: auto;
+ max-height: 70vh;
+ text-align: center;
+ border-bottom: none;
+ padding: 0;
+ margin: 0;
+ }
+
+ .fixed-wrap .tab-nav-theme.mini-scrollbar > li > a {
+ padding: 6px;
+ margin: 1px 0;
+ display: block;
+ font-size: 16px;
+ color: var(--muted-2-color, #888);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .fixed-wrap .tab-nav-theme.mini-scrollbar > li > a:hover {
+ color: var(--main-color, var(--color-primary));
+ }
+
+ .fixed-wrap .tab-nav-theme.mini-scrollbar > li.active > a {
+ color: var(--focus-color, var(--color-primary));
+ font-weight: 500;
+ background: color-mix(in srgb, var(--focus-color, var(--color-primary)) 12%, transparent);
+ border-radius: 6px;
+ }
+
+ .link-nav-submit {
+ display: block;
+ }
+}
+
+@media (max-width: 991px) {
+ .link-nav-submit {
+ display: none;
+ }
+
+ .link-cat-submit {
+ display: block;
+ }
+
+ .link-nav-box > .zib-widget {
+ background: transparent;
+ box-shadow: none;
+ padding: 0;
+ margin: 0;
+ }
+
+ .link-nav-box .nav {
+ display: flex;
+ gap: 8px;
+ overflow-x: auto;
+ margin: 0 0 10px;
+ padding: 0;
+ list-style: none;
+ }
+
+ .link-nav-box .nav > li {
+ display: inline-block;
+ flex: 0 0 auto;
+ }
+
+ .link-nav-box .nav > li > a {
+ padding: 2px 6px;
+ font-size: 1.05em;
+ white-space: nowrap;
+ }
+}
+
+@media (max-width: 640px) {
+ .links-box .links-card {
+ width: calc(50% - 10px);
+ }
+
+ .link-page-search-cover .tab-nav-theme li a {
+ padding: 0 3px;
+ font-size: 14px;
+ }
+
+ .links-page-container .fixed-wrap {
+ overflow: hidden;
+ }
+}
diff --git a/assets/css/routes/posts-navs.css b/assets/css/routes/posts-navs.css
new file mode 100644
index 00000000..fc601cb8
--- /dev/null
+++ b/assets/css/routes/posts-navs.css
@@ -0,0 +1,261 @@
+/**
+ * AKSRT 文章导航页 — zibll postsnavs shell + admin settings.
+ *
+ * @package AKSRT
+ */
+
+/* header card */
+.page-template-posts-navs .content-wrap,
+main.page-template-posts-navs {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 20px;
+}
+
+main.page-template-posts-navs .content-wrap {
+ flex: 1 1 0;
+ min-width: 0;
+}
+
+main.page-template-posts-navs .sidebar {
+ flex: 0 0 260px;
+ max-width: 100%;
+}
+
+.posts-navs .title-theme h2 {
+ margin: 0;
+ font-size: 1.15em;
+}
+
+.posts-navs__list {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.posts-navs__item {
+ margin: 0 0 10px;
+ padding: 0;
+}
+
+.posts-navs__item .text-ellipsis {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.posts-navs__item .icon-circle {
+ display: inline-block;
+ width: 4px;
+ height: 4px;
+ border-radius: 50%;
+ background: var(--muted-3-color, #ccc);
+ margin: 0 0.55em;
+ vertical-align: middle;
+}
+
+.posts-navs__item a {
+ color: var(--color-ink, inherit);
+ text-decoration: none;
+}
+
+.posts-navs__item a:hover {
+ color: var(--focus-color, var(--color-primary));
+}
+
+.posts-navs .theme-box {
+ margin-bottom: 20px;
+}
+
+.posts-navs .box-body.notop {
+ padding-top: 0;
+}
+
+/* TOC sidebar filled by section-navs.js */
+.posts-nav-box .posts-nav-lists,
+.posts-nav-box .aksrt-section-nav {
+ max-height: 400px;
+ padding-left: 10px;
+ overflow-y: auto;
+}
+
+.posts-nav-box .zib-widget {
+ background: var(--main-bg-color, var(--surface-1, #fff));
+ border-radius: 8px;
+ box-shadow: 0 1px 4px var(--main-shadow, rgba(0, 0, 0, 0.06));
+ padding: 10px;
+}
+
+.posts-nav-lists .bl {
+ border-left: 1px solid var(--main-border-color, #eee);
+ padding: 12px 10px 12px 0;
+ list-style: none;
+ margin: 0;
+ position: relative;
+}
+
+.posts-nav-lists li {
+ position: relative;
+ list-style: none;
+}
+
+.posts-nav-lists li a {
+ margin: 0 10px;
+ display: block;
+ border-radius: 4px;
+ padding: 8px;
+ margin-right: 20px;
+ color: var(--muted-2-color, #666);
+ text-decoration: none;
+}
+
+.posts-nav-lists li a:hover,
+.posts-nav-lists li.active a {
+ background: var(--main-shadow, rgba(0, 0, 0, 0.04));
+ color: var(--focus-color, var(--color-primary));
+}
+
+.posts-nav-lists li.n-H1 a,
+.posts-nav-lists li.n-H2 a {
+ font-weight: 700;
+}
+
+/* settings modal */
+#post-navs-sz.modal {
+ position: fixed;
+ inset: 0;
+ z-index: 1050;
+ display: none;
+ align-items: center;
+ justify-content: center;
+ background: rgba(0, 0, 0, 0.45);
+ padding: 16px;
+}
+
+#post-navs-sz.modal.is-open,
+#post-navs-sz.modal.show {
+ display: flex;
+}
+
+#post-navs-sz .modal-dialog {
+ width: min(640px, 100%);
+ max-height: 90vh;
+ overflow: auto;
+}
+
+#post-navs-sz .modal-content {
+ background: var(--main-bg-color, #fff);
+ border-radius: 10px;
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.18);
+}
+
+#post-navs-sz .modal-header,
+#post-navs-sz .modal-body,
+#post-navs-sz .modal-footer {
+ padding: 16px 20px;
+}
+
+#post-navs-sz .modal-header {
+ border-bottom: 1px solid var(--main-border-color, #eee);
+}
+
+#post-navs-sz .modal-footer {
+ border-top: 1px solid var(--main-border-color, #eee);
+ text-align: right;
+}
+
+#post-navs-sz .close {
+ float: right;
+ border: 0;
+ background: transparent;
+ cursor: pointer;
+}
+
+#post-navs-sz .form-control {
+ width: 100%;
+ padding: 8px 10px;
+ border: 1px solid var(--main-border-color, #ddd);
+ border-radius: 6px;
+ box-sizing: border-box;
+}
+
+#post-navs-sz .form-group {
+ margin-bottom: 14px;
+}
+
+#post-navs-sz .row {
+ display: flex;
+ flex-wrap: wrap;
+ margin: 0 -8px;
+}
+
+#post-navs-sz .col-xs-6,
+#post-navs-sz .col-sm-6 {
+ width: 50%;
+ padding: 0 8px;
+ box-sizing: border-box;
+}
+
+.cat-group {
+ height: 200px;
+ background: var(--body-bg-color, var(--surface-2, #f6f7f9));
+ border: 1px solid var(--main-border-color, #ddd);
+ border-radius: 4px;
+ overflow: hidden;
+ padding: 5px;
+ overflow-y: auto;
+}
+
+.sortable-cat-item {
+ background: var(--main-border-color, #e8e8e8);
+ padding: 4px 8px;
+ transition: 0.2s;
+ border-radius: 4px;
+ margin: 2px;
+ display: inline-block;
+ cursor: grab;
+ width: calc(100% - 15px);
+ min-width: 100px;
+ box-sizing: border-box;
+ user-select: none;
+}
+
+.sortable-cat-item .badge {
+ margin-left: 4px;
+ background: rgba(0, 0, 0, 0.08);
+ color: inherit;
+ border-radius: 10px;
+ padding: 0 6px;
+ font-size: 12px;
+}
+
+#cat-sortable-ok .sortable-cat-item {
+ background: rgba(73, 214, 253, 0.12);
+ color: #069cf3;
+}
+
+.sortable-cat-item.is-dragging {
+ opacity: 0.5;
+}
+
+.sortable-cat-item.sortable-selected {
+ background: rgba(251, 82, 82, 0.1) !important;
+ color: #fb5454 !important;
+}
+
+.cat-group.is-drop-target {
+ outline: 2px dashed var(--focus-color, #f04494);
+}
+
+@media (max-width: 991px) {
+ main.page-template-posts-navs .sidebar {
+ flex: 1 1 100%;
+ order: -1;
+ }
+
+ #post-navs-sz .col-xs-6,
+ #post-navs-sz .col-sm-6 {
+ width: 100%;
+ margin-bottom: 12px;
+ }
+}
diff --git a/assets/css/routes/user-auth.css b/assets/css/routes/user-auth.css
new file mode 100644
index 00000000..723a08e6
--- /dev/null
+++ b/assets/css/routes/user-auth.css
@@ -0,0 +1,89 @@
+/**
+ * User identity auth page styles (zibll user-auth).
+ *
+ * @package AKSRT
+ */
+
+.aksrt-user-auth-panel {
+ overflow: hidden;
+ margin-top: 20px;
+}
+
+.aksrt-user-auth-panel .colorful-bg.c-blue {
+ background: linear-gradient(135deg, #4e9bff 0%, #2f6df6 100%);
+ color: #fff;
+}
+
+.aksrt-user-auth-panel .muted-2-color {
+ color: var(--muted-2-color, #888);
+}
+
+.aksrt-user-auth-panel .form-control {
+ width: 100%;
+ padding: 8px 10px;
+ border: 1px solid var(--main-border-color, #ddd);
+ border-radius: 6px;
+ box-sizing: border-box;
+}
+
+.aksrt-user-auth-panel .mb20 {
+ margin-bottom: 20px;
+}
+
+.aksrt-user-auth-panel .mb6 {
+ margin-bottom: 6px;
+}
+
+.aksrt-user-auth-panel .but.c-blue,
+.aksrt-user-auth-panel button.but {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 6px;
+ background: var(--focus-color, #2f6df6);
+ color: #fff;
+ border: 0;
+ border-radius: 6px;
+ padding: 10px 18px;
+ cursor: pointer;
+}
+
+.aksrt-user-auth-panel .btn-block {
+ width: 100%;
+}
+
+.aksrt-user-auth-panel__imgs {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.aksrt-user-auth-panel__imgs .preview-item {
+ width: 96px;
+ height: 96px;
+ border-radius: 6px;
+ overflow: hidden;
+ border: 1px solid var(--main-border-color, #eee);
+}
+
+.aksrt-user-auth-panel__imgs img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ display: block;
+}
+
+.aksrt-user-auth-panel .c-red {
+ color: #e74c3c;
+}
+
+.page-template-user-auth .content-wrap {
+ display: flex;
+ gap: 20px;
+ flex-wrap: wrap;
+}
+
+.page-template-user-auth .content-layout {
+ flex: 1 1 0;
+ min-width: 0;
+}
diff --git a/assets/js/header-userbox.js b/assets/js/header-userbox.js
new file mode 100644
index 00000000..12f20529
--- /dev/null
+++ b/assets/js/header-userbox.js
@@ -0,0 +1,113 @@
+/**
+ * Header user-box: check-in REST + signout modal.
+ *
+ * @package AKSRT
+ */
+(function () {
+ 'use strict';
+
+ function restBase() {
+ if (window.aksrtData && window.aksrtData.restUrl) return window.aksrtData.restUrl.replace(/\/?$/, '/');
+ if (window.aksrtData && window.aksrtData.siteUrl) return String(window.aksrtData.siteUrl).replace(/\/?$/, '/') + 'wp-json/';
+ return '/wp-json/';
+ }
+
+ function restNonce() {
+ return (window.aksrtData && window.aksrtData.restNonce) || '';
+ }
+
+ function toast(msg, type) {
+ if (window.aksrt && typeof window.aksrt.toast === 'function') {
+ window.aksrt.toast(msg, type || 'info');
+ return;
+ }
+ // eslint-disable-next-line no-alert
+ window.alert(msg);
+ }
+
+ function openModal(id) {
+ var modal = document.getElementById(id);
+ if (!modal) return;
+ modal.classList.add('is-open', 'show');
+ modal.setAttribute('aria-hidden', 'false');
+ }
+
+ function closeModal(id) {
+ var modal = document.getElementById(id);
+ if (!modal) return;
+ modal.classList.remove('is-open', 'show');
+ modal.setAttribute('aria-hidden', 'true');
+ }
+
+ function initSignoutModal() {
+ document.addEventListener('click', function (e) {
+ var openBtn = e.target.closest('[data-target="#modal_signout"], [href="#modal_signout"]');
+ if (openBtn) {
+ e.preventDefault();
+ openModal('modal_signout');
+ return;
+ }
+ var dismiss = e.target.closest('#modal_signout [data-dismiss="modal"]');
+ if (dismiss) {
+ e.preventDefault();
+ closeModal('modal_signout');
+ return;
+ }
+ if (e.target && e.target.id === 'modal_signout') {
+ closeModal('modal_signout');
+ }
+ });
+ document.addEventListener('keydown', function (e) {
+ if (e.key === 'Escape') closeModal('modal_signout');
+ });
+ }
+
+ function initCheckin() {
+ document.addEventListener('click', function (e) {
+ var btn = e.target.closest('[data-aksrt-checkin="1"]');
+ if (!btn || btn.disabled) return;
+ e.preventDefault();
+ btn.disabled = true;
+ fetch(restBase() + 'aksrt/v1/signin', {
+ method: 'POST',
+ credentials: 'same-origin',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-WP-Nonce': restNonce(),
+ },
+ body: '{}',
+ })
+ .then(function (r) {
+ return r.json().then(function (data) {
+ return { ok: r.ok, data: data };
+ });
+ })
+ .then(function (res) {
+ if (!res.ok) {
+ var msg = (res.data && (res.data.message || res.data.msg)) || '签到失败';
+ toast(msg, 'danger');
+ btn.disabled = false;
+ return;
+ }
+ toast((res.data && res.data.message) || '签到成功', 'success');
+ btn.classList.add('is-done');
+ btn.innerHTML = ' 今日已签到';
+ })
+ .catch(function () {
+ toast('网络错误', 'danger');
+ btn.disabled = false;
+ });
+ });
+ }
+
+ function init() {
+ initSignoutModal();
+ initCheckin();
+ }
+
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', init);
+ } else {
+ init();
+ }
+})();
diff --git a/assets/js/links-page.js b/assets/js/links-page.js
new file mode 100644
index 00000000..c3eb37c3
--- /dev/null
+++ b/assets/js/links-page.js
@@ -0,0 +1,221 @@
+/**
+ * AKSRT 网址导航页 — search tabs, sticky cat nav, submit modal/AJAX.
+ *
+ * @package AKSRT
+ */
+(function () {
+ 'use strict';
+
+ function qs(sel, root) {
+ return (root || document).querySelector(sel);
+ }
+
+ function qsa(sel, root) {
+ return Array.prototype.slice.call((root || document).querySelectorAll(sel));
+ }
+
+ function ajaxUrl() {
+ if (window.aksrtData && window.aksrtData.ajaxUrl) return window.aksrtData.ajaxUrl;
+ if (window.ajaxurl) return window.ajaxurl;
+ return '/wp-admin/admin-ajax.php';
+ }
+
+ function toast(msg, type) {
+ if (window.aksrt && typeof window.aksrt.toast === 'function') {
+ window.aksrt.toast(msg, type || 'info');
+ return;
+ }
+ if (window.notyf) {
+ try {
+ window.notyf(msg, type === 'danger' ? 'danger' : '');
+ return;
+ } catch (e) { /* ignore */ }
+ }
+ // eslint-disable-next-line no-alert
+ window.alert(msg);
+ }
+
+ /* ---------- search engine tabs ---------- */
+ function initSearchTabs() {
+ var cover = qs('.link-page-search-cover');
+ if (!cover) return;
+
+ qsa('.tab-nav-theme a[data-aksrt-tab-target]', cover).forEach(function (a) {
+ a.addEventListener('click', function (e) {
+ e.preventDefault();
+ var target = a.getAttribute('data-aksrt-tab-target');
+ if (!target) return;
+ qsa('.tab-nav-theme li', cover).forEach(function (li) {
+ li.classList.remove('active');
+ });
+ if (a.parentElement) a.parentElement.classList.add('active');
+ qsa('.tab-pane', cover).forEach(function (pane) {
+ pane.classList.remove('active', 'in');
+ });
+ var pane = qs(target, cover);
+ if (pane) pane.classList.add('active', 'in');
+ });
+ });
+ }
+
+ /* ---------- sticky category nav highlight ---------- */
+ function initCatNav() {
+ var wrap = qs('.links-page-container .fixed-wrap');
+ if (!wrap) return;
+ var nav = qs('.link-nav-box', wrap);
+ var links = qsa('.link-nav-box a[href^="#"]', wrap);
+ var sections = links
+ .map(function (a) {
+ var id = a.getAttribute('href');
+ return id ? document.getElementById(id.replace(/^#/, '')) : null;
+ })
+ .filter(Boolean);
+ if (!links.length || !sections.length) return;
+
+ links.forEach(function (a) {
+ a.addEventListener('click', function (e) {
+ var id = a.getAttribute('href');
+ var el = id ? document.getElementById(id.replace(/^#/, '')) : null;
+ if (!el) return;
+ e.preventDefault();
+ var top = el.getBoundingClientRect().top + window.pageYOffset - 90;
+ window.scrollTo({ top: top, behavior: 'smooth' });
+ });
+ });
+
+ function updateActive() {
+ var y = window.pageYOffset + 120;
+ var current = sections[0];
+ for (var i = 0; i < sections.length; i++) {
+ if (sections[i].offsetTop <= y) current = sections[i];
+ }
+ if (!current) return;
+ links.forEach(function (a) {
+ var li = a.parentElement;
+ if (!li) return;
+ if (a.getAttribute('href') === '#' + current.id) {
+ li.classList.add('active');
+ } else {
+ li.classList.remove('active');
+ }
+ });
+ if (nav) nav.classList.add('affix');
+ }
+
+ window.addEventListener('scroll', updateActive, { passive: true });
+ updateActive();
+ }
+
+ /* ---------- submit modal ---------- */
+ function initSubmitModal() {
+ var modal = qs('#submit-links-modal');
+ if (!modal) return;
+
+ function openModal(e) {
+ if (e) e.preventDefault();
+ modal.classList.add('is-open', 'show');
+ modal.setAttribute('aria-hidden', 'false');
+ document.documentElement.classList.add('aksrt-modal-open');
+ }
+
+ function closeModal(e) {
+ if (e) e.preventDefault();
+ modal.classList.remove('is-open', 'show');
+ modal.setAttribute('aria-hidden', 'true');
+ document.documentElement.classList.remove('aksrt-modal-open');
+ }
+
+ qsa('a[href="#submit-links-modal"], [data-toggle="modal"][href="#submit-links-modal"]').forEach(function (btn) {
+ btn.addEventListener('click', openModal);
+ });
+
+ qsa('[data-dismiss="modal"]', modal).forEach(function (btn) {
+ btn.addEventListener('click', closeModal);
+ });
+
+ modal.addEventListener('click', function (e) {
+ if (e.target === modal) closeModal(e);
+ });
+
+ document.addEventListener('keydown', function (e) {
+ if (e.key === 'Escape' && modal.classList.contains('is-open')) closeModal(e);
+ });
+
+ var fileInput = qs('.aksrt-links-logo-input', modal);
+ var preview = qs('.aksrt-links-logo-preview', modal);
+ if (fileInput && preview) {
+ fileInput.addEventListener('change', function () {
+ var file = fileInput.files && fileInput.files[0];
+ if (!file) return;
+ var url = URL.createObjectURL(file);
+ preview.src = url;
+ });
+ }
+
+ var form = qs('.aksrt-links-submit-form', modal);
+ if (!form) return;
+
+ form.addEventListener('submit', function (e) {
+ e.preventDefault();
+ var btn = qs('.aksrt-links-submit-btn', form);
+ if (btn) {
+ btn.disabled = true;
+ btn.classList.add('loading');
+ }
+
+ var fd = new FormData(form);
+ if (!fd.get('action')) fd.set('action', 'aksrt_frontend_links_submit');
+
+ fetch(ajaxUrl(), {
+ method: 'POST',
+ body: fd,
+ credentials: 'same-origin',
+ })
+ .then(function (r) {
+ return r.json();
+ })
+ .then(function (data) {
+ if (!data || data.error) {
+ toast((data && data.msg) || '提交失败', 'danger');
+ return;
+ }
+ toast(data.msg || '提交成功', 'success');
+ if (data.reload) {
+ window.setTimeout(function () {
+ window.location.reload();
+ }, 600);
+ } else {
+ closeModal();
+ form.reset();
+ }
+ })
+ .catch(function () {
+ toast('网络错误,请稍后重试', 'danger');
+ })
+ .finally(function () {
+ if (btn) {
+ btn.disabled = false;
+ btn.classList.remove('loading');
+ }
+ });
+ });
+ }
+
+ function init() {
+ if (!document.body.classList.contains('page-template-templates-pages-page-links-php')
+ && !qs('.page-template-links')
+ && !qs('.links-page-container')
+ && !qs('#submit-links-modal')) {
+ // Still bind if modal exists alone.
+ }
+ initSearchTabs();
+ initCatNav();
+ initSubmitModal();
+ }
+
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', init);
+ } else {
+ init();
+ }
+})();
diff --git a/assets/js/posts-navs-page.js b/assets/js/posts-navs-page.js
new file mode 100644
index 00000000..aa81a3fc
--- /dev/null
+++ b/assets/js/posts-navs-page.js
@@ -0,0 +1,255 @@
+/**
+ * AKSRT 文章导航页 — admin settings modal + HTML5 drag-sort (no SortableJS dependency).
+ * TOC generation is handled by section-navs.js via [data-nav] + .posts-nav-box.
+ *
+ * @package AKSRT
+ */
+(function () {
+ 'use strict';
+
+ function qs(sel, root) {
+ return (root || document).querySelector(sel);
+ }
+
+ function qsa(sel, root) {
+ return Array.prototype.slice.call((root || document).querySelectorAll(sel));
+ }
+
+ function ajaxUrl() {
+ if (window.aksrtData && window.aksrtData.ajaxUrl) return window.aksrtData.ajaxUrl;
+ if (window.ajaxurl) return window.ajaxurl;
+ return '/wp-admin/admin-ajax.php';
+ }
+
+ function toast(msg, type) {
+ if (window.aksrt && typeof window.aksrt.toast === 'function') {
+ window.aksrt.toast(msg, type || 'info');
+ return;
+ }
+ // eslint-disable-next-line no-alert
+ window.alert(msg);
+ }
+
+ function initModal() {
+ var modal = qs('#post-navs-sz');
+ if (!modal) return;
+
+ function openModal(e) {
+ if (e) e.preventDefault();
+ modal.classList.add('is-open', 'show');
+ modal.setAttribute('aria-hidden', 'false');
+ }
+
+ function closeModal(e) {
+ if (e) e.preventDefault();
+ modal.classList.remove('is-open', 'show');
+ modal.setAttribute('aria-hidden', 'true');
+ }
+
+ qsa('[data-toggle="modal"][data-target="#post-navs-sz"], a[href="#post-navs-sz"]').forEach(function (el) {
+ el.addEventListener('click', openModal);
+ });
+ // Title [设置] uses data-target.
+ qsa('[data-target="#post-navs-sz"]').forEach(function (el) {
+ el.addEventListener('click', openModal);
+ });
+ qsa('[data-dismiss="modal"]', modal).forEach(function (btn) {
+ btn.addEventListener('click', closeModal);
+ });
+ modal.addEventListener('click', function (e) {
+ if (e.target === modal) closeModal(e);
+ });
+ document.addEventListener('keydown', function (e) {
+ if (e.key === 'Escape' && modal.classList.contains('is-open')) closeModal(e);
+ });
+ }
+
+ function initDragSort() {
+ var left = qs('#cat-sortable');
+ var right = qs('#cat-sortable-ok');
+ if (!left || !right) return;
+
+ var dragEl = null;
+
+ function onDragStart(e) {
+ dragEl = e.currentTarget;
+ dragEl.classList.add('is-dragging');
+ try {
+ e.dataTransfer.effectAllowed = 'move';
+ e.dataTransfer.setData('text/plain', dragEl.getAttribute('data-id') || '');
+ } catch (err) { /* IE */ }
+ }
+
+ function onDragEnd() {
+ if (dragEl) dragEl.classList.remove('is-dragging');
+ dragEl = null;
+ qsa('.cat-group').forEach(function (g) {
+ g.classList.remove('is-drop-target');
+ });
+ }
+
+ function bindItem(el) {
+ el.setAttribute('draggable', 'true');
+ el.addEventListener('dragstart', onDragStart);
+ el.addEventListener('dragend', onDragEnd);
+ }
+
+ qsa('.sortable-cat-item', left).forEach(bindItem);
+ qsa('.sortable-cat-item', right).forEach(bindItem);
+
+ [left, right].forEach(function (group) {
+ group.addEventListener('dragover', function (e) {
+ e.preventDefault();
+ group.classList.add('is-drop-target');
+ if (!dragEl) return;
+ var after = getDragAfterElement(group, e.clientY);
+ if (after == null) {
+ group.appendChild(dragEl);
+ } else {
+ group.insertBefore(dragEl, after);
+ }
+ });
+ group.addEventListener('dragleave', function () {
+ group.classList.remove('is-drop-target');
+ });
+ group.addEventListener('drop', function (e) {
+ e.preventDefault();
+ group.classList.remove('is-drop-target');
+ });
+ });
+
+ function getDragAfterElement(container, y) {
+ var els = qsa('.sortable-cat-item:not(.is-dragging)', container);
+ var closest = { offset: Number.NEGATIVE_INFINITY, element: null };
+ els.forEach(function (child) {
+ var box = child.getBoundingClientRect();
+ var offset = y - box.top - box.height / 2;
+ if (offset < 0 && offset > closest.offset) {
+ closest = { offset: offset, element: child };
+ }
+ });
+ return closest.element;
+ }
+ }
+
+ function initSave() {
+ var form = qs('#aksrt-posts-navs-settings');
+ if (!form) return;
+
+ form.addEventListener('submit', function (e) {
+ e.preventDefault();
+ var ids = [];
+ qsa('#cat-sortable-ok .sortable-cat-item').forEach(function (item) {
+ var id = item.getAttribute('data-id');
+ if (id) ids.push(id);
+ });
+ if (!ids.length) {
+ toast('请选择需要显示的分类', 'danger');
+ return;
+ }
+
+ var fd = new FormData(form);
+ fd.set('action', 'aksrt_post_navs_settings');
+ // PHP accepts array; append each.
+ fd.delete('navs_show_cat_id');
+ ids.forEach(function (id) {
+ fd.append('navs_show_cat_id[]', id);
+ });
+
+ var btn = qs('button[type="submit"]', form);
+ if (btn) btn.disabled = true;
+
+ fetch(ajaxUrl(), {
+ method: 'POST',
+ body: fd,
+ credentials: 'same-origin',
+ })
+ .then(function (r) { return r.json(); })
+ .then(function (data) {
+ if (!data || data.error) {
+ toast((data && data.msg) || '保存失败', 'danger');
+ return;
+ }
+ toast(data.msg || '保存成功', 'success');
+ if (data.reload) {
+ window.setTimeout(function () { window.location.reload(); }, 400);
+ }
+ })
+ .catch(function () {
+ toast('网络错误', 'danger');
+ })
+ .finally(function () {
+ if (btn) btn.disabled = false;
+ });
+ });
+ }
+
+ /**
+ * Build simple TOC into .posts-nav-box if section-navs hasn't already.
+ * Uses category h2 headings inside .posts-navs.
+ */
+ function initFallbackToc() {
+ var box = qs('.posts-nav-box');
+ var root = qs('.posts-navs[data-nav]');
+ if (!box || !root) return;
+ if (box.querySelector('.posts-nav-lists, .aksrt-section-nav, .toc-list')) return;
+
+ var headings = qsa('.title-theme h2, h2', root);
+ if (headings.length < 1) return;
+
+ var title = box.getAttribute('data-title') || '导航目录';
+ var list = '';
+ headings.forEach(function (h, i) {
+ if (!h.id) h.id = 'navs-sec-' + i;
+ list += '
' + (h.textContent || '').trim() + '';
+ });
+
+ box.innerHTML =
+ '' +
+ '';
+
+ qsa('a[href^="#"]', box).forEach(function (a) {
+ a.addEventListener('click', function (e) {
+ var id = a.getAttribute('href');
+ var el = id ? document.getElementById(id.replace(/^#/, '')) : null;
+ if (!el) return;
+ e.preventDefault();
+ var top = el.getBoundingClientRect().top + window.pageYOffset - 90;
+ window.scrollTo({ top: top, behavior: 'smooth' });
+ });
+ });
+
+ function highlight() {
+ var y = window.pageYOffset + 120;
+ var current = headings[0];
+ headings.forEach(function (h) {
+ if (h.offsetTop <= y) current = h;
+ });
+ qsa('li', box).forEach(function (li) {
+ var a = li.querySelector('a');
+ if (a && current && a.getAttribute('href') === '#' + current.id) {
+ li.classList.add('active');
+ } else {
+ li.classList.remove('active');
+ }
+ });
+ }
+ window.addEventListener('scroll', highlight, { passive: true });
+ highlight();
+ }
+
+ function init() {
+ initModal();
+ initDragSort();
+ initSave();
+ // Defer so section-navs.js can own TOC first.
+ window.setTimeout(initFallbackToc, 50);
+ }
+
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', init);
+ } else {
+ init();
+ }
+})();
diff --git a/assets/js/user-auth-page.js b/assets/js/user-auth-page.js
new file mode 100644
index 00000000..8de307e5
--- /dev/null
+++ b/assets/js/user-auth-page.js
@@ -0,0 +1,64 @@
+/**
+ * User auth apply form AJAX.
+ *
+ * @package AKSRT
+ */
+(function () {
+ 'use strict';
+
+ function ajaxUrl() {
+ if (window.aksrtData && window.aksrtData.ajaxUrl) return window.aksrtData.ajaxUrl;
+ return '/wp-admin/admin-ajax.php';
+ }
+
+ function toast(msg, type) {
+ if (window.aksrt && typeof window.aksrt.toast === 'function') {
+ window.aksrt.toast(msg, type || 'info');
+ return;
+ }
+ // eslint-disable-next-line no-alert
+ window.alert(msg);
+ }
+
+ function init() {
+ var form = document.querySelector('.aksrt-user-auth-form');
+ if (!form) return;
+
+ form.addEventListener('submit', function (e) {
+ e.preventDefault();
+ var btn = form.querySelector('button[type="submit"]');
+ if (btn) btn.disabled = true;
+ var fd = new FormData(form);
+ if (!fd.get('action')) fd.set('action', 'aksrt_user_auth_apply');
+
+ fetch(ajaxUrl(), {
+ method: 'POST',
+ body: fd,
+ credentials: 'same-origin',
+ })
+ .then(function (r) { return r.json(); })
+ .then(function (data) {
+ if (!data || data.error) {
+ toast((data && data.msg) || '提交失败', 'danger');
+ return;
+ }
+ toast(data.msg || '提交成功', 'success');
+ if (data.reload) {
+ window.setTimeout(function () { window.location.reload(); }, 500);
+ }
+ })
+ .catch(function () {
+ toast('网络错误', 'danger');
+ })
+ .finally(function () {
+ if (btn) btn.disabled = false;
+ });
+ });
+ }
+
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', init);
+ } else {
+ init();
+ }
+})();
diff --git a/functions.php b/functions.php
index da58522d..5a9f176e 100644
--- a/functions.php
+++ b/functions.php
@@ -249,6 +249,18 @@ if (class_exists('\AKSRT\Core\CommentActions')) {
if (class_exists('\AKSRT\Core\GoRedirect')) {
\AKSRT\Core\GoRedirect::get_instance()->init();
}
+if (class_exists('\AKSRT\Core\LinksSubmit')) {
+ \AKSRT\Core\LinksSubmit::get_instance()->init();
+}
+if (class_exists('\AKSRT\Core\LinksPageMeta')) {
+ \AKSRT\Core\LinksPageMeta::get_instance()->init();
+}
+if (class_exists('\AKSRT\Core\PostsNavs')) {
+ \AKSRT\Core\PostsNavs::get_instance()->init();
+}
+if (class_exists('\AKSRT\User\AuthApply')) {
+ \AKSRT\User\AuthApply::get_instance()->init();
+}
if (class_exists('\AKSRT\Messages\SiteNotice')) {
\AKSRT\Messages\SiteNotice::get_instance()->init();
}
diff --git a/header.php b/header.php
index 115573c1..628799c9 100644
--- a/header.php
+++ b/header.php
@@ -303,11 +303,32 @@ if (!empty($aksrt_bg_styles)) {
+ ' . $checkin . ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ }
+ }
+ if (function_exists('aksrt_header_user_wallet_mini')) {
+ echo '' . aksrt_header_user_wallet_mini(get_current_user_id()) . '
'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ } else {
+ ?>
+
+
@@ -326,7 +347,7 @@ if (!empty($aksrt_bg_styles)) {
-
+
@@ -370,6 +391,16 @@ if (!empty($aksrt_bg_styles)) {
+
+ render_social_buttons(__('快速登录', 'aksrt'));
+ if ($oauth_html !== '') {
+ echo '' . $oauth_html . '
'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ }
+ }
+ ?>
+
@@ -385,6 +416,8 @@ if (!empty($aksrt_bg_styles)) {
+
+
diff --git a/inc/bootstrap.php b/inc/bootstrap.php
index 79b751a0..2996a21e 100644
--- a/inc/bootstrap.php
+++ b/inc/bootstrap.php
@@ -43,6 +43,8 @@ require_once AKSRT_DIR . '/inc/helpers/aksrt-coupon-order.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-credits.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-null.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-ajax-list.php';
+require_once AKSRT_DIR . '/inc/helpers/aksrt-links.php';
+require_once AKSRT_DIR . '/inc/helpers/aksrt-header-userbox.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-identity.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-rewards.php';
require_once AKSRT_DIR . '/inc/helpers/menu-decoration.php';
diff --git a/inc/core-hooks/part-2.php b/inc/core-hooks/part-2.php
index 7ab3b95b..9664fed8 100644
--- a/inc/core-hooks/part-2.php
+++ b/inc/core-hooks/part-2.php
@@ -7,12 +7,11 @@ defined('ABSPATH') || exit;
add_filter('show_admin_bar', '__return_false');
// ============================================================
-// 隐藏不需要的默认菜单项
+// WordPress 链接管理(网址导航 / 书签)
+// zibll enables link_manager; AKSRT keeps it for page-links.
// ============================================================
-add_action('admin_menu', function () {
- remove_menu_page('link-manager.php');
-});
+add_filter('pre_option_link_manager_enabled', '__return_true');
// ============================================================
// Gravatar 头像源替换(4层拦截:get_avatar_url / pre_get_avatar_data / avatar_defaults / ob_start 兜底)
diff --git a/inc/helpers/aksrt-header-userbox.php b/inc/helpers/aksrt-header-userbox.php
new file mode 100644
index 00000000..442ec454
--- /dev/null
+++ b/inc/helpers/aksrt-header-userbox.php
@@ -0,0 +1,161 @@
+ 0 ? $user_id : get_current_user_id();
+ if ($user_id <= 0 || !class_exists('\AKSRT\Credits\Signin')) {
+ return '';
+ }
+ $cfg = class_exists('\AKSRT\Settings\Settings')
+ ? \AKSRT\Settings\Settings::get_signin_reward_settings()
+ : ['enabled' => false];
+ if (empty($cfg['enabled'])) {
+ return '';
+ }
+
+ // Lightweight today status via private API if available.
+ $signed = false;
+ try {
+ $signin = \AKSRT\Credits\Signin::get_instance();
+ // Prefer public method if present.
+ if (method_exists($signin, 'is_signed_today')) {
+ $signed = (bool) $signin->is_signed_today($user_id);
+ } else {
+ // Fallback: direct meta/table probe via rest_today logic is heavy; use option day key.
+ $day = wp_date('Y-m-d');
+ $signed = (bool) get_user_meta($user_id, 'aksrt_signin_' . $day, true);
+ }
+ } catch (\Throwable $e) {
+ $signed = false;
+ }
+
+ if ($signed) {
+ return '';
+ }
+
+ return '';
+ }
+endif;
+
+if (!function_exists('aksrt_header_user_wallet_mini')) :
+ /**
+ * Mini wallet strip: credits + cash balance.
+ */
+ function aksrt_header_user_wallet_mini(int $user_id = 0): string {
+ $user_id = $user_id > 0 ? $user_id : get_current_user_id();
+ if ($user_id <= 0) {
+ return '';
+ }
+ $credits = function_exists('aksrt_user_credits') ? (int) aksrt_user_credits($user_id) : 0;
+ $currency = class_exists('\AKSRT\Settings\Settings')
+ ? \AKSRT\Settings\Settings::get_currency_name()
+ : __('积分', 'aksrt');
+ $wallet = 0.0;
+ if (class_exists('\AKSRT\Credits\Balance')) {
+ $wallet = (float) \AKSRT\Credits\Balance::balance($user_id);
+ }
+ $center = function_exists('aksrt_get_user_center_url') ? aksrt_get_user_center_url('assets') : '#';
+
+ $html = '';
+ return $html;
+ }
+endif;
+
+if (!function_exists('aksrt_header_user_badges_row')) :
+ /**
+ * Identity / medal chips under profile.
+ */
+ function aksrt_header_user_badges_row(int $user_id = 0): string {
+ $user_id = $user_id > 0 ? $user_id : get_current_user_id();
+ if ($user_id <= 0 || !function_exists('aksrt_render_user_identity_chips')) {
+ return '';
+ }
+ $chips = aksrt_render_user_identity_chips($user_id, 'card');
+ if ($chips === '') {
+ return '';
+ }
+ return '';
+ }
+endif;
+
+if (!function_exists('aksrt_header_payvip_bar')) :
+ /**
+ * VIP status / open CTA bar.
+ */
+ function aksrt_header_payvip_bar(int $user_id = 0): string {
+ $user_id = $user_id > 0 ? $user_id : get_current_user_id();
+ if ($user_id <= 0) {
+ return '';
+ }
+ $badge = function_exists('aksrt_render_vip_badge') ? aksrt_render_vip_badge($user_id, 'md') : '';
+ if ($badge !== '') {
+ return '';
+ }
+ // Guest-style open VIP for non-members if VIP feature on.
+ $vip_url = function_exists('aksrt_get_user_center_url') ? aksrt_get_user_center_url('vip') : '#';
+ $enabled = true;
+ if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_vip_settings')) {
+ $vs = \AKSRT\Settings\Settings::get_vip_settings();
+ $enabled = !empty($vs['enabled']) || !empty($vs['vip1_enabled']) || !empty($vs['vip2_enabled']);
+ }
+ if (!$enabled) {
+ return '';
+ }
+ return '';
+ }
+endif;
+
+if (!function_exists('aksrt_render_signout_modal')) :
+ /**
+ * Confirm logout modal markup (once per page).
+ */
+ function aksrt_render_signout_modal(): void {
+ static $done = false;
+ if ($done || !is_user_logged_in()) {
+ return;
+ }
+ $done = true;
+ $logout = wp_logout_url(home_url('/'));
+ ?>
+
+ create_go_link($url);
+ }
+ return $url;
+ }
+endif;
+
+if (!function_exists('aksrt_get_page_links_settings')) :
+ /**
+ * Read page_links_* meta for a page.
+ *
+ * @return array
+ */
+ function aksrt_get_page_links_settings(int $post_id = 0): array {
+ if ($post_id <= 0) {
+ $post_id = (int) get_queried_object_id();
+ }
+ $cats = get_post_meta($post_id, 'page_links_category', true);
+ if (!is_array($cats)) {
+ $cats = $cats !== '' && $cats !== null ? array_filter(array_map('intval', (array) $cats)) : [];
+ } else {
+ $cats = array_values(array_filter(array_map('intval', $cats)));
+ }
+ $search_types = get_post_meta($post_id, 'page_links_search_types', true);
+ if (!is_array($search_types)) {
+ $search_types = $search_types ? array_values(array_filter(array_map('sanitize_key', (array) $search_types))) : [];
+ } else {
+ $search_types = array_values(array_filter(array_map('sanitize_key', $search_types)));
+ }
+ $submit_cats = get_post_meta($post_id, 'page_links_submit_cats', true);
+ if (!is_array($submit_cats)) {
+ $submit_cats = $submit_cats !== '' && $submit_cats !== null ? array_filter(array_map('intval', (array) $submit_cats)) : [];
+ } else {
+ $submit_cats = array_values(array_filter(array_map('intval', $submit_cats)));
+ }
+
+ $style = sanitize_key((string) get_post_meta($post_id, 'page_links_style', true));
+ if (!in_array($style, ['card', 'bigcard', 'image', 'simple'], true)) {
+ $style = 'card';
+ }
+ $orderby = sanitize_key((string) get_post_meta($post_id, 'page_links_orderby', true));
+ if (!in_array($orderby, ['name', 'updated', 'rating', 'rand', 'id', 'length'], true)) {
+ $orderby = 'name';
+ }
+ $order = strtoupper((string) get_post_meta($post_id, 'page_links_order', true));
+ if (!in_array($order, ['ASC', 'DESC'], true)) {
+ $order = 'ASC';
+ }
+ $position = sanitize_key((string) get_post_meta($post_id, 'page_links_content_position', true));
+ if (!in_array($position, ['top', 'bottom'], true)) {
+ $position = 'top';
+ }
+
+ return [
+ 'content_s' => (bool) get_post_meta($post_id, 'page_links_content_s', true),
+ 'content_position' => $position,
+ 'search_s' => (bool) get_post_meta($post_id, 'page_links_search_s', true),
+ 'search_types' => $search_types,
+ 'category' => $cats,
+ 'style' => $style,
+ 'limit' => max(0, (int) get_post_meta($post_id, 'page_links_limit', true)),
+ 'orderby' => $orderby,
+ 'order' => $order,
+ 'go_s' => (bool) get_post_meta($post_id, 'page_links_go_s', true),
+ 'blank_s' => (bool) get_post_meta($post_id, 'page_links_blank_s', true),
+ // Default nofollow ON (zibll default true).
+ 'nofollow_s' => get_post_meta($post_id, 'page_links_nofollow_s', true) === ''
+ ? true
+ : (bool) get_post_meta($post_id, 'page_links_nofollow_s', true),
+ 'submit_s' => (bool) get_post_meta($post_id, 'page_links_submit_s', true),
+ 'submit_sign_s' => get_post_meta($post_id, 'page_links_submit_sign_s', true) === ''
+ ? true
+ : (bool) get_post_meta($post_id, 'page_links_submit_sign_s', true),
+ 'submit_cats' => $submit_cats,
+ 'submit_title' => (string) (get_post_meta($post_id, 'page_links_submit_title', true) ?: __('申请入驻', 'aksrt')),
+ 'submit_dec' => (string) get_post_meta($post_id, 'page_links_submit_dec', true),
+ ];
+ }
+endif;
+
+if (!function_exists('aksrt_links_box')) :
+ /**
+ * Render bookmark cards (zibll zib_links_box).
+ *
+ * @param array $links Bookmark rows from get_bookmarks().
+ */
+ function aksrt_links_box($links = [], string $type = 'card', bool $nofollow = true, bool $go_link = false, bool $blank_s = false): string {
+ if (empty($links) || !is_array($links)) {
+ return '';
+ }
+ $type = in_array($type, ['card', 'bigcard', 'image', 'simple'], true) ? $type : 'card';
+ $placeholder = get_template_directory_uri() . '/assets/img/placeholder.svg';
+ $html = '';
+ $i = 0;
+
+ foreach ($links as $raw) {
+ $link = (array) $raw;
+ if (empty($link['href']) && !empty($link['link_url'])) {
+ $link['href'] = $link['link_url'];
+ }
+ if (empty($link['title']) && !empty($link['link_name'])) {
+ $link['title'] = $link['link_name'];
+ }
+ if (empty($link['src']) && !empty($link['link_image'])) {
+ $link['src'] = $link['link_image'];
+ }
+ if (empty($link['desc']) && !empty($link['link_description'])) {
+ $link['desc'] = $link['link_description'];
+ }
+ if ($blank_s) {
+ $link['blank'] = true;
+ }
+ if (empty($link['blank']) && !empty($link['link_target'])) {
+ $link['blank'] = true;
+ }
+
+ $href = !empty($link['href']) ? (string) $link['href'] : '';
+ $title = !empty($link['title']) ? (string) $link['title'] : '';
+ if ($href === '' || $title === '') {
+ continue;
+ }
+
+ if ($go_link || !empty($link['go_link'])) {
+ $href = aksrt_go_link($href, true);
+ } else {
+ $href = esc_url($href);
+ }
+
+ $src = !empty($link['src']) ? esc_url((string) $link['src']) : '';
+ $blank = !empty($link['blank']) ? ' target="_blank"' : '';
+ $dec = !empty($link['desc']) ? (string) $link['desc'] : '';
+ $rel = $nofollow ? ' rel="nofollow noopener noreferrer"' : ' rel="noopener noreferrer"';
+ $img_src = $src !== '' ? $src : $placeholder;
+ $img = '
';
+ $data_dec = $dec !== ''
+ ? ' title="' . esc_attr($title) . '" data-content="' . esc_attr($dec) . '"'
+ : ' data-content="' . esc_attr($title) . '"';
+
+ if ($type === 'bigcard') {
+ $html .= '';
+ } elseif ($type === 'image') {
+ $html .= '' . $img . '';
+ } elseif ($type === 'simple') {
+ $sc = $i === 0 ? '' : 'icon-spot';
+ $html .= '' . esc_html($title) . '';
+ } else {
+ $html .= '';
+ }
+ $i++;
+ }
+
+ return $html;
+ }
+endif;
+
+if (!function_exists('aksrt_page_links_html')) :
+ /**
+ * Build the multi/single category links block for a page.
+ */
+ function aksrt_page_links_html(int $post_id = 0): string {
+ $post_id = $post_id > 0 ? $post_id : (int) get_queried_object_id();
+ $s = aksrt_get_page_links_settings($post_id);
+ $cats = $s['category'];
+ if (empty($cats)) {
+ if (current_user_can('manage_links')) {
+ return '';
+ }
+ return '' . esc_html__('暂无链接', 'aksrt') . '
';
+ }
+
+ $limit = (int) $s['limit'];
+ $orderby = (string) $s['orderby'];
+ $order = (string) $s['order'];
+ $style = (string) $s['style'];
+ $nofollow = (bool) $s['nofollow_s'];
+ $go_s = (bool) $s['go_s'];
+ $blank_s = (bool) $s['blank_s'];
+ $submit_s = (bool) $s['submit_s'];
+ $submit_title = (string) $s['submit_title'];
+ $is_mobile = wp_is_mobile();
+ $links_con = '';
+
+ if (count($cats) > 1) {
+ $link_cat_con = '';
+ $link_cat_nav = '';
+ foreach ($cats as $cat_id) {
+ $args = [
+ 'orderby' => $orderby,
+ 'order' => $order,
+ 'limit' => $limit > 0 ? $limit : -1,
+ 'category' => (int) $cat_id,
+ ];
+ $_link = aksrt_links_box(get_bookmarks($args), $style, $nofollow, $go_s, $blank_s);
+ if (!$_link) {
+ continue;
+ }
+ $term = get_term((int) $cat_id, 'link_category');
+ if (!$term || is_wp_error($term)) {
+ continue;
+ }
+ $_id = 'links-' . (int) $cat_id;
+ $link_cat_con .= '';
+ $link_cat_nav .= '' . esc_html($term->name) . '';
+ }
+
+ if ($link_cat_con === '') {
+ $links_con = '';
+ } else {
+ $submit_nav = $submit_s
+ ? ''
+ : '';
+ $submit_con = $submit_s
+ ? ''
+ : '';
+ $offset_top = $is_mobile ? '-8' : '';
+ $offset_bottom = $is_mobile ? '20' : '-30';
+ $links_con = ''
+ . '
' . $link_cat_con . $submit_con . '
';
+ }
+ } else {
+ $cat_id = (int) $cats[0];
+ $args = [
+ 'orderby' => $orderby,
+ 'order' => $order,
+ 'limit' => $limit > 0 ? $limit : -1,
+ 'category' => $cat_id,
+ ];
+ $submit_con = $submit_s
+ ? ''
+ : '';
+ $links_con = ''
+ . aksrt_links_box(get_bookmarks($args), $style, $nofollow, $go_s, $blank_s)
+ . '
' . $submit_con;
+ }
+
+ if ($links_con === '') {
+ if (current_user_can('manage_links')) {
+ return '';
+ }
+ return '' . esc_html__('暂无链接', 'aksrt') . '
';
+ }
+
+ return '' . $links_con . '
';
+ }
+endif;
+
+if (!function_exists('aksrt_link_get_search_cover')) :
+ /**
+ * Search cover with multi-engine tabs (zibll zib_link_get_search_cover).
+ */
+ function aksrt_link_get_search_cover(int $post_id = 0): string {
+ $post_id = $post_id > 0 ? $post_id : (int) get_queried_object_id();
+ $s = aksrt_get_page_links_settings($post_id);
+ if (empty($s['search_s']) || empty($s['search_types'])) {
+ return '';
+ }
+
+ $search_types_args = [
+ 'self' => [
+ 'name' => __('站内', 'aksrt'),
+ 'input_name' => 's',
+ 'url' => home_url('/'),
+ ],
+ 'baidu' => [
+ 'name' => __('百度', 'aksrt'),
+ 'input_name' => 'wd',
+ 'url' => 'https://www.baidu.com/s',
+ ],
+ 'google' => [
+ 'name' => __('谷歌', 'aksrt'),
+ 'input_name' => 'q',
+ 'url' => 'https://www.google.com/search',
+ ],
+ 'bing' => [
+ 'name' => __('必应', 'aksrt'),
+ 'input_name' => 'q',
+ 'url' => 'https://cn.bing.com/search',
+ ],
+ 'sogou' => [
+ 'name' => __('搜狗', 'aksrt'),
+ 'input_name' => 'query',
+ 'url' => 'https://www.sogou.com/web',
+ ],
+ '360' => [
+ 'name' => '360',
+ 'input_name' => 'q',
+ 'url' => 'https://www.so.com/s',
+ ],
+ ];
+
+ $type_nav = '';
+ $type_con = '';
+ $i = 0;
+ foreach ($s['search_types'] as $k) {
+ if (!isset($search_types_args[$k])) {
+ continue;
+ }
+ $cfg = $search_types_args[$k];
+ $active = $i === 0 ? ' active' : '';
+ $pane_id = 'link-page-' . $post_id . '-' . $k;
+ $type_nav .= ''
+ . esc_html($cfg['name']) . '';
+ $type_con .= '';
+ $i++;
+ }
+ if ($type_nav === '') {
+ return '';
+ }
+
+ $title = get_the_title($post_id);
+ $img = '';
+ $thumb_id = get_post_thumbnail_id($post_id);
+ if ($thumb_id) {
+ $image = wp_get_attachment_image_src($thumb_id, 'full');
+ $img = !empty($image[0]) ? (string) $image[0] : '';
+ }
+ if ($img === '') {
+ $img = (string) get_post_meta($post_id, 'page_header_cover_img', true);
+ }
+ if ($img === '' && class_exists('\AKSRT\Settings\Settings')) {
+ $img = (string) \AKSRT\Settings\Settings::get_value('page_header_cover_img', '');
+ }
+ if ($img === '') {
+ $img = get_template_directory_uri() . '/assets/img/placeholder.svg';
+ }
+ $src = get_template_directory_uri() . '/assets/img/placeholder.svg';
+
+ $search = '';
+
+ return ''
+ . '
 . ')
'
+ . $search . '
';
+ }
+endif;
+
+if (!function_exists('aksrt_submit_links_modal')) :
+ /**
+ * Frontend submit modal markup (zibll zib_submit_links_modal).
+ *
+ * @param array{title?:string,dec?:string,sign?:bool,cats?:int[]} $args
+ */
+ function aksrt_submit_links_modal(array $args = []): string {
+ $defaults = [
+ 'title' => __('申请入驻', 'aksrt'),
+ 'dec' => '',
+ 'sign' => true,
+ 'cats' => [],
+ ];
+ $args = array_merge($defaults, $args);
+ $title = (string) $args['title'];
+ $header = $title !== ''
+ ? ''
+ . ''
+ . esc_html($title) . '
'
+ : '';
+
+ $body = '';
+ if (!empty($args['dec'])) {
+ $body .= '' . wp_kses_post((string) $args['dec']) . '
';
+ }
+
+ $need_login = !empty($args['sign']) && !is_user_logged_in();
+ if ($need_login) {
+ $sign_url = function_exists('aksrt_get_login_url')
+ ? aksrt_get_login_url()
+ : (function_exists('aksrt_get_sign_page_url') ? aksrt_get_sign_page_url('login') : wp_login_url());
+ $body .= '';
+ $body .= '
' . esc_html__('请先登录', 'aksrt') . '
';
+ $body .= '
'
+ . '' . esc_html__('登录', 'aksrt') . '
';
+ if (class_exists('\AKSRT\Auth\OAuth') && method_exists(\AKSRT\Auth\OAuth::get_instance(), 'render_social_buttons')) {
+ $social = (string) \AKSRT\Auth\OAuth::get_instance()->render_social_buttons(__('使用以下方式快速登录', 'aksrt'));
+ if ($social !== '') {
+ $body .= '
' . $social . '
';
+ }
+ }
+ $body .= '
';
+ } else {
+ $term_args = [
+ 'taxonomy' => 'link_category',
+ 'hide_empty' => false,
+ ];
+ if (!empty($args['cats']) && is_array($args['cats'])) {
+ $term_args['include'] = array_map('intval', $args['cats']);
+ $term_args['orderby'] = 'include';
+ }
+ $terms = get_terms($term_args);
+ $cats_options = '';
+ if (!is_wp_error($terms) && !empty($terms)) {
+ foreach ($terms as $item) {
+ $cats_options .= '';
+ }
+ }
+ $cats_field = $cats_options !== ''
+ ? '' . esc_html__('网站类别', 'aksrt') . '
'
+ . '
'
+ : '';
+
+ $placeholder_upload = get_template_directory_uri() . '/assets/img/placeholder.svg';
+ $body .= '';
+ }
+
+ return ''
+ . '
'
+ . $header . $body
+ . '
';
+ }
+endif;
diff --git a/src/AKSRT/Admin/Native/UsersMenus.php b/src/AKSRT/Admin/Native/UsersMenus.php
index 7a579e85..f3ea77ac 100644
--- a/src/AKSRT/Admin/Native/UsersMenus.php
+++ b/src/AKSRT/Admin/Native/UsersMenus.php
@@ -550,6 +550,18 @@ class UsersMenus {
} elseif ($status === 'verified') {
delete_user_meta($user_id, 'aksrt_user_verify_reason');
}
+ // Promote apply payload to public auth info when approved.
+ if ($status === 'verified') {
+ $apply = get_user_meta($user_id, 'aksrt_user_verify_apply', true);
+ if (is_array($apply)) {
+ update_user_meta($user_id, 'aksrt_user_verify_info', [
+ 'name' => (string) ($apply['name'] ?? ''),
+ 'desc' => (string) ($apply['desc'] ?? ''),
+ 'type' => (string) ($apply['type'] ?? ''),
+ 'time' => current_time('Y-m-d H:i'),
+ ]);
+ }
+ }
$log = get_option('aksrt_verify_review_log', []);
$log = is_array($log) ? $log : [];
$log[] = [
diff --git a/src/AKSRT/Core/LinksPageMeta.php b/src/AKSRT/Core/LinksPageMeta.php
new file mode 100644
index 00000000..fc6aa66b
--- /dev/null
+++ b/src/AKSRT/Core/LinksPageMeta.php
@@ -0,0 +1,302 @@
+ID;
+ if (!$this->is_links_template($post_id)) {
+ echo '' . esc_html__('将页面模板设为「AKSRT - 网址导航」后在此配置分类、样式与提交模块。', 'aksrt') . '
';
+ return;
+ }
+
+ $s = function_exists('aksrt_get_page_links_settings')
+ ? aksrt_get_page_links_settings($post_id)
+ : [];
+
+ wp_nonce_field('aksrt_page_links_meta', 'aksrt_page_links_meta_nonce');
+
+ $terms = get_terms([
+ 'taxonomy' => 'link_category',
+ 'hide_empty' => false,
+ ]);
+ if (is_wp_error($terms)) {
+ $terms = [];
+ }
+
+ $selected_cats = array_map('intval', (array) ($s['category'] ?? []));
+ $submit_cats = array_map('intval', (array) ($s['submit_cats'] ?? []));
+ $search_types = (array) ($s['search_types'] ?? []);
+ $engine_options = [
+ 'self' => __('站内', 'aksrt'),
+ 'baidu' => __('百度', 'aksrt'),
+ 'google' => __('谷歌', 'aksrt'),
+ 'bing' => __('必应', 'aksrt'),
+ 'sogou' => __('搜狗', 'aksrt'),
+ '360' => '360',
+ ];
+ ?>
+
+
+ |
+
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+ 链接管理 中创建分类与链接。', 'aksrt')),
+ esc_url(admin_url('link-manager.php'))
+ );
+ ?>
+
+
+
+
+
+ |
+
+
+ |
+
+ __('图文列表', 'aksrt'),
+ 'bigcard' => __('大卡片', 'aksrt'),
+ 'image' => __('纯图片', 'aksrt'),
+ ];
+ foreach ($styles as $key => $label) :
+ ?>
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+ is_links_template($post_id) && empty($_POST['page_links_category']) && empty($_POST['page_links_submit_s'])) {
+ // Still allow save if user just switched template in same request.
+ $tpl = isset($_POST['page_template']) ? (string) wp_unslash($_POST['page_template']) : '';
+ if ($tpl !== 'templates/pages/page-links.php') {
+ return;
+ }
+ }
+
+ $bool_keys = [
+ 'page_links_content_s',
+ 'page_links_search_s',
+ 'page_links_go_s',
+ 'page_links_blank_s',
+ 'page_links_nofollow_s',
+ 'page_links_submit_s',
+ 'page_links_submit_sign_s',
+ ];
+ foreach ($bool_keys as $key) {
+ update_post_meta($post_id, $key, isset($_POST[$key]) ? 1 : 0);
+ }
+
+ $position = isset($_POST['page_links_content_position']) ? sanitize_key((string) wp_unslash($_POST['page_links_content_position'])) : 'top';
+ if (!in_array($position, ['top', 'bottom'], true)) {
+ $position = 'top';
+ }
+ update_post_meta($post_id, 'page_links_content_position', $position);
+
+ $style = isset($_POST['page_links_style']) ? sanitize_key((string) wp_unslash($_POST['page_links_style'])) : 'card';
+ if (!in_array($style, ['card', 'bigcard', 'image', 'simple'], true)) {
+ $style = 'card';
+ }
+ update_post_meta($post_id, 'page_links_style', $style);
+
+ $orderby = isset($_POST['page_links_orderby']) ? sanitize_key((string) wp_unslash($_POST['page_links_orderby'])) : 'name';
+ if (!in_array($orderby, ['name', 'updated', 'rating', 'rand', 'id', 'length'], true)) {
+ $orderby = 'name';
+ }
+ update_post_meta($post_id, 'page_links_orderby', $orderby);
+
+ $order = isset($_POST['page_links_order']) ? strtoupper(sanitize_text_field(wp_unslash((string) $_POST['page_links_order']))) : 'ASC';
+ update_post_meta($post_id, 'page_links_order', $order === 'DESC' ? 'DESC' : 'ASC');
+
+ $limit = isset($_POST['page_links_limit']) ? max(0, (int) $_POST['page_links_limit']) : 0;
+ update_post_meta($post_id, 'page_links_limit', $limit);
+
+ $cats = isset($_POST['page_links_category']) ? array_values(array_filter(array_map('intval', (array) wp_unslash($_POST['page_links_category'])))) : [];
+ update_post_meta($post_id, 'page_links_category', $cats);
+
+ $submit_cats = isset($_POST['page_links_submit_cats']) ? array_values(array_filter(array_map('intval', (array) wp_unslash($_POST['page_links_submit_cats'])))) : [];
+ update_post_meta($post_id, 'page_links_submit_cats', $submit_cats);
+
+ $engines = isset($_POST['page_links_search_types']) ? array_values(array_filter(array_map('sanitize_key', (array) wp_unslash($_POST['page_links_search_types'])))) : [];
+ $allowed = ['self', 'baidu', 'google', 'bing', 'sogou', '360'];
+ $engines = array_values(array_intersect($engines, $allowed));
+ update_post_meta($post_id, 'page_links_search_types', $engines);
+
+ $title = isset($_POST['page_links_submit_title']) ? sanitize_text_field(wp_unslash((string) $_POST['page_links_submit_title'])) : '';
+ update_post_meta($post_id, 'page_links_submit_title', $title);
+
+ $dec = isset($_POST['page_links_submit_dec']) ? wp_kses_post(wp_unslash((string) $_POST['page_links_submit_dec'])) : '';
+ update_post_meta($post_id, 'page_links_submit_dec', $dec);
+ }
+}
diff --git a/src/AKSRT/Core/LinksSubmit.php b/src/AKSRT/Core/LinksSubmit.php
new file mode 100644
index 00000000..50a1de5e
--- /dev/null
+++ b/src/AKSRT/Core/LinksSubmit.php
@@ -0,0 +1,123 @@
+ 1, 'ys' => 'danger', 'msg' => __('安全校验失败,请刷新后重试', 'aksrt')]);
+ }
+
+ if (isset($_COOKIE['aksrt_links_submit_time'])) {
+ wp_send_json(['error' => 1, 'ys' => 'danger', 'msg' => __('操作过于频繁,请稍候再试', 'aksrt')]);
+ }
+
+ $link_name = isset($_POST['link_name']) ? sanitize_text_field(wp_unslash((string) $_POST['link_name'])) : '';
+ $link_url = isset($_POST['link_url']) ? esc_url_raw(wp_unslash((string) $_POST['link_url'])) : '';
+ $link_desc = isset($_POST['link_description']) ? sanitize_text_field(wp_unslash((string) $_POST['link_description'])) : '';
+ $cat_raw = isset($_POST['link_category']) ? wp_unslash($_POST['link_category']) : [];
+
+ if ($link_name === '') {
+ wp_send_json(['error' => 1, 'ys' => 'danger', 'msg' => __('请填写网站名称', 'aksrt')]);
+ }
+ if ($link_url === '' || !wp_http_validate_url($link_url)) {
+ wp_send_json(['error' => 1, 'ys' => 'danger', 'msg' => __('网站地址格式错误', 'aksrt')]);
+ }
+
+ // Optional logo upload.
+ $logo_url = '';
+ if (!empty($_FILES['image']['name'])) {
+ require_once ABSPATH . 'wp-admin/includes/file.php';
+ require_once ABSPATH . 'wp-admin/includes/media.php';
+ require_once ABSPATH . 'wp-admin/includes/image.php';
+ $attachment_id = media_handle_upload('image', 0);
+ if (is_wp_error($attachment_id)) {
+ wp_send_json(['error' => 1, 'ys' => 'danger', 'msg' => $attachment_id->get_error_message()]);
+ }
+ $src = wp_get_attachment_image_src((int) $attachment_id, 'medium');
+ $logo_url = !empty($src[0]) ? (string) $src[0] : (string) wp_get_attachment_url((int) $attachment_id);
+ }
+
+ $categories = [];
+ if (is_array($cat_raw)) {
+ $categories = array_values(array_filter(array_map('intval', $cat_raw)));
+ } elseif ($cat_raw !== '' && $cat_raw !== null) {
+ $categories = [absint($cat_raw)];
+ }
+
+ // Duplicate URL guard.
+ global $wpdb;
+ $exists = (int) $wpdb->get_var(
+ $wpdb->prepare(
+ "SELECT COUNT(1) FROM {$wpdb->links} WHERE link_url = %s",
+ $link_url
+ )
+ );
+ if ($exists > 0) {
+ wp_send_json(['error' => 1, 'ys' => 'danger', 'msg' => __('您的链接已提交,请勿重复提交', 'aksrt')]);
+ }
+
+ if (!function_exists('wp_insert_link')) {
+ require_once ABSPATH . 'wp-admin/includes/bookmark.php';
+ }
+
+ $linkdata = [
+ 'link_name' => $link_name,
+ 'link_url' => $link_url,
+ 'link_description' => $link_desc,
+ 'link_image' => $logo_url,
+ // Non-admins create invisible links pending review (zibll parity).
+ 'link_visible' => current_user_can('manage_links') ? 'Y' : 'N',
+ 'link_category' => $categories,
+ ];
+
+ $links_id = wp_insert_link($linkdata, true);
+ if (is_wp_error($links_id)) {
+ wp_send_json(['error' => 1, 'ys' => 'danger', 'msg' => $links_id->get_error_message()]);
+ }
+
+ // 30s client throttle cookie.
+ if (!headers_sent()) {
+ setcookie('aksrt_links_submit_time', (string) time(), time() + 30, COOKIEPATH ?: '/', COOKIE_DOMAIN, is_ssl(), true);
+ }
+
+ $msg = $linkdata['link_visible'] === 'Y'
+ ? __('提交成功', 'aksrt')
+ : __('提交成功,等待管理员处理', 'aksrt');
+
+ /**
+ * Fires after a frontend link submission is stored.
+ *
+ * @param array $linkdata Sanitized bookmark data.
+ * @param int $links_id New link ID.
+ */
+ do_action('aksrt_frontend_links_submit_success', $linkdata, (int) $links_id);
+
+ wp_send_json(['error' => 0, 'msg' => $msg, 'reload' => true]);
+ }
+}
diff --git a/src/AKSRT/Core/PostsNavs.php b/src/AKSRT/Core/PostsNavs.php
new file mode 100644
index 00000000..4021fb78
--- /dev/null
+++ b/src/AKSRT/Core/PostsNavs.php
@@ -0,0 +1,77 @@
+ 1, 'ys' => 'danger', 'msg' => __('权限不足', 'aksrt')]);
+ }
+ if (!check_ajax_referer('aksrt_post_navs_settings', '_wpnonce', false)) {
+ wp_send_json(['error' => 1, 'ys' => 'danger', 'msg' => __('安全校验失败', 'aksrt')]);
+ }
+
+ $page_id = isset($_POST['page_id']) ? absint($_POST['page_id']) : 0;
+ if ($page_id <= 0 || get_post_type($page_id) !== 'page') {
+ wp_send_json(['error' => 1, 'ys' => 'danger', 'msg' => __('无效页面', 'aksrt')]);
+ }
+
+ $cat_ids = [];
+ if (isset($_POST['navs_show_cat_id'])) {
+ $raw = wp_unslash($_POST['navs_show_cat_id']);
+ if (is_array($raw)) {
+ $cat_ids = array_values(array_filter(array_map('intval', $raw)));
+ } elseif (is_string($raw) && $raw !== '') {
+ $decoded = json_decode($raw, true);
+ if (is_array($decoded)) {
+ $cat_ids = array_values(array_filter(array_map('intval', $decoded)));
+ } else {
+ $cat_ids = array_values(array_filter(array_map('intval', explode(',', $raw))));
+ }
+ }
+ }
+
+ if (empty($cat_ids)) {
+ wp_send_json(['error' => 1, 'ys' => 'danger', 'msg' => __('请选择需要显示的分类', 'aksrt')]);
+ }
+
+ if (isset($_POST['navs_page_name'])) {
+ update_post_meta($page_id, 'navs_page_name', sanitize_text_field(wp_unslash((string) $_POST['navs_page_name'])));
+ }
+ if (isset($_POST['navs_page_desc'])) {
+ update_post_meta($page_id, 'navs_page_desc', sanitize_text_field(wp_unslash((string) $_POST['navs_page_desc'])));
+ }
+ update_post_meta($page_id, 'navs_show_cat_id', $cat_ids);
+
+ wp_send_json([
+ 'error' => 0,
+ 'msg' => __('保存成功', 'aksrt'),
+ 'reload'=> true,
+ 'ids' => $cat_ids,
+ ]);
+ }
+}
diff --git a/src/AKSRT/Core/ScriptsPart1b.php b/src/AKSRT/Core/ScriptsPart1b.php
index 47f1ab73..18bcd8a0 100644
--- a/src/AKSRT/Core/ScriptsPart1b.php
+++ b/src/AKSRT/Core/ScriptsPart1b.php
@@ -129,6 +129,27 @@ trait ScriptsPart1b {
}
}
+ // Header user-box density (check-in / wallet / signout modal)
+ $hub_css = get_template_directory() . '/assets/css/frontend/nav/header-userbox.css';
+ if (file_exists($hub_css)) {
+ wp_enqueue_style(
+ 'aksrt-header-userbox',
+ $base_uri . '/assets/css/frontend/nav/header-userbox.css',
+ [$core_dep],
+ (string) filemtime($hub_css)
+ );
+ }
+ $hub_js = get_template_directory() . '/assets/js/header-userbox.js';
+ if (file_exists($hub_js)) {
+ wp_enqueue_script(
+ 'aksrt-header-userbox',
+ $base_uri . '/assets/js/header-userbox.js',
+ [],
+ (string) filemtime($hub_js),
+ true
+ );
+ }
+
// Print stylesheet — only load on singular pages
if (is_singular()) {
wp_enqueue_style(
@@ -381,6 +402,85 @@ trait ScriptsPart1b {
);
}
+ // 网址导航页(zibll links.php)
+ if (is_page_template('templates/pages/page-links.php')) {
+ $links_css = get_template_directory() . '/assets/css/routes/links.css';
+ if (file_exists($links_css)) {
+ wp_enqueue_style(
+ 'aksrt-route-links',
+ $base_uri . '/assets/css/routes/links.css',
+ ['aksrt-tokens'],
+ (string) filemtime($links_css)
+ );
+ }
+ $links_js = get_template_directory() . '/assets/js/links-page.js';
+ if (file_exists($links_js)) {
+ wp_enqueue_script(
+ 'aksrt-links-page',
+ $base_uri . '/assets/js/links-page.js',
+ ['jquery'],
+ (string) filemtime($links_js),
+ true
+ );
+ }
+ }
+
+ // 文章导航页(zibll postsnavs.php)
+ if (is_page_template('templates/pages/page-posts-navs.php')) {
+ $pn_css = get_template_directory() . '/assets/css/routes/posts-navs.css';
+ if (file_exists($pn_css)) {
+ wp_enqueue_style(
+ 'aksrt-route-posts-navs',
+ $base_uri . '/assets/css/routes/posts-navs.css',
+ ['aksrt-tokens'],
+ (string) filemtime($pn_css)
+ );
+ }
+ $section_navs = get_template_directory() . '/assets/js/section-navs.js';
+ if (file_exists($section_navs)) {
+ wp_enqueue_script(
+ 'aksrt-section-navs',
+ $base_uri . '/assets/js/section-navs.js',
+ ['jquery'],
+ (string) filemtime($section_navs),
+ true
+ );
+ }
+ $pn_js = get_template_directory() . '/assets/js/posts-navs-page.js';
+ if (file_exists($pn_js)) {
+ wp_enqueue_script(
+ 'aksrt-posts-navs-page',
+ $base_uri . '/assets/js/posts-navs-page.js',
+ ['jquery'],
+ (string) filemtime($pn_js),
+ true
+ );
+ }
+ }
+
+ // 用户身份认证页(zibll user-auth.php)
+ if (is_page_template('templates/pages/page-user-auth.php')) {
+ $ua_css = get_template_directory() . '/assets/css/routes/user-auth.css';
+ if (file_exists($ua_css)) {
+ wp_enqueue_style(
+ 'aksrt-route-user-auth',
+ $base_uri . '/assets/css/routes/user-auth.css',
+ ['aksrt-tokens'],
+ (string) filemtime($ua_css)
+ );
+ }
+ $ua_js = get_template_directory() . '/assets/js/user-auth-page.js';
+ if (file_exists($ua_js)) {
+ wp_enqueue_script(
+ 'aksrt-user-auth-page',
+ $base_uri . '/assets/js/user-auth-page.js',
+ [],
+ (string) filemtime($ua_js),
+ true
+ );
+ }
+ }
+
// 交易中心共享壳层(购物车 / 订单 / 收益)
$is_commerce_center = is_page_template('templates/pages/page-orders.php')
|| is_page_template('templates/pages/page-cart.php')
diff --git a/src/AKSRT/Core/Templates.php b/src/AKSRT/Core/Templates.php
index f4e1f2bf..e653710f 100644
--- a/src/AKSRT/Core/Templates.php
+++ b/src/AKSRT/Core/Templates.php
@@ -46,6 +46,8 @@ class Templates {
'templates/pages/page-submit.php' => __('AKSRT - 写文章/投稿', 'aksrt'),
'templates/pages/page-posts-navs.php' => __('AKSRT - 文章导航', 'aksrt'),
'templates/pages/page-friends.php' => __('AKSRT - 友情链接', 'aksrt'),
+ 'templates/pages/page-links.php' => __('AKSRT - 网址导航', 'aksrt'),
+ 'templates/pages/page-user-auth.php' => __('AKSRT - 用户身份认证', 'aksrt'),
'templates/pages/page-orders.php' => __('AKSRT - 订单中心', 'aksrt'),
'templates/pages/page-revenue.php' => __('AKSRT - 收益中心', 'aksrt'),
'templates/pages/page-cart.php' => __('AKSRT - 购物车', 'aksrt'),
diff --git a/src/AKSRT/User/AuthApply.php b/src/AKSRT/User/AuthApply.php
new file mode 100644
index 00000000..f6107796
--- /dev/null
+++ b/src/AKSRT/User/AuthApply.php
@@ -0,0 +1,207 @@
+
+ * }
+ */
+ public static function settings(): array {
+ $all = class_exists('\AKSRT\Settings\Settings')
+ ? (array) \AKSRT\Settings\Settings::get_all()
+ : [];
+ $enabled = !isset($all['user_verify_enabled']) || !empty($all['user_verify_enabled']);
+ $types_raw = (string) ($all['user_verify_apply_option'] ?? "real_name|实名认证\norganization|企业认证");
+ $types = [];
+ foreach (preg_split('/\r\n|\r|\n/', $types_raw) as $line) {
+ $line = trim($line);
+ if ($line === '') {
+ continue;
+ }
+ $parts = array_map('trim', explode('|', $line, 2));
+ $slug = sanitize_key($parts[0] ?? '');
+ $label = $parts[1] ?? $parts[0];
+ if ($slug === '') {
+ continue;
+ }
+ $types[] = ['slug' => $slug, 'label' => (string) $label];
+ }
+ return [
+ 'enabled' => $enabled,
+ 'allow_apply' => !isset($all['user_verify_allow_apply']) || !empty($all['user_verify_allow_apply']),
+ 'public_display' => !isset($all['user_verify_public_display']) || !empty($all['user_verify_public_display']),
+ 'badge_text' => (string) ($all['user_verify_badge_text'] ?? __('已认证', 'aksrt')),
+ 'limit_level' => max(0, (int) ($all['user_verify_limit_level'] ?? 0)),
+ 'desc' => (string) ($all['user_verify_desc'] ?? ''),
+ 'disable_desc' => (string) ($all['user_verify_disable_desc'] ?? ''),
+ 'types' => $types,
+ ];
+ }
+
+ public static function get_status(int $user_id): string {
+ if ($user_id <= 0) {
+ return '';
+ }
+ return sanitize_key((string) get_user_meta($user_id, self::STATUS_META, true));
+ }
+
+ public static function is_verified(int $user_id): bool {
+ return self::get_status($user_id) === 'verified';
+ }
+
+ /**
+ * @return array
+ */
+ public static function get_auth_info(int $user_id): array {
+ $info = get_user_meta($user_id, self::INFO_META, true);
+ return is_array($info) ? $info : [];
+ }
+
+ /**
+ * @return array
+ */
+ public static function get_apply_payload(int $user_id): array {
+ $apply = get_user_meta($user_id, self::APPLY_META, true);
+ return is_array($apply) ? $apply : [];
+ }
+
+ public function ajax_apply(): void {
+ if (!is_user_logged_in()) {
+ wp_send_json(['error' => 1, 'msg' => __('请先登录', 'aksrt')]);
+ }
+ if (!check_ajax_referer('aksrt_user_auth_apply', '_wpnonce', false)) {
+ wp_send_json(['error' => 1, 'msg' => __('安全校验失败', 'aksrt')]);
+ }
+
+ $user_id = get_current_user_id();
+ $s = self::settings();
+ if (!$s['enabled'] || !$s['allow_apply']) {
+ wp_send_json(['error' => 1, 'msg' => __('暂不能申请身份认证', 'aksrt')]);
+ }
+ if (self::is_verified($user_id)) {
+ wp_send_json(['error' => 1, 'msg' => __('您已是认证用户', 'aksrt')]);
+ }
+ if (self::get_status($user_id) === 'pending') {
+ wp_send_json(['error' => 1, 'msg' => __('您的申请正在审核中', 'aksrt')]);
+ }
+ if ($s['limit_level'] > 0 && class_exists('\AKSRT\User\Level')) {
+ $lv = (int) Level::get_level($user_id);
+ if ($lv < $s['limit_level']) {
+ wp_send_json([
+ 'error' => 1,
+ 'msg' => sprintf(
+ /* translators: %d: required level */
+ __('等级不足,需达到 LV.%d 后申请', 'aksrt'),
+ $s['limit_level']
+ ),
+ ]);
+ }
+ }
+
+ $name = isset($_POST['name']) ? sanitize_text_field(wp_unslash((string) $_POST['name'])) : '';
+ $desc = isset($_POST['desc']) ? sanitize_textarea_field(wp_unslash((string) $_POST['desc'])) : '';
+ $msg = isset($_POST['msg']) ? sanitize_textarea_field(wp_unslash((string) $_POST['msg'])) : '';
+ $type = isset($_POST['type']) ? sanitize_key((string) wp_unslash($_POST['type'])) : '';
+ if ($name === '') {
+ wp_send_json(['error' => 1, 'msg' => __('请填写认证身份名称', 'aksrt')]);
+ }
+
+ $images = [];
+ if (!empty($_FILES['image']['name'])) {
+ require_once ABSPATH . 'wp-admin/includes/file.php';
+ require_once ABSPATH . 'wp-admin/includes/media.php';
+ require_once ABSPATH . 'wp-admin/includes/image.php';
+
+ $files = $_FILES['image'];
+ // Normalize multi-file upload.
+ $names = $files['name'];
+ if (!is_array($names)) {
+ $names = [$names];
+ $tmp = [
+ 'name' => $names,
+ 'type' => [$files['type']],
+ 'tmp_name' => [$files['tmp_name']],
+ 'error' => [$files['error']],
+ 'size' => [$files['size']],
+ ];
+ $files = $tmp;
+ }
+ $count = min(3, count($files['name']));
+ for ($i = 0; $i < $count; $i++) {
+ if (empty($files['name'][$i]) || (int) $files['error'][$i] !== UPLOAD_ERR_OK) {
+ continue;
+ }
+ $file = [
+ 'name' => $files['name'][$i],
+ 'type' => $files['type'][$i],
+ 'tmp_name' => $files['tmp_name'][$i],
+ 'error' => $files['error'][$i],
+ 'size' => $files['size'][$i],
+ ];
+ $_FILES['aksrt_auth_img'] = $file;
+ $aid = media_handle_upload('aksrt_auth_img', 0);
+ if (!is_wp_error($aid)) {
+ $url = wp_get_attachment_url((int) $aid);
+ if ($url) {
+ $images[] = $url;
+ }
+ }
+ }
+ unset($_FILES['aksrt_auth_img']);
+ }
+
+ $payload = [
+ 'name' => $name,
+ 'desc' => $desc,
+ 'msg' => $msg,
+ 'type' => $type,
+ 'img' => $images,
+ 'time' => current_time('Y-m-d H:i'),
+ ];
+ update_user_meta($user_id, self::APPLY_META, $payload);
+ update_user_meta($user_id, self::STATUS_META, 'pending');
+ delete_user_meta($user_id, self::REASON_META);
+
+ /**
+ * @param int $user_id
+ * @param array $payload
+ */
+ do_action('aksrt_user_auth_apply_submitted', $user_id, $payload);
+
+ wp_send_json([
+ 'error' => 0,
+ 'msg' => __('提交成功,请等待管理员审核', 'aksrt'),
+ 'reload' => true,
+ ]);
+ }
+}
diff --git a/templates/pages/page-links.php b/templates/pages/page-links.php
new file mode 100644
index 00000000..4dcf05ea
--- /dev/null
+++ b/templates/pages/page-links.php
@@ -0,0 +1,82 @@
+
+
+
+
+
' . esc_html(get_the_title()) . '
';
+ }
+ }
+
+ if (function_exists('aksrt_link_get_search_cover')) {
+ echo aksrt_link_get_search_cover($post_id); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ }
+
+ $links_html = function_exists('aksrt_page_links_html') ? aksrt_page_links_html($post_id) : '';
+ $content_s = !empty($s['content_s']);
+ $position = (string) ($s['content_position'] ?? 'top');
+
+ if ($position !== 'top') {
+ echo $links_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ }
+
+ if ($content_s) {
+ echo '
';
+ }
+
+ if ($position === 'top') {
+ echo $links_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ }
+ endwhile;
+
+ if (comments_open() || get_comments_number()) {
+ comments_template();
+ }
+ ?>
+
+
+
+
+ (string) ($s['submit_title'] ?? __('申请入驻', 'aksrt')),
+ 'dec' => (string) ($s['submit_dec'] ?? ''),
+ 'sign' => !empty($s['submit_sign_s']),
+ 'cats' => (array) ($s['submit_cats'] ?? []),
+ ]);
+}
+
+get_footer();
diff --git a/templates/pages/page-posts-navs.php b/templates/pages/page-posts-navs.php
index 28e84ebe..2d371d28 100644
--- a/templates/pages/page-posts-navs.php
+++ b/templates/pages/page-posts-navs.php
@@ -1,65 +1,228 @@
ID : (int) get_queried_object_id();
-$categories = get_categories(['hide_empty' => true, 'orderby' => 'count', 'order' => 'DESC', 'number' => 20]);
-$tags = get_tags(['hide_empty' => true, 'orderby' => 'count', 'order' => 'DESC', 'number' => 40]);
-
-if (function_exists('aksrt_archive_open_shell')) {
- aksrt_archive_open_shell([
- 'main_class' => 'site-main container content-shell content-shell--page page-content-default',
- 'has_sidebar' => false,
- 'page_kind' => 'posts-navs',
- ]);
+$show_cat_id = get_post_meta($post_id, 'navs_show_cat_id', true);
+if (!is_array($show_cat_id)) {
+ $show_cat_id = $show_cat_id !== '' && $show_cat_id !== null
+ ? array_values(array_filter(array_map('intval', (array) $show_cat_id)))
+ : [];
+} else {
+ $show_cat_id = array_values(array_filter(array_map('intval', $show_cat_id)));
}
+
+$page_desc = (string) get_post_meta($post_id, 'navs_page_desc', true);
+$page_name = (string) get_post_meta($post_id, 'navs_page_name', true);
+$title = get_the_title($post_id);
+$page_name = $page_name !== '' ? $page_name : $title;
+
+$all_cats = get_categories([
+ 'orderby' => 'term_group',
+ 'order' => 'ASC',
+ 'hide_empty' => false,
+]);
+
+$can_admin = is_user_logged_in() && current_user_can('manage_options');
+
+get_header();
?>
-
- esc_html(get_the_title() ?: __('文章导航', 'aksrt')),
+
+
+
+
+
+
+
+
+
+
+ []
+
+
+
+
+
+
+
+
+
+ true]);
+ } elseif (function_exists('aksrt_get_share_html')) {
+ echo aksrt_get_share_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+ (int) $c_id,
+ 'numberposts' => -1,
+ 'post_status' => 'publish',
+ 'orderby' => 'date',
+ 'order' => 'DESC',
+ 'suppress_filters' => false,
]);
- ?>
+ if (empty($posts)) {
+ continue;
+ }
+ $section_id = 'navs-cat-' . (int) $c_id;
+ echo '
';
+ echo '
' . esc_html($the_cat->name) . '
';
+ echo '
';
+ foreach ($posts as $p) {
+ $time_tip = get_the_time('Y年m月d日 H:i', $p);
+ $time_ago = human_time_diff(get_the_time('U', $p), current_time('timestamp')) . __('前', 'aksrt');
+ $views = function_exists('aksrt_get_post_views') ? (int) aksrt_get_post_views($p->ID) : 0;
+ $likes = (int) get_post_meta($p->ID, 'like', true);
+ if ($likes <= 0) {
+ $likes = (int) get_post_meta($p->ID, 'aksrt_like', true);
+ }
+ $post_tip = sprintf(
+ /* translators: 1: views 2: likes */
+ __('阅读(%1$s) 点赞(%2$s)', 'aksrt'),
+ (string) $views,
+ (string) $likes
+ );
+ $subtitle = (string) get_post_meta($p->ID, 'subtitle', true);
+ if ($subtitle === '') {
+ $subtitle = (string) get_post_meta($p->ID, 'aksrt_subtitle', true);
+ }
+ echo '- ';
+ echo '
';
+ }
+ echo '
';
+ }
+ } elseif ($can_admin) {
+ echo '
';
+ echo '
' . esc_html__('尚未选择分类,请点击标题旁「设置」配置要展示的分类。', 'aksrt') . '
';
+ echo '
';
+ } else {
+ echo '
';
+ echo '
' . esc_html__('暂无导航内容', 'aksrt') . '
';
+ echo '
';
+ }
+ ?>
+
+
+
+
+
-
-
-
-
-
-
-
- name); ?>
- count); ?>
-
-
+
+
+
+
false]);
-}
+endif;
get_footer();
diff --git a/templates/pages/page-user-auth.php b/templates/pages/page-user-auth.php
new file mode 100644
index 00000000..62a6ef8e
--- /dev/null
+++ b/templates/pages/page-user-auth.php
@@ -0,0 +1,203 @@
+ true, 'allow_apply' => true];
+$user_id = get_current_user_id();
+$status = $user_id && class_exists(AuthApply::class) ? AuthApply::get_status($user_id) : '';
+$info = $user_id && class_exists(AuthApply::class) ? AuthApply::get_auth_info($user_id) : [];
+$apply = $user_id && class_exists(AuthApply::class) ? AuthApply::get_apply_payload($user_id) : [];
+$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url(get_permalink()) : wp_login_url(get_permalink());
+
+get_header();
+?>
+
+
+
+
+
+
+ '',
+ 'after' => '
',
+ ]);
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0 && class_exists('\AKSRT\User\Level')) {
+ $lv = (int) \AKSRT\User\Level::get_level($user_id);
+ if ($lv < $limit) {
+ $blocked_level = true;
+ }
+ }
+ ?>
+
+
+
+
+
+
+
+
+ ' . esc_html(sprintf(__('原因:%s', 'aksrt'), $reason)) . '
';
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+