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>
104 lines
5.7 KiB
JavaScript
104 lines
5.7 KiB
JavaScript
/**
|
|
* 「收款接口显示顺序」契约(后台 sortable 控件 → 收银台支付方式顺序)。
|
|
*
|
|
* 背景:后台 收款接口 → 收款接口显示顺序 曾整列空白、保存后顺序被静默改写,
|
|
* 且没有任何前台代码消费该配置。本契约锁定四件事:
|
|
* 1) sortable 项使用 JioField 实际读取的 `label` 键(写 `title` 会渲染成空白);
|
|
* 2) 持久化必须保留用户提交的键顺序(键顺序即配置值本身);
|
|
* 3) 排序只保留一份实现,并且真的作用到收银台;
|
|
* 4) 相关的重复实现 / 死模块不回潮。
|
|
*/
|
|
const test = require('node:test');
|
|
const assert = require('node:assert');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
|
|
const root = path.join(__dirname, '..', '..');
|
|
const read = (...seg) => fs.readFileSync(path.join(root, ...seg), 'utf8');
|
|
|
|
const schemaPhp = read('src', 'Admin', 'Schema', 'SchemaPayment.php');
|
|
const schemaJs = read('assets', 'admin', 'src', 'schema', 'sections', 'payment', 'gateway.js');
|
|
const aksField = read('assets', 'admin', 'src', 'components', 'form', 'JioField.vue');
|
|
const provider = read('src', 'Admin', 'SchemaProvider.php');
|
|
const pay = read('inc', 'helpers', 'jio-pay.php');
|
|
const gateway = read('src', 'Payment', 'Gateway.php');
|
|
const wallet = read('inc', 'helpers', 'user-center-renderers', 'credits-wallet.php');
|
|
const pointsRenderer = read('inc', 'helpers', 'user-center-renderers', 'credits-balance.php');
|
|
const vipPackages = read('src', 'Content', 'VipServicePackages.php');
|
|
const balanceCharge = read('src', 'Credits', 'BalanceServiceCharge.php');
|
|
|
|
test('sortable 项使用渲染组件读取的 label 键', () => {
|
|
// 渲染侧读取 item.label —— items 里写 title 会让每一行只剩上下箭头。
|
|
assert.match(aksField, /\{\{\s*item\.label\s*\}\}/);
|
|
|
|
assert.match(schemaJs, /items:\s*\[\s*\{ key: 'wechat', label: '微信' \}/);
|
|
assert.match(schemaJs, /\{ key: 'card_pass', label: '卡密' \}/);
|
|
assert.doesNotMatch(schemaJs, /title: '微信'/);
|
|
|
|
assert.match(schemaPhp, /\['key' => 'wechat', 'label' => '微信'\]/);
|
|
assert.match(schemaPhp, /\['key' => 'card_pass', 'label' => '卡密'\]/);
|
|
assert.doesNotMatch(schemaPhp, /'key' => 'wechat', 'title' => '微信'/);
|
|
});
|
|
|
|
test('sortable 持久化保留提交键顺序', () => {
|
|
const start = provider.indexOf("if ($type === 'sortable') {");
|
|
const end = provider.indexOf("if ($type === 'link') {", start);
|
|
assert.ok(start >= 0 && end > start, 'SchemaProvider 应存在 sortable 分支');
|
|
|
|
const block = provider.slice(start, end);
|
|
const resultLoopStart = block.indexOf('foreach ($value as $item_key');
|
|
assert.ok(resultLoopStart > 0, '结果必须按提交顺序(遍历 $value)构建');
|
|
|
|
const definitionsLoop = block.slice(0, resultLoopStart);
|
|
const resultLoop = block.slice(resultLoopStart);
|
|
|
|
// items 定义只用于白名单校验,不得据此产出结果键顺序。
|
|
assert.doesNotMatch(definitionsLoop, /\$items\[/);
|
|
assert.match(definitionsLoop, /\$definitions\[\$item_key\] = \$item_schema;/, 'items 定义应收敛为白名单');
|
|
// 键顺序即排序值:按提交顺序写入结果,且丢弃未定义的槽位键。
|
|
assert.match(resultLoop, /!isset\(\$definitions\[\$item_key\]\)/);
|
|
assert.match(resultLoop, /\$items\[\$item_key\] = \$this->sanitize_object_fields/);
|
|
});
|
|
|
|
test('排序只有一份实现,无调用方的重复实现已移除', () => {
|
|
assert.match(pay, /if \(!function_exists\('jio_sort_payment_methods'\)\)/);
|
|
assert.match(pay, /function jio_sort_payment_methods\(array \$methods\): array/);
|
|
assert.match(pay, /\$configured = is_array\(\$settings\) \? \(\$settings\['pay_sdk_order'\] \?\? \[\]\) : \[\];/);
|
|
// 槽位映射与后台 sortable 项一一对应,易支付子通道随所属渠道槽位。
|
|
assert.match(pay, /'wechat'\s+=> \['wechatpay', 'epay_wxpay'\]/);
|
|
assert.match(pay, /'alipay'\s+=> \['alipay', 'epay_alipay'\]/);
|
|
assert.match(pay, /'card_pass' => \['card_pass'\]/);
|
|
|
|
// 旧的无调用方实现(第二套排序逻辑)已删除。
|
|
assert.doesNotMatch(gateway, /function get_available\(/);
|
|
assert.doesNotMatch(gateway, /function apply_sdk_order\(/);
|
|
assert.doesNotMatch(gateway, /function get_status_summary\(/);
|
|
});
|
|
|
|
test('基础渠道列表与卡密渠道都经过同一排序实现', () => {
|
|
// 内容收银台 / 会员购买 / 余额充值共用基础列表。
|
|
assert.match(pay, /return jio_sort_payment_methods\(\$methods\);/);
|
|
assert.match(balanceCharge, /jio_sort_payment_methods\(\$methods\)/);
|
|
assert.match(vipPackages, /jio_sort_payment_methods\(\$methods\)/);
|
|
// 购买积分弹窗自建余额 + 卡密列表,同样排序。
|
|
assert.match(pointsRenderer, /jio_sort_payment_methods\(\$points_methods\)/);
|
|
// 卡密输入盒是 method 条件块,位置无关:卡密渠道可被移到任意槽位。
|
|
assert.match(wallet, /in_array\('card_pass', array_column\(\$methods, 'id'\), true\)/);
|
|
});
|
|
|
|
test('会员弹窗不再保留重复的支付方式列表回退分支', () => {
|
|
assert.doesNotMatch(vipPackages, /class_exists\('\\\\Jio\\\\Payment\\\\Gateway'\)/);
|
|
// 卡密渠道注入契约保持(对齐参考主题 zibpay_get_payment_methods)。
|
|
assert.match(vipPackages, /'id' => 'card_pass', 'name' => __\('卡密', 'jio'\)/);
|
|
});
|
|
|
|
test('未被引用的后台 schema 默认值死模块不回潮', () => {
|
|
assert.equal(
|
|
fs.existsSync(path.join(root, 'assets', 'admin', 'src', 'constants', 'settings-defaults.js')),
|
|
false,
|
|
'settings-defaults.js 无任何引用方,应保持删除'
|
|
);
|
|
const schemaIndex = read('assets', 'admin', 'src', 'schema', 'index.js');
|
|
assert.doesNotMatch(schemaIndex, /getSchemaDefaults|getSchemaSectionKeys|getDomainSchemas|CANONICAL_SCHEMA_DOMAINS/);
|
|
});
|