diff --git a/functions.php b/functions.php index 30be330..3965a4e 100644 --- a/functions.php +++ b/functions.php @@ -23,6 +23,10 @@ require get_template_directory() . '/inc/theme-core.php'; // 站点配置 require get_template_directory() . '/inc/theme-setting.php'; +// 纪念日自动哀悼(按日期判断,需在 theme-setting 之后, +// 因为它用到 kratos_option) +require get_template_directory() . '/inc/theme-mourning.php'; + // 文章配置 require get_template_directory() . '/inc/theme-article.php'; @@ -38,5 +42,12 @@ require get_template_directory() . '/inc/theme-navwalker.php'; // 对象存储配置 require get_template_directory() . '/inc/theme-dogecloud.php'; -// SMTP 配置 +// 邮件模板:必须先于 theme-mail.php 加载, +// 因为后者在发信时会调用 yang_mail_render() +require get_template_directory() . '/inc/theme-mail-template.php'; + +// 邮件治理:统一接管发信通道、去重、关掉重复通知 +require get_template_directory() . '/inc/theme-mail.php'; + +// SMTP 配置(连通性相关,实际接管在 theme-mail.php) require get_template_directory() . '/inc/theme-smtp.php'; \ No newline at end of file diff --git a/header.php b/header.php index fbdb758..a7c28cd 100644 --- a/header.php +++ b/header.php @@ -18,7 +18,7 @@ - +
diff --git a/inc/options-framework/css/optionsframework.css b/inc/options-framework/css/optionsframework.css index a1e2fdd..20ecbac 100644 --- a/inc/options-framework/css/optionsframework.css +++ b/inc/options-framework/css/optionsframework.css @@ -308,3 +308,54 @@ #optionsframework .about-content .tips b { margin-left: 3px; } + +/* ── 多选复选框组(multicheck)──────────────────────────────── + 框架原本没有这个类型的渲染分支,所以也没有配套样式。 + 不加样式的话,9 个纪念日会挤成一行流水文字,看不出是一个可勾选的清单。 + 这里做成两列表格状,并把说明文字压到第二行、颜色调淡, + 让「名称」是视觉主体、「日期说明」是补充信息。 */ +#optionsframework .of-multicheck { + margin: 0; + padding: 2px 0 0; + border: 0; +} + +#optionsframework .of-multicheck-item { + display: flex; + align-items: flex-start; + gap: 8px; + padding: 9px 12px; + margin: 0 0 2px; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.15s ease; +} + +#optionsframework .of-multicheck-item:hover { + background-color: #f3f5f7; +} + +#optionsframework .of-multicheck-item input[type="checkbox"] { + margin: 3px 0 0; + flex: 0 0 auto; +} + +/* 名称与说明两行文字共用的竖排容器 */ +#optionsframework .of-multicheck-text { + display: flex; + flex-direction: column; + flex: 1 1 auto; +} + +#optionsframework .of-multicheck-label { + font-size: 14px; + color: #23282d; + line-height: 1.5; +} + +#optionsframework .of-multicheck-note { + font-size: 12px; + color: #727777; + line-height: 1.5; + margin-top: 3px; +} diff --git a/inc/options-framework/includes/class-options-interface.php b/inc/options-framework/includes/class-options-interface.php index 059c52e..df4be70 100644 --- a/inc/options-framework/includes/class-options-interface.php +++ b/inc/options-framework/includes/class-options-interface.php @@ -210,6 +210,46 @@ class Options_Framework_Interface $output .= ''; break; + // 多选复选框组 + // + // 框架原来只在保存侧处理了 multicheck(把未提交的项补 false), + // **没有渲染分支、也没有 of_sanitize_multicheck**, + // 所以这个类型此前是不可用的。这里补齐两处。 + // + // 值统一存成 array( 键 => 1|0 ),而不是「勾选了的键组成的列表」: + // 用 map 才能区分「用户明确取消勾选」和「这个键是新增的」。 + // 若存成列表,用户取消全部勾选后存进去是空数组, + // 读的时候无法与「从未配置」区分,会静默回退到默认值。 + case "multicheck": + $name = $option_name . '[' . $value['id'] . ']'; + $saved = is_array($val) ? $val : array(); + if (!empty($value['options'])) { + $output .= ''; + } + break; + // Color picker case "color": $default_color = ''; diff --git a/inc/options-framework/includes/class-options-sanitization.php b/inc/options-framework/includes/class-options-sanitization.php index e366935..cd93fb3 100644 --- a/inc/options-framework/includes/class-options-sanitization.php +++ b/inc/options-framework/includes/class-options-sanitization.php @@ -95,6 +95,36 @@ function of_sanitize_checkbox( $input ) { } add_filter( 'of_sanitize_checkbox', 'of_sanitize_checkbox' ); +/** + * Sanitization for multicheck input + * + * 保存成 array( 键 => 1|0 ),键表来自选项定义里的 options。 + * + * 关键点:**所有已知键都要出现在结果里**,未勾选的写 0。 + * 如果只保留勾选的键,用户取消全部勾选后存进去是空数组, + * 读取时无法与「这个选项从未配置过」区分,会静默回退到默认值, + * 表现成「取消勾选不生效」。这是同类字段最常见的 bug。 + * + * 输入的键先与选项定义里的白名单求交集,防止用户 POST 伪造任意键。 + * + * @param array $input 提交上来的值 + * @param array $option 选项定义(含 options 白名单) + * @return array + */ +function of_sanitize_multicheck( $input, $option ) { + $output = array(); + if ( ! isset( $option['options'] ) || ! is_array( $option['options'] ) ) { + return $output; + } + $input = is_array( $input ) ? $input : array(); + foreach ( $option['options'] as $key => $value ) { + // 只认白名单里的键;值为真即视为勾选 + $output[ $key ] = ( isset( $input[ $key ] ) && $input[ $key ] ) ? 1 : 0; + } + return $output; +} +add_filter( 'of_sanitize_multicheck', 'of_sanitize_multicheck', 10, 2 ); + /** * File upload sanitization. * diff --git a/inc/theme-mail-template.php b/inc/theme-mail-template.php new file mode 100644 index 0000000..64c9e7a --- /dev/null +++ b/inc/theme-mail-template.php @@ -0,0 +1,374 @@ +` + `cellpadding` 在老 + * Outlook 里可靠。现在的 web 布局写法在邮件里必崩。 + * + * 2. **样式必须内联**。Gmail 会把 `` 里的 ` + + + + + + + +|
+
+
+
+
+
+
+您收到这封邮件,是因为本站记录了与您邮箱相关的订阅或互动。
+
+
+ |
' . __('您的留言已经通过了管理员的审核,摘要信息如下:', 'kratos') . '
-' . htmlspecialchars_decode(get_option('blogname'), ENT_QUOTES) . '
-' . date("Y年m月d日", time()) . '
-' . __('您的留言有了新的回复,摘要信息如下:', 'kratos') . '
-' . htmlspecialchars_decode(get_option('blogname'), ENT_QUOTES) . '
-' . date("Y年m月d日", time()) . '
-