feat(M08-D): 补广告与装修管理

This commit is contained in:
Codex
2026-08-10 12:57:05 +08:00
parent ec4219ae31
commit c1c02421a1
17 changed files with 913 additions and 21 deletions
@@ -129,13 +129,13 @@ async function readMigrationVersions(pool) {
const [rows] = await pool.query(
`SELECT version, name
FROM qipai_schema_migrations
WHERE version IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
WHERE version IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ORDER BY version`,
['2026061601', '2026061802', '2026061803', '2026061804',
'2026061805', '2026061806', '2026061807', '2026061808', '2026061809',
'2026061810', '2026061811', '2026062012', '2026062013', '2026062014',
'2026062015', '2026062216', '2026062217', '2026062218', '2026062219',
'2026062220']
'2026062220', '2026081002']
);
return rows;
}
@@ -1684,6 +1684,24 @@ async function assertContentManagement(pool, context) {
mimeType: 'image/webp', byteSize: 1024, width: 1200, height: 600,
checksumSha256: 'a'.repeat(64)
});
const duplicateAsset = await repository.registerAsset(actor, storeId, {
storagePath: `tenants/${context.tenantId}/stores/${storeId}/duplicate.webp`,
publicUrl: `https://api.txyundm.cn/uploads/tenants/${context.tenantId}/stores/${storeId}/duplicate.webp`,
mimeType: 'image/webp', byteSize: 1024, width: 1200, height: 600,
checksumSha256: 'a'.repeat(64)
});
assert.equal(duplicateAsset.assetId, asset.assetId);
const globalAsset = await repository.registerAsset(actor, undefined, {
storagePath: `tenants/${context.tenantId}/global/sanitized.webp`,
publicUrl: `https://api.txyundm.cn/uploads/tenants/${context.tenantId}/global/sanitized.webp`,
mimeType: 'image/webp', byteSize: 1024, width: 1200, height: 600,
checksumSha256: 'a'.repeat(64)
});
assert.notEqual(globalAsset.assetId, asset.assetId);
assert.deepEqual(
(await repository.listAssets(actor, storeId)).map((item) => item.id).sort(),
[asset.assetId, globalAsset.assetId].sort()
);
const draft1 = await repository.saveDecoration(actor, {
storeId, templateCode: 'classic', schemaVersion: 1,
content: { components: [{ type: 'HERO', props: { assetId: asset.assetId } }] }
@@ -1705,13 +1723,22 @@ async function assertContentManagement(pool, context) {
{ version: 1, status: 'ARCHIVED' },
{ version: 2, status: 'PUBLISHED' }
]);
assert.equal((await repository.listDecorations(actor, storeId)).length, 2);
const ad = await repository.saveAdvertisement(actor, {
scopeType: 'STORE', storeId, title: 'Store banner', imageAssetId: asset.assetId,
targetType: 'PAGE', targetValue: '/pages/index/index',
startsAt: null, endsAt: null, status: 'ACTIVE', sortOrder: 1
});
assert.match(ad.advertisementId, /^[1-9]\d*$/);
assert.equal((await repository.listAdvertisements(actor))[0].scopeType, 'STORE');
await repository.updateAdvertisement(actor, ad.advertisementId, {
scopeType: 'STORE', storeId, title: 'Updated store banner', imageAssetId: asset.assetId,
targetType: 'NONE', targetValue: '', startsAt: null, endsAt: null,
status: 'INACTIVE', sortOrder: 2
});
const savedAd = (await repository.listAdvertisements(actor))[0];
assert.equal(savedAd.scopeType, 'STORE');
assert.equal(savedAd.title, 'Updated store banner');
assert.equal(savedAd.imageAssetId, asset.assetId);
await assert.rejects(
() => repository.saveAdvertisement(actor, {
scopeType: 'PLATFORM', title: 'forbidden', imageAssetId: asset.assetId,
@@ -1998,7 +2025,8 @@ try {
{ version: '2026062217', name: 'm05c_third_party' },
{ version: '2026062218', name: 'm05d_profit_sharing' },
{ version: '2026062219', name: 'm06b_device_topology' },
{ version: '2026062220', name: 'm06c_iot_messages' }
{ version: '2026062220', name: 'm06c_iot_messages' },
{ version: '2026081002', name: 'm08d_content_asset_scope' }
]);
await assertTaskDurability(pool);
const loginContext = await assertPlatformTenantIsolation(pool);
@@ -2048,7 +2076,8 @@ try {
{ version: '2026062217', name: 'm05c_third_party' },
{ version: '2026062218', name: 'm05d_profit_sharing' },
{ version: '2026062219', name: 'm06b_device_topology' },
{ version: '2026062220', name: 'm06c_iot_messages' }
{ version: '2026062220', name: 'm06c_iot_messages' },
{ version: '2026081002', name: 'm08d_content_asset_scope' }
]);
await assertLegacyCompatibility(pool);
console.log('PASS: second up and verify restored the schema.');