From 715920c2565b1310765bf40d19f9bae6924c7ea5 Mon Sep 17 00:00:00 2001 From: wx-jincw Date: Sat, 23 May 2026 10:48:59 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E5=90=88=E5=B9=B6=E8=AE=BF?= =?UTF-8?q?=E5=AE=A2=E7=99=BB=E8=AE=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/property.js | 29 + app/pages.json | 28 + .../supply_chain/components/CustomHeader.vue | 97 ++++ .../supply_chain/visitor_credential/index.vue | 274 ++++++++++ .../supply_chain/visitor_records/index.vue | 299 ++++++++++ .../components/VisitorInput.vue | 185 +++++++ .../supply_chain/visitor_register/index.vue | 514 ++++++++++++++++++ app/pages/supply_chain/visitor_user/index.vue | 212 ++++++++ 8 files changed, 1638 insertions(+) create mode 100644 app/pages/supply_chain/components/CustomHeader.vue create mode 100644 app/pages/supply_chain/visitor_credential/index.vue create mode 100644 app/pages/supply_chain/visitor_records/index.vue create mode 100644 app/pages/supply_chain/visitor_register/components/VisitorInput.vue create mode 100644 app/pages/supply_chain/visitor_register/index.vue create mode 100644 app/pages/supply_chain/visitor_user/index.vue diff --git a/app/api/property.js b/app/api/property.js index 128f13b..d2f0ebf 100644 --- a/app/api/property.js +++ b/app/api/property.js @@ -262,3 +262,32 @@ export function bindingWx(data) { export function unbindWx(data) { return request.post('unbindWx', data, { useAdminUrl: true }); } + +// ===== 访客登记模块 ===== + +// 访客登记 - 新增 +export function api_addVisit(data) { + return request.post( + 'autogencode/dcvisitbook/save', + data, + { useAdminUrl: true } + ); +} + +// 访客登记 - 记录列表 +export function api_visitRecordList(params) { + return request.get( + 'autogencode/dcvisitbook/list', + params, + { useAdminUrl: true } + ); +} + +// 访客登记 - 详情/凭证信息 +export function api_visitInfo(id) { + return request.get( + 'autogencode/dcvisitbook/info/' + id, + {}, + { useAdminUrl: true } + ); +} diff --git a/app/pages.json b/app/pages.json index 6120da4..0c43ff9 100644 --- a/app/pages.json +++ b/app/pages.json @@ -360,6 +360,34 @@ "navigationStyle": "custom" // #endif } + }, + { + "path": "visitor_register/index", + "style": { + "navigationBarTitleText": "访客登记", + "navigationStyle": "custom" + } + }, + { + "path": "visitor_records/index", + "style": { + "navigationBarTitleText": "访问记录", + "navigationStyle": "custom" + } + }, + { + "path": "visitor_user/index", + "style": { + "navigationBarTitleText": "访客个人中心", + "navigationStyle": "custom" + } + }, + { + "path": "visitor_credential/index", + "style": { + "navigationBarTitleText": "访问凭证", + "navigationStyle": "custom" + } } ] }, diff --git a/app/pages/supply_chain/components/CustomHeader.vue b/app/pages/supply_chain/components/CustomHeader.vue new file mode 100644 index 0000000..5f6351d --- /dev/null +++ b/app/pages/supply_chain/components/CustomHeader.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/app/pages/supply_chain/visitor_credential/index.vue b/app/pages/supply_chain/visitor_credential/index.vue new file mode 100644 index 0000000..f93c235 --- /dev/null +++ b/app/pages/supply_chain/visitor_credential/index.vue @@ -0,0 +1,274 @@ + + + + + diff --git a/app/pages/supply_chain/visitor_records/index.vue b/app/pages/supply_chain/visitor_records/index.vue new file mode 100644 index 0000000..d755c48 --- /dev/null +++ b/app/pages/supply_chain/visitor_records/index.vue @@ -0,0 +1,299 @@ + + + + + diff --git a/app/pages/supply_chain/visitor_register/components/VisitorInput.vue b/app/pages/supply_chain/visitor_register/components/VisitorInput.vue new file mode 100644 index 0000000..d0015ff --- /dev/null +++ b/app/pages/supply_chain/visitor_register/components/VisitorInput.vue @@ -0,0 +1,185 @@ + + + + + diff --git a/app/pages/supply_chain/visitor_register/index.vue b/app/pages/supply_chain/visitor_register/index.vue new file mode 100644 index 0000000..1c276a1 --- /dev/null +++ b/app/pages/supply_chain/visitor_register/index.vue @@ -0,0 +1,514 @@ + + + + + diff --git a/app/pages/supply_chain/visitor_user/index.vue b/app/pages/supply_chain/visitor_user/index.vue new file mode 100644 index 0000000..b39b677 --- /dev/null +++ b/app/pages/supply_chain/visitor_user/index.vue @@ -0,0 +1,212 @@ + + + + + From ddf7b9fbc7cc9f992db14eac2bc168152f9c6299 Mon Sep 17 00:00:00 2001 From: wx-jincw Date: Sat, 23 May 2026 14:53:37 +0800 Subject: [PATCH 2/5] =?UTF-8?q?fix:=20=E5=BE=AE=E4=BF=A1=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/public.js | 9 ++ app/config/app.js | 9 +- app/manifest.json | 4 +- .../com/zbkj/common/constants/Constants.java | 2 + .../request/WxBindingAccountRequest.java | 40 +++++++++ .../front/controller/WeChatController.java | 13 +++ .../zbkj/front/service/UserCenterService.java | 13 +++ .../service/impl/UserCenterServiceImpl.java | 83 +++++++++++++++++++ 8 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 crmeb/crmeb-common/src/main/java/com/zbkj/common/request/WxBindingAccountRequest.java diff --git a/app/api/public.js b/app/api/public.js index 91144d0..ab3cc6c 100644 --- a/app/api/public.js +++ b/app/api/public.js @@ -90,6 +90,15 @@ export function getUserPhone(data){ return request.post('wechat/register/binding/phone',data,{noAuth : true}); } +/** + * 小程序微信绑定已有账号(账号+密码) + * 关闭强制获取手机号时使用,将微信 openId 关联到已有账号 + * @param {Object} data { account, password, key } + */ +export function bindRoutineAccount(data) { + return request.post('wechat/register/binding/account', data, { noAuth: true }); +} + /** * APP微信登录 * @param {Object} data diff --git a/app/config/app.js b/app/config/app.js index eadf9eb..6c1f665 100644 --- a/app/config/app.js +++ b/app/config/app.js @@ -38,5 +38,12 @@ module.exports = { // 缓存时间 0 永久 EXPIRE:0, //分页最多显示条数 - LIMIT: 10 + LIMIT: 10, + /** + * 小程序微信登录:新用户是否强制获取手机号 + * true=开启(弹出微信手机号授权,走 register/binding/phone) + * false=关闭(跳转账号密码页,走 register/binding/account 绑定已有账号) + * 可被后端 wechat/getLogo 返回的 routineLoginRequirePhone 覆盖 + */ + MP_WECHAT_REQUIRE_PHONE: true }; diff --git a/app/manifest.json b/app/manifest.json index 6e796ed..b1c5a4e 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -2,8 +2,8 @@ "name" : "八方物业", "appid" : "__UNI__B905528", "description" : "八方物业", - "versionName" : "1.0.2", - "versionCode" : 1002, + "versionName" : "1.0.3", + "versionCode" : 1003, "transformPx" : false, /* 5+App特有相关 */ "app-plus" : { diff --git a/crmeb/crmeb-common/src/main/java/com/zbkj/common/constants/Constants.java b/crmeb/crmeb-common/src/main/java/com/zbkj/common/constants/Constants.java index 1e15f3a..9308c8c 100644 --- a/crmeb/crmeb-common/src/main/java/com/zbkj/common/constants/Constants.java +++ b/crmeb/crmeb-common/src/main/java/com/zbkj/common/constants/Constants.java @@ -162,6 +162,8 @@ public class Constants { public static final String CONFIG_KEY_FRONT_API_URL = "front_api_url"; //移动商城接口地址 public static final String CONFIG_KEY_SITE_LOGO = "mobile_top_logo"; //logo地址 public static final String CONFIG_KEY_MOBILE_LOGIN_LOGO = "mobile_login_logo"; // 移动端登录 logo + /** 小程序微信登录是否强制获取手机号:1=开启(默认),0=关闭(走账号密码绑定微信) */ + public static final String CONFIG_KEY_ROUTINE_LOGIN_REQUIRE_PHONE = "routine_login_require_phone"; public static final String CONFIG_KEY_SITE_NAME = "site_name"; //网站名称 public static final String CONFIG_SITE_TENG_XUN_MAP_KEY = "tengxun_map_key"; //腾讯地图key public static final String CONFIG_BANK_LIST = "user_extract_bank"; //可提现银行 diff --git a/crmeb/crmeb-common/src/main/java/com/zbkj/common/request/WxBindingAccountRequest.java b/crmeb/crmeb-common/src/main/java/com/zbkj/common/request/WxBindingAccountRequest.java new file mode 100644 index 0000000..40058db --- /dev/null +++ b/crmeb/crmeb-common/src/main/java/com/zbkj/common/request/WxBindingAccountRequest.java @@ -0,0 +1,40 @@ +package com.zbkj.common.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.zbkj.common.constants.RegularConstants; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import java.io.Serializable; + +/** + * 小程序微信绑定已有账号请求对象 + * 用于关闭「强制获取手机号」时,通过账号密码将微信 openId 关联到已有用户 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@ApiModel(value = "WxBindingAccountRequest", description = "小程序微信绑定已有账号请求对象") +public class WxBindingAccountRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "账号(手机号)", required = true) + @NotBlank(message = "账号不能为空") + @Pattern(regexp = RegularConstants.PHONE_TWO, message = "请输入正确的手机号") + @JsonProperty("account") + private String account; + + @ApiModelProperty(value = "密码", required = true) + @NotBlank(message = "密码不能为空") + private String password; + + @ApiModelProperty(value = "微信授权 register 阶段返回的 key", required = true) + @NotBlank(message = "key不能为空") + private String key; +} diff --git a/crmeb/crmeb-front/src/main/java/com/zbkj/front/controller/WeChatController.java b/crmeb/crmeb-front/src/main/java/com/zbkj/front/controller/WeChatController.java index bdf5371..3e0863e 100644 --- a/crmeb/crmeb-front/src/main/java/com/zbkj/front/controller/WeChatController.java +++ b/crmeb/crmeb-front/src/main/java/com/zbkj/front/controller/WeChatController.java @@ -3,6 +3,7 @@ package com.zbkj.front.controller; import com.zbkj.common.model.wechat.TemplateMessage; import com.zbkj.common.request.RegisterAppWxRequest; import com.zbkj.common.request.RegisterThirdUserRequest; +import com.zbkj.common.request.WxBindingAccountRequest; import com.zbkj.common.request.WxBindingPhoneRequest; import com.zbkj.common.response.CommonResult; import com.zbkj.common.response.LoginResponse; @@ -87,6 +88,16 @@ public class WeChatController { return CommonResult.success(userCenterService.registerBindingPhone(request)); } + /** + * 小程序微信绑定已有账号(账号+密码) + * 关闭 routine_login_require_phone 后,新微信用户通过此接口关联已有账号 + */ + @ApiOperation(value = "小程序微信绑定已有账号") + @RequestMapping(value = "/register/binding/account", method = RequestMethod.POST) + public CommonResult registerBindingAccount(@RequestBody @Validated WxBindingAccountRequest request){ + return CommonResult.success(userCenterService.registerBindingAccount(request)); + } + /** * 获取微信公众号js配置 */ @@ -105,6 +116,8 @@ public class WeChatController { public CommonResult> getLogo(){ Map map = new HashMap<>(); map.put("logoUrl", userCenterService.getLogo()); + // 1=微信登录新用户强制获取手机号,0=跳转账号密码绑定微信 + map.put("routineLoginRequirePhone", userCenterService.getRoutineLoginRequirePhone()); return CommonResult.success(map); } diff --git a/crmeb/crmeb-front/src/main/java/com/zbkj/front/service/UserCenterService.java b/crmeb/crmeb-front/src/main/java/com/zbkj/front/service/UserCenterService.java index 559bd37..b89b2c7 100644 --- a/crmeb/crmeb-front/src/main/java/com/zbkj/front/service/UserCenterService.java +++ b/crmeb/crmeb-front/src/main/java/com/zbkj/front/service/UserCenterService.java @@ -173,6 +173,19 @@ public interface UserCenterService extends IService { */ LoginResponse registerBindingPhone(WxBindingPhoneRequest request); + /** + * 小程序微信绑定已有账号(账号+密码) + * @param request 请求参数 + * @return 登录信息 + */ + LoginResponse registerBindingAccount(WxBindingAccountRequest request); + + /** + * 小程序微信登录是否强制获取手机号 + * @return 1=开启,0=关闭 + */ + String getRoutineLoginRequirePhone(); + /** * 用户积分记录列表 * @param pageParamRequest 分页参数 diff --git a/crmeb/crmeb-front/src/main/java/com/zbkj/front/service/impl/UserCenterServiceImpl.java b/crmeb/crmeb-front/src/main/java/com/zbkj/front/service/impl/UserCenterServiceImpl.java index 0cb8fca..9b2449e 100644 --- a/crmeb/crmeb-front/src/main/java/com/zbkj/front/service/impl/UserCenterServiceImpl.java +++ b/crmeb/crmeb-front/src/main/java/com/zbkj/front/service/impl/UserCenterServiceImpl.java @@ -489,6 +489,16 @@ public class UserCenterServiceImpl extends ServiceImpl implements return systemConfigService.getValueByKey(Constants.CONFIG_KEY_MOBILE_LOGIN_LOGO); } + /** + * 小程序微信登录是否强制获取手机号 + * 系统配置 routine_login_require_phone:1=开启(默认),0=关闭(走账号密码绑定) + */ + @Override + public String getRoutineLoginRequirePhone() { + String value = systemConfigService.getValueByKey(Constants.CONFIG_KEY_ROUTINE_LOGIN_REQUIRE_PHONE); + return StrUtil.isBlank(value) ? "1" : value; + } + /** * 小程序登录 * @param code String 前端临时授权code @@ -854,6 +864,79 @@ public class UserCenterServiceImpl extends ServiceImpl implements return loginResponse; } + /** + * 小程序微信绑定已有账号(账号+密码) + * 关闭「强制获取手机号」时,新微信用户通过已有账号完成关联,下次可直接微信登录 + */ + @Override + public LoginResponse registerBindingAccount(WxBindingAccountRequest request) { + Object cache = redisUtil.get(request.getKey()); + if (ObjectUtil.isNull(cache)) { + throw new CrmebException("微信授权已过期,请重新点击微信登录"); + } + RegisterThirdUserRequest registerThirdUserRequest = JSONObject.parseObject(cache.toString(), RegisterThirdUserRequest.class); + if (!Constants.USER_LOGIN_TYPE_PROGRAM.equals(registerThirdUserRequest.getType())) { + throw new CrmebException("仅支持小程序微信绑定"); + } + + User user = userService.getByPhone(request.getAccount()); + if (ObjectUtil.isNull(user)) { + throw new CrmebException("此账号未注册"); + } + if (!user.getStatus()) { + throw new CrmebException("此账号被禁用"); + } + + String encryptedPassword = CrmebUtil.encryptPassword(request.getPassword(), request.getAccount()); + if (!user.getPwd().equals(encryptedPassword)) { + throw new CrmebException("密码错误"); + } + + UserToken boundByUser = userTokenService.getTokenByUserId(user.getUid(), Constants.THIRD_LOGIN_TOKEN_TYPE_PROGRAM); + if (ObjectUtil.isNotNull(boundByUser)) { + throw new CrmebException("该账号已绑定微信小程序"); + } + + UserToken boundByOpenId = userTokenService.getByOpenidAndType( + registerThirdUserRequest.getOpenId(), Constants.THIRD_LOGIN_TOKEN_TYPE_PROGRAM); + if (ObjectUtil.isNotNull(boundByOpenId)) { + throw new CrmebException("该微信已绑定其他账号"); + } + + User finalUser = user; + Boolean execute = transactionTemplate.execute(e -> { + userTokenService.bind( + registerThirdUserRequest.getOpenId(), + Constants.THIRD_LOGIN_TOKEN_TYPE_PROGRAM, + finalUser.getUid()); + return Boolean.TRUE; + }); + if (!execute) { + throw new CrmebException("绑定微信失败,请稍后重试"); + } + + if (ObjectUtil.isNotNull(registerThirdUserRequest.getSpreadPid()) && registerThirdUserRequest.getSpreadPid() > 0) { + loginService.bindSpread(user, registerThirdUserRequest.getSpreadPid()); + } + + user.setLastLoginTime(DateUtil.nowDateTime()); + userService.updateById(user); + redisUtil.delete(request.getKey()); + + LoginResponse loginResponse = new LoginResponse(); + try { + loginResponse.setToken(tokenComponent.createToken(user)); + } catch (Exception e) { + logger.error(StrUtil.format("绑定微信账号后生成token失败,uid={}", user.getUid())); + e.printStackTrace(); + } + loginResponse.setType("login"); + loginResponse.setUid(user.getUid()); + loginResponse.setNikeName(user.getNickname()); + loginResponse.setPhone(user.getPhone()); + return loginResponse; + } + /** * 用户积分记录列表 * @param pageParamRequest 分页参数 From 7fa05c4d1bfdaa5f949bfb9312ac4afd9a50885a Mon Sep 17 00:00:00 2001 From: wx-jincw Date: Sat, 23 May 2026 16:40:52 +0800 Subject: [PATCH 3/5] =?UTF-8?q?fix:=20=E9=BB=98=E8=AE=A4=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=89=8B=E6=9C=BA=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/zbkj/common/constants/Constants.java | 2 +- .../main/java/com/zbkj/front/controller/WeChatController.java | 2 +- .../com/zbkj/front/service/impl/UserCenterServiceImpl.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crmeb/crmeb-common/src/main/java/com/zbkj/common/constants/Constants.java b/crmeb/crmeb-common/src/main/java/com/zbkj/common/constants/Constants.java index 9308c8c..9ad1a21 100644 --- a/crmeb/crmeb-common/src/main/java/com/zbkj/common/constants/Constants.java +++ b/crmeb/crmeb-common/src/main/java/com/zbkj/common/constants/Constants.java @@ -162,7 +162,7 @@ public class Constants { public static final String CONFIG_KEY_FRONT_API_URL = "front_api_url"; //移动商城接口地址 public static final String CONFIG_KEY_SITE_LOGO = "mobile_top_logo"; //logo地址 public static final String CONFIG_KEY_MOBILE_LOGIN_LOGO = "mobile_login_logo"; // 移动端登录 logo - /** 小程序微信登录是否强制获取手机号:1=开启(默认),0=关闭(走账号密码绑定微信) */ + /** 小程序微信登录是否强制获取手机号:1=开启,0=关闭(默认,走账号密码绑定微信) */ public static final String CONFIG_KEY_ROUTINE_LOGIN_REQUIRE_PHONE = "routine_login_require_phone"; public static final String CONFIG_KEY_SITE_NAME = "site_name"; //网站名称 public static final String CONFIG_SITE_TENG_XUN_MAP_KEY = "tengxun_map_key"; //腾讯地图key diff --git a/crmeb/crmeb-front/src/main/java/com/zbkj/front/controller/WeChatController.java b/crmeb/crmeb-front/src/main/java/com/zbkj/front/controller/WeChatController.java index 3e0863e..d6efd6f 100644 --- a/crmeb/crmeb-front/src/main/java/com/zbkj/front/controller/WeChatController.java +++ b/crmeb/crmeb-front/src/main/java/com/zbkj/front/controller/WeChatController.java @@ -116,7 +116,7 @@ public class WeChatController { public CommonResult> getLogo(){ Map map = new HashMap<>(); map.put("logoUrl", userCenterService.getLogo()); - // 1=微信登录新用户强制获取手机号,0=跳转账号密码绑定微信 + // 1=微信登录新用户强制获取手机号,0=跳转账号密码绑定微信(默认) map.put("routineLoginRequirePhone", userCenterService.getRoutineLoginRequirePhone()); return CommonResult.success(map); } diff --git a/crmeb/crmeb-front/src/main/java/com/zbkj/front/service/impl/UserCenterServiceImpl.java b/crmeb/crmeb-front/src/main/java/com/zbkj/front/service/impl/UserCenterServiceImpl.java index 9b2449e..b5fa412 100644 --- a/crmeb/crmeb-front/src/main/java/com/zbkj/front/service/impl/UserCenterServiceImpl.java +++ b/crmeb/crmeb-front/src/main/java/com/zbkj/front/service/impl/UserCenterServiceImpl.java @@ -491,12 +491,12 @@ public class UserCenterServiceImpl extends ServiceImpl implements /** * 小程序微信登录是否强制获取手机号 - * 系统配置 routine_login_require_phone:1=开启(默认),0=关闭(走账号密码绑定) + * 系统配置 routine_login_require_phone:1=开启,0=关闭(默认,走账号密码绑定) */ @Override public String getRoutineLoginRequirePhone() { String value = systemConfigService.getValueByKey(Constants.CONFIG_KEY_ROUTINE_LOGIN_REQUIRE_PHONE); - return StrUtil.isBlank(value) ? "1" : value; + return StrUtil.isBlank(value) ? "0" : value; } /** From 71aa31628dda29072d3739279d2efc36a9b4f702 Mon Sep 17 00:00:00 2001 From: wx-jincw Date: Sat, 23 May 2026 17:38:36 +0800 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20=E5=BE=AE=E4=BF=A1=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=E8=B4=A6=E5=8F=B7=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/config/app.js | 2 +- app/libs/login.js | 64 ++++++------- app/pages/users/login/index.vue | 68 ++++++++++++- app/pages/users/wechat_login/index.vue | 128 ++++++++++++++++++++----- 4 files changed, 195 insertions(+), 67 deletions(-) diff --git a/app/config/app.js b/app/config/app.js index 6c1f665..9df0501 100644 --- a/app/config/app.js +++ b/app/config/app.js @@ -45,5 +45,5 @@ module.exports = { * false=关闭(跳转账号密码页,走 register/binding/account 绑定已有账号) * 可被后端 wechat/getLogo 返回的 routineLoginRequirePhone 覆盖 */ - MP_WECHAT_REQUIRE_PHONE: true + MP_WECHAT_REQUIRE_PHONE: false }; diff --git a/app/libs/login.js b/app/libs/login.js index 66c50ec..2a56654 100644 --- a/app/libs/login.js +++ b/app/libs/login.js @@ -38,46 +38,36 @@ export function _toLogin(push, pathLogin) { pathLogin = '/page/users/login/index' Cache.set('login_back_url',path); } - - // // #ifdef H5 - // if (isWeixin()) { - // let urlData = location.pathname + location.search - // if (urlData.indexOf('?') !== -1) { - // urlData += '&go_longin=1'; - // } else { - // urlData += '?go_longin=1'; - // } - // if (!Cache.has('snsapiKey')) { - // auth.oAuth('snsapi_base', urlData); - // } else { - // if (['/pages/user/index'].indexOf(login_back_url) == -1) { - // uni.navigateTo({ - // url: '/pages/users/wechat_login/index' - // }) - // } - // } - // } else { - // if (['/pages/user/index'].indexOf(login_back_url) == -1) { - // uni.navigateTo({ - // url: '/pages/users/login/index' - // }) - // } - // } - // // #endif - - // if (['pages/user/index','/pages/user/index'].indexOf(login_back_url) == -1) { - // // #ifdef MP - // uni.navigateTo({ - // url: '/pages/users/wechat_login/index' - // }) - // // #endif - // } - + if (['pages/user/index','/pages/user/index'].indexOf(login_back_url) == -1) { + // #ifdef H5 + if (isWeixin()) { + let urlData = location.pathname + location.search + if (urlData.indexOf('?') !== -1) { + urlData += '&go_longin=1'; + } else { + urlData += '?go_longin=1'; + } + if (!Cache.has('snsapiKey')) { + auth.oAuth('snsapi_base', urlData); + } else { + uni.navigateTo({ + url: '/pages/users/wechat_login/index' + }) + } + } else { + uni.navigateTo({ + url: '/pages/users/login/index' + }) + } + // #endif + + // #ifdef MP uni.navigateTo({ - url: '/pages/users/login/index' + url: '/pages/users/wechat_login/index' }) - } + // #endif + } } diff --git a/app/pages/users/login/index.vue b/app/pages/users/login/index.vue index 4e5458b..5889207 100644 --- a/app/pages/users/login/index.vue +++ b/app/pages/users/login/index.vue @@ -47,9 +47,12 @@
登录
-
登录
+
{{ bindWechatMode ? '绑定微信登录' : '登录' }}
-
微信登录
+
微信登录
+ + +
请使用已有账号密码完成微信绑定,绑定后可直接微信登录
@@ -80,7 +83,7 @@ validatorDefaultCatch } from "@/utils/dialog"; import { - getLogo, appAuth, appleLogin + getLogo, appAuth, appleLogin, bindRoutineAccount } from "@/api/public"; import { VUE_APP_API_URL @@ -116,7 +119,10 @@ appleLoginStatus: false, // 苹果登录强制绑定手机号码状态 appleUserInfo: null, appleShow: false, // 苹果登录版本必须要求ios13以上的 - pendingGzhCode: '' // 公众号授权未绑定时,随账号密码一并提交 + pendingGzhCode: '', // 公众号授权未绑定时,随账号密码一并提交 + // 小程序:微信绑定已有账号模式(来自 wechat_login 页 register 流程) + bindWechatMode: false, + wechatBindAuthKey: '' }; }, watch:{ @@ -132,7 +138,13 @@ this.getCode(); this.getLogoImage(); }, - onLoad() { + onLoad(options) { + // #ifdef MP-WEIXIN + if (options.bindWechat === '1' && options.authKey) { + this.bindWechatMode = true; + this.wechatBindAuthKey = decodeURIComponent(options.authKey); + } + // #endif let self = this uni.getSystemInfo({ success: function(res) { @@ -445,6 +457,43 @@ if (!that.password) return that.$util.Tips({ title: '请填写密码' }); + + // 小程序微信绑定模式:校验账号密码并将微信 openId 关联到该账号 + // #ifdef MP-WEIXIN + if (that.bindWechatMode) { + if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) { + return that.$util.Tips({ + title: '请输入正确的手机号码' + }); + } + if (!that.wechatBindAuthKey) { + return that.$util.Tips({ + title: '微信授权已失效,请返回重新授权' + }); + } + uni.showLoading({ title: '绑定中' }); + bindRoutineAccount({ + account: that.account, + password: that.password, + key: that.wechatBindAuthKey + }).then(res => { + uni.hideLoading(); + that.wechatBindAuthKey = ''; + that.bindWechatMode = false; + that.$store.commit('LOGIN', { + token: res.data.token + }); + that.getUserInfo(res.data); + }).catch(e => { + uni.hideLoading(); + that.$util.Tips({ + title: e + }); + }); + return; + } + // #endif + const loginPayload = { account: that.account, password: that.password, @@ -686,6 +735,15 @@ margin-top: 32rpx; background-color: #07c160; } + + .bind-wechat-tip { + margin-top: 24rpx; + padding: 0 20rpx; + text-align: center; + font-size: 24rpx; + color: #999; + line-height: 1.6; + } .tips { margin: 30rpx; diff --git a/app/pages/users/wechat_login/index.vue b/app/pages/users/wechat_login/index.vue index ad56bab..0e35e5b 100644 --- a/app/pages/users/wechat_login/index.vue +++ b/app/pages/users/wechat_login/index.vue @@ -23,7 +23,11 @@ - + + + + + @@ -72,7 +76,11 @@ authKey: '', options: '', userInfo: {}, - codeNum: 0 + codeNum: 0, + // 小程序:是否强制获取微信手机号(true=弹手机号授权,false=跳转账号密码绑定) + requirePhone: false, + // 微信授权后待绑定的 key(关闭手机号时缓存,供「绑定已有账号」使用) + pendingBindAuthKey: '' } }, components: { @@ -80,9 +88,11 @@ routinePhone }, onLoad(options) { - // getLogo().then(res => { - // this.logoUrl = res.data.logoUrl - // }) + // #ifdef MP + // 先用本地配置同步初始化,避免 getLogo 未返回前 requirePhone 被误判 + this.requirePhone = this.parseRequirePhoneFlag(this.$config.MP_WECHAT_REQUIRE_PHONE); + this.loadMpLoginConfig(); + // #endif let that = this // #ifdef H5 document.body.addEventListener("focusout", () => { @@ -131,6 +141,66 @@ }, methods: { + // #ifdef MP + /** + * 是否强制获取微信手机号(仅 "1" / true 为开启,其余均为关闭) + */ + parseRequirePhoneFlag(value) { + return value === true || value === 1 || String(value) === '1'; + }, + /** + * 拉取小程序微信登录配置(是否强制获取手机号) + * 后端 system_config.routine_login_require_phone:1=开启,0=关闭(默认) + * 未配置时使用 app/config/app.js 中的 MP_WECHAT_REQUIRE_PHONE + */ + loadMpLoginConfig() { + const localDefault = this.parseRequirePhoneFlag(this.$config.MP_WECHAT_REQUIRE_PHONE); + return getLogo().then(res => { + const cfg = (res && res.data) ? res.data : {}; + if (cfg.logoUrl) { + this.logoUrl = cfg.logoUrl; + } + // 仅当后端明确返回 routineLoginRequirePhone 时才覆盖本地默认 + if (cfg.routineLoginRequirePhone !== undefined && cfg.routineLoginRequirePhone !== null && cfg.routineLoginRequirePhone !== '') { + this.requirePhone = this.parseRequirePhoneFlag(cfg.routineLoginRequirePhone); + } else { + this.requirePhone = localDefault; + } + return this.requirePhone; + }).catch(() => { + this.requirePhone = localDefault; + return this.requirePhone; + }); + }, + /** + * 关闭强制手机号时:跳转账号密码页进行微信绑定 + * 若尚未微信授权,提示先点「微信登录」 + */ + goBindAccountLogin() { + if (!this.pendingBindAuthKey) { + return this.$util.Tips({ + title: '请先点击上方「微信登录」完成授权' + }); + } + uni.navigateTo({ + url: '/pages/users/login/index?bindWechat=1&authKey=' + encodeURIComponent(this.pendingBindAuthKey) + }); + }, + /** + * 新微信用户且关闭强制手机号:跳转绑定页 + */ + goWechatBindLogin(authKey) { + this.pendingBindAuthKey = authKey; + uni.navigateTo({ + url: '/pages/users/login/index?bindWechat=1&authKey=' + encodeURIComponent(authKey) + }); + }, + // #endif + goAccountLogin() { + uni.navigateTo({ + url: '/pages/users/login/index' + }); + }, back() { uni.navigateBack(); }, @@ -224,19 +294,22 @@ uni.showLoading({ title: '正在登录中' }); - Routine.getUserProfile() - .then(res => { - Routine.getCode() - .then(code => { - self.getWxUser(code, res); - }) - .catch(res => { - uni.hideLoading(); - }); - }) - .catch(res => { - uni.hideLoading(); - }); + // 先确保开关配置已加载,再发起微信登录,避免 requirePhone 竞态导致误弹手机号 + self.loadMpLoginConfig().finally(() => { + Routine.getUserProfile() + .then(res => { + Routine.getCode() + .then(code => { + self.getWxUser(code, res); + }) + .catch(() => { + uni.hideLoading(); + }); + }) + .catch(() => { + uni.hideLoading(); + }); + }); }, getWxUser(code, res) { @@ -254,17 +327,24 @@ userInfo.type = 'routine' Routine.authUserInfo(userInfo.code, userInfo) .then(res => { - self.authKey = res.data.key; - if (res.data.type === 'register') { + const payload = (res && res.data) ? res.data : (res || {}); + self.authKey = payload.key; + if (payload.type === 'register') { uni.hideLoading(); - self.isPhoneBox = true + self.isPhoneBox = false; + // 开关开启:弹出微信手机号授权;关闭:跳转账号密码绑定页 + if (self.requirePhone) { + self.isPhoneBox = true; + } else { + self.goWechatBindLogin(payload.key); + } } - if (res.data.type === 'login') { + if (payload.type === 'login') { uni.hideLoading(); self.$store.commit('LOGIN', { - token: res.data.token + token: payload.token }); - self.$store.commit("SETUID", res.data.uid); + self.$store.commit("SETUID", payload.uid); self.getUserInfo(); self.$util.Tips({ title: res, From 175974b4384227b537b5cddc056b77662664c4b8 Mon Sep 17 00:00:00 2001 From: wx-jincw Date: Sun, 24 May 2026 12:54:27 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix=EF=BC=9A=E7=99=BB=E5=BD=95=E8=B7=B3?= =?UTF-8?q?=E8=BD=AC=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/libs/login.js | 41 ++++++++++++++++++++++++++ app/pages/users/login/index.vue | 7 +++-- app/pages/users/wechat_login/index.vue | 16 +++++----- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/app/libs/login.js b/app/libs/login.js index 2a56654..3442785 100644 --- a/app/libs/login.js +++ b/app/libs/login.js @@ -8,6 +8,47 @@ import auth from './wechat'; import { LOGIN_STATUS, USER_INFO, EXPIRES_TIME, STATE_R_KEY, BACK_URL} from './../config/cache'; +const LOGIN_PAGE_ROUTE = 'pages/users/login/index'; +const WECHAT_LOGIN_PAGE_ROUTE = 'pages/users/wechat_login/index'; + +function normalizeRoute(route) { + return (route || '').replace(/^\//, ''); +} + +function getPrevPageRoute() { + const pages = getCurrentPages(); + if (pages.length < 2) { + return ''; + } + return normalizeRoute(pages[pages.length - 2].route); +} + +/** + * 登录页 ⇄ 微信登录页切换:上一页已是目标页则返回,避免反复 navigateTo 堆栈 + */ +export function switchLoginPage(url) { + const targetRoute = normalizeRoute((url || '').split('?')[0].replace(/^\//, '')); + const prevRoute = getPrevPageRoute(); + if (prevRoute && prevRoute === targetRoute && url.indexOf('?') === -1) { + uni.navigateBack(); + return; + } + uni.navigateTo({ url }); +} + +/** + * 微信授权后进入账号绑定页(replace 当前页,避免栈里叠多层登录相关页面) + */ +export function openLoginBindPage(authKey) { + const url = `/pages/users/login/index?bindWechat=1&authKey=${encodeURIComponent(authKey)}`; + const prevRoute = getPrevPageRoute(); + if (prevRoute === LOGIN_PAGE_ROUTE) { + uni.redirectTo({ url }); + return; + } + uni.redirectTo({ url }); +} + function prePage(){ let pages = getCurrentPages(); let prePage = pages[pages.length - 1]; diff --git a/app/pages/users/login/index.vue b/app/pages/users/login/index.vue index 5889207..72d45e9 100644 --- a/app/pages/users/login/index.vue +++ b/app/pages/users/login/index.vue @@ -88,6 +88,9 @@ import { VUE_APP_API_URL } from "@/utils"; + import { + switchLoginPage + } from '@/libs/login'; // #ifdef MP-WEIXIN import { wxGZHAuth @@ -520,9 +523,7 @@ }); }, goWechatLogin() { - uni.navigateTo({ - url: "/pages/users/wechat_login/index" - }); + switchLoginPage('/pages/users/wechat_login/index'); }, getUserInfo(data){ this.$store.commit("SETUID", data.uid); diff --git a/app/pages/users/wechat_login/index.vue b/app/pages/users/wechat_login/index.vue index 0e35e5b..7701a34 100644 --- a/app/pages/users/wechat_login/index.vue +++ b/app/pages/users/wechat_login/index.vue @@ -63,6 +63,10 @@ } from '@/api/user.js' import Routine from '@/libs/routine'; import wechat from "@/libs/wechat"; + import { + switchLoginPage, + openLoginBindPage + } from '@/libs/login'; export default { data() { return { @@ -182,24 +186,18 @@ title: '请先点击上方「微信登录」完成授权' }); } - uni.navigateTo({ - url: '/pages/users/login/index?bindWechat=1&authKey=' + encodeURIComponent(this.pendingBindAuthKey) - }); + openLoginBindPage(this.pendingBindAuthKey); }, /** * 新微信用户且关闭强制手机号:跳转绑定页 */ goWechatBindLogin(authKey) { this.pendingBindAuthKey = authKey; - uni.navigateTo({ - url: '/pages/users/login/index?bindWechat=1&authKey=' + encodeURIComponent(authKey) - }); + openLoginBindPage(authKey); }, // #endif goAccountLogin() { - uni.navigateTo({ - url: '/pages/users/login/index' - }); + switchLoginPage('/pages/users/login/index'); }, back() { uni.navigateBack();