shinnosuke
2026-09-21 7844f5af457ff3b7d3f8eeac8799e8d281e635a1
talent-card-server/src/main/java/com/talentcard/server/business/auth/TalentAuthService.java
@@ -125,11 +125,17 @@
                """, openId);
        if (!binding.isEmpty() && number(binding.get(0).get("id")) != talentId) {
            long previousTalentId = number(binding.get(0).get("id"));
            jdbc.update("update talent_user set openid = null where id = ?", previousTalentId);
            jdbc.update("update talent_session set revoked_at = coalesce(revoked_at, now()) where talent_id = ? and revoked_at is null", previousTalentId);
        }
        // uk_openid 是唯一索引:已软删/停用的历史账号照样占着这个 openid,不先摘掉就会撞唯一键(接口报「服务器内部错误」)。
        releaseOpenId(openId, talentId);
        jdbc.update("update talent_user set openid = ? where id = ?", openId, talentId);
        return issueSession(talentId);
    }
    /** 把 openid 从除 keepTalentId 之外的所有行上摘掉(含软删、停用的历史账号)。 */
    private void releaseOpenId(String openId, long keepTalentId) {
        jdbc.update("update talent_user set openid = null where openid = ? and id <> ?", openId, keepTalentId);
    }
    private long registerVisitor(String openId, String mobile) {
@@ -144,6 +150,8 @@
            jdbc.update("update talent_user set mobile = ? where id = ?", mobile, talentId);
            return talentId;
        }
        // 没有可用的绑定时要把历史占用清掉,否则下面这条 insert 会撞 uk_openid。
        jdbc.update("update talent_user set openid = null where openid = ?", openId);
        jdbc.update("""
                insert into talent_user(openid, name, mobile, talent_level, source_area_type, status)
                values (?, '普通游客', ?, '普通游客', 'LOCAL', 1)