diff --git a/src/pages.json b/src/pages.json
index 42016ac..1cfba8e 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -44,6 +44,13 @@
"disableScroll": true
}
},
+ {
+ "path": "pages/root/force-change-password",
+ "style": {
+ "navigationBarTitleText": "修改密码",
+ "disableScroll": true
+ }
+ },
{
"path": "pages/user/address/index",
"style": {
diff --git a/src/pages/root/force-change-password.vue b/src/pages/root/force-change-password.vue
new file mode 100644
index 0000000..9ec2021
--- /dev/null
+++ b/src/pages/root/force-change-password.vue
@@ -0,0 +1,115 @@
+
+
+
+
+
+ 首次登录须修改密码,请设置新密码后重新登录
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 确认修改
+
+
+ 返回登录
+
+
+
+
+
+
+
diff --git a/src/pages/root/forgot-password.vue b/src/pages/root/forgot-password.vue
index 488a3d6..d8fcf05 100644
--- a/src/pages/root/forgot-password.vue
+++ b/src/pages/root/forgot-password.vue
@@ -39,7 +39,7 @@ import { router } from "@@/index"
const MOBILE_REG = /^[1](([3][0-9])|([4][0,1,4-9])|([5][0-3,5-9])|([6][2,5,6,7])|([7][0-8])|([8][0-9])|([9][0-3,5-9]))[0-9]{8}$/
const SMS_CODE_REG = /^\d{6}$/
-const PASSWORD_REG = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,20}$/
+const PASSWORD_REG = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z0-9]{8,20}$/
const applyForm = reactive({
mobile: "",
@@ -65,7 +65,7 @@ const applyFormRules = reactive({
],
newPassword: [
{ required: true, message: "请输入新密码" },
- { required: true, rule: PASSWORD_REG, message: "密码需为8-20位且包含大小写字母、数字和特殊字符" },
+ { required: true, rule: PASSWORD_REG, message: "密码需为8-20位字母和数字组合" },
],
})
diff --git a/src/pages/root/login.vue b/src/pages/root/login.vue
index 0ef6bed..74fb417 100644
--- a/src/pages/root/login.vue
+++ b/src/pages/root/login.vue
@@ -34,6 +34,8 @@ onShow(() => {
})
+const CREDENTIALS_EXPIRED = "credentials_expired"
+
const applyFormRef = ref(null)
const doSubmit = async () => {
applyFormRef.value.submit()
@@ -44,25 +46,33 @@ const doSubmit = async () => {
const rememberUser = constant.storageConstant.REMEMBER_USER
uni.removeStorageSync(tokenKey)
uni.showLoading({ title: "登录中...", mask: true })
- const res: any = await userApi.login({
- ...applyForm,
- grant_type: "password",
- scope: "server",
- })
- if (res.code != 0) {
- uni.showToast({ title: res.msg + ",登录失败,请重新登录", icon: "error" })
- return
+ try {
+ const res: any = await userApi.login({
+ ...applyForm,
+ grant_type: "password",
+ scope: "server",
+ })
+ if (res.code != 0) {
+ if (res.data === CREDENTIALS_EXPIRED) {
+ uni.showToast({ title: "请先修改密码", icon: "none" })
+ router.jump("/pages/root/force-change-password", { username: applyForm.username })
+ return
+ }
+ uni.showToast({ title: (res.msg || "登录失败") + ",请重新登录", icon: "error" })
+ return
+ }
+ uni.setStorageSync(tokenKey, res.data)
+ const { data: userData } = await userApi.userInfo()
+ uni.setStorageSync(userInfoKey, userData)
+ uni.setStorageSync(rememberUser, {
+ username: applyForm.username,
+ password: applyForm.password,
+ } as GlobalSetting.RememberUser)
+ uni.showToast({ title: "登录成功", icon: "none" })
+ router.jump("/pages/tabbar/my")
+ } finally {
+ uni.hideLoading()
}
- uni.setStorageSync(tokenKey, res.data)
- const { data: userData } = await userApi.userInfo()
- uni.setStorageSync(userInfoKey, userData)
- uni.setStorageSync(rememberUser, {
- username: applyForm.username,
- password: applyForm.password,
- } as GlobalSetting.RememberUser)
- uni.hideLoading()
- uni.showToast({ title: "登录成功", icon: "none" })
- router.jump("/pages/tabbar/my")
}
const disposeLogin = () => {
diff --git a/src/pages/tabbar/my.vue b/src/pages/tabbar/my.vue
index c35528f..daba787 100644
--- a/src/pages/tabbar/my.vue
+++ b/src/pages/tabbar/my.vue
@@ -93,14 +93,14 @@ const state = reactive({
menuList: [
{ text: "地址", icon: "/static/icon/scan.png", path: "/pages/user/map-address/index" },
{ text: "扫一扫", icon: "/static/icon/scan.png", path: "" },
- { text: "钱包", icon: "/static/icon/service_3.png", path: "/pages/wallet/list" },
- { text: "喜好", icon: "/static/icon/service_4.png", path: "/pages/tabbar/canteenAnalyse" },
- { text: "记录", icon: "/static/icon/service_1.png", path: "/pages/ordering-food/records" },
+ { text: "钱包管理", icon: "/static/icon/service_3.png", path: "/pages/wallet/list" },
+ { text: "喜好分析", icon: "/static/icon/service_4.png", path: "/pages/tabbar/canteenAnalyse" },
+ { text: "报餐记录", icon: "/static/icon/service_1.png", path: "/pages/ordering-food/records" },
// { text: "测试通知", icon: "/static/icon/service_1.png", path: "" },
// { text: "外卖配送录入", icon: "/static/icon/service_1.png", path: "/pages/delivery/rider" },
// { text: "外卖查询", icon: "/static/icon/service_6.png", path: "/pages/delivery/query" },
// { text: "我的人脸", icon: "/static/icon/service_5.png", path: "/pages/human-face/list" },
- { text: "兑换", icon: "/static/icon/service_7.png", path: "/pages/ad/make-money" },
+ { text: "积分兑换", icon: "/static/icon/service_7.png", path: "/pages/ad/make-money" },
// { text: "车辆管理", icon: "/static/icon/service_6.png", path: "/pages/car/user-car/list" },
],
appInfo: "",
@@ -341,7 +341,7 @@ const onTabMenu = async (item: any) => {
case "扫一扫":
await appScanCode()
break
- case "商品":
+ case "商品管理":
await gotoOnlineDishManage()
break
default:
@@ -401,19 +401,19 @@ onShow(async () => {
appHotUpdateRef.value?.checkUpdate()
})
-/** 按角色在「钱包 / 喜好」之后插入:商品、订单管理、骑手配送、报餐统计 */
+/** 按角色在「钱包管理 / 喜好分析」之后插入:商品管理、商家订单、骑手配送、报餐统计 */
const syncRoleMenus = async () => {
await refreshUserRoleCodes()
- const roleLabels = new Set(["商品", "商家", "配送", "统计"])
+ const roleLabels = new Set(["商品管理", "商家订单", "骑手配送", "报餐统计"])
const base = (state.menuList || []).filter((x: any) => !roleLabels.has(x?.text))
const roleEntries: any[] = []
if (hasRoleCode(ROLE_ONLINE_CANTEEN_MCH)) {
- roleEntries.push({ text: "商品", icon: "/static/icon/service_12.png", path: "/pages/merchant/online-dish-manage" })
- roleEntries.push({ text: "商家", icon: "/static/icon/service_13.png", path: "/pages/canteen-delivery/mch-list" })
- roleEntries.push({ text: "统计", icon: "/static/icon/service_6.png", path: "/pages/ordering-food/stats" })
+ roleEntries.push({ text: "商品管理", icon: "/static/icon/service_12.png", path: "/pages/merchant/online-dish-manage" })
+ roleEntries.push({ text: "商家订单", icon: "/static/icon/service_13.png", path: "/pages/canteen-delivery/mch-list" })
+ roleEntries.push({ text: "报餐统计", icon: "/static/icon/service_6.png", path: "/pages/ordering-food/stats" })
}
if (hasRoleCode(ROLE_CANTEEN_RIDER)) {
- roleEntries.push({ text: "配送", icon: "/static/icon/service_11.png", path: "/pages/canteen-delivery/list" })
+ roleEntries.push({ text: "骑手配送", icon: "/static/icon/service_11.png", path: "/pages/canteen-delivery/list" })
}
state.menuList = [...base.slice(0, 2), ...roleEntries, ...base.slice(2)]
}
diff --git a/src/sheep/api/user.ts b/src/sheep/api/user.ts
index 86551c9..a6ce610 100644
--- a/src/sheep/api/user.ts
+++ b/src/sheep/api/user.ts
@@ -106,6 +106,14 @@ export default {
data,
}),
+ // 首次登录/密码过期强制改密(无需登录)
+ resetUserPassword: (data: { username: string; password: string; newpassword1: string }) =>
+ request({
+ url: "/admin/register/password",
+ method: "POST",
+ data,
+ }),
+
// 设备认证
verifyDevice: (data: { mobilePhone: string; code: string }) =>
request({
diff --git a/src/sheep/utils/request.ts b/src/sheep/utils/request.ts
index 0a11a48..2941907 100644
--- a/src/sheep/utils/request.ts
+++ b/src/sheep/utils/request.ts
@@ -9,7 +9,7 @@ import { APPENV } from "../constant"
const TOKEN_KEY = constant.storageConstant.TOKEN
const USER_INFO_KEY = constant.storageConstant.USERINFO
-const SKIP_AUTH_URLS = ["/thirdparty/thirdPartyOAth2", "/sys/auth/refresh-token", "/auth/oauth2/token", "/admin/user/forgot-password", "/admin/stats/access/track"]
+const SKIP_AUTH_URLS = ["/thirdparty/thirdPartyOAth2", "/sys/auth/refresh-token", "/auth/oauth2/token", "/admin/user/forgot-password", "/admin/register/password", "/admin/stats/access/track"]
const SKIP_REFRESH_TOKEN = ["/sys/auth/refresh-token", "/auth/token/check_token"]
let refreshTokenLock = true
@@ -91,8 +91,8 @@ https.interceptors.response.use(
uni.showToast({ title: "登录已过期,请重新登录", icon: "none" })
router.jump("/pages/root/login")
}
- // 显示错误信息
- else if (error?.data?.msg) {
+ // 登录错误由登录页自行处理
+ else if (error?.data?.msg && error.config?.url !== "/auth/oauth2/token") {
uni.showToast({ title: error.data.msg, icon: "none", mask: true })
}
return Promise.resolve(error.data)