feat(settings): 个人信息手机号/邮箱开放自助修改——保存按钮启用走 /api/user/UpdateContact(前端校验与后端同口径:手机号 1[3-9] 段位/邮箱格式/长度),成功以接口返回的最新 BoaUser 合并 store.userInfo 即时回显(规避 CAS principal 缓存旧值);BaseApi 新增 updateContact(任务B·前端)

This commit is contained in:
chenxing
2026-10-02 08:56:46 +08:00
parent f52ce4136e
commit 1d34e5745d
2 changed files with 54 additions and 4 deletions
+9
View File
@@ -14,6 +14,15 @@ class Base extends Abstract {
return this.getRequest({ url, isMsg: false });
}
/**
* 修改本人联系方式(手机号/邮箱,至少一项非空;后端经 UserBase 开放接口落库)。
* 成功返回更新后的最新用户信息(BoaUser,含新 phone/email),供调用方刷新 store 规避 CAS principal 旧值。
*/
updateContact(phone: string, email: string) {
const url = path + "/user/UpdateContact";
return this.postRequest<any>({ url, data: { phone, email } });
}
/**
*获取用户全部角色
* @memberof Basic
+45 -4
View File
@@ -88,8 +88,8 @@
</div>
</div>
<div class="pane-foot">
<!-- 保存占位:接口待 UserBase 支持本人自助修改,本轮不做(拍板结论) -->
<button class="btn primary" disabled title="接口待 UserBase 支持本人自助修改,本轮暂不可用">保存修改</button>
<!-- 手机/邮箱保存(任务B 2026-10-02):走 /api/user/UpdateContact,后端经开放接口直写 UserBase -->
<button class="btn primary" :disabled="profileSaving" @click="onSaveProfile">保存修改</button>
<button class="btn plain" @click="resetProfileForm">重置</button>
</div>
</div>
@@ -533,7 +533,7 @@ import { Message } from "view-ui-plus";
/**
* 设置中心(/settings):左 216px 分组导航卡 + 右内容卡(B 方案左右双卡)。
* 五个 pane 已对接真实数据(设置对接 2026-09-30,零新接口):
* profile 读 store.userInfo(保存占位——接口待 UserBase 支持本人自助修改,本轮不做);
* profile 读 store.userInfo(手机/邮箱本人可改:UpdateContact 直写 UserBase,2026-10-02 任务B);
* password 走 updatePassword + 确认登出流程(照抄 UserInfoModal);
* avatar 移植 UserInfoModal 直传上传(预设色块/「使用默认头像」保持占位);
* logo/wallpaper 管理列表 + 直传 + 删除照抄 SysSetting.vue,LOGO 保存走 saveSchLogo(schId 后端按登录人推断),
@@ -662,7 +662,48 @@ function resetProfileForm() {
profileForm.mobile = profileView.value.phone;
profileForm.email = profileView.value.email;
}
/** 保存占位:接口待 UserBase 支持本人自助修改,本轮不做(拍板结论) */
/* ===== 手机/邮箱保存(任务B 2026-10-02):/api/user/UpdateContact → UserBase /oapi/user/self/contact ===== */
const profileSaving = ref(false);
/** 前端校验与后端同口径(UserBase ValidatorUtil.isPhone / CONTACT_EMAIL),双端拦截不一致数据 */
const PHONE_RE = /^1[3-9]\d{9}$/;
const EMAIL_RE = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)+$/;
async function onSaveProfile() {
const phone = profileForm.mobile.trim();
const email = profileForm.email.trim();
if (!phone && !email) {
Message.warning("手机号与邮箱至少填写一项");
return;
}
if (phone && !PHONE_RE.test(phone)) {
Message.warning("手机号格式不正确");
return;
}
if (email && email.length > 100) {
Message.warning("邮箱长度不能超过100字符");
return;
}
if (email && !EMAIL_RE.test(email)) {
Message.warning("邮箱格式不正确");
return;
}
if (profileSaving.value) return;
profileSaving.value = true;
try {
// 成功返回 UserBase 更新后的最新 BoaUser:合并进 store.userInfo 即时回显,
// 规避 CAS principal 缓存旧值(UserBase 侧缓存已随更新驱逐,下次 GetUserInfo 也是新值)
const fresh: any = await BaseApi.updateContact(phone, email);
if (fresh && typeof fresh === "object") {
store.userInfo = { ...store.userInfo, ...fresh };
}
Message.success("保存成功");
} catch (error) {
Message.error("保存失败:" + error);
} finally {
profileSaving.value = false;
}
}
/* ===== password:updatePassword + 确认登出(流程照抄 UserInfoModal) ===== */
const passwordForm = reactive({ old: "", next: "", confirm: "" });