feat(front-submit): 1:1 写文章/投稿页对齐 zibll newposts

Register AKSRT 写文章/投稿 page template, wire header publish entry to
front submit URL, rewrite page-submit as dual-column TinyMCE compose with
featured cover, multi-category/topics/filters, pay box, drafts, and
capability-gated FrontSubmit AJAX (pay/featured traits).
This commit is contained in:
2026-07-18 13:29:27 +08:00
parent cd4b1a73dc
commit 518e825bdd
25 changed files with 3029 additions and 982 deletions
+221
View File
@@ -0,0 +1,221 @@
<?php
/**
* Submit page context builder — shared by page-submit shell + partials.
*
* Expects no output. Returns $ctx array.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
$front = class_exists('\AKSRT\Core\FrontSubmit') ? \AKSRT\Core\FrontSubmit::get_instance() : null;
$user_id = get_current_user_id();
$settings = $front ? $front->settings() : (class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_submit_settings() : []);
$enabled = !isset($settings['enabled']) || !empty($settings['enabled']);
$edit_id = isset($_GET['edit']) ? absint($_GET['edit']) : 0;
$edit_post = null;
if ($edit_id > 0 && $front) {
if ($front->can_edit_post($edit_id, $user_id)) {
$edit_post = get_post($edit_id);
if (!$edit_post || $edit_post->post_type !== 'post') {
$edit_post = null;
$edit_id = 0;
}
} else {
$edit_id = 0;
}
}
$is_guest = $user_id <= 0;
$can_add = $front ? $front->can_submit($user_id) : false;
$can_edit = $edit_post instanceof WP_Post;
$is_can_new = $can_edit || $can_add;
// Caps.
$cap = static function (string $c) use ($front, $user_id, $edit_id): bool {
if ($front) {
return $front->user_can_cap($c, $user_id, $edit_id ?: null);
}
return function_exists('aksrt_user_can') ? aksrt_user_can($c, $user_id, $edit_id ?: null) : ($user_id > 0);
};
$post_meta = [];
if ($edit_post) {
$raw_meta = get_post_meta($edit_post->ID, \AKSRT\Core\DomainModel::POST_META_KEY, true);
$post_meta = is_array($raw_meta) ? $raw_meta : [];
}
$pay_meta = ($edit_post && function_exists('aksrt_get_pay_meta'))
? aksrt_get_pay_meta($edit_post->ID)
: (class_exists('\AKSRT\Core\DomainModel') ? \AKSRT\Core\DomainModel::default_pay_meta() : []);
// Featured initial args for JS.
$featured_args = ['type' => '', 'data' => new stdClass(), 'options' => [
'image' => $cap('new_post_image_cover'),
'slide' => $cap('new_post_slide_cover'),
'video' => $cap('new_post_video_cover'),
'ratio' => 50,
]];
if ($edit_post) {
if (!empty($post_meta['featured_video'])) {
$featured_args['type'] = 'video';
$featured_args['data'] = [
'url' => (string) $post_meta['featured_video'],
'pic' => (string) ($post_meta['thumbnail_url'] ?? ''),
];
} elseif (!empty($post_meta['featured_slide'])) {
$slides = array_filter(array_map('trim', explode(',', (string) $post_meta['featured_slide'])));
$featured_args['type'] = 'slide';
$featured_args['data'] = array_map(static function ($u) {
return ['url' => $u];
}, $slides);
} else {
$thumb = get_the_post_thumbnail_url($edit_post, 'full')
?: (string) ($post_meta['thumbnail_url'] ?? $post_meta['cover_images'] ?? '');
if ($thumb !== '') {
$featured_args['type'] = 'image';
$featured_args['data'] = ['url' => $thumb];
}
}
}
// Terms.
$cat_args = [
'taxonomy' => 'category',
'hide_empty' => false,
'orderby' => 'name',
'order' => 'ASC',
];
if (!empty($settings['allowed_cat_ids'])) {
$cat_args['include'] = $settings['allowed_cat_ids'];
} else {
$cat_args['parent'] = 0;
}
$categories = get_terms($cat_args);
if (is_wp_error($categories)) {
$categories = [];
}
$current_cats = $edit_post ? wp_get_post_categories($edit_post->ID) : [];
$topics_terms = [];
$current_topics = [];
if (!empty($settings['topics_s']) && taxonomy_exists('topics')) {
$topics_terms = get_terms(['taxonomy' => 'topics', 'hide_empty' => false, 'orderby' => 'name', 'order' => 'ASC']);
if (is_wp_error($topics_terms)) {
$topics_terms = [];
}
if ($edit_post) {
$t = wp_get_object_terms($edit_post->ID, 'topics', ['fields' => 'ids']);
$current_topics = is_wp_error($t) ? [] : $t;
}
}
$custom_dimensions = [];
$current_cf = [];
if (!empty($settings['custom_filter_s']) && class_exists('\AKSRT\Settings\Settings')) {
$filter_all = \AKSRT\Settings\Settings::get_post_filter_settings();
$custom_dimensions = $filter_all['custom_filter'] ?? [];
if ($edit_post && !empty($custom_dimensions)) {
foreach ($custom_dimensions as $dim) {
$key = sanitize_key((string) ($dim['key'] ?? ''));
if ($key === '') {
continue;
}
$current_cf[$key] = get_post_meta($edit_post->ID, '_aksrt_cf_' . $key, true);
}
}
}
$current_title = $edit_post ? $edit_post->post_title : '';
$current_content = $edit_post ? $edit_post->post_content : '';
$current_excerpt = $edit_post ? $edit_post->post_excerpt : '';
$current_tags = $edit_post ? implode(', ', wp_get_post_tags($edit_post->ID, ['fields' => 'names'])) : '';
$post_status = $edit_post ? $edit_post->post_status : '';
$post_modified = $edit_post ? $edit_post->post_modified : '';
$draft_count = 0;
$user_drafts = [];
if ($user_id > 0) {
$user_drafts = get_posts([
'post_type' => 'post',
'post_status' => 'draft',
'author' => $user_id,
'numberposts' => 10,
'orderby' => 'modified',
'order' => 'DESC',
]);
$draft_count = count($user_drafts);
}
// VIP labels / points.
$vip = class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_vip_settings')
? \AKSRT\Settings\Settings::get_vip_settings()
: [];
if (empty($vip) && class_exists('\AKSRT\Settings\PaymentRuntime')) {
// Fallback: read common keys.
$all = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
$vip = [
'vip1_enabled' => !empty($all['pay_user_vip_1_s']),
'vip2_enabled' => !empty($all['pay_user_vip_2_s']),
'vip1_name' => (string) ($all['pay_user_vip_1_name'] ?? 'VIP1'),
'vip2_name' => (string) ($all['pay_user_vip_2_name'] ?? 'VIP2'),
];
}
$points_enabled = class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'credits_enabled')
? \AKSRT\Settings\Settings::credits_enabled()
: false;
$submit_label = __('发布', 'aksrt');
if ($is_guest) {
$submit_label = __('审核', 'aksrt');
} elseif ($edit_post && in_array($post_status, ['publish', 'pending'], true)) {
$submit_label = __('保存', 'aksrt');
} elseif (($settings['review_mode'] ?? 'pending') === 'pending' && !$cap('new_post_audit_no')) {
$submit_label = __('审核', 'aksrt');
}
$ai_available = class_exists('\AKSRT\Ai\AI') && \AKSRT\Ai\AI::get_instance()->is_available();
return [
'front' => $front,
'user_id' => $user_id,
'settings' => $settings,
'enabled' => $enabled,
'edit_id' => $edit_id,
'edit_post' => $edit_post,
'is_guest' => $is_guest,
'is_can_new' => $is_can_new,
'cap' => $cap,
'post_meta' => $post_meta,
'pay_meta' => $pay_meta,
'featured_args' => $featured_args,
'categories' => $categories,
'current_cats' => $current_cats,
'topics_terms' => $topics_terms,
'current_topics' => $current_topics,
'custom_dimensions' => $custom_dimensions,
'current_cf' => $current_cf,
'current_title' => $current_title,
'current_content' => $current_content,
'current_excerpt' => $current_excerpt,
'current_tags' => $current_tags,
'post_status' => $post_status,
'post_modified' => $post_modified,
'draft_count' => $draft_count,
'user_drafts' => $user_drafts,
'vip' => $vip,
'points_enabled' => $points_enabled,
'submit_label' => $submit_label,
'ai_available' => $ai_available,
'can_pay' => $cap('new_post_pay'),
'can_pay_download' => $cap('new_post_pay_download'),
'can_cover_image' => $cap('new_post_image_cover'),
'can_cover_slide' => $cap('new_post_slide_cover'),
'can_cover_video' => $cap('new_post_video_cover'),
'can_upload_img' => $cap('new_post_upload_img'),
'can_upload_video' => $cap('new_post_upload_video'),
'can_upload_file' => $cap('new_post_upload_file'),
'can_hide' => $cap('new_post_hide'),
'can_iframe' => $cap('new_post_iframe_video'),
];
+123
View File
@@ -0,0 +1,123 @@
<?php
/**
* Main column: cover + title + editor + status.
*
* @var array $ctx
* @package AKSRT
*/
defined('ABSPATH') || exit;
$settings = $ctx['settings'];
$edit_post = $ctx['edit_post'];
$is_can_new = !empty($ctx['is_can_new']);
?>
<div class="aksrt-submit-main">
<div class="aksrt-submit-panel aksrt-submit-panel--editor">
<?php
$featured_path = get_template_directory() . '/templates/parts/submit/featured.php';
if (file_exists($featured_path)) {
include $featured_path;
}
?>
<div class="aksrt-submit-title-wrap">
<textarea
name="post_title"
id="submit-title"
class="aksrt-submit-title"
rows="1"
maxlength="<?php echo esc_attr((string) ((int) ($settings['title_max'] ?? 30) * 4)); ?>"
placeholder="<?php echo esc_attr((string) ($settings['title_placeholder'] ?? __('请输入标题', 'aksrt'))); ?>"
data-auto-height
data-max-height="<?php echo wp_is_mobile() ? '110' : '78'; ?>"
><?php echo esc_textarea((string) $ctx['current_title']); ?></textarea>
</div>
<?php if (!$is_can_new) : ?>
<div class="aksrt-submit-nocan">
<div class="aksrt-submit-nocan__icon"><i class="fas fa-lock"></i></div>
<p><?php esc_html_e('无法发布', 'aksrt'); ?></p>
<p class="muted"><?php esc_html_e('你当前没有前台投稿权限,请联系管理员开通。', 'aksrt'); ?></p>
</div>
<?php else : ?>
<div class="aksrt-submit-editor-wrap">
<?php
$toolbar1 = 'formatselect,bold,italic,bullist,numlist,alignleft,aligncenter,alignright,link,blockquote,code,fullscreen';
$plugins = 'paste,link,lists,fullscreen,wordpress,wplink,charmap';
if (!empty($ctx['can_upload_img']) || !empty($ctx['can_upload_video']) || !empty($ctx['can_upload_file'])) {
// media_buttons handle uploads; keep toolbar clean.
}
$editor_settings = [
'textarea_name' => 'post_content',
'textarea_rows' => 20,
'editor_height' => wp_is_mobile() ? 460 : 470,
'media_buttons' => !empty($ctx['can_upload_img']) || !empty($ctx['can_upload_video']) || !empty($ctx['can_upload_file']),
'default_editor' => 'tinymce',
'quicktags' => false,
'teeny' => false,
'tinymce' => [
'toolbar1' => $toolbar1,
'toolbar2' => 'fontsizeselect,forecolor,removeformat,undo,redo,wp_help',
'plugins' => $plugins,
'placeholder' => (string) ($settings['content_placeholder'] ?? ''),
],
];
wp_editor((string) $ctx['current_content'], 'post_content', $editor_settings);
?>
</div>
<?php if (!empty($ctx['can_hide']) || !empty($ctx['can_pay'])) : ?>
<div class="aksrt-submit-shortcode-tools">
<?php if (!empty($ctx['can_hide'])) : ?>
<button type="button" class="but" data-insert-shortcode="hide" title="<?php esc_attr_e('插入隐藏内容', 'aksrt'); ?>">
<i class="fas fa-eye-slash"></i> <?php esc_html_e('隐藏内容', 'aksrt'); ?>
</button>
<?php endif; ?>
<?php if (!empty($ctx['can_pay'])) : ?>
<button type="button" class="but" data-insert-shortcode="payshow" title="<?php esc_attr_e('插入付费可见内容', 'aksrt'); ?>">
<i class="fas fa-lock"></i> <?php esc_html_e('付费可见', 'aksrt'); ?>
</button>
<?php endif; ?>
</div>
<?php endif; ?>
<?php endif; ?>
<div class="aksrt-submit-status-row">
<span class="aksrt-submit-view-btn">
<?php if ($edit_post) : ?>
<a class="but c-blue" target="_blank" href="<?php echo esc_url(get_permalink($edit_post)); ?>">
<i class="fa fa-file-text-o"></i> <?php esc_html_e('预览文章', 'aksrt'); ?>
</a>
<?php if (current_user_can('manage_options')) : ?>
<a class="but c-yellow" href="<?php echo esc_url(get_edit_post_link($edit_post)); ?>">
<?php esc_html_e('后台编辑', 'aksrt'); ?>
</a>
<?php endif; ?>
<?php elseif (!empty($ctx['draft_count']) && $ctx['user_id'] > 0) : ?>
<?php
$draft_url = function_exists('aksrt_get_user_home_url')
? add_query_arg(['tab' => 'post', 'post_status' => 'draft'], aksrt_get_user_home_url($ctx['user_id']))
: '';
?>
<?php if ($draft_url !== '') : ?>
<a class="but" target="_blank" href="<?php echo esc_url($draft_url); ?>">
<?php
printf(
/* translators: %d: draft count */
esc_html__('您已有 %d 篇草稿 点击查看', 'aksrt'),
(int) $ctx['draft_count']
);
?>
<i class="fa fa-angle-right"></i>
</a>
<?php endif; ?>
<?php endif; ?>
</span>
<span class="aksrt-submit-modified-time">
<?php if (!empty($ctx['post_modified'])) : ?>
<span class="badg"><?php echo esc_html(sprintf(__('最后保存:%s', 'aksrt'), $ctx['post_modified'])); ?></span>
<?php endif; ?>
</span>
</div>
</div>
</div>
+71
View File
@@ -0,0 +1,71 @@
<?php
/**
* Cover featured editor box.
*
* @var array $ctx
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (empty($ctx['settings']['allow_cover'])) {
return;
}
if (empty($ctx['can_cover_image']) && empty($ctx['can_cover_slide']) && empty($ctx['can_cover_video'])) {
return;
}
$args = $ctx['featured_args'] ?? [];
$type = (string) ($args['type'] ?? '');
$data = $args['data'] ?? [];
$can_image = !empty($ctx['can_cover_image']);
$can_slide = !empty($ctx['can_cover_slide']);
$can_video = !empty($ctx['can_cover_video']);
?>
<div class="aksrt-submit-featured featured-edit"
data-featured-args="<?php echo esc_attr(wp_json_encode($args)); ?>"
data-can-image="<?php echo $can_image ? '1' : '0'; ?>"
data-can-slide="<?php echo $can_slide ? '1' : '0'; ?>"
data-can-video="<?php echo $can_video ? '1' : '0'; ?>">
<div class="aksrt-submit-featured__preview" data-featured-preview>
<?php if ($type === 'image' && !empty($data['url'])) : ?>
<img src="<?php echo esc_url((string) $data['url']); ?>" alt="">
<?php elseif ($type === 'slide' && is_array($data) && !empty($data[0]['url'])) : ?>
<img src="<?php echo esc_url((string) $data[0]['url']); ?>" alt="">
<span class="aksrt-submit-featured__badge"><i class="fas fa-images"></i></span>
<?php elseif ($type === 'video') : ?>
<?php if (!empty($data['pic'])) : ?>
<img src="<?php echo esc_url((string) $data['pic']); ?>" alt="">
<?php else : ?>
<div class="aksrt-submit-featured__video-placeholder"><i class="fas fa-play"></i></div>
<?php endif; ?>
<span class="aksrt-submit-featured__badge"><i class="fas fa-video"></i></span>
<?php else : ?>
<div class="aksrt-submit-featured__empty">
<i class="fas fa-image"></i>
<span><?php esc_html_e('设置文章封面', 'aksrt'); ?></span>
</div>
<?php endif; ?>
</div>
<div class="aksrt-submit-featured__actions">
<?php if ($can_image) : ?>
<button type="button" class="but" data-featured-action="image">
<i class="fas fa-image"></i> <?php esc_html_e('图片', 'aksrt'); ?>
</button>
<?php endif; ?>
<?php if ($can_slide) : ?>
<button type="button" class="but" data-featured-action="slide">
<i class="fas fa-images"></i> <?php esc_html_e('幻灯片', 'aksrt'); ?>
</button>
<?php endif; ?>
<?php if ($can_video) : ?>
<button type="button" class="but" data-featured-action="video">
<i class="fas fa-video"></i> <?php esc_html_e('视频', 'aksrt'); ?>
</button>
<?php endif; ?>
<button type="button" class="but c-red" data-featured-action="close" <?php echo $type === '' ? 'hidden' : ''; ?>>
<i class="fas fa-trash"></i> <?php esc_html_e('清除', 'aksrt'); ?>
</button>
</div>
<input type="hidden" name="featured_type" value="<?php echo esc_attr($type); ?>" data-featured-type>
<input type="hidden" name="featured_data" value="<?php echo esc_attr(wp_json_encode(['type' => $type, 'data' => $data])); ?>" data-featured-json>
</div>
+128
View File
@@ -0,0 +1,128 @@
<?php
/**
* Pay content sidebar card.
*
* @var array $ctx
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (empty($ctx['can_pay'])) {
return;
}
$settings = $ctx['settings'];
$pay = is_array($ctx['pay_meta'] ?? null) ? $ctx['pay_meta'] : [];
$enabled = !empty($pay['pay_type']) && ($pay['pay_type'] !== 'no');
$modo = (($pay['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
$points_on = !empty($ctx['points_enabled']);
$vip_manual = !empty($settings['pay_vip_price_s']);
$vip1_on = !empty($ctx['vip']['vip1_enabled']);
$vip2_on = !empty($ctx['vip']['vip2_enabled']);
$vip1_name = (string) ($ctx['vip']['vip1_name'] ?? 'VIP1');
$vip2_name = (string) ($ctx['vip']['vip2_name'] ?? 'VIP2');
$downloads = is_array($pay['downloads'] ?? null) ? $pay['downloads'] : [];
?>
<div class="aksrt-submit-panel aksrt-submit-pay dependency-box" data-pay-box>
<div class="aksrt-submit-panel__title"><?php esc_html_e('付费内容', 'aksrt'); ?></div>
<div class="aksrt-submit-panel__body">
<div class="aksrt-submit-pay__row">
<span><?php esc_html_e('内容付费', 'aksrt'); ?></span>
<label class="aksrt-switch">
<input type="checkbox" name="pay_enabled" value="1" <?php checked($enabled); ?> data-pay-toggle>
<span class="aksrt-switch__ui"></span>
</label>
</div>
<div class="aksrt-submit-pay__body" data-pay-fields <?php echo $enabled ? '' : 'hidden'; ?>>
<?php if ($points_on) : ?>
<div class="aksrt-submit-pay__row">
<span><?php esc_html_e('支付类型', 'aksrt'); ?></span>
<div class="aksrt-submit-segmented">
<button type="button" class="but <?php echo $modo !== 'points' ? 'active' : ''; ?>" data-pay-modo="0"><?php esc_html_e('现金', 'aksrt'); ?></button>
<button type="button" class="but <?php echo $modo === 'points' ? 'active' : ''; ?>" data-pay-modo="points"><?php esc_html_e('积分', 'aksrt'); ?></button>
</div>
</div>
<?php endif; ?>
<input type="hidden" name="aksrt_pay[pay_modo]" value="<?php echo esc_attr($modo); ?>" data-pay-modo-input>
<input type="hidden" name="aksrt_pay[pay_type]" value="<?php echo esc_attr((string) ($pay['pay_type'] ?? 'reading')); ?>" data-pay-type-input>
<div data-pay-cash <?php echo $modo === 'points' ? 'hidden' : ''; ?>>
<label class="aksrt-submit-field">
<span><?php esc_html_e('设置价格', 'aksrt'); ?></span>
<input type="number" step="0.01" min="0" name="aksrt_pay[price]" class="aksrt-form-input" value="<?php echo esc_attr((string) ($pay['price'] ?? '')); ?>">
</label>
<?php if ($vip_manual && $vip1_on) : ?>
<label class="aksrt-submit-field">
<span><?php echo esc_html(sprintf(__('%s 价格', 'aksrt'), $vip1_name)); ?></span>
<input type="number" step="0.01" min="0" name="aksrt_pay[vip1_price]" class="aksrt-form-input" value="<?php echo esc_attr((string) ($pay['vip1_price'] ?? '')); ?>">
</label>
<?php endif; ?>
<?php if ($vip_manual && $vip2_on) : ?>
<label class="aksrt-submit-field">
<span><?php echo esc_html(sprintf(__('%s 价格', 'aksrt'), $vip2_name)); ?></span>
<input type="number" step="0.01" min="0" name="aksrt_pay[vip2_price]" class="aksrt-form-input" value="<?php echo esc_attr((string) ($pay['vip2_price'] ?? '')); ?>">
</label>
<?php endif; ?>
</div>
<div data-pay-points <?php echo $modo !== 'points' ? 'hidden' : ''; ?>>
<label class="aksrt-submit-field">
<span><?php esc_html_e('设置积分', 'aksrt'); ?></span>
<input type="number" step="1" min="0" name="aksrt_pay[points_price]" class="aksrt-form-input" value="<?php echo esc_attr((string) ($pay['points_price'] ?? '')); ?>">
</label>
<?php if ($vip_manual && $vip1_on) : ?>
<label class="aksrt-submit-field">
<span><?php echo esc_html(sprintf(__('%s 积分', 'aksrt'), $vip1_name)); ?></span>
<input type="number" step="1" min="0" name="aksrt_pay[vip1_points]" class="aksrt-form-input" value="<?php echo esc_attr((string) ($pay['vip1_points'] ?? '')); ?>">
</label>
<?php endif; ?>
<?php if ($vip_manual && $vip2_on) : ?>
<label class="aksrt-submit-field">
<span><?php echo esc_html(sprintf(__('%s 积分', 'aksrt'), $vip2_name)); ?></span>
<input type="number" step="1" min="0" name="aksrt_pay[vip2_points]" class="aksrt-form-input" value="<?php echo esc_attr((string) ($pay['vip2_points'] ?? '')); ?>">
</label>
<?php endif; ?>
</div>
<?php if (!empty($ctx['can_pay_download'])) : ?>
<div class="aksrt-submit-pay-downloads" data-pay-downloads>
<div class="aksrt-submit-pay__row">
<strong><?php esc_html_e('付费下载', 'aksrt'); ?></strong>
<button type="button" class="but hollow c-blue" data-pay-download-add>
<i class="fas fa-plus"></i> <?php esc_html_e('添加资源', 'aksrt'); ?>
</button>
</div>
<div class="aksrt-submit-pay-downloads__list" data-pay-download-list>
<?php foreach ($downloads as $i => $row) :
$url = (string) ($row['url'] ?? '');
$label = (string) ($row['label'] ?? '');
$code = (string) ($row['extract_code'] ?? '');
?>
<div class="aksrt-submit-pay-downloads__item" data-pay-download-item>
<input type="url" class="aksrt-form-input" name="aksrt_pay[downloads][<?php echo (int) $i; ?>][url]" value="<?php echo esc_attr($url); ?>" placeholder="<?php esc_attr_e('资源链接', 'aksrt'); ?>">
<input type="text" class="aksrt-form-input" name="aksrt_pay[downloads][<?php echo (int) $i; ?>][label]" value="<?php echo esc_attr($label); ?>" placeholder="<?php esc_attr_e('名称', 'aksrt'); ?>">
<input type="text" class="aksrt-form-input" name="aksrt_pay[downloads][<?php echo (int) $i; ?>][extract_code]" value="<?php echo esc_attr($code); ?>" placeholder="<?php esc_attr_e('提取码/备注', 'aksrt'); ?>">
<button type="button" class="but c-red cir" data-pay-download-remove title="<?php esc_attr_e('删除', 'aksrt'); ?>"><i class="fas fa-trash"></i></button>
</div>
<?php endforeach; ?>
</div>
<template data-pay-download-tpl>
<div class="aksrt-submit-pay-downloads__item" data-pay-download-item>
<input type="url" class="aksrt-form-input" data-name="url" placeholder="<?php esc_attr_e('资源链接', 'aksrt'); ?>">
<input type="text" class="aksrt-form-input" data-name="label" placeholder="<?php esc_attr_e('名称', 'aksrt'); ?>">
<input type="text" class="aksrt-form-input" data-name="extract_code" placeholder="<?php esc_attr_e('提取码/备注', 'aksrt'); ?>">
<button type="button" class="but c-red cir" data-pay-download-remove title="<?php esc_attr_e('删除', 'aksrt'); ?>"><i class="fas fa-trash"></i></button>
</div>
</template>
</div>
<?php endif; ?>
<p class="aksrt-submit-hint"><?php esc_html_e('请确保已经在文中添加了付费可见的隐藏内容', 'aksrt'); ?></p>
</div>
<p class="aksrt-submit-hint" data-pay-off-hint <?php echo $enabled ? 'hidden' : ''; ?>>
<?php esc_html_e('如果您在文章中添加了付费可见的隐藏内容,请在此设置付费功能', 'aksrt'); ?>
</p>
</div>
</div>
+85
View File
@@ -0,0 +1,85 @@
<?php
/**
* Submit actions + drafts list.
*
* @var array $ctx
* @package AKSRT
*/
defined('ABSPATH') || exit;
$settings = $ctx['settings'];
$is_can_new = !empty($ctx['is_can_new']);
$edit_post = $ctx['edit_post'];
$status = (string) $ctx['post_status'];
$can_draft = !empty($ctx['user_id']) && empty($ctx['is_guest']) && !empty($settings['draft_save']);
if ($edit_post && in_array($status, ['publish', 'pending'], true)) {
// Still allow draft button? zibll hides draft for publish/pending.
$can_draft = false;
}
?>
<div class="aksrt-submit-panel">
<div class="aksrt-submit-panel__body aksrt-submit-actions">
<p class="aksrt-submit-ready"><?php esc_html_e('Are you ready', 'aksrt'); ?></p>
<input type="hidden" name="posts_id" value="<?php echo esc_attr((string) (int) $ctx['edit_id']); ?>">
<input type="hidden" name="status" id="submit-status" value="pending">
<input type="hidden" name="_nonce" value="<?php echo esc_attr(wp_create_nonce('aksrt_submit')); ?>">
<?php if (!$is_can_new) : ?>
<p class="aksrt-submit-hint"><?php esc_html_e('暂无发布权限', 'aksrt'); ?></p>
<?php else : ?>
<?php if (!empty($ctx['is_guest'])) : ?>
<p class="aksrt-submit-hint"><?php esc_html_e('您当前未登录,不能保存草稿,文章提交后不可再修改!', 'aksrt'); ?></p>
<?php endif; ?>
<?php if (!empty($settings['captcha']) && function_exists('aksrt_render_captcha')) : ?>
<div class="aksrt-submit-captcha">
<?php aksrt_render_captcha('submit'); ?>
</div>
<?php endif; ?>
<div class="aksrt-submit-actions__btns">
<?php if ($can_draft) : ?>
<button type="button" class="but jb-green aksrt-submit-btn" data-action="posts_draft">
<i class="fa fa-dot-circle-o"></i> <?php esc_html_e('保存草稿', 'aksrt'); ?>
</button>
<?php endif; ?>
<button type="button" class="but jb-blue aksrt-submit-btn" data-action="posts_save" id="aksrt-submit-btn">
<i class="fa fa-check-square-o"></i>
<?php
printf(
/* translators: %s: 发布|审核|保存 */
esc_html__('提交%s', 'aksrt'),
esc_html((string) $ctx['submit_label'])
);
?>
</button>
</div>
<?php endif; ?>
</div>
</div>
<?php if (!empty($ctx['user_drafts'])) : ?>
<div class="aksrt-submit-panel aksrt-submit-drafts">
<div class="aksrt-submit-panel__title">
<i class="fas fa-file-alt"></i> <?php esc_html_e('我的草稿', 'aksrt'); ?>
</div>
<div class="aksrt-submit-panel__body">
<?php foreach ($ctx['user_drafts'] as $draft) :
$edit_url = function_exists('aksrt_get_new_post_url')
? aksrt_get_new_post_url((int) $draft->ID)
: add_query_arg('edit', $draft->ID, get_permalink());
?>
<div class="aksrt-submit-drafts__item" data-draft-id="<?php echo esc_attr((string) $draft->ID); ?>">
<a href="<?php echo esc_url($edit_url); ?>" class="aksrt-submit-drafts__link">
<span class="aksrt-submit-drafts__name"><?php echo esc_html($draft->post_title ?: __('无标题', 'aksrt')); ?></span>
<time><?php echo esc_html(get_the_modified_date('Y-m-d H:i', $draft)); ?></time>
</a>
<button type="button" class="aksrt-submit-drafts__delete" data-draft-id="<?php echo esc_attr((string) $draft->ID); ?>" title="<?php esc_attr_e('删除草稿', 'aksrt'); ?>">
<i class="fas fa-trash"></i>
</button>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
+126
View File
@@ -0,0 +1,126 @@
<?php
/**
* Sidebar: guest + terms + tags.
*
* @var array $ctx
* @package AKSRT
*/
defined('ABSPATH') || exit;
$settings = $ctx['settings'];
$term_helper = get_template_directory() . '/templates/parts/submit/term-checks.php';
if (file_exists($term_helper)) {
require_once $term_helper;
}
?>
<?php if (!empty($ctx['is_guest'])) : ?>
<div class="aksrt-submit-panel">
<div class="aksrt-submit-panel__title"><?php esc_html_e('用户信息', 'aksrt'); ?></div>
<div class="aksrt-submit-panel__body">
<p class="aksrt-submit-hint"><?php esc_html_e('请输入昵称', 'aksrt'); ?></p>
<input class="aksrt-form-input" type="text" name="user_name" placeholder="<?php esc_attr_e('请输入昵称', 'aksrt'); ?>" required>
<p class="aksrt-submit-hint"><?php esc_html_e('请输入您的联系方式', 'aksrt'); ?></p>
<input class="aksrt-form-input" type="text" name="contact_details" placeholder="<?php esc_attr_e('输入联系方式', 'aksrt'); ?>">
</div>
</div>
<?php endif; ?>
<div class="aksrt-submit-panel">
<div class="aksrt-submit-panel__title"><?php esc_html_e('文章参数', 'aksrt'); ?></div>
<div class="aksrt-submit-panel__body term-select-box">
<?php if (!empty($settings['allow_category'])) : ?>
<details class="aksrt-submit-drop" open>
<summary>
<span><i class="fa fa-folder-open-o"></i> <?php esc_html_e('分类', 'aksrt'); ?></span>
<i class="fa fa-angle-right"></i>
</summary>
<div class="aksrt-submit-drop__body">
<?php
if (!empty($ctx['categories'])) {
aksrt_submit_render_term_checks($ctx['categories'], array_map('intval', $ctx['current_cats']), 'category');
} else {
echo '<p class="aksrt-submit-hint">' . esc_html__('暂无可选择的分类', 'aksrt') . '</p>';
}
?>
</div>
</details>
<?php endif; ?>
<?php if (!empty($settings['topics_s']) && !empty($ctx['topics_terms'])) : ?>
<details class="aksrt-submit-drop">
<summary>
<span><i class="fa fa-cube"></i> <?php esc_html_e('专题', 'aksrt'); ?></span>
<i class="fa fa-angle-right"></i>
</summary>
<div class="aksrt-submit-drop__body">
<?php aksrt_submit_render_term_checks($ctx['topics_terms'], array_map('intval', $ctx['current_topics']), 'topics', 'topics'); ?>
</div>
</details>
<?php endif; ?>
<?php if (!empty($settings['custom_filter_s']) && !empty($ctx['custom_dimensions'])) : ?>
<?php foreach ($ctx['custom_dimensions'] as $dim) :
$key = sanitize_key((string) ($dim['key'] ?? ''));
if ($key === '') {
continue;
}
$name = (string) ($dim['name'] ?? $key);
$vals = is_array($dim['vals'] ?? null) ? $dim['vals'] : [];
$cur = $ctx['current_cf'][$key] ?? [];
if (!is_array($cur)) {
$cur = $cur === '' || $cur === null ? [] : [$cur];
}
$cur = array_map('strval', $cur);
?>
<details class="aksrt-submit-drop">
<summary>
<span><i class="fa fa-filter"></i> <?php echo esc_html($name); ?></span>
<i class="fa fa-angle-right"></i>
</summary>
<div class="aksrt-submit-drop__body aksrt-submit-tags">
<?php foreach ($vals as $val) :
$vk = is_array($val) ? (string) ($val['key'] ?? '') : (string) $val;
$vn = is_array($val) ? (string) ($val['name'] ?? $vk) : (string) $val;
if ($vk === '') {
continue;
}
$active = in_array($vk, $cur, true);
?>
<label class="aksrt-submit-tag <?php echo $active ? 'is-active' : ''; ?>">
<input type="checkbox" name="cf_<?php echo esc_attr($key); ?>[]" value="<?php echo esc_attr($vk); ?>" <?php checked($active); ?>>
<span><?php echo esc_html($vn); ?></span>
</label>
<?php endforeach; ?>
</div>
</details>
<?php endforeach; ?>
<?php endif; ?>
<?php if (!empty($settings['allow_tags'])) : ?>
<div class="aksrt-submit-field">
<div class="aksrt-submit-field__label">
<?php esc_html_e('标签', 'aksrt'); ?>
<?php if (!empty($ctx['ai_available'])) : ?>
<button type="button" class="aksrt-ai-assist-btn" data-ai-action="tags" hidden><?php esc_html_e('AI 建议标签', 'aksrt'); ?></button>
<?php endif; ?>
</div>
<p class="aksrt-submit-hint"><?php esc_html_e('填写文章的标签,每个标签用逗号隔开', 'aksrt'); ?></p>
<textarea class="aksrt-form-input" rows="3" name="tags" placeholder="<?php esc_attr_e('输入文章标签', 'aksrt'); ?>"><?php echo esc_textarea((string) $ctx['current_tags']); ?></textarea>
</div>
<?php endif; ?>
<?php if (!empty($settings['allow_excerpt'])) : ?>
<div class="aksrt-submit-field">
<div class="aksrt-submit-field__label">
<?php esc_html_e('摘要', 'aksrt'); ?>
<?php if (!empty($ctx['ai_available'])) : ?>
<button type="button" class="aksrt-ai-assist-btn" data-ai-action="summary" hidden><?php esc_html_e('AI 生成摘要', 'aksrt'); ?></button>
<?php endif; ?>
</div>
<textarea class="aksrt-form-input" rows="3" name="excerpt" maxlength="300" placeholder="<?php esc_attr_e('可选:文章摘要', 'aksrt'); ?>"><?php echo esc_textarea((string) $ctx['current_excerpt']); ?></textarea>
</div>
<?php endif; ?>
</div>
</div>
+71
View File
@@ -0,0 +1,71 @@
<?php
/**
* Hierarchical multi-check term list.
*
* @param WP_Term[] $terms
* @param int[] $checked
* @param string $name
* @param string $taxonomy
* @param int $parent
* @param int $depth
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_submit_render_term_checks')) :
function aksrt_submit_render_term_checks(array $terms, array $checked, string $name, string $taxonomy = 'category', int $parent = 0, int $depth = 0): void {
$children_map = [];
$roots = [];
foreach ($terms as $term) {
if (!$term instanceof WP_Term) {
continue;
}
$pid = (int) $term->parent;
if (!isset($children_map[$pid])) {
$children_map[$pid] = [];
}
$children_map[$pid][] = $term;
}
$render = static function (int $pid, int $d) use (&$render, $children_map, $checked, $name): void {
if (empty($children_map[$pid])) {
return;
}
foreach ($children_map[$pid] as $term) {
$tid = (int) $term->term_id;
$pad = $d > 0 ? ' style="margin-left:' . (int) ($d * 16) . 'px"' : '';
echo '<div' . $pad . '><label class="aksrt-submit-check">';
echo '<input type="checkbox" name="' . esc_attr($name) . '[]" value="' . esc_attr((string) $tid) . '"' . (in_array($tid, $checked, true) ? ' checked' : '') . '>';
echo '<span>' . esc_html($term->name) . '</span></label></div>';
$render($tid, $d + 1);
}
};
// If include list was used without hierarchy, still render flat.
if (empty($children_map) && !empty($terms)) {
foreach ($terms as $term) {
if (!$term instanceof WP_Term) {
continue;
}
$tid = (int) $term->term_id;
echo '<div><label class="aksrt-submit-check">';
echo '<input type="checkbox" name="' . esc_attr($name) . '[]" value="' . esc_attr((string) $tid) . '"' . (in_array($tid, $checked, true) ? ' checked' : '') . '>';
echo '<span>' . esc_html($term->name) . '</span></label></div>';
}
return;
}
$render($parent, $depth);
// Orphans (included children without parent in set).
$seen_parents = array_keys($children_map);
foreach ($terms as $term) {
if (!$term instanceof WP_Term) {
continue;
}
$pid = (int) $term->parent;
if ($pid > 0 && !isset($children_map[$pid]) && !isset($children_map[0])) {
// already handled if parent missing — skip double.
}
}
}
endif;