feat: 同步管理端、用户端与后端业务,并接通线上 Web 接口

补齐平台订阅、外部登录、CRM 同步与用户端页面;Nginx 转发用户端接口,登录页使用 Google 与 Apple 标志。

Co-authored-by: Cursor <cursoragent@cursor.com>
这个提交包含在:
wikiboss
2026-09-23 18:01:47 +08:00
父节点 8ea9c25386
当前提交 62e0ae4435
共有 227 个文件被更改,包括 21855 次插入 和 5264 次删除

查看文件

@@ -8,6 +8,10 @@ import {
AdminNfcSecurityController,
adminNfcSecurityCurdOption,
} from '../../../src/modules/nfc/controller/admin/security';
import {
AUDIT_ACTION_NFC_FREEZE,
BaseAuditLogService,
} from '../../../src/modules/base/service/audit';
/**
* CoolController 元数据(脚本路径解析为异步)
@@ -114,12 +118,17 @@ class MemoryNfcDeviceRepo {
}
function createService(
seed: Array<Partial<NfcDeviceEntity>> = []
seed: Array<Partial<NfcDeviceEntity>> = [],
auditRecord?: jest.Mock
): NfcSecurityService {
const service = new NfcSecurityService();
service.nfcDeviceEntity = new MemoryNfcDeviceRepo(
seed
) as unknown as NfcSecurityService['nfcDeviceEntity'];
const auditService = new BaseAuditLogService();
auditService.record = (auditRecord ||
jest.fn(async dto => dto)) as unknown as BaseAuditLogService['record'];
service.baseAuditLogService = auditService;
return service;
}
@@ -227,6 +236,43 @@ describe('T24 NFC 挂失冻结 API (nfc/security)', () => {
CoolCommException
);
});
it('freeze 成功后应写入 nfc_freeze 审计(含操作者与 uid/设备 id)', async () => {
const record = jest.fn(async dto => dto);
const service = createService(seedDevices(), record);
service.baseCtx = {
admin: { userId: 42, username: 'SecAdmin' },
} as unknown as NfcSecurityService['baseCtx'];
const frozen = await service.freeze({ uid: '04:7A:B2:8F:1C:6D:80' });
expect(frozen.status).toBe('suspended');
expect(record).toHaveBeenCalledTimes(1);
expect(record).toHaveBeenCalledWith(
expect.objectContaining({
module: 'nfc',
action: AUDIT_ACTION_NFC_FREEZE,
operatorId: 42,
operatorName: 'SecAdmin',
status: 1,
})
);
const detail = JSON.parse(String(record.mock.calls[0][0].detail));
expect(detail.uid).toBe('04:7A:B2:8F:1C:6D:80');
expect(detail.deviceId).toBe(1);
expect(detail).not.toHaveProperty('secret');
expect(detail).not.toHaveProperty('phone');
});
it('freeze 失败(设备不存在)时不得记成功审计', async () => {
const record = jest.fn(async dto => dto);
const service = createService(seedDevices(), record);
await expect(service.freeze({ id: 9999 })).rejects.toThrow(
CoolCommException
);
expect(record).not.toHaveBeenCalled();
});
});
describe('2. 后台控制器 /admin/nfc/security', () => {