Commencez votre voyage transfrontalier
Contactez-nous

Développement de sites web, service à la clientèle

Service clientèle

Panneaux d'affichage WordPress personnalisés : vous pouvez personnaliser plusieurs panneaux d'affichage afin qu'ils tournent automatiquement et qu'ils affichent un compte à rebours, qui peut ensuite être ajouté au menu de navigation de l'arrière-plan.
add_action('init', function() {
register_post_type('announcement_bar', [
'labels' => [
'name' => '公告栏',
'add_new_item' => '添加新公告',
'edit_item' => '编辑公告',
],
'public' => false,
'show_ui' => true,
'menu_icon' => 'dashicons-megaphone',
'supports' => ['title', 'page-attributes'],
]);
});
add_action('add_meta_boxes', function() {
add_meta_box('announcement_fields', '公告设置', function($post) {
$meta = get_post_meta($post->ID);
$val = function($key, $default = '') use ($meta) {
return isset($meta[$key][0]) ? esc_attr($meta[$key][0]) : $default;
};
?>
<p><label>链接地址:<input type="url" name="link" value="<?php echo $val('link'); ?>" style="width:100%"></label></p>
<p><label><input type="checkbox" name="enable_timer" value="1" <?php checked($val('enable_timer'), '1'); ?>> 启用倒计时</label></p>
<p><label>倒计时目标时间:<input type="datetime-local" name="timer_end" value="<?php echo $val('timer_end'); ?>"></label></p>
<?php
}, 'announcement_bar');
});
add_action('save_post', function($post_id) {
if (get_post_type($post_id) !== 'announcement_bar') return;
foreach (['link', 'timer_end'] as $field) {
if (isset($_POST[$field])) update_post_meta($post_id, $field, sanitize_text_field($_POST[$field]));
}
update_post_meta($post_id, 'enable_timer', isset($_POST['enable_timer']) ? '1' : '0');
});
add_action('admin_menu', function() {
add_submenu_page(
'edit.php?post_type=announcement_bar',
'公告栏全局设置',
'公告栏设置',
'manage_options',
'announcement_bar_options',
function() {
if ($_POST && current_user_can('manage_options')) {
update_option('announcement_bar_enabled', isset($_POST['enabled']) ? 1 : 0);
update_option('announcement_bar_autoplay', isset($_POST['autoplay']) ? 1 : 0);
update_option('announcement_bar_interval', intval($_POST['interval']));
update_option('announcement_bar_bg', sanitize_hex_color($_POST['bg']));
update_option('announcement_bar_text', sanitize_hex_color($_POST['text']));
update_option('announcement_bar_timerbg', sanitize_hex_color($_POST['timerbg']));
update_option('announcement_bar_timertext', sanitize_hex_color($_POST['timertext']));
echo '<div class="updated"><p>设置已保存!</p></div>';
}
$bg = esc_attr(get_option('announcement_bar_bg', '#222222'));
$text = esc_attr(get_option('announcement_bar_text', '#ffffff'));
$timerbg = esc_attr(get_option('announcement_bar_timerbg', '#ff4444'));
$timertext = esc_attr(get_option('announcement_bar_timertext', '#ffffff'));
?>
<div class="wrap">
<h2>公告栏全局设置</h2>
<form method="post">
<table class="form-table">
<tr>
<th><label>启用公告栏</label></th>
<td><input type="checkbox" name="enabled" value="1" <?php checked(get_option('announcement_bar_enabled'), 1); ?>></td>
</tr>
<tr>
<th><label>启用轮播(所有设备)</label></th>
<td><input type="checkbox" name="autoplay" value="1" <?php checked(get_option('announcement_bar_autoplay'), 1); ?>></td>
</tr>
<tr>
<th><label>轮播间隔(毫秒)</label></th>
<td><input type="number" name="interval" value="<?php echo esc_attr(get_option('announcement_bar_interval', 5000)); ?>" min="1000" step="500"></td>
</tr>
<tr>
<th><label>背景颜色</label></th>
<td>
<input type="color" id="bg_color_picker" value="<?php echo $bg; ?>">
<input type="text" name="bg" id="bg_color_text" value="<?php echo $bg; ?>" style="width:100px;">
</td>
</tr>
<tr>
<th><label>字体颜色</label></th>
<td>
<input type="color" id="text_color_picker" value="<?php echo $text; ?>">
<input type="text" name="text" id="text_color_text" value="<?php echo $text; ?>" style="width:100px;">
</td>
</tr>
<tr>
<th><label>倒计时背景颜色</label></th>
<td>
<input type="color" id="timerbg_color_picker" value="<?php echo $timerbg; ?>">
<input type="text" name="timerbg" id="timerbg_color_text" value="<?php echo $timerbg; ?>" style="width:100px;">
</td>
</tr>
<tr>
<th><label>倒计时字体颜色</label></th>
<td>
<input type="color" id="timertext_color_picker" value="<?php echo $timertext; ?>">
<input type="text" name="timertext" id="timertext_color_text" value="<?php echo $timertext; ?>" style="width:100px;">
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded',function(){
var bgPicker=document.getElementById('bg_color_picker');
var bgText=document.getElementById('bg_color_text');
var textPicker=document.getElementById('text_color_picker');
var textText=document.getElementById('text_color_text');
var timerbgPicker=document.getElementById('timerbg_color_picker');
var timerbgText=document.getElementById('timerbg_color_text');
var timertextPicker=document.getElementById('timertext_color_picker');
var timertextText=document.getElementById('timertext_color_text');
if(bgPicker&&bgText){
bgPicker.addEventListener('input',function(){bgText.value=bgPicker.value;});
bgText.addEventListener('input',function(){bgPicker.value=bgText.value;});
}
if(textPicker&&textText){
textPicker.addEventListener('input',function(){textText.value=textPicker.value;});
textText.addEventListener('input',function(){textPicker.value=textText.value;});
}
if(timerbgPicker&&timerbgText){
timerbgPicker.addEventListener('input',function(){timerbgText.value=timerbgPicker.value;});
timerbgText.addEventListener('input',function(){timerbgPicker.value=timerbgText.value;});
}
if(timertextPicker&&timertextText){
timertextPicker.addEventListener('input',function(){timertextText.value=timertextPicker.value;});
timertextText.addEventListener('input',function(){timertextPicker.value=timertextText.value;});
}
});
</script>
<?php
}
);
});
add_action('wp_body_open', function() {
if (!get_option('announcement_bar_enabled')) return;
$bg_color = get_option('announcement_bar_bg', '#222222');
$text_color = get_option('announcement_bar_text', '#ffffff');
$timerbg = get_option('announcement_bar_timerbg', '#ff4444');
$timertext = get_option('announcement_bar_timertext', '#ffffff');
$autoplay = get_option('announcement_bar_autoplay') ? 'true' : '0';
$interval = intval(get_option('announcement_bar_interval', 5000));
$posts = get_posts([
'post_type' => 'announcement_bar',
'post_status' => 'publish',
'orderby' => 'menu_order',
'order' => 'ASC',
'numberposts' => -1
]);
if (!$posts) return;
echo '<div class="announcement-bar-swiper"><div class="swiper-wrapper">';
foreach ($posts as $post) {
$link = get_post_meta($post->ID, 'link', true);
$text = esc_html($post->post_title);
$enable_timer = get_post_meta($post->ID, 'enable_timer', true);
$timer_end = get_post_meta($post->ID, 'timer_end', true);
echo '<div class="swiper-slide bar-has-timer" style="color:'.$text_color.';background:'.$bg_color.';font-weight:bold;">';
echo '<div class="bar-center-wrap">';
echo '<span class="bar-main">'.($link ? '<a href="'.esc_url($link).'">'.$text.'</a>' : $text).'</span>';
if ($enable_timer && $timer_end) {
echo '<span class="bar-countdown" data-end="'.esc_attr($timer_end).'" data-bg="'.esc_attr($timerbg).'" data-txt="'.esc_attr($timertext).'"></span>';
}
echo '</div>';
echo '</div>';
}
echo '</div></div>';
});
add_action('wp_footer', function() {
$interval = intval(get_option('announcement_bar_interval', 5000));
$autoplay = get_option('announcement_bar_autoplay') ? 'true' : '0';
?>
<style>
.announcement-bar-swiper {
font-size: 14px; position: relative; overflow: hidden; z-index: 9999;
width: 100vw; max-width: 100vw;
}
.announcement-bar-swiper .swiper-wrapper { display: flex;}
.announcement-bar-swiper .swiper-slide {
display: flex; justify-content: center; align-items: center;
padding: 10px 20px; font-weight: bold; color: inherit;
white-space: normal; word-break: break-all;
font-size: 14px; box-sizing: border-box;
width: 100vw !important; max-width: 100vw; min-width: 100vw;
}
.announcement-bar-swiper .bar-center-wrap {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
width: 100%;
}
.announcement-bar-swiper .bar-main { display: inline-block; }
.announcement-bar-swiper .swiper-slide * { color: inherit !important; font-size: inherit !important;}
.announcement-bar-swiper a { color: inherit !important; text-decoration: none;}
.announcement-bar-swiper .bar-countdown {
display: inline-flex;
align-items: center;
gap: 6px;
margin-left: 0;
line-height: 1;
}
.announcement-bar-swiper .bar-countdown .time-num {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 32px;
padding: 2px 8px;
border-radius: 0; /* 去掉圆角 */
font-family: monospace;
font-weight: bold;
font-size: inherit;
}
.announcement-bar-swiper .bar-countdown .time-label {
margin: 0 2px;
font-family: inherit;
background: none !important;
padding: 0;
min-width: unset;
border-radius: 0;
}
@media (max-width: 767.98px) {
.announcement-bar-swiper { padding-left:0; padding-right:0;}
.announcement-bar-swiper .swiper-wrapper {
display: flex !important;
flex-direction: row !important;
width: 100vw;
}
.announcement-bar-swiper .swiper-slide {
flex-direction: column !important;
align-items: center !important;
justify-content: center !important;
gap: 0 !important;
box-sizing: border-box;
padding-left: 20px !important;
padding-right: 20px !important;
width: 100vw !important;
max-width: 100vw !important;
min-width: 100vw !important;
margin: 0 !important;
}
.announcement-bar-swiper .bar-center-wrap {
width: 100%;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8px;
}
.announcement-bar-swiper .bar-main {
width:100%;
justify-content:center;
text-align: center;
padding-bottom: 0;
}
.announcement-bar-swiper .bar-countdown {
width: 100%;
margin: 0;
justify-content: center;
margin-bottom: 0;
}
}
@media (min-width: 768px) {
.announcement-bar-swiper .swiper-wrapper { display: flex;}
.announcement-bar-swiper .swiper-slide {flex-direction: row !important;}
.announcement-bar-swiper .bar-countdown {margin-left:10px;margin-top:0;}
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
var autoplay = <?php echo $autoplay; ?>;
var interval = <?php echo $interval; ?>;
if (typeof Swiper !== 'undefined') {
new Swiper('.announcement-bar-swiper', {
loop: false,
autoplay: autoplay ? { delay: interval } : false,
slidesPerView: 1,
centeredSlides: false,
spaceBetween: 0,
});
}
document.querySelectorAll('.bar-countdown').forEach(function(el){
const end = new Date(el.dataset.end).getTime();
const bg = el.dataset.bg || '#ff4444';
const txt = el.dataset.txt || '#fff';
function render(left){
const d = Math.floor(left / (1000*60*60*24));
const h = Math.floor((left / (1000*60*60)) % 24);
const m = Math.floor((left / (1000*60)) % 60);
const s = Math.floor((left / 1000) % 60);
el.innerHTML =
'<span class="time-num" style="background:'+bg+';color:'+txt+';">'+String(d).padStart(2,'0')+'</span>' +
'<span class="time-label">D</span>' +
'<span class="time-num" style="background:'+bg+';color:'+txt+';">'+String(h).padStart(2,'0')+'</span>' +
'<span class="time-label">:</span>' +
'<span class="time-num" style="background:'+bg+';color:'+txt+';">'+String(m).padStart(2,'0')+'</span>' +
'<span class="time-label">:</span>' +
'<span class="time-num" style="background:'+bg+';color:'+txt+';">'+String(s).padStart(2,'0')+'</span>';
}
function update(){
const now = new Date().getTime();
const left = Math.max(0, end - now);
render(left);
}
update();
setInterval(update, 1000);
});
});
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.css" />
<script src="https://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.js"></script>
<?php
});