Files
kate522andClaude Opus 5 35bb96e82f refactor: rename the theme brand and every identifier from AKSRT to Jio
Full-project rename. `git grep -i aksrt` is now empty apart from the
DBMigrator 3.3.0 changelog note that documents the rename itself.

Code identifiers
- PHP namespace AKSRT\ -> Jio\ (composer PSR-4 + 378 declarations)
- global constants AKSRT_* -> JIO_* (VERSION/DIR/URI, PAY_TYPE_*, CAPTCHA_*)
- procedural functions, hooks, options, meta keys, table names,
  cookies, query vars, ajax actions and nonces: aksrt_ -> jio_
- text domain aksrt -> jio; Theme Name -> Jio
- JS globals: aksrtData/aksrtAdminData/... -> jioData/jioAdminData/...,
  window.AKSRTCaptcha & friends -> window.JioCaptcha, Aksrt* -> Jio*
- Vue components Aks*.vue -> Jio*.vue (15 files renamed + imports)
- CSS classes/data-attrs/custom properties: aksrt- -> jio-
- REST namespace aksrt/v1 -> jio/v1 (incl. payment gateway callbacks)

Storage layer
- DB tables {prefix}aksrt_* -> {prefix}jio_*; SCHEMA_VERSION 3.2.0 -> 3.3.0
  so dbDelta creates the new names on install
- widget id_base aksrt_widget_* -> jio_widget_*
- uninstall.php drop list rebuilt from the actual migrator tables
  (dropped 3 stale entries, added the 17 missing ones)

Removed
- hardcoded https://api.aksrt.com/version.json default update endpoint;
  get_endpoint() now reads the 「更新端点」 setting and do_check() no-ops
  when it is empty

Files renamed: inc/helpers/aksrt-*.php -> jio-*.php (54),
assets/admin/src/components/form/Aks*.vue -> Jio*.vue (15).
Build artifacts regenerated: assets/css/build, assets/js/runtime,
assets/admin/build.

Verified: audit-psr4-paths errors=0, audit-admin-contracts errors=0
(warnings=56, unchanged baseline), 813/813 widget-system tests,
44/44 phpunit, php -l clean across all PHP.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-11-01 20:05:04 +08:00

810 lines
28 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Jio Gutenberg Blocks
*
* Custom Gutenberg block extensions for the Jio theme.
* Provides 9 generic content blocks adapted from legacy.
*
* Blocks: tabs, tab, enlighter, quote, alert, buttons, collapse, feature, iframe
*
* @package Jio
*/
(function () {
'use strict';
if (!window.wp || !window.wp.blocks) return;
var el = wp.element.createElement;
var Fragment = wp.element.Fragment;
var RawHTML = wp.element.RawHTML;
var registerBlockTypeRaw = wp.blocks.registerBlockType;
var blockEditor = wp.blockEditor || wp.editor || {};
var InspectorControls = blockEditor.InspectorControls || null;
var InnerBlocks = blockEditor.InnerBlocks || null;
var RichText = blockEditor.RichText || null;
var MediaUpload = blockEditor.MediaUpload || null;
var PanelBody = wp.components.PanelBody;
var SelectControl = wp.components.SelectControl;
var TextControl = wp.components.TextControl;
var ToggleControl = wp.components.ToggleControl;
var RangeControl = wp.components.RangeControl;
var Notice = wp.components.Notice;
var useSelect = window.wp.data && window.wp.data.useSelect;
if (!registerBlockTypeRaw || !el) return;
// ── Helper: create element shorthand ──
function h(tag, props, children) {
var args = [tag, props];
if (children !== undefined) {
if (Array.isArray(children)) {
args = args.concat(children);
} else {
args.push(children);
}
}
return el.apply(null, args);
}
// ── Helper: InspectorControls wrapper ──
function withInspector(title, children) {
if (!InspectorControls) return null;
return h(InspectorControls, { key: 'inspector' },
h(PanelBody, { title: title }, children)
);
}
var CATEGORY = 'jio-blocks';
var BLOCK_ICON = h('svg', { viewBox: '0 0 24 24', width: 20, height: 20 },
h('path', { d: 'M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5', fill: 'none', stroke: 'currentColor', strokeWidth: 2 })
);
// Register category BEFORE any registerBlockType (filter-after-register is too late).
if (window.wp.hooks && window.wp.hooks.addFilter) {
wp.hooks.addFilter('blocks.getBlockCategories', 'jio/block-categories', function (categories) {
var list = Array.isArray(categories) ? categories.slice() : [];
var hasJio = list.some(function (c) { return c && c.slug === CATEGORY; });
if (hasJio) return list;
list.push({
slug: CATEGORY,
title: 'Jio',
icon: null,
});
return list;
});
}
// WP 6.9+ expects apiVersion 3 for iframe editor compatibility.
function registerBlockType(name, settings) {
settings = settings || {};
if (settings.apiVersion == null) {
settings.apiVersion = 3;
}
if (!settings.category) {
settings.category = CATEGORY;
}
return registerBlockTypeRaw(name, settings);
}
// ================================================================
// 1. Tabs Block
// ================================================================
registerBlockType('jio/tabs', {
title: '标签页',
icon: BLOCK_ICON,
category: CATEGORY,
description: '可切换的标签页内容容器',
attributes: {
style: { type: 'string', default: 'default' },
},
edit: function (props) {
return h(Fragment, null,
withInspector('标签页设置',
h(SelectControl, {
label: '样式',
value: props.attributes.style,
options: [
{ label: '默认', value: 'default' },
{ label: '线条', value: 'line' },
{ label: '卡片', value: 'card' },
],
onChange: function (v) { props.setAttributes({ style: v }); }
})
),
h('div', { className: 'jio-block-tabs jio-block-tabs--' + props.attributes.style },
h(InnerBlocks, {
allowedBlocks: ['jio/tab'],
template: [['jio/tab', { title: '标签 1' }], ['jio/tab', { title: '标签 2' }]],
})
)
);
},
save: function (props) {
return h('div', { className: 'jio-block-tabs jio-block-tabs--' + props.attributes.style },
h(InnerBlocks.Content, null)
);
},
});
registerBlockType('jio/tab', {
title: '标签页项',
icon: BLOCK_ICON,
category: CATEGORY,
parent: ['jio/tabs'],
attributes: {
title: { type: 'string', default: '标签' },
},
edit: function (props) {
return h(Fragment, null,
h(TextControl, {
label: '标签标题',
value: props.attributes.title,
onChange: function (v) { props.setAttributes({ title: v }); }
}),
h('div', { className: 'jio-block-tab__content' },
h(InnerBlocks, null)
)
);
},
save: function (props) {
return h('div', { className: 'jio-block-tab', 'data-title': props.attributes.title },
h(InnerBlocks.Content, null)
);
},
});
// ================================================================
// 2. EnlighterJS Code Block
// ================================================================
registerBlockType('jio/enlighter', {
title: '代码高亮',
icon: 'editor-code',
category: CATEGORY,
description: '带语法高亮的代码块(EnlighterJS)',
attributes: {
code: { type: 'string', default: '' },
language: { type: 'string', default: 'javascript' },
theme: { type: 'string', default: '' },
linenumbers: { type: 'boolean', default: true },
},
edit: function (props) {
return h(Fragment, null,
withInspector('代码块设置',
h(SelectControl, {
label: '语言',
value: props.attributes.language,
options: [
{ label: 'JavaScript', value: 'javascript' },
{ label: 'TypeScript', value: 'typescript' },
{ label: 'PHP', value: 'php' },
{ label: 'Python', value: 'python' },
{ label: 'Java', value: 'java' },
{ label: 'C/C++', value: 'cpp' },
{ label: 'C#', value: 'csharp' },
{ label: 'Go', value: 'go' },
{ label: 'Rust', value: 'rust' },
{ label: 'Ruby', value: 'ruby' },
{ label: 'Swift', value: 'swift' },
{ label: 'Kotlin', value: 'kotlin' },
{ label: 'HTML', value: 'html' },
{ label: 'CSS/SCSS', value: 'css' },
{ label: 'SQL', value: 'sql' },
{ label: 'Shell/Bash', value: 'shell' },
{ label: 'JSON', value: 'json' },
{ label: 'YAML', value: 'yaml' },
{ label: 'Markdown', value: 'markdown' },
{ label: 'Docker', value: 'dockerfile' },
{ label: 'Diff', value: 'diff' },
{ label: 'XML', value: 'xml' },
],
onChange: function (v) { props.setAttributes({ language: v }); }
}),
h(ToggleControl, {
label: '显示行号',
checked: props.attributes.linenumbers,
onChange: function (v) { props.setAttributes({ linenumbers: v }); }
})
),
h('div', { className: 'jio-block-enlighter' },
h('div', { className: 'jio-block-enlighter__header' },
h('span', { className: 'jio-block-enlighter__lang' }, props.attributes.language)
),
h('textarea', {
className: 'jio-block-enlighter__code',
value: props.attributes.code,
onChange: function (e) { props.setAttributes({ code: e.target.value }); },
placeholder: '在此输入代码...',
rows: 10,
spellCheck: false,
})
)
);
},
save: function (props) {
var attrs = {
className: 'gl',
'data-enlighter-language': props.attributes.language,
};
if (props.attributes.theme) attrs['data-enlighter-theme'] = props.attributes.theme;
if (!props.attributes.linenumbers) attrs['data-enlighter-linenumbers'] = 'false';
return h('pre', { className: 'enlighter-pre' },
h('code', attrs, props.attributes.code)
);
},
});
// ================================================================
// 3. Quote Block
// ================================================================
registerBlockType('jio/quote-styled', {
title: '样式引用',
icon: 'editor-quote',
category: CATEGORY,
description: '带颜色样式的引用块',
attributes: {
content: { type: 'string', default: '' },
style: { type: 'string', default: 'gray' },
cite: { type: 'string', default: '' },
},
edit: function (props) {
return h(Fragment, null,
withInspector('引用设置',
h(SelectControl, {
label: '样式',
value: props.attributes.style,
options: [
{ label: '灰色', value: 'gray' },
{ label: '蓝色', value: 'blue' },
{ label: '绿色', value: 'green' },
{ label: '红色', value: 'red' },
{ label: '黄色', value: 'yellow' },
],
onChange: function (v) { props.setAttributes({ style: v }); }
}),
h(TextControl, {
label: '来源',
value: props.attributes.cite,
onChange: function (v) { props.setAttributes({ cite: v }); }
})
),
h('blockquote', { className: 'jio-block-quote jio-block-quote--' + props.attributes.style },
h(RichText, {
tagName: 'p',
value: props.attributes.content,
onChange: function (v) { props.setAttributes({ content: v }); },
placeholder: '输入引用内容...',
}),
props.attributes.cite ? h('cite', null, props.attributes.cite) : null
)
);
},
save: function (props) {
return h('blockquote', { className: 'jio-block-quote jio-block-quote--' + props.attributes.style },
h(RichText.Content, { tagName: 'p', value: props.attributes.content }),
props.attributes.cite ? h('cite', null, props.attributes.cite) : null
);
},
});
// ================================================================
// 4. Alert Block
// ================================================================
registerBlockType('jio/alert', {
title: '提示框',
icon: 'warning',
category: CATEGORY,
description: '通知/警告/成功/信息提示框',
attributes: {
content: { type: 'string', default: '' },
type: { type: 'string', default: 'info' },
dismissible: { type: 'boolean', default: false },
},
edit: function (props) {
return h(Fragment, null,
withInspector('提示框设置',
h(SelectControl, {
label: '类型',
value: props.attributes.type,
options: [
{ label: '信息', value: 'info' },
{ label: '成功', value: 'success' },
{ label: '警告', value: 'warning' },
{ label: '错误', value: 'error' },
],
onChange: function (v) { props.setAttributes({ type: v }); }
}),
h(ToggleControl, {
label: '可关闭',
checked: props.attributes.dismissible,
onChange: function (v) { props.setAttributes({ dismissible: v }); }
})
),
h('div', {
className: 'jio-block-alert jio-block-alert--' + props.attributes.type +
(props.attributes.dismissible ? ' jio-block-alert--dismissible' : '')
},
h(RichText, {
tagName: 'p',
value: props.attributes.content,
onChange: function (v) { props.setAttributes({ content: v }); },
placeholder: '输入提示内容...',
})
)
);
},
save: function (props) {
var cls = 'jio-block-alert jio-block-alert--' + props.attributes.type;
if (props.attributes.dismissible) cls += ' jio-block-alert--dismissible';
return h('div', { className: cls, role: 'alert' },
h(RichText.Content, { tagName: 'p', value: props.attributes.content }),
props.attributes.dismissible ? h('button', { type: 'button', className: 'jio-block-alert__close', 'aria-label': '关闭' }, '×') : null
);
},
});
// ================================================================
// 5. Buttons Block
// ================================================================
registerBlockType('jio/buttons', {
title: '按钮组',
icon: 'button',
category: CATEGORY,
description: '多个按钮组合',
attributes: {
align: { type: 'string', default: 'left' },
},
edit: function (props) {
return h(Fragment, null,
withInspector('按钮组设置',
h(SelectControl, {
label: '对齐',
value: props.attributes.align,
options: [
{ label: '左对齐', value: 'left' },
{ label: '居中', value: 'center' },
{ label: '右对齐', value: 'right' },
],
onChange: function (v) { props.setAttributes({ align: v }); }
})
),
h('div', { className: 'jio-block-buttons jio-block-buttons--' + props.attributes.align },
h(InnerBlocks, {
allowedBlocks: ['jio/button'],
template: [['jio/button', { text: '按钮', style: 'primary' }]],
})
)
);
},
save: function (props) {
return h('div', { className: 'jio-block-buttons jio-block-buttons--' + props.attributes.align },
h(InnerBlocks.Content, null)
);
},
});
registerBlockType('jio/button', {
title: '按钮',
icon: 'button',
category: CATEGORY,
parent: ['jio/buttons'],
attributes: {
text: { type: 'string', default: '按钮' },
url: { type: 'string', default: '' },
style: { type: 'string', default: 'primary' },
size: { type: 'string', default: 'md' },
newTab: { type: 'boolean', default: false },
},
edit: function (props) {
return h(Fragment, null,
withInspector('按钮设置',
h(TextControl, {
label: '链接',
value: props.attributes.url,
onChange: function (v) { props.setAttributes({ url: v }); }
}),
h(SelectControl, {
label: '样式',
value: props.attributes.style,
options: [
{ label: '主要', value: 'primary' },
{ label: '次要', value: 'secondary' },
{ label: '轮廓', value: 'outline' },
{ label: '幽灵', value: 'ghost' },
],
onChange: function (v) { props.setAttributes({ style: v }); }
}),
h(SelectControl, {
label: '大小',
value: props.attributes.size,
options: [
{ label: '小', value: 'sm' },
{ label: '中', value: 'md' },
{ label: '大', value: 'lg' },
],
onChange: function (v) { props.setAttributes({ size: v }); }
}),
h(ToggleControl, {
label: '新窗口打开',
checked: props.attributes.newTab,
onChange: function (v) { props.setAttributes({ newTab: v }); }
})
),
h(RichText, {
tagName: 'span',
className: 'jio-block-btn jio-block-btn--' + props.attributes.style + ' jio-block-btn--' + props.attributes.size,
value: props.attributes.text,
onChange: function (v) { props.setAttributes({ text: v }); },
placeholder: '按钮文字...',
withoutInteractiveFormatting: true,
})
);
},
save: function (props) {
var linkProps = {
className: 'jio-block-btn jio-block-btn--' + props.attributes.style + ' jio-block-btn--' + props.attributes.size,
};
if (props.attributes.url) {
linkProps.href = props.attributes.url;
if (props.attributes.newTab) {
linkProps.target = '_blank';
linkProps.rel = 'noopener noreferrer';
}
return h('a', linkProps, props.attributes.text);
}
return h('span', linkProps, props.attributes.text);
},
});
// ================================================================
// 6. Collapse Block
// ================================================================
registerBlockType('jio/collapse', {
title: '折叠面板',
icon: 'arrow-down',
category: CATEGORY,
description: '可展开/收起的内容面板',
attributes: {
title: { type: 'string', default: '点击展开' },
open: { type: 'boolean', default: false },
},
edit: function (props) {
return h(Fragment, null,
withInspector('折叠面板设置',
h(ToggleControl, {
label: '默认展开',
checked: props.attributes.open,
onChange: function (v) { props.setAttributes({ open: v }); }
})
),
h('div', { className: 'jio-block-collapse' },
h('div', { className: 'jio-block-collapse__header' },
h(RichText, {
tagName: 'span',
className: 'jio-block-collapse__title',
value: props.attributes.title,
onChange: function (v) { props.setAttributes({ title: v }); },
placeholder: '面板标题...',
}),
h('span', { className: 'jio-block-collapse__arrow' }, '▼')
),
h('div', { className: 'jio-block-collapse__body' },
h(InnerBlocks, null)
)
)
);
},
save: function (props) {
return h('details', {
className: 'jio-block-collapse',
open: props.attributes.open ? true : undefined,
},
h('summary', { className: 'jio-block-collapse__header' },
h('span', { className: 'jio-block-collapse__title' }, props.attributes.title)
),
h('div', { className: 'jio-block-collapse__body' },
h(InnerBlocks.Content, null)
)
);
},
});
// ================================================================
// 7. Feature Grid Block
// ================================================================
registerBlockType('jio/feature', {
title: '特性网格',
icon: 'grid-view',
category: CATEGORY,
description: '图标+标题+描述的特性展示网格',
attributes: {
columns: { type: 'number', default: 3 },
},
edit: function (props) {
return h(Fragment, null,
withInspector('特性网格设置',
h(RangeControl, {
label: '列数',
value: props.attributes.columns,
min: 2,
max: 4,
onChange: function (v) { props.setAttributes({ columns: v }); }
})
),
h('div', { className: 'jio-block-feature jio-block-feature--cols-' + props.attributes.columns },
h(InnerBlocks, {
allowedBlocks: ['jio/feature-item'],
template: [
['jio/feature-item', { icon: 'fa fas fa-star', title: '特性一', desc: '特性描述' }],
['jio/feature-item', { icon: 'fa fas fa-heart', title: '特性二', desc: '特性描述' }],
['jio/feature-item', { icon: 'fa fas fa-bolt', title: '特性三', desc: '特性描述' }],
],
})
)
);
},
save: function (props) {
return h('div', { className: 'jio-block-feature jio-block-feature--cols-' + props.attributes.columns },
h(InnerBlocks.Content, null)
);
},
});
registerBlockType('jio/feature-item', {
title: '特性项',
icon: 'star-filled',
category: CATEGORY,
parent: ['jio/feature'],
attributes: {
icon: { type: 'string', default: 'fa fas fa-star' },
title: { type: 'string', default: '' },
desc: { type: 'string', default: '' },
},
edit: function (props) {
return h('div', { className: 'jio-block-feature__item' },
h(TextControl, {
label: '图标类名',
value: props.attributes.icon,
onChange: function (v) { props.setAttributes({ icon: v }); }
}),
h('i', { className: props.attributes.icon + ' jio-block-feature__icon' }),
h(RichText, {
tagName: 'h3',
className: 'jio-block-feature__title',
value: props.attributes.title,
onChange: function (v) { props.setAttributes({ title: v }); },
placeholder: '标题...',
}),
h(RichText, {
tagName: 'p',
className: 'jio-block-feature__desc',
value: props.attributes.desc,
onChange: function (v) { props.setAttributes({ desc: v }); },
placeholder: '描述...',
})
);
},
save: function (props) {
return h('div', { className: 'jio-block-feature__item' },
h('i', { className: props.attributes.icon + ' jio-block-feature__icon' }),
h('h3', { className: 'jio-block-feature__title' }, props.attributes.title),
h('p', { className: 'jio-block-feature__desc' }, props.attributes.desc)
);
},
});
// ================================================================
// 8. Responsive Iframe Block
// ================================================================
registerBlockType('jio/iframe', {
title: '响应式嵌入',
icon: 'video-alt3',
category: CATEGORY,
description: '响应式 iframe 嵌入(视频、地图等)',
attributes: {
src: { type: 'string', default: '' },
ratio: { type: 'string', default: '16:9' },
title: { type: 'string', default: '' },
},
edit: function (props) {
return h(Fragment, null,
withInspector('嵌入设置',
h(TextControl, {
label: 'URL',
value: props.attributes.src,
onChange: function (v) { props.setAttributes({ src: v }); }
}),
h(SelectControl, {
label: '宽高比',
value: props.attributes.ratio,
options: [
{ label: '16:9', value: '16:9' },
{ label: '4:3', value: '4:3' },
{ label: '1:1', value: '1:1' },
{ label: '自适应', value: 'auto' },
],
onChange: function (v) { props.setAttributes({ ratio: v }); }
}),
h(TextControl, {
label: '标题',
value: props.attributes.title,
onChange: function (v) { props.setAttributes({ title: v }); }
})
),
h('div', { className: 'jio-block-iframe jio-block-iframe--' + props.attributes.ratio.replace(':', '-') },
props.attributes.src
? h('iframe', { src: props.attributes.src, title: props.attributes.title || '嵌入内容', allowfullscreen: true })
: h('div', { className: 'jio-block-iframe__placeholder' }, '请输入嵌入 URL')
)
);
},
save: function (props) {
return h('div', { className: 'jio-block-iframe jio-block-iframe--' + props.attributes.ratio.replace(':', '-') },
h('iframe', {
src: props.attributes.src,
title: props.attributes.title || '嵌入内容',
allowfullscreen: true,
loading: 'lazy',
})
);
},
});
// ── Carousel Block (Gallery → Swiper) ──
// MediaUpload lives on wp.blockEditor; skip registration if unavailable.
if (MediaUpload) {
registerBlockType('jio/carousel', {
title: '轮播图',
icon: 'images-alt2',
category: CATEGORY,
description: '图片轮播/幻灯片(基于 Swiper)',
attributes: {
images: { type: 'array', default: [] },
autoplay: { type: 'boolean', default: true },
delay: { type: 'number', default: 3000 },
effect: { type: 'string', default: 'slide' },
},
edit: function (props) {
var attrs = props.attributes;
var setAttributes = props.setAttributes;
var onSelectImages = function (media) {
setAttributes({
images: media.map(function (m) {
return { url: m.url, alt: m.alt || '', id: m.id };
}),
});
};
var inspector = h(InspectorControls, { key: 'insp' },
h(PanelBody, { title: '轮播设置' },
h(ToggleControl, {
label: '自动播放',
checked: attrs.autoplay,
onChange: function (v) { setAttributes({ autoplay: v }); },
}),
h(RangeControl, {
label: '切换间隔(毫秒)',
value: attrs.delay,
min: 1000,
max: 10000,
step: 500,
onChange: function (v) { setAttributes({ delay: v }); },
}),
h(SelectControl, {
label: '切换效果',
value: attrs.effect,
options: [
{ label: '滑动', value: 'slide' },
{ label: '淡入淡出', value: 'fade' },
{ label: '立方体', value: 'cube' },
],
onChange: function (v) { setAttributes({ effect: v }); },
})
)
);
var preview = attrs.images.length > 0
? h('div', { className: 'jio-carousel-preview', style: { display: 'flex', gap: '8px', flexWrap: 'wrap' } },
attrs.images.map(function (img, i) {
return h('img', {
key: i,
src: img.url,
alt: img.alt,
style: { width: '120px', height: '80px', objectFit: 'cover', borderRadius: '6px' },
});
})
)
: h('p', { style: { color: '#999', textAlign: 'center', padding: '20px' } }, '请选择图片');
return h(Fragment, null,
inspector,
h('div', { className: 'jio-carousel-block' },
preview,
h(MediaUpload, {
onSelect: onSelectImages,
allowedTypes: ['image'],
multiple: true,
value: attrs.images.map(function (img) { return img.id; }),
render: function (obj) {
return h(wp.components.Button, {
onClick: obj.open,
variant: 'secondary',
style: { marginTop: '8px' },
}, attrs.images.length ? '重新选择图片' : '选择图片');
},
})
)
);
},
save: function () {
// Dynamic block — rendered via PHP
return null;
},
});
}
// ================================================================
// 9. Paid Fragment Block
// ================================================================
function usePaidReadingConfigured() {
if (!useSelect) return true;
return useSelect(function (select) {
var editor = select('core/editor');
if (!editor || !editor.getEditedPostAttribute) return true;
var meta = editor.getEditedPostAttribute('meta') || {};
var pay = meta._jio_pay || {};
if (pay.pay_type !== 'reading') return false;
return pay.pay_modo === 'points'
? Number(pay.points_price || 0) > 0
: Number(pay.price || 0) > 0;
}, []);
}
registerBlockType('jio/paid-fragment', {
title: '付费可见',
icon: 'lock',
category: CATEGORY,
description: '仅购买文章付费阅读后可见的片段。',
attributes: {
content: { type: 'string', default: '' },
},
edit: function (props) {
var configured = usePaidReadingConfigured();
return h('div', { className: 'jio-paid-fragment-block' },
!configured && Notice ? h(Notice, { status: 'warning', isDismissible: false },
'请在“付费内容设置”中选择“付费阅读”并设置有效价格;未配置时此片段会公开显示。'
) : null,
h('div', { className: 'jio-paid-fragment-block__label' },
h('span', { className: 'dashicons dashicons-lock', 'aria-hidden': true }),
'付费可见片段'
),
h(RichText, {
tagName: 'div',
className: 'jio-paid-fragment-block__content',
value: props.attributes.content,
onChange: function (value) { props.setAttributes({ content: value }); },
placeholder: '输入购买后可见的内容…',
})
);
},
save: function (props) {
// Save a single canonical shortcode so hand-written and block-authored
// content use the identical server-side rendering path.
var shortcode = '[hidecontent type="payshow"]' + props.attributes.content + '[/hidecontent]';
return RawHTML ? h(RawHTML, null, shortcode) : shortcode;
},
});
})();