对齐 Zibll 的 AI 生成 SEO 流程:统一 WP AI Client/主题 Provider 双后端、文章/分类 SEO 框与生成回填、投稿摘要/标签建议,并收敛扩展页为连接配置。
311 lines
14 KiB
PHP
311 lines
14 KiB
PHP
<?php
|
||
/**
|
||
* Template Name: AKSRT - Submit
|
||
*
|
||
* 前台投稿页面模板。
|
||
* 支持标题、摘要、分类、标签、正文、封面、草稿保存。
|
||
*
|
||
* @package AKSRT
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
if (!is_user_logged_in()) {
|
||
wp_redirect(aksrt_get_login_url(get_permalink()));
|
||
exit;
|
||
}
|
||
|
||
$user_id = get_current_user_id();
|
||
$can_submit = class_exists('AKSRT_Front_Submit') && AKSRT_Front_Submit::get_instance()->can_submit($user_id);
|
||
|
||
if (!$can_submit) {
|
||
wp_redirect(home_url('/'));
|
||
exit;
|
||
}
|
||
|
||
// Check if editing existing draft
|
||
$edit_id = isset($_GET['edit']) ? absint($_GET['edit']) : 0;
|
||
$edit_post = null;
|
||
if ($edit_id > 0) {
|
||
$edit_post = get_post($edit_id);
|
||
if (!$edit_post || (int) $edit_post->post_author !== $user_id || $edit_post->post_status !== 'draft') {
|
||
$edit_post = null;
|
||
$edit_id = 0;
|
||
}
|
||
}
|
||
|
||
get_header();
|
||
|
||
// Submit settings
|
||
$submit_settings = [];
|
||
if (class_exists('AKSRT_Settings')) {
|
||
$all = AKSRT_Settings::get_all();
|
||
$submit_settings = [
|
||
'enabled' => !empty($all['front_submit_enabled']),
|
||
'review_mode' => $all['front_submit_review_mode'] ?? 'pending',
|
||
'allow_cover' => !isset($all['front_submit_cover']) || !empty($all['front_submit_cover']),
|
||
'allow_excerpt' => !isset($all['front_submit_excerpt']) || !empty($all['front_submit_excerpt']),
|
||
'allow_category' => !isset($all['front_submit_category']) || !empty($all['front_submit_category']),
|
||
'allow_tags' => !isset($all['front_submit_tags']) || !empty($all['front_submit_tags']),
|
||
'max_images' => (int) ($all['front_submit_max_images'] ?? 5),
|
||
'allowed_cat_ids' => is_array($all['post_article_cat'] ?? null) ? array_map('intval', $all['post_article_cat']) : [],
|
||
'topics_s' => !empty($all['post_article_topics_s']),
|
||
'custom_filter_s' => !isset($all['post_article_custom_filter_s']) || !empty($all['post_article_custom_filter_s']),
|
||
];
|
||
}
|
||
|
||
// §3.7 topics: load topics taxonomy terms
|
||
$topics_terms = [];
|
||
if (!empty($submit_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 = [];
|
||
}
|
||
$current_topics = [];
|
||
if ($edit_post && taxonomy_exists('topics')) {
|
||
$terms = wp_get_object_terms($edit_post->ID, 'topics', ['fields' => 'ids']);
|
||
if (!is_wp_error($terms)) $current_topics = $terms;
|
||
}
|
||
|
||
// §3.4 custom_filter: load dimension definitions for submit form
|
||
$custom_dimensions = [];
|
||
if (!empty($submit_settings['custom_filter_s']) && class_exists('AKSRT_Settings')) {
|
||
$filter_all = AKSRT_Settings::get_post_filter_settings();
|
||
$custom_dimensions = $filter_all['custom_filter'];
|
||
}
|
||
|
||
// §3.4 custom_filter: load current values for edit mode
|
||
$current_cf = [];
|
||
if ($edit_post && !empty($custom_dimensions)) {
|
||
foreach ($custom_dimensions as $dim) {
|
||
$current_cf[$dim['key']] = get_post_meta($edit_post->ID, '_aksrt_cf_' . $dim['key'], true);
|
||
}
|
||
}
|
||
|
||
// §3.7 post_article_cat: filter categories by allowed list
|
||
$cat_args = [
|
||
'taxonomy' => 'category',
|
||
'hide_empty' => false,
|
||
'orderby' => 'name',
|
||
'order' => 'ASC',
|
||
];
|
||
if (!empty($submit_settings['allowed_cat_ids'])) {
|
||
$cat_args['include'] = $submit_settings['allowed_cat_ids'];
|
||
}
|
||
$categories = get_categories($cat_args);
|
||
|
||
// Current values for edit mode
|
||
$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_cats = $edit_post ? wp_get_post_categories($edit_post->ID) : [];
|
||
$current_tags = $edit_post ? implode(', ', wp_get_post_tags($edit_post->ID, ['fields' => 'names'])) : '';
|
||
$current_thumb = $edit_post ? get_the_post_thumbnail_url($edit_post->ID, 'large') : '';
|
||
?>
|
||
|
||
<main id="main-content" class="site-main content-shell content-shell--page" tabindex="-1">
|
||
<div class="aksrt-submit-page container">
|
||
<header class="aksrt-submit-page__header">
|
||
<h1 class="aksrt-submit-page__title">
|
||
<?php echo $edit_post ? esc_html__('编辑草稿', 'aksrt') : esc_html__('投稿', 'aksrt'); ?>
|
||
</h1>
|
||
<p class="aksrt-submit-page__desc">
|
||
<?php echo $edit_post
|
||
? esc_html__('继续编辑你的草稿,完成后提交审核。', 'aksrt')
|
||
: esc_html__('分享你的内容,提交后将进入审核流程。', 'aksrt'); ?>
|
||
</p>
|
||
</header>
|
||
|
||
<form class="aksrt-submit-form" id="aksrt-submit-form" data-aksrt-submit-form data-dirty="false">
|
||
<?php if ($edit_id > 0) : ?>
|
||
<input type="hidden" name="edit_id" value="<?php echo esc_attr((string) $edit_id); ?>">
|
||
<?php endif; ?>
|
||
|
||
<div class="aksrt-form-group">
|
||
<label for="submit-title"><?php esc_html_e('标题', 'aksrt'); ?> *</label>
|
||
<input type="text" id="submit-title" name="title" class="aksrt-form-input" required maxlength="200" placeholder="<?php esc_attr_e('请输入文章标题', 'aksrt'); ?>" value="<?php echo esc_attr($current_title); ?>">
|
||
</div>
|
||
|
||
<?php if (!empty($submit_settings['allow_excerpt'])) : ?>
|
||
<div class="aksrt-form-group">
|
||
<label for="submit-excerpt">
|
||
<?php esc_html_e('摘要', 'aksrt'); ?>
|
||
<button type="button" class="aksrt-ai-assist-btn" data-ai-action="summary" hidden><?php esc_html_e('AI 生成摘要', 'aksrt'); ?></button>
|
||
</label>
|
||
<textarea id="submit-excerpt" name="excerpt" class="aksrt-form-input" rows="3" maxlength="300" placeholder="<?php esc_attr_e('可选:文章摘要', 'aksrt'); ?>"><?php echo esc_textarea($current_excerpt); ?></textarea>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div class="aksrt-submit-form__row">
|
||
<?php if (!empty($submit_settings['allow_category'])) : ?>
|
||
<div class="aksrt-form-group aksrt-submit-form__col">
|
||
<label for="submit-category"><?php esc_html_e('分类', 'aksrt'); ?></label>
|
||
<select id="submit-category" name="category" class="aksrt-form-input">
|
||
<option value=""><?php esc_html_e('选择分类', 'aksrt'); ?></option>
|
||
<?php foreach ($categories as $cat) : ?>
|
||
<option value="<?php echo esc_attr((string) $cat->term_id); ?>" <?php selected(in_array($cat->term_id, $current_cats)); ?>><?php echo esc_html($cat->name); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($submit_settings['allow_tags'])) : ?>
|
||
<div class="aksrt-form-group aksrt-submit-form__col">
|
||
<label for="submit-tags">
|
||
<?php esc_html_e('标签', 'aksrt'); ?>
|
||
<button type="button" class="aksrt-ai-assist-btn" data-ai-action="tags" hidden><?php esc_html_e('AI 建议标签', 'aksrt'); ?></button>
|
||
</label>
|
||
<input type="text" id="submit-tags" name="tags" class="aksrt-form-input" placeholder="<?php esc_attr_e('多个标签用逗号分隔', 'aksrt'); ?>" value="<?php echo esc_attr($current_tags); ?>">
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<?php if (!empty($submit_settings['topics_s']) && !empty($topics_terms)) : ?>
|
||
<div class="aksrt-form-group">
|
||
<label for="submit-topics"><?php esc_html_e('专题', 'aksrt'); ?></label>
|
||
<select id="submit-topics" name="topics[]" class="aksrt-form-input" multiple>
|
||
<?php foreach ($topics_terms as $topic) : ?>
|
||
<option value="<?php echo esc_attr((string) $topic->term_id); ?>" <?php selected(in_array($topic->term_id, $current_topics)); ?>><?php echo esc_html($topic->name); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($submit_settings['custom_filter_s']) && !empty($custom_dimensions)) : ?>
|
||
<?php foreach ($custom_dimensions as $dim) : ?>
|
||
<div class="aksrt-form-group">
|
||
<label for="submit-cf-<?php echo esc_attr($dim['key']); ?>"><?php echo esc_html($dim['name']); ?></label>
|
||
<select id="submit-cf-<?php echo esc_attr($dim['key']); ?>" name="cf_<?php echo esc_attr($dim['key']); ?>" class="aksrt-form-input">
|
||
<option value=""><?php printf(esc_html__('选择%s', 'aksrt'), esc_html($dim['name'])); ?></option>
|
||
<?php foreach ($dim['vals'] as $val) : ?>
|
||
<option value="<?php echo esc_attr($val['key']); ?>" <?php selected(!empty($current_cf[$dim['key']]) && $current_cf[$dim['key']] === $val['key']); ?>><?php echo esc_html($val['name']); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
|
||
<div class="aksrt-form-group">
|
||
<label for="submit-content"><?php esc_html_e('内容', 'aksrt'); ?> *</label>
|
||
<div class="aksrt-submit-form__editor-toolbar">
|
||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="bold" title="<?php esc_attr_e('加粗', 'aksrt'); ?>"><i class="fas fa-bold"></i></button>
|
||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="italic" title="<?php esc_attr_e('斜体', 'aksrt'); ?>"><i class="fas fa-italic"></i></button>
|
||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="code" title="<?php esc_attr_e('代码', 'aksrt'); ?>"><i class="fas fa-code"></i></button>
|
||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="link" title="<?php esc_attr_e('链接', 'aksrt'); ?>"><i class="fas fa-link"></i></button>
|
||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="image" title="<?php esc_attr_e('图片', 'aksrt'); ?>"><i class="fas fa-image"></i></button>
|
||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="quote" title="<?php esc_attr_e('引用', 'aksrt'); ?>"><i class="fas fa-quote-left"></i></button>
|
||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="heading" title="<?php esc_attr_e('标题', 'aksrt'); ?>"><i class="fas fa-heading"></i></button>
|
||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="list" title="<?php esc_attr_e('列表', 'aksrt'); ?>"><i class="fas fa-list-ul"></i></button>
|
||
</div>
|
||
<textarea id="submit-content" name="content" class="aksrt-form-input aksrt-submit-form__textarea" rows="16" required placeholder="<?php esc_attr_e('请输入文章内容(支持 HTML)', 'aksrt'); ?>"><?php echo esc_textarea($current_content); ?></textarea>
|
||
<div class="aksrt-submit-form__word-count" id="submit-word-count"></div>
|
||
</div>
|
||
|
||
<?php if (!empty($submit_settings['allow_cover'])) : ?>
|
||
<div class="aksrt-form-group">
|
||
<label for="submit-thumbnail"><?php esc_html_e('封面图', 'aksrt'); ?></label>
|
||
<div class="aksrt-submit-form__cover-input">
|
||
<input type="url" id="submit-thumbnail" name="thumbnail" class="aksrt-form-input" placeholder="<?php esc_attr_e('输入封面图地址', 'aksrt'); ?>" value="<?php echo esc_url($current_thumb); ?>">
|
||
<button type="button" class="aksrt-submit-form__cover-btn" id="aksrt-pick-cover">
|
||
<i class="fas fa-image"></i>
|
||
<?php esc_html_e('选择图片', 'aksrt'); ?>
|
||
</button>
|
||
</div>
|
||
<div class="aksrt-submit-form__cover-preview" id="cover-preview" <?php echo $current_thumb ? '' : 'style="display:none"'; ?>>
|
||
<img id="cover-preview-img" src="<?php echo esc_url($current_thumb); ?>" alt="">
|
||
<button type="button" class="aksrt-submit-form__cover-remove" id="cover-remove" title="<?php esc_attr_e('移除封面', 'aksrt'); ?>">
|
||
<i class="fas fa-times"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div class="aksrt-submit-form__actions">
|
||
<button type="submit" class="aksrt-auth-submit" id="aksrt-submit-btn">
|
||
<i class="fas fa-paper-plane"></i>
|
||
<?php echo $edit_post ? esc_html__('更新投稿', 'aksrt') : esc_html__('提交投稿', 'aksrt'); ?>
|
||
</button>
|
||
<button type="button" class="btn-outline" id="aksrt-save-draft">
|
||
<i class="fas fa-save"></i>
|
||
<?php esc_html_e('保存草稿', 'aksrt'); ?>
|
||
</button>
|
||
</div>
|
||
|
||
<input type="hidden" name="_nonce" value="<?php echo esc_attr(wp_create_nonce('aksrt_submit')); ?>">
|
||
<input type="hidden" name="status" id="submit-status" value="pending">
|
||
</form>
|
||
|
||
<!-- Draft list -->
|
||
<?php
|
||
$user_drafts = get_posts([
|
||
'post_type' => 'post',
|
||
'post_status' => 'draft',
|
||
'author' => $user_id,
|
||
'numberposts' => 10,
|
||
'orderby' => 'modified',
|
||
'order' => 'DESC',
|
||
]);
|
||
if (!empty($user_drafts)) :
|
||
?>
|
||
<div class="aksrt-submit-drafts">
|
||
<h3 class="aksrt-submit-drafts__title">
|
||
<i class="fas fa-file-alt"></i>
|
||
<?php esc_html_e('我的草稿', 'aksrt'); ?>
|
||
</h3>
|
||
<div class="aksrt-submit-drafts__list">
|
||
<?php foreach ($user_drafts as $draft) : ?>
|
||
<div class="aksrt-submit-drafts__item">
|
||
<a href="<?php echo esc_url(add_query_arg('edit', $draft->ID, get_permalink())); ?>" class="aksrt-submit-drafts__link">
|
||
<span class="aksrt-submit-drafts__name"><?php echo esc_html($draft->post_title ?: __('无标题', 'aksrt')); ?></span>
|
||
<time class="aksrt-submit-drafts__date"><?php echo esc_html(get_the_date('Y-m-d H:i', $draft->ID)); ?></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; ?>
|
||
</div>
|
||
</main>
|
||
|
||
<?php
|
||
// Enqueue the front-submit script
|
||
$front_submit_path = get_template_directory() . '/assets/js/front-submit.js';
|
||
if (file_exists($front_submit_path)) {
|
||
wp_enqueue_script(
|
||
'aksrt-front-submit',
|
||
get_template_directory_uri() . '/assets/js/front-submit.js',
|
||
['aksrt-script'],
|
||
(string) filemtime($front_submit_path),
|
||
true
|
||
);
|
||
$ai_available = class_exists('AKSRT_AI') && AKSRT_AI::get_instance()->is_available();
|
||
wp_localize_script('aksrt-front-submit', 'aksrtSubmitData', [
|
||
'ajaxUrl' => admin_url('admin-ajax.php'),
|
||
'nonce' => wp_create_nonce('aksrt_submit_nonce'),
|
||
'restUrl' => esc_url_raw(rest_url('aksrt/v1')),
|
||
'restNonce' => wp_create_nonce('wp_rest'),
|
||
'ai' => [
|
||
'available' => $ai_available,
|
||
'summary' => $ai_available,
|
||
'tags' => $ai_available,
|
||
],
|
||
'i18n' => [
|
||
'confirmLeave' => __('你有未保存的更改,确定要离开吗?', 'aksrt'),
|
||
'saving' => __('保存中...', 'aksrt'),
|
||
'saved' => __('草稿已保存', 'aksrt'),
|
||
'submitting' => __('提交中...', 'aksrt'),
|
||
'submitted' => __('投稿已提交', 'aksrt'),
|
||
'error' => __('操作失败,请重试', 'aksrt'),
|
||
'confirmDelete' => __('确定要删除这个草稿吗?', 'aksrt'),
|
||
'aiGenerating' => __('生成中…', 'aksrt'),
|
||
'aiFailed' => __('AI 生成失败', 'aksrt'),
|
||
'needContent' => __('请先填写正文内容', 'aksrt'),
|
||
'aiFilled' => __('已填入,可继续编辑', 'aksrt'),
|
||
],
|
||
]);
|
||
}
|
||
|
||
get_footer();
|