/** * 用户中心左侧栏图标契约(参考主题 1:1 对齐)。 * * 硬约束: * 1) 「我的服务 / 功能设置」两个网格使用参考主题的 icon-but-box / user-icon-but-box * 外壳,图标全部来自主题内置 SVG sprite(jio_icon_markup('jiosvg-*')), * 不再出现 Font Awesome 字形。 * 2) 侧栏其余部件(余额/积分卡、创作/推广卡、VIP 入口、抽屉触发器)同样只使用 * sprite 图标,箭头统一为 jiosvg-right,保证侧栏只剩一种图标族。 * 3) 旧的 uc-service-grid 外壳、色调底色与计数角标必须已彻底移除,不得残留。 */ 'use strict'; const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const test = require('node:test'); const root = path.resolve(__dirname, '..', '..'); const read = (file) => fs.readFileSync(path.join(root, file), 'utf8'); const sidebarDir = 'inc/helpers/user-center-renderers/'; const sidebarFiles = [ 'sidebar-nav.php', 'sidebar-commerce.php', 'sidebar-creator.php', 'sidebar-vip.php', 'profile-sidebar.php', ]; test('服务/设置网格使用参考主题 icon-but-box 外壳与 sprite 图标', () => { const nav = read(sidebarDir + 'sidebar-nav.php'); assert.match(nav, /class="flex ac hh text-center icon-but-box user-icon-but-box"/); assert.match(nav, /
<\?php echo \$icon_html;/); assert.match(nav, /
/); assert.match(nav, /jio_icon_markup\('jiosvg-' \. \(string\) \$item\['icon'\]\)/); // 参考主题选型:我的服务 = trend-color / user-auth / order-color。 assert.match(nav, /'icon'\s+=>\s+'trend-color'/); assert.match(nav, /'icon'\s+=>\s+'user-auth'/); assert.match(nav, /'icon'\s+=>\s+'order-color'/); // 功能设置 = msg-color / user-color / security-color。 assert.match(nav, /'icon'\s+=>\s+'msg-color'/); assert.match(nav, /'icon'\s+=>\s+'user-color'/); assert.match(nav, /'icon'\s+=>\s+'security-color'/); // 每项都带 tab,保证 icon-but-* 类名完整且选中态可同步。 for (const tab of ['level', 'auth', 'orders', 'msg', 'profile', 'settings']) { assert.match(nav, new RegExp(`'tab'\\s+=>\\s+'${tab}'`), `missing tab key: ${tab}`); } // Jio 的跳转契约保留 + data-tab,不搬参考主题的 。 assert.match(nav, //); assert.doesNotMatch(nav, /data-onclick/); }); test('侧栏部件(VIP 与创作/推广卡除外)不再出现 Font Awesome 字形', () => { // VIP 入口与创作/推广卡 1:1 参考主题,箭头沿用 fa-chevron-circle-right / fa-angle-right。 const faAllowed = new Set(['sidebar-vip.php', 'sidebar-creator.php']); for (const file of sidebarFiles.filter((f) => !faAllowed.has(f))) { const source = read(sidebarDir + file); assert.doesNotMatch(source, /fa\s+fas\s+fa-/, `${file} still renders a Font Awesome glyph`); assert.doesNotMatch(source, / { const shell = read('assets/css/routes/user-center/shell.css'); assert.doesNotMatch(shell, /uc-service-grid/); for (const file of sidebarFiles) { assert.doesNotMatch(read(sidebarDir + file), /uc-service-grid/); } // 计数角标与 tone 键随色调 CSS 一并成为死代码。 assert.doesNotMatch(shell, /uc-service-grid__icon small/); assert.doesNotMatch(read(sidebarDir + 'sidebar-nav.php'), /\$item\['count'\]/); assert.doesNotMatch(read(sidebarDir + 'sidebar-nav.php'), /'tone'/); // 参考主题网格尺寸落地。 assert.match(shell, /\.user-icon-but-box > a \{[^}]*width: calc\(25% - 10px\)/s); assert.match(shell, /\.user-icon-but-box > a \{[^}]*min-width: 50px/s); // 参考主题网格项没有 hover / 选中变色,只继承正文色。 assert.doesNotMatch(shell, /\.user-icon-but-box > a\.is-active/); assert.match(shell, /\.user-icon-but-box > a \{[^}]*color: inherit/s); // 外壳与标题 1:1 参考主题 jio-widget-box padding-6 / padding-6 ml3。 const nav = read(sidebarDir + 'sidebar-nav.php'); assert.match(nav, /class="uc-sidebar-iconbox jio-widget-box padding-6 mb10-sm"/); assert.match(nav, /class="uc-sidebar-iconbox jio-widget-box padding-6"/); assert.match(nav, /
<\?php esc_html_e\('我的服务'/); assert.match(nav, /
<\?php esc_html_e\('功能设置'/); assert.doesNotMatch(nav, /uc-sidebar__heading/); assert.match(shell, /\.uc-sidebar-iconbox\.jio-widget-box \{/); // 卡片上的 已换成 ,元素选择器需覆盖两者。 assert.match(shell, /\.uc-summary-card__body > svg/); // 旧的琥珀 VIP 券与 uc-center-card 已被参考主题结构替换。 assert.doesNotMatch(shell, /uc-center-card/); assert.doesNotMatch(shell, /uc-sidebar-vip__/); assert.match(shell, /\.uc-sidebar-centers > \.jio-widget-box/); // 文章/评论/收藏/粉丝统计。 const stats = read(sidebarDir + 'sidebar-stats.php'); assert.match(stats, /mb10-sm mb20 flex ac jsa jio-widget-box padding-10 text-center/); assert.match(stats, /<\?php echo esc_html\(jio_cut_count\(/); assert.match(stats, /
/); assert.doesNotMatch(stats, /uc-stats|uc-sidebar__section/); assert.doesNotMatch(shell, /\.uc-stats/); assert.doesNotMatch(read('assets/css/routes/user-center/responsive.css'), /\.uc-stats/); assert.match(shell, /\.uc-sidebar-statistics\.jio-widget-box \{/); }); test('所用 sprite key 均在前端 sprite 中定义', () => { const sprite = read('assets/js/runtime/svg-icon.js'); const keys = [ 'trend-color', 'user-auth', 'order-color', 'msg-color', 'user-color', 'security-color', 'money-color-2', 'points-color', 'merchant-color', 'money-color', 'vip_1', 'time', 'menu', 'right', 'comment-color', ]; for (const key of keys) { assert.match(sprite, new RegExp(`jio_svgs\\['${key}'\\]\\s*=`), `sprite key missing: ${key}`); } }); test('导航栏用户浮层的余额/积分磁贴与侧栏使用同一组 sprite key', () => { const nav = read(sidebarDir + 'sidebar-commerce.php'); const wallet = read('inc/helpers/jio-header-userbox.php'); assert.match(wallet, /jio_icon_markup\('jiosvg-money-color-2', 'em14'\)/); assert.match(wallet, /jio_icon_markup\('jiosvg-points-color', 'em14'\)/); assert.match(nav, /jio_icon_markup\('jiosvg-money-color-2'\)/); assert.match(nav, /jio_icon_markup\('jiosvg-points-color'\)/); // 磁贴箭头沿用参考主题的 fa-angle-right,不做多余替换。 assert.match(wallet, /fa fas fa-angle-right em12/); assert.doesNotMatch(wallet, /fa fas fa-money-bill-wave/); assert.doesNotMatch(wallet, /fa fas fa-coins/); }); test('余额/积分资产卡的标题图标与参考主题一致', () => { const wallet = read('inc/helpers/user-center-renderers/credits-wallet.php'); const balance = read('inc/helpers/user-center-renderers/credits-balance.php'); // 参考主题:余额用 money-color-2,积分用 points-color,两者都是彩色 sprite。 assert.match(wallet, /jio_icon_markup\('jiosvg-money-color-2', 'em12 mr6'\)/); assert.match(balance, /jio_icon_markup\('jiosvg-points-color', 'em12 mr6'\)/); // 卡片标题不再退回 Font Awesome 字形。 for (const [name, source] of [['credits-wallet.php', wallet], ['credits-balance.php', balance]]) { const title = source.slice(source.indexOf('uc-asset-card__title'), source.indexOf('uc-asset-card__title') + 400); assert.doesNotMatch(title, /fa fas fa-money-bill|fa fas fa-coins/, name); } }); test('等级页经验任务行使用参考主题的 trend-color 图标', () => { const level = read('inc/helpers/user-center-renderers/profile-level.php'); // 参考主题:每条经验任务 = trend-color + 「+ N」,成长体系标题同图标。 assert.match(level, /jio_icon_markup\('jiosvg-trend-color', 'icon mr6 em09'\)/); assert.match(level, /jio_icon_markup\('jiosvg-trend-color', 'icon mr6 em12'\)/); assert.doesNotMatch(level, /fa fas fa-bolt|fa fas fa-chart-line/); });