UserController.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. package modules.user;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.jdcloud.sdk.service.sms.model.BatchSendResponse;
  4. import com.jfinal.aop.Before;
  5. import com.jfinal.aop.Inject;
  6. import com.jfinal.kit.HashKit;
  7. import com.jfinal.kit.StrKit;
  8. import common.interceptor.LoginInterceptor;
  9. import common.interceptor.empty.EmptyInterface;
  10. import common.interceptor.role.RequiredRoleInterface;
  11. import common.model.User;
  12. import common.utils.http.MyController;
  13. import common.utils.http.MyRet;
  14. import common.utils.http.VerifyCode;
  15. import common.utils.jdcloud.SMS;
  16. import java.util.HashMap;
  17. import java.util.List;
  18. import java.util.Map;
  19. public class UserController extends MyController {
  20. // 验证码相关的常量
  21. private static final long SEND_VERIFY_CODE_DELAY = 60 * 1000; // 验证码发送间隔
  22. private static final long VERIFY_CODE_EXPIRATION_TIME = 5 * 60 * 1000; // 验证码有效期,5 分钟 (300 秒)
  23. // 角色相关常量
  24. public static final int ROLE_SUPER_ADMIN = 0; // 超级管理员
  25. public static final int ROLE_CHECK_ADMIN = 1; // 审核管理员
  26. public static final int ROLE_USER = 2; // 普通用户
  27. @Inject
  28. private UserService service;
  29. public void hello() {
  30. renderJson(MyRet.ok(service.hello()));
  31. }
  32. @EmptyInterface({"mobile_number"})
  33. public void sendVerifyCode() {
  34. // --- 核心修改部分 ---
  35. // 通过 MyController 获取解析后的 JSON 对象,拦截器也使用了这个方法
  36. JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
  37. // 从 JSON 对象中获取 mobile_number
  38. String mobileNumber = requestBodyJson.getString("mobile_number");
  39. // 2. 校验发送间隔
  40. // 从 Session 中获取上次发送验证码的时间戳
  41. Long lastSendTime = getSessionAttr("last_send_verify_code_time");
  42. if (lastSendTime != null) {
  43. long currentTime = System.currentTimeMillis();
  44. if (currentTime - lastSendTime < SEND_VERIFY_CODE_DELAY) {
  45. // 计算还需要等待多少秒
  46. long remainingSeconds = (SEND_VERIFY_CODE_DELAY - (currentTime - lastSendTime)) / 1000 + 1; // +1 确保显示完整秒数
  47. renderJson(MyRet.fail("验证码发送过于频繁,请 " + remainingSeconds + " 秒后再试"));
  48. return;
  49. }
  50. }
  51. // 3. 生成验证码
  52. String verifyCode = VerifyCode.randomVerifyCode();
  53. // 4. 将验证码和发送时间戳存入 Session
  54. setSessionAttr("verify_code", verifyCode); // 验证码本身
  55. setSessionAttr("last_send_verify_code_time", System.currentTimeMillis()); // 记录本次发送时间戳
  56. // 5. 实际发送验证码(这里是模拟发送)
  57. BatchSendResponse response = SMS.sendVerifyCodeByMobileNumber(mobileNumber, verifyCode);
  58. String jsonResponse = JSONObject.toJSONString(response);
  59. boolean isSentSuccessfully = response.getResult().getStatus();
  60. if (isSentSuccessfully) {
  61. renderJson(MyRet.ok("验证码已发送,请注意查收。").setData(jsonResponse));
  62. } else {
  63. // 短信服务商返回发送失败的情况处理
  64. renderJson(MyRet.fail("验证码发送失败,请稍后再试").setData(jsonResponse));
  65. }
  66. }
  67. @EmptyInterface({"mobile_number", "pwd_md5", "repeat_pwd_md5", "verify_code"})
  68. public void register() {
  69. // --- 核心修改部分:从 JSON 请求体中获取参数 ---
  70. JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
  71. // 因为 EmptyInterceptor 已经保证了这些字段不为空,这里可以直接获取
  72. String mobileNumber = requestBodyJson.getString("mobile_number");
  73. String pwd = requestBodyJson.getString("pwd_md5");
  74. String repeatPwd = requestBodyJson.getString("repeat_pwd_md5");
  75. String userVerifyCode = requestBodyJson.getString("verify_code");
  76. // 2. 密码重复校验
  77. if (!pwd.equals(repeatPwd)) {
  78. renderJson(MyRet.fail("两次输入密码不一致"));
  79. return;
  80. }
  81. // 3. 验证码校验
  82. MyRet verifyCodeRet = checkVerifyCode(userVerifyCode);
  83. if (!verifyCodeRet.isOk()) {
  84. renderJson(verifyCodeRet);
  85. return;
  86. }
  87. // 4. 构建 User 对象并处理业务逻辑
  88. // 因为 getPara("mobile_number") 已经获取了手机号,这里可以手动设置
  89. // 或者优化 getModel 的用法,让它只获取数据库字段,然后手动设置 mobileNumber。
  90. // 但为了保持原先 getModel 的语义,这里继续使用。
  91. User user = getModel(User.class, "", true);
  92. // 确保 mobile_number 填充正确
  93. if (StrKit.isBlank(user.getStr("mobile_number"))) {
  94. // 如果 getModel 没能获取到 mobile_number,则手动设置,确保数据完整性
  95. user.set("mobile_number", mobileNumber);
  96. }
  97. // 参数补充
  98. user.set("role", 2); // 例如:2表示普通用户
  99. // 密码加密并存储
  100. user.set("pwd_md5_md5", HashKit.md5(pwd));
  101. user.set("integral", 0);
  102. user.set("is_deleted", 0); // 0表示未禁用
  103. // 5. 调用服务层进行用户保存
  104. renderJson(service.saveUser(user));
  105. }
  106. @EmptyInterface({"mobile_number"})
  107. public void login() {
  108. // --- 从 JSON 请求体中获取参数 ---
  109. JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
  110. // 因为 EmptyInterceptor 已经保证了这些字段不为空,这里可以直接获取
  111. String mobileNumber = requestBodyJson.getString("mobile_number");
  112. String pwdMd5 = requestBodyJson.getString("pwd_md5");
  113. String verifyCode = requestBodyJson.getString("verify_code");
  114. // 1. 校验手机号是否被注册
  115. if (!service.isUserExists(mobileNumber)) {
  116. renderJson(MyRet.fail("该手机号未注册。"));
  117. return;
  118. }
  119. // 2.判断是使用密码还是验证码登录
  120. MyRet ret = MyRet.fail("参数缺失,需要pwd_md5或verify_code").setData(requestBodyJson);
  121. // 如果传入了密码优先使用密码登录
  122. if (StrKit.notBlank(pwdMd5)) {
  123. ret = service.login(mobileNumber, HashKit.md5(pwdMd5));
  124. }
  125. // 如果有验证码传入进行验证码校验
  126. if (StrKit.notBlank(verifyCode)) {
  127. MyRet verifyCodeRet = checkVerifyCode(verifyCode);
  128. if (!verifyCodeRet.isOk()) {
  129. renderJson(verifyCodeRet);
  130. return;
  131. }
  132. ret = service.verifyCodeLogin(mobileNumber);
  133. }
  134. if (ret.isOk()) {
  135. String token = createToken("dl-token");
  136. // 更新用户登录时间
  137. service.updateUserLoginTime(mobileNumber);
  138. // 更新用户token
  139. service.updateToken(mobileNumber, token);
  140. // 将token传回前端
  141. ret.set("token", token);
  142. // 其它参数的封装
  143. setSessionAttr("user_id", ((User)ret.get("data")).getStr("id"));
  144. setSessionAttr("mobile_number", ((User)ret.get("data")).getStr("mobile_number"));
  145. setSessionAttr("role", ((User)ret.get("data")).getStr("role"));
  146. }
  147. renderJson(ret);
  148. }
  149. // 慧用工免登请求地址,用来换取手机号
  150. public void tokenToMobileNumber() {
  151. // --- 从 JSON 请求体中获取参数 ---
  152. JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
  153. System.out.println(requestBodyJson.toJSONString());
  154. String token = requestBodyJson.getString("token");
  155. if (StrKit.notBlank(token)) {
  156. renderText(service.findMobileNumberByToken(token));
  157. } else {
  158. renderText("");
  159. }
  160. }
  161. // 慧用工签约回调地址
  162. public void hygSign() {
  163. // --- 从 JSON 请求体中获取参数 ---
  164. JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
  165. System.out.println(requestBodyJson.toJSONString());
  166. String workerid = requestBodyJson.getString("workerid");
  167. if (StrKit.notBlank(workerid)) {
  168. System.out.println(workerid);
  169. // renderText(service.update(hygSign));
  170. renderText("ok");
  171. } else {
  172. renderText("");
  173. }
  174. }
  175. @Before(LoginInterceptor.class)
  176. public void getUserInfo() {
  177. User user = service.findUserByMobileNumber(this.<String>getSessionAttr("mobile_number"));
  178. if (user == null) {
  179. removeSessionAttr("dl-token");
  180. removeSessionAttr("role");
  181. removeSessionAttr("mobile_number");
  182. renderJson(MyRet.fail("登录信息失效,请重新登录。").setCode(MyRet.CODE_NO_LOGIN));
  183. } else {
  184. renderJson(MyRet.ok("获取成功").setData(user));
  185. }
  186. }
  187. public void logout() {
  188. removeSessionAttr("user_id");
  189. removeSessionAttr("mobile_number");
  190. removeSessionAttr("dl-token");
  191. removeSessionAttr("role");
  192. renderJson(MyRet.ok("已成功登出。"));
  193. }
  194. /**
  195. * 更新用户的方法,传什么更新什么,不传就不更新,id必须传
  196. */
  197. @Before(LoginInterceptor.class)
  198. @RequiredRoleInterface({UserController.ROLE_SUPER_ADMIN})
  199. @EmptyInterface({"id"})
  200. public void updateByAdmin() {
  201. JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
  202. String id = requestBodyJson.getString("id");
  203. User user = service.findUserById(id);
  204. // 检查用户合法性
  205. if (user == null) {
  206. renderJson(MyRet.fail("用户获取不合法,该id对应的用户不存在,不要乱传参数。id: " + id));
  207. return;
  208. }
  209. // 校验昵称是否需要修改
  210. String nickname = requestBodyJson.getString("nickname");
  211. if (StrKit.notBlank(nickname)) {
  212. user.set("nickname", nickname);
  213. }
  214. // 校验手机号是否需要修改
  215. String mobileNumber = requestBodyJson.getString("mobile_number");
  216. if (StrKit.notBlank(mobileNumber)) {
  217. user.set("mobile_number", mobileNumber);
  218. }
  219. // 密码修改
  220. String pwdMd5 = requestBodyJson.getString("pwd_md5");
  221. if (StrKit.notBlank(pwdMd5)) {
  222. user.set("pwd_md5_md5", HashKit.md5(pwdMd5));
  223. }
  224. // 权限修改
  225. String roleStr = requestBodyJson.getString("role");
  226. if (StrKit.notBlank(roleStr)) {
  227. try {
  228. int roleInt = Integer.parseInt(roleStr); // 转换为 int 类型
  229. if (roleInt == ROLE_SUPER_ADMIN) {
  230. renderJson(MyRet.fail("为了安全考虑!不能在该接口设置超级管理员!请联系开发者处理!"));
  231. return;
  232. } else if (user.getInt("role") == 0) {
  233. renderJson(MyRet.fail("为了安全考虑!不能在该接口将超级管理员降级!请联系开发者处理!"));
  234. return;
  235. } else {
  236. user.set("role", roleInt);
  237. }
  238. } catch (Exception e) {
  239. // 处理转换失败的情况,例如记录日志,或者返回错误信息给前端
  240. renderJson(MyRet.fail("role 格式不正确" + e.getMessage()));
  241. return; // 中断后续操作
  242. }
  243. }
  244. // 推荐人修改
  245. String referrerIdStr = requestBodyJson.getString("referrer_id");
  246. if (StrKit.notBlank(referrerIdStr)) {
  247. try {
  248. long referrerIdLong = Long.parseLong(referrerIdStr); // 或者 int,根据数据库字段大小
  249. user.set("referrer_id", referrerIdLong);
  250. } catch (Exception e) {
  251. renderJson(MyRet.fail("referrer_id 格式不正确: " + e.getMessage()));
  252. return;
  253. }
  254. }
  255. // 积分修改
  256. String integralStr = requestBodyJson.getString("integral");
  257. if (StrKit.notBlank(integralStr)) {
  258. try {
  259. int integralInt = Integer.parseInt(integralStr);
  260. user.set("integral", integralInt);
  261. } catch (Exception e) {
  262. renderJson(MyRet.fail("integral 格式不正确: " + e.getMessage()));
  263. return;
  264. }
  265. }
  266. // 更新时间
  267. user.set("update_time", System.currentTimeMillis());
  268. // 执行更新业务
  269. if (user.update()) {
  270. renderJson(MyRet.ok("用户更新成功").setData(service.findUserByMobileNumber(user.getMobileNumber())));
  271. } else {
  272. renderJson(MyRet.fail("用户更新失败,请将此日志复制给开发者" + user));
  273. }
  274. }
  275. @Before(LoginInterceptor.class)
  276. @RequiredRoleInterface({UserController.ROLE_SUPER_ADMIN})
  277. public void count() {
  278. renderJson(MyRet.ok("查询成功").setData(service.count(null)));
  279. }
  280. @Before(LoginInterceptor.class)
  281. @RequiredRoleInterface({UserController.ROLE_SUPER_ADMIN})
  282. @EmptyInterface({"page_size", "page_number"})
  283. public void users() {
  284. JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
  285. // 页面大小
  286. String pageSizeStr = requestBodyJson.getString("page_size");
  287. int pageSizeInt;
  288. try {
  289. pageSizeInt = Integer.parseInt(pageSizeStr);
  290. if (pageSizeInt <= 0) {
  291. renderJson(MyRet.fail("页面大小(page_size)期待是正整数,你传的是: " + pageSizeStr));
  292. return;
  293. }
  294. } catch (Exception e) {
  295. renderJson(MyRet.fail("页面大小(page_size)格式不正确: " + e.getMessage()));
  296. return;
  297. }
  298. // 页码
  299. String pageNumberStr = requestBodyJson.getString("page_number");
  300. int pageNumberInt;
  301. try {
  302. pageNumberInt = Integer.parseInt(pageNumberStr);
  303. if (pageNumberInt <= 0) {
  304. renderJson(MyRet.fail("页码(page_number)期待是正整数,你传的是: " + pageNumberStr));
  305. return;
  306. }
  307. } catch (Exception e) {
  308. renderJson(MyRet.fail("页码(page_number)格式不正确: " + e.getMessage()));
  309. return;
  310. }
  311. // 查询条件
  312. String keywords = requestBodyJson.getString("keywords");
  313. // 最终结果封装
  314. List<User> users = service.users(pageNumberInt, pageSizeInt, keywords);
  315. Integer totalUsers = service.count(keywords);
  316. Map<String, Object> response = new HashMap<>();
  317. response.put("list", users);
  318. response.put("total_row", users.toArray().length);
  319. response.put("total_page", 1 + (users.toArray().length / pageSizeInt));
  320. response.put("page_size", pageSizeInt);
  321. response.put("page_number", pageNumberInt);
  322. response.put("total_user_count", totalUsers);
  323. renderJson(MyRet.ok("查询成功").setData(response));
  324. }
  325. /*
  326. *
  327. ### 验证码修改密码
  328. POST {{ baseUrl }}/user/updatePwd
  329. Content-Type: application/json
  330. {
  331. "mobile_number": "17781855864",
  332. "new_pwd_md5": "e10adc3949ba59abbe56e057f20f883e",
  333. "verify_code": "9119"
  334. }
  335. *
  336. * */
  337. // @EmptyInterface(keyArray = {"mobile_number", "new_pwd_md5", "verify_code"})
  338. // public void updatePwd() {
  339. // // --- 核心修改部分:从 JSON 请求体中获取参数 ---
  340. // JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
  341. //
  342. // // 因为 EmptyInterceptor 已经保证了这些字段不为空,这里可以直接获取
  343. // String mobileNumber = requestBodyJson.getString("mobile_number");
  344. // String pwdMd5 = requestBodyJson.getString("new_pwd_md5");
  345. // String verifyCode = requestBodyJson.getString("verify_code");
  346. // }
  347. private MyRet checkVerifyCode(String userVerifyCode) {
  348. // 3. 验证码校验
  349. String storedVerifyCode = getSessionAttr("verify_code");
  350. Long sendTime = getSessionAttr("last_send_verify_code_time");
  351. if (StrKit.isBlank(storedVerifyCode) || sendTime == null) {
  352. // Session中没有验证码或发送时间,可能从未发送过,或Session已失效/过期
  353. return MyRet.fail("请先获取验证码或验证码已失效");
  354. }
  355. // 校验有效期
  356. long currentTime = System.currentTimeMillis();
  357. if (currentTime - sendTime > VERIFY_CODE_EXPIRATION_TIME) {
  358. // 验证码已过期
  359. // 可以在这里清除Session中的验证码,防止不必要的存储
  360. removeSessionAttr("verify_code");
  361. removeSessionAttr("last_send_verify_code_time");
  362. return MyRet.fail("验证码已过期,请重新获取");
  363. }
  364. // 校验用户输入的验证码是否与Session中存储的一致
  365. if (!userVerifyCode.equals(storedVerifyCode)) {
  366. renderJson(MyRet.fail("验证码不正确"));
  367. return MyRet.fail("验证码已过期,请重新获取");
  368. }
  369. removeSessionAttr("verify_code");
  370. return MyRet.ok("验证码校验通过");
  371. }
  372. }