From f0d8f6bac4b720e7635284cea115b4cb17b83fcf Mon Sep 17 00:00:00 2001 From: liu <2302563948@qq.com> Date: Fri, 21 Aug 2026 11:01:37 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B4=A6=E6=88=B7=E5=AF=86=E7=A0=81=E7=99=BB?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.config.ts | 2 +- src/pages/change-password/index.config.ts | 3 + src/pages/change-password/index.less | 48 +++++ src/pages/change-password/index.tsx | 111 +++++++++++ src/pages/login/index.less | 55 ++++-- src/pages/login/index.tsx | 104 +++++----- src/pages/profile/index.tsx | 43 ++--- src/pages/register/index.config.ts | 4 - src/pages/register/index.less | 196 ------------------- src/pages/register/index.tsx | 222 ---------------------- src/services/auth.ts | 51 ++--- src/stores/auth/useAuthStore.ts | 27 +-- src/types/user.ts | 61 ++---- 13 files changed, 328 insertions(+), 599 deletions(-) create mode 100644 src/pages/change-password/index.config.ts create mode 100644 src/pages/change-password/index.less create mode 100644 src/pages/change-password/index.tsx delete mode 100644 src/pages/register/index.config.ts delete mode 100644 src/pages/register/index.less delete mode 100644 src/pages/register/index.tsx diff --git a/src/app.config.ts b/src/app.config.ts index 10b4f41..422e995 100644 --- a/src/app.config.ts +++ b/src/app.config.ts @@ -14,7 +14,7 @@ export default defineAppConfig({ 'pages/payment-detail/index', 'pages/settings/index', 'pages/login/index', - 'pages/register/index', + 'pages/change-password/index', 'pages/store-info/index', ], window: { diff --git a/src/pages/change-password/index.config.ts b/src/pages/change-password/index.config.ts new file mode 100644 index 0000000..96fdbcc --- /dev/null +++ b/src/pages/change-password/index.config.ts @@ -0,0 +1,3 @@ +export default definePageConfig({ + navigationBarTitleText: '修改密码', +}) diff --git a/src/pages/change-password/index.less b/src/pages/change-password/index.less new file mode 100644 index 0000000..15d24d2 --- /dev/null +++ b/src/pages/change-password/index.less @@ -0,0 +1,48 @@ +.change-password-page { + min-height: 100vh; + background: #f7f8fa; + padding: 20rpx 24rpx 60rpx; + box-sizing: border-box; + + // ===== 表单区块 ===== + .pwd-section { + background: #fff; + border-radius: 20rpx; + padding: 8rpx 28rpx; + margin-bottom: 20rpx; + } + + // ===== 表单行 ===== + .pwd-field { + display: flex; + align-items: center; + padding: 28rpx 0; + border-bottom: 1rpx solid #f2f3f5; + + &:last-child { + border-bottom: none; + } + + &__label { + width: 160rpx; + flex-shrink: 0; + font-size: 28rpx; + color: #323233; + } + + &__input { + flex: 1; + font-size: 28rpx; + color: #323233; + } + + &__placeholder { + color: #c8c9cc; + } + } + + // ===== 提交按钮 ===== + .pwd-submit { + margin-top: 40rpx; + } +} diff --git a/src/pages/change-password/index.tsx b/src/pages/change-password/index.tsx new file mode 100644 index 0000000..92cbdfc --- /dev/null +++ b/src/pages/change-password/index.tsx @@ -0,0 +1,111 @@ +import { useCallback, useState } from 'react' +import Taro from '@tarojs/taro' +import { View, Text, Input } from '@tarojs/components' +import { Button } from '@antmjs/vantui' +import { changePasswordApi } from '@/services/auth' +import './index.less' + +/** 新密码长度限制(与后端一致:6~20 位) */ +const LIMITS = { + passwordMin: 6, + passwordMax: 20, +} as const + +/** + * 修改密码页 + * 修改成功后现有 token 仍然有效,无需重新登录 + */ +export default function ChangePasswordPage() { + /** 原密码 */ + const [oldPassword, setOldPassword] = useState('') + /** 新密码 */ + const [newPassword, setNewPassword] = useState('') + /** 确认新密码 */ + const [rePassword, setRePassword] = useState('') + const [saving, setSaving] = useState(false) + + /** 提交:PUT /mini/auth/password */ + const handleSubmit = useCallback(async () => { + if (saving) return + if (!oldPassword) { + Taro.showToast({ title: '请输入原密码', icon: 'none' }) + return + } + if (newPassword.length < LIMITS.passwordMin) { + Taro.showToast({ title: `新密码至少 ${LIMITS.passwordMin} 位`, icon: 'none' }) + return + } + if (newPassword !== rePassword) { + Taro.showToast({ title: '两次输入的密码不一致', icon: 'none' }) + return + } + setSaving(true) + try { + await changePasswordApi({ oldPassword, newPassword, rePassword }) + Taro.showToast({ title: '密码修改成功', icon: 'success' }) + setTimeout(() => Taro.navigateBack(), 800) + } catch { + // 错误提示已由 request 层 toast(原密码不正确等) + } finally { + setSaving(false) + } + }, [saving, oldPassword, newPassword, rePassword]) + + return ( + + {/* ========== 密码表单 ========== */} + + + 原密码 + setOldPassword(e.detail.value)} + /> + + + 新密码 + setNewPassword(e.detail.value)} + /> + + + 确认新密码 + setRePassword(e.detail.value)} + onConfirm={handleSubmit} + /> + + + + {/* ========== 提交 ========== */} + + + ) +} diff --git a/src/pages/login/index.less b/src/pages/login/index.less index 50befb1..b64fb01 100644 --- a/src/pages/login/index.less +++ b/src/pages/login/index.less @@ -100,17 +100,44 @@ } } -/* ========== 功能介绍 ========== */ -.login-features { - margin-bottom: 80px; +/* ========== 登录表单 ========== */ +.login-form { + width: 100%; + background: #f7f8fa; + border-radius: 24px; + padding: 0 32px; + margin-bottom: 60px; +} - .feature-text { - font-size: 26px; - color: #c8c9cc; - letter-spacing: 2px; +.form-item { + display: flex; + align-items: center; + height: 112px; + border-bottom: 1px solid #ebedf0; + + &:last-child { + border-bottom: none; } } +.form-label { + width: 120px; + font-size: 30px; + color: #323233; + flex-shrink: 0; +} + +.form-input { + flex: 1; + height: 100%; + font-size: 30px; + color: #323233; +} + +.form-input-placeholder { + color: #c8c9cc; +} + /* ========== 登录操作区 ========== */ .login-actions { width: 100%; @@ -144,23 +171,17 @@ opacity: 0.75; } -/* ========== 去注册入口 ========== */ -.login-switch { +/* ========== 客服提示 ========== */ +.login-tip { display: flex; align-items: center; justify-content: center; margin-top: 32px; - .switch-text { - font-size: 28px; + .tip-text { + font-size: 26px; color: #969799; } - - .switch-link { - font-size: 28px; - color: #ee0a24; - margin-left: 8px; - } } /* ========== 协议文字 ========== */ diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index 617b3e8..d2c5256 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -1,18 +1,24 @@ -import { useCallback, useEffect, useState } from 'react' +import { useCallback, useState } from 'react' import Taro from '@tarojs/taro' -import { View, Text, Button } from '@tarojs/components' +import { View, Text, Button, Input } from '@tarojs/components' import CustomNavBar from '@/components/NavBar' import useAuthStore from '@/stores/auth/useAuthStore' import './index.less' +/** 登录账号长度限制(与后端一致:4~20 位) */ +const USERNAME_MAX = 20 +/** 密码长度限制 */ +const PASSWORD_MAX = 20 + export default function LoginPage() { const login = useAuthStore(s => s.login) - const isLoggedIn = useAuthStore(s => !!s.token && !!s.user) + /** 登录账号(商家后台分配) */ + const [username, setUsername] = useState('') + /** 登录密码 */ + const [password, setPassword] = useState('') const [submitting, setSubmitting] = useState(false) - const isWeb = Taro.getEnv() === Taro.ENV_TYPE.WEB - /** 返回上一页(无页面栈时回首页) */ const goBack = useCallback(() => { const pages = Taro.getCurrentPages() @@ -23,50 +29,29 @@ export default function LoginPage() { } }, []) - /** 前往注册页 */ - const goRegister = useCallback(() => { - Taro.navigateTo({ url: '/pages/register/index' }) - }, []) - - /** 已登录 → 自动返回 */ - useEffect(() => { - if (isLoggedIn) goBack() - }, [isLoggedIn, goBack]) - - /** 微信一键登录(wx.login code 换 openid,仅已注册用户可登录) */ + /** 账号密码登录:POST /mini/auth/login */ const handleLogin = useCallback(async () => { if (submitting) return - // H5 环境无法获取微信登录凭证 - if (isWeb) { - Taro.showToast({ title: '请在微信小程序中使用微信登录', icon: 'none' }) + const account = username.trim() + if (!account) { + Taro.showToast({ title: '请输入登录账号', icon: 'none' }) + return + } + if (!password) { + Taro.showToast({ title: '请输入登录密码', icon: 'none' }) return } setSubmitting(true) try { - const res = await Taro.login() - if (!res.code) { - Taro.showToast({ title: '获取登录凭证失败', icon: 'none' }) - return - } - await login({ code: res.code }) - // 登录成功后由 effect 自动返回 - } catch (e: any) { - // 未注册用户:引导前往注册页(其余错误已由 request 层提示) - if (typeof e?.msg === 'string' && e.msg.includes('用户不存在')) { - Taro.showModal({ - title: '未注册', - content: '该微信账号尚未注册,需授权手机号并填写门店编码完成注册', - confirmText: '去注册', - cancelText: '取消', - success: res => { - if (res.confirm) goRegister() - }, - }) - } + await login({ username: account, password }) + Taro.showToast({ title: '登录成功', icon: 'success' }) + goBack() + } catch { + // 错误提示已由 request 层 toast(账号或密码错误 / 账号已停用等) } finally { setSubmitting(false) } - }, [login, submitting, isWeb, goRegister]) + }, [login, submitting, username, password, goBack]) /** 查看用户协议 */ const handleShowAgreement = useCallback(() => { @@ -94,9 +79,34 @@ export default function LoginPage() { 门店订货 · 对账结算 · 一站式采购 - {/* 功能介绍 */} - - 在线订货 · 价格透明 · 周期对账 + {/* 登录表单 */} + + + 账号 + setUsername(e.detail.value)} + /> + + + 密码 + setPassword(e.detail.value)} + onConfirm={handleLogin} + /> + {/* 登录操作 */} @@ -107,13 +117,11 @@ export default function LoginPage() { loading={submitting} disabled={submitting} > - {submitting ? '登录中...' : '微信一键登录'} + {submitting ? '登录中...' : '登 录'} - {/* 未注册用户入口 */} - - 还没有账号? - 立即注册 + + 账号密码由商家分配,如需帮助请联系客服 diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx index 945d28c..eefe04d 100644 --- a/src/pages/profile/index.tsx +++ b/src/pages/profile/index.tsx @@ -8,7 +8,6 @@ import { getBillListApi } from '@/services/bill' import type { BillSummary } from '@/services/bill' import { ORDER_NAV_ITEMS } from '@/types/order' import { resolveAvatarUrl } from '@/utils/format' -import type { UserType } from '@/types/user' import './index.less' /** 菜单项(订单/账单入口已由上方专区承载,后续单独页面开发时在此追加) */ @@ -38,9 +37,9 @@ export default function ProfilePage() { const loggedIn = !!token && !!user - /** 功能菜单(门店账号追加「门店信息」「支付记录」入口) */ + /** 功能菜单(登录门店可用:门店信息 / 支付记录 / 修改密码) */ const menuItems = useMemo(() => { - if (!user?.store) return MENU_ITEMS + if (!loggedIn) return MENU_ITEMS return [ { key: 'store-info', @@ -54,9 +53,15 @@ export default function ProfilePage() { icon: 'balance-o', onClick: () => Taro.navigateTo({ url: '/pages/payment-records/index' }), }, + { + key: 'change-password', + label: '修改密码', + icon: 'lock', + onClick: () => Taro.navigateTo({ url: '/pages/change-password/index' }), + }, ...MENU_ITEMS, ] - }, [user?.store]) + }, [loggedIn]) useDidShow(() => { if (!loggedIn) return @@ -70,13 +75,6 @@ export default function ProfilePage() { .catch(() => {}) }) - /** 身份标签 */ - const getTypeLabel = useCallback((type: UserType): string => { - if (type === 1) return '门店' - if (type === 2) return '供应商' - return '待绑定' - }, []) - /** 订单总汇 → 订单列表页(按状态) */ const handleOrderNav = useCallback((status?: number) => { Taro.navigateTo({ url: `/pages/order-list/index?status=${status ?? 'all'}` }) @@ -130,29 +128,18 @@ export default function ProfilePage() { /> ) : ( - {user?.nickname?.[0] || '用'} + {user?.name?.[0] || '店'} )} - {user?.nickname} - {user?.phone || '未绑定手机号'} + {user?.name} + {user?.phone || '未设置联系电话'} - {user?.type === 0 && ( - 绑定手机号 - )} - {user?.store ? ( - <> - 门店 · {user.store.name} - {user.store.level && ( - {user.store.level.name} - )} - - ) : user?.supplier ? ( - 供应商 · {user.supplier.name} - ) : ( - {getTypeLabel(user?.type ?? 0)},联系客服或绑定手机号 + 门店编码 · {user?.code} + {user?.level && ( + {user.level.name} )} diff --git a/src/pages/register/index.config.ts b/src/pages/register/index.config.ts deleted file mode 100644 index 0a728e8..0000000 --- a/src/pages/register/index.config.ts +++ /dev/null @@ -1,4 +0,0 @@ -export default definePageConfig({ - navigationStyle: 'custom', - navigationBarTitleText: '注册', -}) diff --git a/src/pages/register/index.less b/src/pages/register/index.less deleted file mode 100644 index 2058bbc..0000000 --- a/src/pages/register/index.less +++ /dev/null @@ -1,196 +0,0 @@ -/* ======================================== - 注册页面 - ======================================== */ - -.register-page { - min-height: 100vh; - background: #fff; -} - -/* ========== 内容区域 ========== */ -.register-content { - display: flex; - flex-direction: column; - align-items: center; - padding: 80px 60px 0; -} - -/* ========== 品牌区域 ========== */ -.register-brand { - display: flex; - flex-direction: column; - align-items: center; - margin-bottom: 60px; - - .logo-wrapper { - width: 160px; - height: 160px; - border-radius: 50%; - background: linear-gradient(160deg, #ee0a24 0%, #ff4d4f 100%); - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 24px; - box-shadow: 0 8px 32px rgba(238, 10, 36, 0.3); - } - - .logo-text { - font-size: 80px; - color: #fff; - font-weight: 700; - } - - .app-name { - font-size: 44px; - font-weight: 600; - color: #323233; - margin-bottom: 12px; - } - - .app-slogan { - font-size: 28px; - color: #969799; - } -} - -/* ========== 注册表单 ========== */ -.register-form { - width: 100%; - background: #f7f8fa; - border-radius: 24px; - padding: 0 32px; - margin-bottom: 80px; -} - -.form-item { - display: flex; - align-items: center; - height: 112px; - border-bottom: 1px solid #ebedf0; - - &:last-child { - border-bottom: none; - } -} - -.form-label { - width: 160px; - font-size: 30px; - color: #323233; - flex-shrink: 0; -} - -.form-input { - flex: 1; - height: 100%; - font-size: 30px; - color: #323233; -} - -.form-input-placeholder { - color: #c8c9cc; -} - -/* 手机号已授权状态 */ -.form-phone-ok { - flex: 1; - display: flex; - align-items: center; - - .form-phone-ok__text { - font-size: 30px; - color: #07c160; - } -} - -/* 手机号授权按钮(微信原生 Button 需重置样式) */ -.phone-auth-btn { - flex: 1; - height: 64px; - line-height: 64px; - background: #fff0f0; - color: #ee0a24; - font-size: 28px; - font-weight: 500; - border: none; - border-radius: 32px; - text-align: center; - padding: 0 32px; - - /* 重置微信 Button 默认样式 */ - &::after { - border: none; - } -} - -/* ========== 注册操作区 ========== */ -.register-actions { - width: 100%; - display: flex; - flex-direction: column; - align-items: center; -} - -.register-btn { - width: 100%; - height: 96px; - line-height: 96px; - background: linear-gradient(160deg, #ee0a24 0%, #ff4d4f 100%); - color: #fff; - font-size: 34px; - font-weight: 500; - border: none; - border-radius: 48px; - text-align: center; - padding: 0; - box-shadow: 0 6px 24px rgba(238, 10, 36, 0.35); - transition: opacity 0.2s; - - /* 重置微信 Button 默认样式 */ - &::after { - border: none; - } -} - -.register-btn--loading { - opacity: 0.75; -} - -/* ========== 去登录入口 ========== */ -.register-switch { - display: flex; - align-items: center; - justify-content: center; - margin-top: 32px; - - .switch-text { - font-size: 28px; - color: #969799; - } - - .switch-link { - font-size: 28px; - color: #ee0a24; - margin-left: 8px; - } -} - -/* ========== 协议文字 ========== */ -.register-agreement { - display: flex; - align-items: center; - justify-content: center; - flex-wrap: wrap; - margin-top: 32px; - line-height: 1.6; - - .agree-text { - font-size: 24px; - color: #c8c9cc; - } - - .agree-link { - font-size: 24px; - color: #ee0a24; - } -} diff --git a/src/pages/register/index.tsx b/src/pages/register/index.tsx deleted file mode 100644 index 08d4b79..0000000 --- a/src/pages/register/index.tsx +++ /dev/null @@ -1,222 +0,0 @@ -import { useCallback, useEffect, useState } from 'react' -import Taro from '@tarojs/taro' -import { View, Text, Button, Input } from '@tarojs/components' -import CustomNavBar from '@/components/NavBar' -import useAuthStore from '@/stores/auth/useAuthStore' -import './index.less' - -export default function RegisterPage() { - const register = useAuthStore(s => s.register) - const isLoggedIn = useAuthStore(s => !!s.token && !!s.user) - - /** 门店编码(后台门店管理维护) */ - const [storeCode, setStoreCode] = useState('') - /** 微信手机号授权得到的 code */ - const [phoneCode, setPhoneCode] = useState('') - const [submitting, setSubmitting] = useState(false) - - const isWeb = Taro.getEnv() === Taro.ENV_TYPE.WEB - - /** 返回上一页(无页面栈时回首页) */ - const goBack = useCallback(() => { - const pages = Taro.getCurrentPages() - if (pages.length > 1) { - Taro.navigateBack() - } else { - Taro.switchTab({ url: '/pages/index/index' }) - } - }, []) - - /** 前往登录页 */ - const goLogin = useCallback(() => { - const pages = Taro.getCurrentPages() - if (pages.length > 1) { - Taro.navigateBack() - } else { - Taro.navigateTo({ url: '/pages/login/index' }) - } - }, []) - - /** 已注册成功(登录态就绪)→ 自动返回 */ - useEffect(() => { - if (isLoggedIn) goBack() - }, [isLoggedIn, goBack]) - - /** 发起注册:wx.login 换 code → POST /mini/auth/register */ - const doRegister = useCallback( - async (phoneCodeValue: string) => { - if (submitting) return - if (isWeb) { - Taro.showToast({ title: '请在微信小程序中注册', icon: 'none' }) - return - } - const code = storeCode.trim() - if (!code) { - Taro.showToast({ title: '请填写门店编码', icon: 'none' }) - return - } - setSubmitting(true) - try { - const res = await Taro.login() - if (!res.code) { - Taro.showToast({ title: '获取登录凭证失败', icon: 'none' }) - return - } - await register({ code: res.code, phoneCode: phoneCodeValue, storeCode: code }) - // 注册成功后由 effect 自动返回 - } catch (e: any) { - // 该微信已注册:引导前往登录(其余错误已由 request 层提示) - if (typeof e?.msg === 'string' && e.msg.includes('已经注册')) { - Taro.showModal({ - title: '提示', - content: '该微信已经注册,请直接登录', - confirmText: '去登录', - cancelText: '取消', - success: res => { - if (res.confirm) goLogin() - }, - }) - } - } finally { - setSubmitting(false) - } - }, - [register, submitting, isWeb, storeCode, goLogin], - ) - - /** 微信手机号授权(openType getPhoneNumber) */ - const handleGetPhoneNumber = useCallback( - (e: any) => { - if (isWeb) { - Taro.showToast({ title: '请在微信小程序中授权手机号', icon: 'none' }) - return - } - const detail = e.detail || {} - - // 用户拒绝授权 - if (detail.errMsg && !detail.errMsg.includes(':ok')) { - Taro.showToast({ title: '需要授权手机号才能注册', icon: 'none' }) - return - } - - if (!detail.code) { - Taro.showToast({ title: '未获取到手机号授权凭证', icon: 'none' }) - return - } - - setPhoneCode(detail.code) - if (storeCode.trim()) { - // 门店编码已填 → 直接发起注册 - doRegister(detail.code) - } else { - Taro.showToast({ title: '手机号已授权,请填写门店编码', icon: 'none' }) - } - }, - [isWeb, storeCode, doRegister], - ) - - /** 点击注册按钮(门店编码已填 + 手机号已授权) */ - const handleSubmit = useCallback(() => { - if (!phoneCode) { - Taro.showToast({ title: '请先授权手机号', icon: 'none' }) - return - } - if (!storeCode.trim()) { - Taro.showToast({ title: '请填写门店编码', icon: 'none' }) - return - } - doRegister(phoneCode) - }, [phoneCode, storeCode, doRegister]) - - /** 查看用户协议 */ - const handleShowAgreement = useCallback(() => { - Taro.showToast({ title: '用户协议即将上线', icon: 'none' }) - }, []) - - /** 查看隐私政策 */ - const handleShowPrivacy = useCallback(() => { - Taro.showToast({ title: '隐私政策即将上线', icon: 'none' }) - }, []) - - return ( - - {/* ========== 导航栏 ========== */} - - - {/* ========== 内容区域 ========== */} - - {/* 品牌区域 */} - - - - - 订货采购 - 注册即绑定门店,开启订货之旅 - - - {/* 注册表单 */} - - {/* 门店编码 */} - - 门店编码 - setStoreCode(e.detail.value)} - /> - - - {/* 手机号授权 */} - - 手机号 - {phoneCode ? ( - - 已授权 - - ) : ( - - )} - - - - {/* 注册操作 */} - - - - {/* 已注册用户入口 */} - - 已有账号? - 去登录 - - - - 注册即代表同意 - - 《用户协议》 - - - - 《隐私政策》 - - - - - - ) -} diff --git a/src/services/auth.ts b/src/services/auth.ts index 30229a1..89460ac 100644 --- a/src/services/auth.ts +++ b/src/services/auth.ts @@ -1,39 +1,42 @@ -import { get, post } from '@/utils/request' +import { get, post, put } from '@/utils/request' import type { User } from '@/types/user' -/** 微信登录参数 */ -export interface WxLoginParams { - /** wx.login 的临时凭证 */ - code: string +/** 账号密码登录参数 */ +export interface LoginParams { + /** 登录账号(商家后台分配,4~20 位) */ + username: string + /** 登录密码 */ + password: string } -/** 微信注册参数 */ -export interface RegisterParams { - /** wx.login 的临时凭证 */ - code: string - /** wx.getPhoneNumber 授权得到的 code */ - phoneCode: string - /** 门店编码(后台门店管理维护) */ - storeCode: string -} - -/** 登录 / 注册返回 */ +/** 登录返回 */ export interface AuthResult { token: string + /** 门店即用户(扁平结构) */ user: User } -/** 微信登录(仅已注册用户可登录):POST /mini/auth/login */ -export function wxLoginApi(params: WxLoginParams) { +/** 修改密码参数 */ +export interface ChangePasswordParams { + /** 原密码 */ + oldPassword: string + /** 新密码(6~20 位) */ + newPassword: string + /** 确认新密码(须与 newPassword 一致) */ + rePassword: string +} + +/** 账号密码登录:POST /mini/auth/login */ +export function loginApi(params: LoginParams) { return post('/mini/auth/login', params) } -/** 微信注册(code 换 openid + phoneCode 换手机号 + storeCode 绑定门店):POST /mini/auth/register */ -export function registerApi(params: RegisterParams) { - return post('/mini/auth/register', params) -} - -/** 当前用户信息(含门店客户等级):GET /mini/auth/info */ +/** 当前门店信息(含客户等级):GET /mini/auth/info */ export function getUserInfoApi() { return get('/mini/auth/info') } + +/** 修改密码(成功后现有 token 仍有效):PUT /mini/auth/password */ +export function changePasswordApi(params: ChangePasswordParams) { + return put('/mini/auth/password', params) +} diff --git a/src/stores/auth/useAuthStore.ts b/src/stores/auth/useAuthStore.ts index 24a5d81..053f19b 100644 --- a/src/stores/auth/useAuthStore.ts +++ b/src/stores/auth/useAuthStore.ts @@ -1,7 +1,7 @@ import { create } from 'zustand' import Taro from '@tarojs/taro' -import { registerApi, wxLoginApi } from '@/services/auth' -import type { RegisterParams, WxLoginParams } from '@/services/auth' +import { loginApi } from '@/services/auth' +import type { LoginParams } from '@/services/auth' import type { User } from '@/types/user' /** 存储 key */ @@ -26,7 +26,7 @@ function loadFromStorage(): { user: User | null; token: string | null } { return { user: null, token: null } } -/** 登录 / 注册成功后持久化 token 与用户信息 */ +/** 登录成功后持久化 token 与门店信息 */ function persistAuth(token: string, user: User): void { try { Taro.setStorageSync(STORAGE_KEYS.TOKEN, token) @@ -40,11 +40,10 @@ interface AuthState { user: User | null token: string | null loading: boolean - login: (params: WxLoginParams) => Promise - /** 微信注册(手机号授权 + 门店编码绑定门店) */ - register: (params: RegisterParams) => Promise + /** 账号密码登录(门店账号由商家后台分配) */ + login: (params: LoginParams) => Promise logout: () => void - /** 更新用户信息(用于编辑资料后同步 store) */ + /** 更新门店信息(用于编辑资料后同步 store) */ setUser: (user: User) => void } @@ -57,17 +56,9 @@ const useAuthStore = create((set) => { token: initial.token, loading: !!(initial.token && initial.user), // 已恢复则立即 ready - /** 登录(仅已注册用户可登录,未注册由页面引导去注册) */ - login: async (params: WxLoginParams) => { - const res = await wxLoginApi(params) - const { token, user } = res.data - set({ user, token }) - persistAuth(token, user) - }, - - /** 注册:POST /mini/auth/register */ - register: async (params: RegisterParams) => { - const res = await registerApi(params) + /** 账号密码登录:POST /mini/auth/login */ + login: async (params: LoginParams) => { + const res = await loginApi(params) const { token, user } = res.data set({ user, token }) persistAuth(token, user) diff --git a/src/types/user.ts b/src/types/user.ts index 3786e9d..f638deb 100644 --- a/src/types/user.ts +++ b/src/types/user.ts @@ -4,54 +4,33 @@ export interface StoreLevel { name: string } -/** 门店信息 */ -export interface StoreInfo { - id: number - name: string - /** 客户等级(level_id > 0 才可展示价格) */ - level: StoreLevel | null -} - -/** 供应商信息 */ -export interface SupplierInfo { - id: number - name: string -} - -/** 用户类型:0 待绑定 / 1 门店 / 2 供应商 */ -export type UserType = 0 | 1 | 2 - -export const USER_TYPE_MAP: Record = { - 0: '待绑定', - 1: '门店', - 2: '供应商', -} - -/** 用户信息(user 表实际返回字段) */ +/** + * 登录门店信息(门店即用户) + * 用户表与门店表已合并:登录 / auth/info 返回的 user 就是门店本身(扁平结构) + */ export interface User { id: number - /** 用户名(注册时生成 wx_xxxx) */ + /** 门店名称 */ + name: string + /** 门店编码(后台分配) */ + code: string + /** 登录账号(后台分配,4~20 位) */ username: string - /** 昵称(注册默认「微信用户」) */ - nickname: string + /** 头像(可能为空) */ avatar: string - /** 手机号(未绑定为空) */ + level_id: number + /** 客户等级(level_id > 0 才可展示价格) */ + level: StoreLevel | null + /** 联系人 */ + contact: string + /** 联系电话 */ phone: string - /** 绑定门店ID(0 未绑定) */ - store_id: number + /** 地址 */ + address: string + /** 回款周期天数 */ + payment_cycle_days: number /** 1 正常 / 0 停用 */ status: number - /** 微信标识 */ - openid: string - unionid: string - email: string last_login_at: string | null created_at: string | null - updated_at: string | null - /** 兼容旧 /mini/auth/info 返回(身份类型) */ - type?: UserType - /** 兼容旧 /mini/auth/info 返回(门店信息) */ - store?: StoreInfo | null - /** 兼容旧 /mini/auth/info 返回(供应商信息) */ - supplier?: SupplierInfo | null }