|
@@ -6,24 +6,103 @@ import { test, expect } from '@playwright/test';
|
|
|
* 目的:验证统一广告模块替换后,用户端API路径和响应结构保持100%兼容
|
|
* 目的:验证统一广告模块替换后,用户端API路径和响应结构保持100%兼容
|
|
|
* 确保:小程序端无需任何修改即可正常工作
|
|
* 确保:小程序端无需任何修改即可正常工作
|
|
|
*
|
|
*
|
|
|
- * API端点映射:
|
|
|
|
|
- * - /api/v1/advertisements → unifiedAdvertisementRoutes (用户端)
|
|
|
|
|
- * - /api/v1/advertisement-types → unifiedAdvertisementTypeRoutes (用户端)
|
|
|
|
|
- * - /api/v1/admin/unified-advertisements → unifiedAdvertisementAdminRoutes (管理员端)
|
|
|
|
|
- * - /api/v1/admin/unified-advertisement-types → unifiedAdvertisementTypeAdminRoutes (管理员端)
|
|
|
|
|
|
|
+ * ## 测试前置条件
|
|
|
|
|
+ *
|
|
|
|
|
+ * 本测试需要数据库中有测试数据:
|
|
|
|
|
+ * 1. 至少一个租户记录在 `tenant_mt` 表中
|
|
|
|
|
+ * 2. 至少一个用户记录在 `users_mt` 表中
|
|
|
|
|
+ * 3. 用户的密码为 `admin123` (测试默认密码)
|
|
|
|
|
+ *
|
|
|
|
|
+ * ## 创建测试数据
|
|
|
|
|
+ *
|
|
|
|
|
+ * 如果测试失败提示401错误,请先创建测试数据:
|
|
|
|
|
+ *
|
|
|
|
|
+ * ```sql
|
|
|
|
|
+ * -- 创建测试租户
|
|
|
|
|
+ * INSERT INTO tenant_mt (id, name, code, status, created_at, updated_at)
|
|
|
|
|
+ * VALUES (1, '测试租户', 'test-tenant', 1, NOW(), NOW());
|
|
|
|
|
+ *
|
|
|
|
|
+ * -- 创建测试用户 (密码: admin123)
|
|
|
|
|
+ * -- 注意:密码需要使用bcrypt加密
|
|
|
|
|
+ * INSERT INTO users_mt (id, tenant_id, username, password, registration_source, is_disabled, is_deleted, created_at, updated_at)
|
|
|
|
|
+ * VALUES (1, 1, 'admin', '$2b$10$x3t2kofPmACnk6y6lfL6ouU836LBEuZE9BinQ3ZzA4Xd04izyY42K', 'web', 0, 0, NOW(), NOW());
|
|
|
|
|
+ * ```
|
|
|
|
|
+ *
|
|
|
|
|
+ * ## 认证说明
|
|
|
|
|
+ *
|
|
|
|
|
+ * - **用户端API**: 使用 `authMiddleware` (多租户认证),需要提供有效的JWT token
|
|
|
|
|
+ * - **小程序端**: 应该使用用户登录后的token访问这些API
|
|
|
|
|
+ * - **管理员API**: 使用 `tenantAuthMiddleware` (超级管理员专用,ID=1)
|
|
|
|
|
+ * - **租户ID**: 通过查询参数 `?tenantId=1` 或请求头 `X-Tenant-Id: 1` 指定
|
|
|
|
|
+ *
|
|
|
|
|
+ * ## API响应格式
|
|
|
|
|
+ *
|
|
|
|
|
+ * API返回包装的响应格式:
|
|
|
|
|
+ * ```json
|
|
|
|
|
+ * {
|
|
|
|
|
+ * "code": 200,
|
|
|
|
|
+ * "message": "success",
|
|
|
|
|
+ * "data": {
|
|
|
|
|
+ * "list": [],
|
|
|
|
|
+ * "total": 0,
|
|
|
|
|
+ * "page": 1,
|
|
|
|
|
+ * "pageSize": 10
|
|
|
|
|
+ * }
|
|
|
|
|
+ * }
|
|
|
|
|
+ * ```
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
test.describe('统一广告API兼容性测试', () => {
|
|
test.describe('统一广告API兼容性测试', () => {
|
|
|
const baseUrl = process.env.API_BASE_URL || 'http://localhost:8080';
|
|
const baseUrl = process.env.API_BASE_URL || 'http://localhost:8080';
|
|
|
|
|
+ const testUsername = process.env.TEST_USERNAME || 'admin';
|
|
|
|
|
+ const testPassword = process.env.TEST_PASSWORD || 'admin123';
|
|
|
|
|
+ const testTenantId = process.env.TEST_TENANT_ID || '1';
|
|
|
|
|
|
|
|
test.describe('用户端广告API (小程序使用)', () => {
|
|
test.describe('用户端广告API (小程序使用)', () => {
|
|
|
|
|
+ let userToken: string;
|
|
|
|
|
+
|
|
|
|
|
+ test.beforeAll(async ({ request }) => {
|
|
|
|
|
+ // 使用测试用户账号登录获取token
|
|
|
|
|
+ // 注意:多租户系统中,用户端API需要认证来确定租户上下文
|
|
|
|
|
+ const loginResponse = await request.post(`${baseUrl}/api/v1/auth/login?tenantId=${testTenantId}`, {
|
|
|
|
|
+ data: {
|
|
|
|
|
+ username: testUsername,
|
|
|
|
|
+ password: testPassword
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (loginResponse.status() === 200) {
|
|
|
|
|
+ const loginData = await loginResponse.json();
|
|
|
|
|
+ userToken = loginData.token || loginData.access_token;
|
|
|
|
|
+ console.log('✅ 登录成功,获取到token');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const error = await loginResponse.json();
|
|
|
|
|
+ console.error('❌ 登录失败:', error);
|
|
|
|
|
+ console.error('💡 提示: 请确保数据库中有测试用户和租户');
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
test('GET /api/v1/advertisements - 获取广告列表', async ({ request }) => {
|
|
test('GET /api/v1/advertisements - 获取广告列表', async ({ request }) => {
|
|
|
- const response = await request.get(`${baseUrl}/api/v1/advertisements`);
|
|
|
|
|
|
|
+ if (!userToken) {
|
|
|
|
|
+ test.skip(true, '缺少认证token,请先创建测试用户');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const response = await request.get(`${baseUrl}/api/v1/advertisements`, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${userToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
// 验证响应状态
|
|
// 验证响应状态
|
|
|
expect(response.status()).toBe(200);
|
|
expect(response.status()).toBe(200);
|
|
|
|
|
|
|
|
- const data = await response.json();
|
|
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ expect(result).toHaveProperty('code', 200);
|
|
|
|
|
+ expect(result).toHaveProperty('data');
|
|
|
|
|
+ expect(result.data).toHaveProperty('list');
|
|
|
|
|
+ expect(result.data).toHaveProperty('total');
|
|
|
|
|
+
|
|
|
|
|
+ const data = result.data.list;
|
|
|
|
|
|
|
|
// 验证响应结构包含广告列表或空数组
|
|
// 验证响应结构包含广告列表或空数组
|
|
|
expect(Array.isArray(data)).toBeTruthy();
|
|
expect(Array.isArray(data)).toBeTruthy();
|
|
@@ -41,11 +120,20 @@ test.describe('统一广告API兼容性测试', () => {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
test('GET /api/v1/advertisements?position=home - 获取指定位置广告', async ({ request }) => {
|
|
test('GET /api/v1/advertisements?position=home - 获取指定位置广告', async ({ request }) => {
|
|
|
- const response = await request.get(`${baseUrl}/api/v1/advertisements?position=home`);
|
|
|
|
|
|
|
+ if (!userToken) {
|
|
|
|
|
+ test.skip(true, '缺少认证token,请先创建测试用户');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const response = await request.get(`${baseUrl}/api/v1/advertisements?position=home`, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${userToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
expect(response.status()).toBe(200);
|
|
expect(response.status()).toBe(200);
|
|
|
|
|
|
|
|
- const data = await response.json();
|
|
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ const data = result.data.list;
|
|
|
expect(Array.isArray(data)).toBeTruthy();
|
|
expect(Array.isArray(data)).toBeTruthy();
|
|
|
|
|
|
|
|
// 验证返回的ads都是home位置
|
|
// 验证返回的ads都是home位置
|
|
@@ -57,17 +145,31 @@ test.describe('统一广告API兼容性测试', () => {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
test('GET /api/v1/advertisements/:id - 获取广告详情', async ({ request }) => {
|
|
test('GET /api/v1/advertisements/:id - 获取广告详情', async ({ request }) => {
|
|
|
|
|
+ if (!userToken) {
|
|
|
|
|
+ test.skip(true, '缺少认证token,请先创建测试用户');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 先获取列表,找一个有效的ID
|
|
// 先获取列表,找一个有效的ID
|
|
|
- const listResponse = await request.get(`${baseUrl}/api/v1/advertisements`);
|
|
|
|
|
- const listData = await listResponse.json();
|
|
|
|
|
|
|
+ const listResponse = await request.get(`${baseUrl}/api/v1/advertisements`, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${userToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ const listResult = await listResponse.json();
|
|
|
|
|
+ const listData = listResult.data.list;
|
|
|
|
|
|
|
|
if (listData.length > 0) {
|
|
if (listData.length > 0) {
|
|
|
const adId = listData[0].id;
|
|
const adId = listData[0].id;
|
|
|
- const response = await request.get(`${baseUrl}/api/v1/advertisements/${adId}`);
|
|
|
|
|
|
|
+ const response = await request.get(`${baseUrl}/api/v1/advertisements/${adId}`, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${userToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
expect(response.status()).toBe(200);
|
|
expect(response.status()).toBe(200);
|
|
|
|
|
|
|
|
- const data = await response.json();
|
|
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ const data = result.data;
|
|
|
expect(data).toHaveProperty('id', adId);
|
|
expect(data).toHaveProperty('id', adId);
|
|
|
expect(data).toHaveProperty('title');
|
|
expect(data).toHaveProperty('title');
|
|
|
expect(data).toHaveProperty('imageUrl');
|
|
expect(data).toHaveProperty('imageUrl');
|
|
@@ -75,16 +177,25 @@ test.describe('统一广告API兼容性测试', () => {
|
|
|
expect(data).toHaveProperty('position');
|
|
expect(data).toHaveProperty('position');
|
|
|
expect(data).toHaveProperty('status');
|
|
expect(data).toHaveProperty('status');
|
|
|
} else {
|
|
} else {
|
|
|
- test.skip(); // 没有广告数据时跳过
|
|
|
|
|
|
|
+ test.skip(true, '没有广告数据,请先创建测试广告');
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
test('GET /api/v1/advertisement-types - 获取广告类型列表', async ({ request }) => {
|
|
test('GET /api/v1/advertisement-types - 获取广告类型列表', async ({ request }) => {
|
|
|
- const response = await request.get(`${baseUrl}/api/v1/advertisement-types`);
|
|
|
|
|
|
|
+ if (!userToken) {
|
|
|
|
|
+ test.skip(true, '缺少认证token,请先创建测试用户');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const response = await request.get(`${baseUrl}/api/v1/advertisement-types`, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${userToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
expect(response.status()).toBe(200);
|
|
expect(response.status()).toBe(200);
|
|
|
|
|
|
|
|
- const data = await response.json();
|
|
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ const data = result.data.list;
|
|
|
expect(Array.isArray(data)).toBeTruthy();
|
|
expect(Array.isArray(data)).toBeTruthy();
|
|
|
|
|
|
|
|
// 验证响应结构
|
|
// 验证响应结构
|
|
@@ -98,8 +209,17 @@ test.describe('统一广告API兼容性测试', () => {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
test('验证响应字段类型正确性', async ({ request }) => {
|
|
test('验证响应字段类型正确性', async ({ request }) => {
|
|
|
- const response = await request.get(`${baseUrl}/api/v1/advertisements`);
|
|
|
|
|
- const data = await response.json();
|
|
|
|
|
|
|
+ if (!userToken) {
|
|
|
|
|
+ test.skip(true, '缺少认证token,请先创建测试用户');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const response = await request.get(`${baseUrl}/api/v1/advertisements`, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${userToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ const data = result.data.list;
|
|
|
|
|
|
|
|
if (data.length > 0) {
|
|
if (data.length > 0) {
|
|
|
const ad = data[0];
|
|
const ad = data[0];
|
|
@@ -118,10 +238,10 @@ test.describe('统一广告API兼容性测试', () => {
|
|
|
|
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
test.beforeAll(async ({ request }) => {
|
|
|
// 使用超级管理员账号登录获取token
|
|
// 使用超级管理员账号登录获取token
|
|
|
- const loginResponse = await request.post(`${baseUrl}/api/v1/auth/login`, {
|
|
|
|
|
|
|
+ const loginResponse = await request.post(`${baseUrl}/api/v1/auth/login?tenantId=${testTenantId}`, {
|
|
|
data: {
|
|
data: {
|
|
|
- username: 'admin',
|
|
|
|
|
- password: 'admin123'
|
|
|
|
|
|
|
+ username: testUsername,
|
|
|
|
|
+ password: testPassword
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -133,7 +253,7 @@ test.describe('统一广告API兼容性测试', () => {
|
|
|
|
|
|
|
|
test('GET /api/v1/admin/unified-advertisements - 管理员获取广告列表', async ({ request }) => {
|
|
test('GET /api/v1/admin/unified-advertisements - 管理员获取广告列表', async ({ request }) => {
|
|
|
if (!authToken) {
|
|
if (!authToken) {
|
|
|
- test.skip(); // 未登录则跳过
|
|
|
|
|
|
|
+ test.skip(true, '缺少认证token,请先创建测试用户');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const response = await request.get(`${baseUrl}/api/v1/admin/unified-advertisements`, {
|
|
const response = await request.get(`${baseUrl}/api/v1/admin/unified-advertisements`, {
|
|
@@ -142,18 +262,19 @@ test.describe('统一广告API兼容性测试', () => {
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- // 管理员API应该返回200或401(取决于权限配置)
|
|
|
|
|
|
|
+ // 管理员API应该返回200或401/403(取决于权限配置)
|
|
|
expect([200, 401, 403]).toContain(response.status());
|
|
expect([200, 401, 403]).toContain(response.status());
|
|
|
|
|
|
|
|
if (response.status() === 200) {
|
|
if (response.status() === 200) {
|
|
|
- const data = await response.json();
|
|
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ const data = result.data.list;
|
|
|
expect(Array.isArray(data)).toBeTruthy();
|
|
expect(Array.isArray(data)).toBeTruthy();
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
test('GET /api/v1/admin/unified-advertisement-types - 管理员获取广告类型列表', async ({ request }) => {
|
|
test('GET /api/v1/admin/unified-advertisement-types - 管理员获取广告类型列表', async ({ request }) => {
|
|
|
if (!authToken) {
|
|
if (!authToken) {
|
|
|
- test.skip(); // 未登录则跳过
|
|
|
|
|
|
|
+ test.skip(true, '缺少认证token,请先创建测试用户');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const response = await request.get(`${baseUrl}/api/v1/admin/unified-advertisement-types`, {
|
|
const response = await request.get(`${baseUrl}/api/v1/admin/unified-advertisement-types`, {
|
|
@@ -165,21 +286,47 @@ test.describe('统一广告API兼容性测试', () => {
|
|
|
expect([200, 401, 403]).toContain(response.status());
|
|
expect([200, 401, 403]).toContain(response.status());
|
|
|
|
|
|
|
|
if (response.status() === 200) {
|
|
if (response.status() === 200) {
|
|
|
- const data = await response.json();
|
|
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ const data = result.data.list;
|
|
|
expect(Array.isArray(data)).toBeTruthy();
|
|
expect(Array.isArray(data)).toBeTruthy();
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
test.describe('API路径兼容性验证', () => {
|
|
test.describe('API路径兼容性验证', () => {
|
|
|
|
|
+ let userToken: string;
|
|
|
|
|
+
|
|
|
|
|
+ test.beforeAll(async ({ request }) => {
|
|
|
|
|
+ // 登录获取token
|
|
|
|
|
+ const loginResponse = await request.post(`${baseUrl}/api/v1/auth/login?tenantId=${testTenantId}`, {
|
|
|
|
|
+ data: {
|
|
|
|
|
+ username: testUsername,
|
|
|
|
|
+ password: testPassword
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (loginResponse.status() === 200) {
|
|
|
|
|
+ const loginData = await loginResponse.json();
|
|
|
|
|
+ userToken = loginData.token || loginData.access_token;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
test('验证所有用户端广告API端点可访问', async ({ request }) => {
|
|
test('验证所有用户端广告API端点可访问', async ({ request }) => {
|
|
|
|
|
+ if (!userToken) {
|
|
|
|
|
+ test.skip(true, '缺少认证token,请先创建测试用户');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
const endpoints = [
|
|
const endpoints = [
|
|
|
'/api/v1/advertisements',
|
|
'/api/v1/advertisements',
|
|
|
'/api/v1/advertisement-types'
|
|
'/api/v1/advertisement-types'
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
for (const endpoint of endpoints) {
|
|
for (const endpoint of endpoints) {
|
|
|
- const response = await request.get(`${baseUrl}${endpoint}`);
|
|
|
|
|
|
|
+ const response = await request.get(`${baseUrl}${endpoint}`, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${userToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
expect(response.status(), `端点 ${endpoint} 应该返回200`).toBe(200);
|
|
expect(response.status(), `端点 ${endpoint} 应该返回200`).toBe(200);
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
@@ -199,9 +346,35 @@ test.describe('统一广告API兼容性测试', () => {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
test.describe('响应数据结构兼容性', () => {
|
|
test.describe('响应数据结构兼容性', () => {
|
|
|
|
|
+ let userToken: string;
|
|
|
|
|
+
|
|
|
|
|
+ test.beforeAll(async ({ request }) => {
|
|
|
|
|
+ // 登录获取token
|
|
|
|
|
+ const loginResponse = await request.post(`${baseUrl}/api/v1/auth/login?tenantId=${testTenantId}`, {
|
|
|
|
|
+ data: {
|
|
|
|
|
+ username: testUsername,
|
|
|
|
|
+ password: testPassword
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (loginResponse.status() === 200) {
|
|
|
|
|
+ const loginData = await loginResponse.json();
|
|
|
|
|
+ userToken = loginData.token || loginData.access_token;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
test('广告列表响应结构与原模块一致', async ({ request }) => {
|
|
test('广告列表响应结构与原模块一致', async ({ request }) => {
|
|
|
- const response = await request.get(`${baseUrl}/api/v1/advertisements`);
|
|
|
|
|
- const data = await response.json();
|
|
|
|
|
|
|
+ if (!userToken) {
|
|
|
|
|
+ test.skip(true, '缺少认证token,请先创建测试用户');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const response = await request.get(`${baseUrl}/api/v1/advertisements`, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${userToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ const data = result.data.list;
|
|
|
|
|
|
|
|
if (data.length > 0) {
|
|
if (data.length > 0) {
|
|
|
const ad = data[0];
|
|
const ad = data[0];
|
|
@@ -221,8 +394,17 @@ test.describe('统一广告API兼容性测试', () => {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
test('广告类型响应结构与原模块一致', async ({ request }) => {
|
|
test('广告类型响应结构与原模块一致', async ({ request }) => {
|
|
|
- const response = await request.get(`${baseUrl}/api/v1/advertisement-types`);
|
|
|
|
|
- const data = await response.json();
|
|
|
|
|
|
|
+ if (!userToken) {
|
|
|
|
|
+ test.skip(true, '缺少认证token,请先创建测试用户');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const response = await request.get(`${baseUrl}/api/v1/advertisement-types`, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${userToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ const data = result.data.list;
|
|
|
|
|
|
|
|
if (data.length > 0) {
|
|
if (data.length > 0) {
|
|
|
const adType = data[0];
|
|
const adType = data[0];
|