Parcourir la Source

会员管理代码

wwh il y a 2 semaines
Parent
commit
5a7fb72aab

+ 11 - 3
baqing-shop/src/main/java/com/ruoyi/web/modules/account/controller/MemberAppController.java

@@ -14,9 +14,10 @@ import com.ruoyi.common.annotation.Anonymous;
14 14
 import com.ruoyi.common.constant.Constants;
15 15
 import com.ruoyi.common.core.controller.BaseController;
16 16
 import com.ruoyi.common.core.domain.AjaxResult;
17
-import com.ruoyi.web.modules.account.domain.BizMember;
18 17
 import com.ruoyi.web.modules.account.domain.BizMemberAddress;
18
+import com.ruoyi.web.modules.account.dto.MemberChangePasswordDTO;
19 19
 import com.ruoyi.web.modules.account.dto.MemberLoginDTO;
20
+import com.ruoyi.web.modules.account.dto.MemberProfileUpdateDTO;
20 21
 import com.ruoyi.web.modules.account.dto.MemberRegisterDTO;
21 22
 import com.ruoyi.web.modules.account.dto.MemberSmsSendDTO;
22 23
 import com.ruoyi.web.modules.account.service.IMemberAddressService;
@@ -70,9 +71,16 @@ public class MemberAppController extends BaseController
70 71
     }
71 72
 
72 73
     @PutMapping("/profile")
73
-    public AjaxResult updateProfile(@RequestBody BizMember profile)
74
+    public AjaxResult updateProfile(@RequestBody MemberProfileUpdateDTO dto)
74 75
     {
75
-        memberAppService.updateProfile(requireMemberId(), profile);
76
+        memberAppService.updateProfile(requireMemberId(), dto);
77
+        return success();
78
+    }
79
+
80
+    @PutMapping("/password")
81
+    public AjaxResult changePassword(@RequestBody MemberChangePasswordDTO dto)
82
+    {
83
+        memberAppService.changePassword(requireMemberId(), dto);
76 84
         return success();
77 85
     }
78 86
 

+ 43 - 2
baqing-shop/src/main/java/com/ruoyi/web/modules/account/domain/BizMember.java

@@ -7,7 +7,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
7 7
 import com.ruoyi.common.core.domain.BaseEntity;
8 8
 
9 9
 /**
10
- * C 端会员 biz_member
10
+ * C 端会员 biz_member(账号字段来自 sys_user JOIN)
11 11
  */
12 12
 public class BizMember extends BaseEntity
13 13
 {
@@ -17,13 +17,24 @@ public class BizMember extends BaseEntity
17 17
 
18 18
     private String mobile;
19 19
 
20
-    /** 会员名称 */
20
+    /** 会员名称 → sys_user.user_name */
21 21
     private String memberCode;
22 22
 
23
+    /** sys_user.nick_name */
23 24
     private String nickName;
24 25
 
25 26
     private String password;
26 27
 
28
+    /** sys_user.email */
29
+    private String email;
30
+
31
+    /** sys_user.sex(0男 1女 2未知) */
32
+    private String sex;
33
+
34
+    /** sys_user.birthday */
35
+    @JsonFormat(pattern = "yyyy-MM-dd")
36
+    private Date birthday;
37
+
27 38
     /** 会员等级(biz_member_level.level_no,选填) */
28 39
     private Integer memberLevel;
29 40
 
@@ -97,6 +108,36 @@ public class BizMember extends BaseEntity
97 108
         this.password = password;
98 109
     }
99 110
 
111
+    public String getEmail()
112
+    {
113
+        return email;
114
+    }
115
+
116
+    public void setEmail(String email)
117
+    {
118
+        this.email = email;
119
+    }
120
+
121
+    public String getSex()
122
+    {
123
+        return sex;
124
+    }
125
+
126
+    public void setSex(String sex)
127
+    {
128
+        this.sex = sex;
129
+    }
130
+
131
+    public Date getBirthday()
132
+    {
133
+        return birthday;
134
+    }
135
+
136
+    public void setBirthday(Date birthday)
137
+    {
138
+        this.birthday = birthday;
139
+    }
140
+
100 141
     public Integer getMemberLevel()
101 142
     {
102 143
         return memberLevel;

+ 43 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/account/dto/MemberChangePasswordDTO.java

@@ -0,0 +1,43 @@
1
+package com.ruoyi.web.modules.account.dto;
2
+
3
+/**
4
+ * C 端修改密码
5
+ */
6
+public class MemberChangePasswordDTO
7
+{
8
+    private String oldPassword;
9
+
10
+    private String newPassword;
11
+
12
+    private String confirmPassword;
13
+
14
+    public String getOldPassword()
15
+    {
16
+        return oldPassword;
17
+    }
18
+
19
+    public void setOldPassword(String oldPassword)
20
+    {
21
+        this.oldPassword = oldPassword;
22
+    }
23
+
24
+    public String getNewPassword()
25
+    {
26
+        return newPassword;
27
+    }
28
+
29
+    public void setNewPassword(String newPassword)
30
+    {
31
+        this.newPassword = newPassword;
32
+    }
33
+
34
+    public String getConfirmPassword()
35
+    {
36
+        return confirmPassword;
37
+    }
38
+
39
+    public void setConfirmPassword(String confirmPassword)
40
+    {
41
+        this.confirmPassword = confirmPassword;
42
+    }
43
+}

+ 72 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/account/dto/MemberProfileUpdateDTO.java

@@ -0,0 +1,72 @@
1
+package com.ruoyi.web.modules.account.dto;
2
+
3
+import java.util.Date;
4
+import com.fasterxml.jackson.annotation.JsonFormat;
5
+
6
+/**
7
+ * C 端更新个人资料(写入 sys_user,member_id = user_id)
8
+ */
9
+public class MemberProfileUpdateDTO
10
+{
11
+    private String nickName;
12
+
13
+    private String avatar;
14
+
15
+    private String email;
16
+
17
+    /** 0男 1女 2未知 */
18
+    private String sex;
19
+
20
+    @JsonFormat(pattern = "yyyy-MM-dd")
21
+    private Date birthday;
22
+
23
+    public String getNickName()
24
+    {
25
+        return nickName;
26
+    }
27
+
28
+    public void setNickName(String nickName)
29
+    {
30
+        this.nickName = nickName;
31
+    }
32
+
33
+    public String getAvatar()
34
+    {
35
+        return avatar;
36
+    }
37
+
38
+    public void setAvatar(String avatar)
39
+    {
40
+        this.avatar = avatar;
41
+    }
42
+
43
+    public String getEmail()
44
+    {
45
+        return email;
46
+    }
47
+
48
+    public void setEmail(String email)
49
+    {
50
+        this.email = email;
51
+    }
52
+
53
+    public String getSex()
54
+    {
55
+        return sex;
56
+    }
57
+
58
+    public void setSex(String sex)
59
+    {
60
+        this.sex = sex;
61
+    }
62
+
63
+    public Date getBirthday()
64
+    {
65
+        return birthday;
66
+    }
67
+
68
+    public void setBirthday(Date birthday)
69
+    {
70
+        this.birthday = birthday;
71
+    }
72
+}

+ 7 - 3
baqing-shop/src/main/java/com/ruoyi/web/modules/account/service/IMemberAppService.java

@@ -1,9 +1,11 @@
1 1
 package com.ruoyi.web.modules.account.service;
2 2
 
3 3
 import java.util.Map;
4
-import com.ruoyi.web.modules.account.domain.BizMember;
4
+import com.ruoyi.web.modules.account.dto.MemberChangePasswordDTO;
5 5
 import com.ruoyi.web.modules.account.dto.MemberLoginDTO;
6
+import com.ruoyi.web.modules.account.dto.MemberProfileUpdateDTO;
6 7
 import com.ruoyi.web.modules.account.dto.MemberRegisterDTO;
8
+import com.ruoyi.web.modules.account.vo.MemberProfileAppVO;
7 9
 
8 10
 /**
9 11
  * C 端会员 Service
@@ -16,7 +18,9 @@ public interface IMemberAppService
16 18
 
17 19
     Map<String, Object> login(MemberLoginDTO dto);
18 20
 
19
-    BizMember getProfile(Long memberId);
21
+    MemberProfileAppVO getProfile(Long memberId);
20 22
 
21
-    void updateProfile(Long memberId, BizMember profile);
23
+    void updateProfile(Long memberId, MemberProfileUpdateDTO dto);
24
+
25
+    void changePassword(Long memberId, MemberChangePasswordDTO dto);
22 26
 }

+ 106 - 38
baqing-shop/src/main/java/com/ruoyi/web/modules/account/service/impl/MemberAppServiceImpl.java

@@ -19,13 +19,16 @@ import com.ruoyi.framework.web.service.UserDetailsServiceImpl;
19 19
 import com.ruoyi.system.service.ISysUserService;
20 20
 import com.ruoyi.web.modules.account.constant.MemberConstants;
21 21
 import com.ruoyi.web.modules.account.domain.BizMember;
22
+import com.ruoyi.web.modules.account.dto.MemberChangePasswordDTO;
22 23
 import com.ruoyi.web.modules.account.dto.MemberCreateDTO;
23 24
 import com.ruoyi.web.modules.account.dto.MemberLoginDTO;
25
+import com.ruoyi.web.modules.account.dto.MemberProfileUpdateDTO;
24 26
 import com.ruoyi.web.modules.account.dto.MemberRegisterDTO;
25 27
 import com.ruoyi.web.modules.account.mapper.BizMemberMapper;
26 28
 import com.ruoyi.web.modules.account.service.IMemberAppService;
27 29
 import com.ruoyi.web.modules.account.service.IMemberSmsService;
28 30
 import com.ruoyi.web.modules.account.support.MemberRegistrationSupport;
31
+import com.ruoyi.web.modules.account.vo.MemberProfileAppVO;
29 32
 import com.ruoyi.web.modules.content.facade.IMallServiceAgreementFacade;
30 33
 
31 34
 /**
@@ -36,6 +39,8 @@ public class MemberAppServiceImpl implements IMemberAppService
36 39
 {
37 40
     private static final Pattern MOBILE_PATTERN = Pattern.compile("^1\\d{10}$");
38 41
 
42
+    private static final Pattern EMAIL_PATTERN = Pattern.compile("^[\\w.-]+@[\\w.-]+\\.\\w+$");
43
+
39 44
     @Autowired
40 45
     private BizMemberMapper memberMapper;
41 46
 
@@ -119,60 +124,123 @@ public class MemberAppServiceImpl implements IMemberAppService
119 124
     }
120 125
 
121 126
     @Override
122
-    public BizMember getProfile(Long memberId)
127
+    public MemberProfileAppVO getProfile(Long memberId)
123 128
     {
124
-        BizMember member = memberMapper.selectById(memberId);
125
-        if (member == null)
129
+        BizMember member = requireMember(memberId);
130
+        return toProfileVo(member);
131
+    }
132
+
133
+    @Override
134
+    @Transactional(rollbackFor = Exception.class)
135
+    public void updateProfile(Long memberId, MemberProfileUpdateDTO dto)
136
+    {
137
+        requireMember(memberId);
138
+        if (dto == null)
126 139
         {
127
-            throw new ServiceException("会员不存在");
140
+            throw new ServiceException("参数不能为空");
128 141
         }
129
-        member.setPassword(null);
130
-        return member;
142
+        if (StringUtils.isEmpty(dto.getNickName()))
143
+        {
144
+            throw new ServiceException("请输入昵称");
145
+        }
146
+        validateEmail(dto.getEmail());
147
+        validateSex(dto.getSex());
148
+        validateBirthday(dto.getBirthday());
149
+
150
+        BizMember accountUpdate = new BizMember();
151
+        accountUpdate.setMemberId(memberId);
152
+        accountUpdate.setUpdateBy(String.valueOf(memberId));
153
+        accountUpdate.setNickName(dto.getNickName().trim());
154
+        accountUpdate.setAvatar(dto.getAvatar());
155
+        accountUpdate.setEmail(dto.getEmail());
156
+        accountUpdate.setSex(dto.getSex());
157
+        accountUpdate.setBirthday(dto.getBirthday());
158
+        memberMapper.updateAccount(accountUpdate);
131 159
     }
132 160
 
133 161
     @Override
134 162
     @Transactional(rollbackFor = Exception.class)
135
-    public void updateProfile(Long memberId, BizMember profile)
163
+    public void changePassword(Long memberId, MemberChangePasswordDTO dto)
136 164
     {
137
-        BizMember existing = memberMapper.selectById(memberId);
138
-        if (existing == null)
165
+        BizMember member = requireMember(memberId);
166
+        if (dto == null || StringUtils.isEmpty(dto.getOldPassword()) || StringUtils.isEmpty(dto.getNewPassword())
167
+                || StringUtils.isEmpty(dto.getConfirmPassword()))
139 168
         {
140
-            throw new ServiceException("会员不存在");
169
+            throw new ServiceException("请完整填写密码信息");
170
+        }
171
+        if (!dto.getNewPassword().equals(dto.getConfirmPassword()))
172
+        {
173
+            throw new ServiceException("两次输入的密码不一致");
174
+        }
175
+        if (!SecurityUtils.matchesPassword(dto.getOldPassword(), member.getPassword()))
176
+        {
177
+            throw new ServiceException("旧密码错误");
141 178
         }
179
+
142 180
         BizMember accountUpdate = new BizMember();
143 181
         accountUpdate.setMemberId(memberId);
144 182
         accountUpdate.setUpdateBy(String.valueOf(memberId));
145
-        if (StringUtils.isNotEmpty(profile.getMemberCode()))
146
-        {
147
-            if (profile.getMemberCode().length() > 64)
148
-            {
149
-                throw new ServiceException("会员名称过长");
150
-            }
151
-            SysUser check = new SysUser();
152
-            check.setUserId(memberId);
153
-            check.setUserName(profile.getMemberCode());
154
-            if (!sysUserService.checkUserNameUnique(check))
155
-            {
156
-                throw new ServiceException("会员名称已存在");
157
-            }
158
-            accountUpdate.setMemberCode(profile.getMemberCode());
159
-        }
160
-        accountUpdate.setNickName(profile.getNickName());
161
-        accountUpdate.setAvatar(profile.getAvatar());
162
-        if (StringUtils.isNotEmpty(profile.getPassword()))
163
-        {
164
-            accountUpdate.setPassword(SecurityUtils.encryptPassword(profile.getPassword()));
165
-        }
183
+        accountUpdate.setPassword(SecurityUtils.encryptPassword(dto.getNewPassword()));
166 184
         memberMapper.updateAccount(accountUpdate);
185
+    }
186
+
187
+    private BizMember requireMember(Long memberId)
188
+    {
189
+        BizMember member = memberMapper.selectById(memberId);
190
+        if (member == null)
191
+        {
192
+            throw new ServiceException("会员不存在");
193
+        }
194
+        return member;
195
+    }
196
+
197
+    private MemberProfileAppVO toProfileVo(BizMember member)
198
+    {
199
+        MemberProfileAppVO vo = new MemberProfileAppVO();
200
+        vo.setMemberId(member.getMemberId());
201
+        vo.setMobile(member.getMobile());
202
+        vo.setMemberCode(member.getMemberCode());
203
+        vo.setNickName(member.getNickName());
204
+        vo.setAvatar(member.getAvatar());
205
+        vo.setEmail(member.getEmail());
206
+        vo.setSex(member.getSex());
207
+        vo.setBirthday(member.getBirthday());
208
+        return vo;
209
+    }
210
+
211
+    private void validateEmail(String email)
212
+    {
213
+        if (StringUtils.isEmpty(email))
214
+        {
215
+            return;
216
+        }
217
+        if (!EMAIL_PATTERN.matcher(email.trim()).matches())
218
+        {
219
+            throw new ServiceException("邮箱格式不正确");
220
+        }
221
+    }
222
+
223
+    private void validateSex(String sex)
224
+    {
225
+        if (StringUtils.isEmpty(sex))
226
+        {
227
+            return;
228
+        }
229
+        if (!"0".equals(sex) && !"1".equals(sex) && !"2".equals(sex))
230
+        {
231
+            throw new ServiceException("性别参数不正确");
232
+        }
233
+    }
167 234
 
168
-        BizMember bizUpdate = new BizMember();
169
-        bizUpdate.setMemberId(memberId);
170
-        bizUpdate.setMemberLevel(profile.getMemberLevel());
171
-        bizUpdate.setRemark(profile.getRemark());
172
-        bizUpdate.setUpdateBy(String.valueOf(memberId));
173
-        if (profile.getMemberLevel() != null || profile.getRemark() != null)
235
+    private void validateBirthday(java.util.Date birthday)
236
+    {
237
+        if (birthday == null)
238
+        {
239
+            return;
240
+        }
241
+        if (birthday.after(DateUtils.getNowDate()))
174 242
         {
175
-            memberMapper.update(bizUpdate);
243
+            throw new ServiceException("出生日期不能为未来日期");
176 244
         }
177 245
     }
178 246
 

+ 110 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/account/vo/MemberProfileAppVO.java

@@ -0,0 +1,110 @@
1
+package com.ruoyi.web.modules.account.vo;
2
+
3
+import java.util.Date;
4
+import com.fasterxml.jackson.annotation.JsonFormat;
5
+
6
+/**
7
+ * C 端个人资料(只读 + 可编辑字段展示)
8
+ */
9
+public class MemberProfileAppVO
10
+{
11
+    /** 用户 ID = sys_user.user_id */
12
+    private Long memberId;
13
+
14
+    private String mobile;
15
+
16
+    /** 会员名称 = sys_user.user_name */
17
+    private String memberCode;
18
+
19
+    private String nickName;
20
+
21
+    private String avatar;
22
+
23
+    private String email;
24
+
25
+    /** 0男 1女 2未知 */
26
+    private String sex;
27
+
28
+    @JsonFormat(pattern = "yyyy-MM-dd")
29
+    private Date birthday;
30
+
31
+    public Long getMemberId()
32
+    {
33
+        return memberId;
34
+    }
35
+
36
+    public void setMemberId(Long memberId)
37
+    {
38
+        this.memberId = memberId;
39
+    }
40
+
41
+    public String getMobile()
42
+    {
43
+        return mobile;
44
+    }
45
+
46
+    public void setMobile(String mobile)
47
+    {
48
+        this.mobile = mobile;
49
+    }
50
+
51
+    public String getMemberCode()
52
+    {
53
+        return memberCode;
54
+    }
55
+
56
+    public void setMemberCode(String memberCode)
57
+    {
58
+        this.memberCode = memberCode;
59
+    }
60
+
61
+    public String getNickName()
62
+    {
63
+        return nickName;
64
+    }
65
+
66
+    public void setNickName(String nickName)
67
+    {
68
+        this.nickName = nickName;
69
+    }
70
+
71
+    public String getAvatar()
72
+    {
73
+        return avatar;
74
+    }
75
+
76
+    public void setAvatar(String avatar)
77
+    {
78
+        this.avatar = avatar;
79
+    }
80
+
81
+    public String getEmail()
82
+    {
83
+        return email;
84
+    }
85
+
86
+    public void setEmail(String email)
87
+    {
88
+        this.email = email;
89
+    }
90
+
91
+    public String getSex()
92
+    {
93
+        return sex;
94
+    }
95
+
96
+    public void setSex(String sex)
97
+    {
98
+        this.sex = sex;
99
+    }
100
+
101
+    public Date getBirthday()
102
+    {
103
+        return birthday;
104
+    }
105
+
106
+    public void setBirthday(Date birthday)
107
+    {
108
+        this.birthday = birthday;
109
+    }
110
+}

+ 2 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/entry/service/impl/MerchantEntryApplyServiceImpl.java

@@ -131,6 +131,8 @@ public class MerchantEntryApplyServiceImpl implements IMerchantEntryApplyService
131 131
             vo.setRejectReason(apply.getRejectReason());
132 132
             vo.setMerchantId(apply.getMerchantId());
133 133
             vo.setShopId(apply.getShopId());
134
+            vo.setPublicityStartTime(apply.getPublicityStartTime());
135
+            vo.setPublicityEndTime(apply.getPublicityEndTime());
134 136
             rows.add(vo);
135 137
         }
136 138
         return rows;

+ 26 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/entry/vo/EntryApplyMyVO.java

@@ -26,6 +26,12 @@ public class EntryApplyMyVO
26 26
 
27 27
     private Long shopId;
28 28
 
29
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
30
+    private Date publicityStartTime;
31
+
32
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
33
+    private Date publicityEndTime;
34
+
29 35
     public Long getApplyId()
30 36
     {
31 37
         return applyId;
@@ -105,4 +111,24 @@ public class EntryApplyMyVO
105 111
     {
106 112
         this.shopId = shopId;
107 113
     }
114
+
115
+    public Date getPublicityStartTime()
116
+    {
117
+        return publicityStartTime;
118
+    }
119
+
120
+    public void setPublicityStartTime(Date publicityStartTime)
121
+    {
122
+        this.publicityStartTime = publicityStartTime;
123
+    }
124
+
125
+    public Date getPublicityEndTime()
126
+    {
127
+        return publicityEndTime;
128
+    }
129
+
130
+    public void setPublicityEndTime(Date publicityEndTime)
131
+    {
132
+        this.publicityEndTime = publicityEndTime;
133
+    }
108 134
 }

+ 9 - 0
baqing-shop/src/main/resources/mapper/account/BizMemberMapper.xml

@@ -7,6 +7,9 @@
7 7
         <result property="mobile" column="mobile"/>
8 8
         <result property="memberCode" column="member_code"/>
9 9
         <result property="nickName" column="nick_name"/>
10
+        <result property="email" column="email"/>
11
+        <result property="sex" column="sex"/>
12
+        <result property="birthday" column="birthday"/>
10 13
         <result property="password" column="password"/>
11 14
         <result property="memberLevel" column="member_level"/>
12 15
         <result property="status" column="status"/>
@@ -27,6 +30,9 @@
27 30
                u.phonenumber as mobile,
28 31
                u.user_name as member_code,
29 32
                u.nick_name,
33
+               u.email,
34
+               u.sex,
35
+               u.birthday,
30 36
                u.password,
31 37
                m.member_level,
32 38
                u.status,
@@ -135,6 +141,9 @@
135 141
         <set>
136 142
             <if test="memberCode != null and memberCode != ''">user_name = #{memberCode},</if>
137 143
             <if test="nickName != null">nick_name = #{nickName},</if>
144
+            <if test="email != null">email = #{email},</if>
145
+            <if test="sex != null">sex = #{sex},</if>
146
+            <if test="birthday != null">birthday = #{birthday},</if>
138 147
             <if test="password != null and password != ''">password = #{password},</if>
139 148
             <if test="avatar != null">avatar = #{avatar},</if>
140 149
             update_by = #{updateBy},

+ 68 - 0
baqing-shop/src/test/java/com/ruoyi/web/modules/account/service/MemberAppServiceImplTest.java

@@ -22,10 +22,13 @@ import com.ruoyi.framework.web.service.UserDetailsServiceImpl;
22 22
 import com.ruoyi.system.service.ISysUserService;
23 23
 import com.ruoyi.web.modules.account.constant.MemberConstants;
24 24
 import com.ruoyi.web.modules.account.domain.BizMember;
25
+import com.ruoyi.web.modules.account.dto.MemberChangePasswordDTO;
25 26
 import com.ruoyi.web.modules.account.dto.MemberLoginDTO;
27
+import com.ruoyi.web.modules.account.dto.MemberProfileUpdateDTO;
26 28
 import com.ruoyi.web.modules.account.dto.MemberRegisterDTO;
27 29
 import com.ruoyi.web.modules.account.mapper.BizMemberMapper;
28 30
 import com.ruoyi.web.modules.account.service.impl.MemberAppServiceImpl;
31
+import com.ruoyi.web.modules.account.vo.MemberProfileAppVO;
29 32
 import com.ruoyi.web.modules.content.facade.IMallServiceAgreementFacade;
30 33
 import com.ruoyi.web.modules.account.support.MemberRegistrationSupport;
31 34
 
@@ -154,6 +157,71 @@ class MemberAppServiceImplTest
154 157
         assertEquals("账号已禁用,请联系客服", ex.getMessage());
155 158
     }
156 159
 
160
+    @Test
161
+    void getProfile_returnsVoWithSysUserFields()
162
+    {
163
+        BizMember member = activeMember();
164
+        member.setNickName("买家A");
165
+        member.setEmail("a@test.com");
166
+        member.setSex("0");
167
+        when(memberMapper.selectById(1L)).thenReturn(member);
168
+
169
+        MemberProfileAppVO vo = memberAppService.getProfile(1L);
170
+
171
+        assertEquals(1L, vo.getMemberId());
172
+        assertEquals("买家A", vo.getNickName());
173
+        assertEquals("a@test.com", vo.getEmail());
174
+        assertEquals("0", vo.getSex());
175
+    }
176
+
177
+    @Test
178
+    void updateProfile_updatesSysUserByMemberId()
179
+    {
180
+        when(memberMapper.selectById(1L)).thenReturn(activeMember());
181
+
182
+        MemberProfileUpdateDTO dto = new MemberProfileUpdateDTO();
183
+        dto.setNickName("新昵称");
184
+        dto.setEmail("new@test.com");
185
+        dto.setSex("1");
186
+
187
+        memberAppService.updateProfile(1L, dto);
188
+
189
+        verify(memberMapper).updateAccount(any(BizMember.class));
190
+    }
191
+
192
+    @Test
193
+    void changePassword_wrongOldPassword_rejected()
194
+    {
195
+        BizMember member = activeMember();
196
+        member.setPassword(SecurityUtils.encryptPassword("Pass1234"));
197
+        when(memberMapper.selectById(1L)).thenReturn(member);
198
+
199
+        MemberChangePasswordDTO dto = new MemberChangePasswordDTO();
200
+        dto.setOldPassword("wrong");
201
+        dto.setNewPassword("New12345");
202
+        dto.setConfirmPassword("New12345");
203
+
204
+        ServiceException ex = assertThrows(ServiceException.class, () -> memberAppService.changePassword(1L, dto));
205
+        assertEquals("旧密码错误", ex.getMessage());
206
+    }
207
+
208
+    @Test
209
+    void changePassword_success()
210
+    {
211
+        BizMember member = activeMember();
212
+        member.setPassword(SecurityUtils.encryptPassword("Pass1234"));
213
+        when(memberMapper.selectById(1L)).thenReturn(member);
214
+
215
+        MemberChangePasswordDTO dto = new MemberChangePasswordDTO();
216
+        dto.setOldPassword("Pass1234");
217
+        dto.setNewPassword("New12345");
218
+        dto.setConfirmPassword("New12345");
219
+
220
+        memberAppService.changePassword(1L, dto);
221
+
222
+        verify(memberMapper).updateAccount(any(BizMember.class));
223
+    }
224
+
157 225
     private MemberRegisterDTO registerDto()
158 226
     {
159 227
         MemberRegisterDTO dto = new MemberRegisterDTO();

+ 0 - 38
doc/消费者APP/我的/我的功能需求-草稿.md

@@ -1,38 +0,0 @@
1
-做一个“我的”功能模块:
2
-
3
-
4
-
5
-1. 前置条件:会员通过APP已登录
6
-
7
-2. 账号管理
8
-
9
-   编辑个人资料:用户ID(不可编辑)、昵称、出生日期、手机号码(不可编辑)、邮箱、性别、头像。
10
-
11
-   修改密码:输入旧密码、新密码、确认密码,保存完成修改
12
-
13
-3. 收货地址
14
-
15
-   1、已添加地址列表,默认地址置顶,其余按添加时间倒序排列
16
-   2、支持添加新地址,填写收货人、手机号码、所在地区、详细地址、是否设为默认地址,选择设为默认地址则自动将原默认地址设为非默认
17
-   3、支持删除已添加的地址;
18
-   4、支持将非默认地址设为默认地址,并自动将原默认地址设为非默认
19
-   5、支持编辑已添加的地址,修改收货人、手机号码、所在地区、详细地址、是否设为默认地址,选择设为默认地址则自动将原默认地址设为非默认
20
-
21
-4. 商家入驻
22
-
23
-   1、当前已登录的会员可以通过个人、企业两种主体申请商户入驻。
24
-
25
-   2、以下两种主体类型二选一
26
-    1、个人入驻:
27
-   (1)个人信息:证件类型(身份证)、姓名、证件号码、出生日期、证件有效期(区间有效/长期有效)、居住地址、性别、证件照正面照片、证件照反面照片;
28
-   (2)经营信息:联系人信息(联系人姓名、联系人手机、联系人邮箱)、结算账户信息(开户银行、
29
-   支行名称、银行卡号)、商户信息(商户名称、客服电话、经营地址、详细地址)、店铺信息(店铺名称、店铺Logo、联系电话、店铺简介)、补充信息(补充照片)
30
-    2、企业入驻
31
-   (1)法定代表人信息:证件类型(身份证)、姓名、证件号码、出生日期、证件有效期(区间有效/长期有效)、居住地址、性别、证件照正面照片、证件照反面照片;
32
-   (2)经营信息:联系人信息(联系人姓名、联系人手机、联系人邮箱)、结算账户信息(开户银行、
33
-   支行名称、对公银行卡号、开户许可证)、商户信息(商户名称、客服电话、经营地址、详细地址、营业执照电子版)、店铺信息(店铺名称、店铺Logo、联系电话、店铺简介)
34
-   (3)企业信息:企业信息(企业名称、注册地址、详细地圳、经营范围、统一社会信用代码、营业期限(区间有效/长期有效))、补充信息(补充照片)
35
-
36
-5. 异常返回:统一格式 code、msg、data。
37
-
38
-6. 技术栈:RuoYi v3.9.2-springboot2 分支 + MySQL-5.7.39。

+ 1 - 0
sql/biz_member.sql

@@ -1,7 +1,7 @@
1 1
 -- =============================================================================
2 2
 -- C 端会员 biz_member(与 sys_user 复用)
3 3
 -- 映射:member_id = user_id;手机号=phonenumber;会员名称=user_name;昵称=nick_name;
4
+--       邮箱=email;性别=sex;出生日期=birthday;密码=password;头像=avatar;状态=status
4 5
 -- 注册:先 insert sys_user(分配 role_key=member),再 insert biz_member(member_id = user_id)
5 6
 -- =============================================================================
6 7
 CREATE TABLE IF NOT EXISTS `biz_member` (