feat(passport): 支持邮箱和用户ID登录合并账号登录
- LoginParam 接口新增 email 和 userId 字段 - 新增 loginByEmail 和 loginByUserId 接口调用,逻辑与 login 类似 - 登录页账号输入框改为 account,支持输入邮箱或用户ID - 提交时根据账号格式(邮箱或纯数字)调用对应登录接口 - 校验规则改为校验 account 字段,格式不符时提示错误 - 手机号短信登录改用 loginBySuperAdminSms 接口替代 loginBySms - 登录成功后保存租户ID和用户ID至 localStorage - 优化登录页相关导入及逻辑,提升登录体验
This commit is contained in:
40
.workbuddy/memory/2026-07-18.md
Normal file
40
.workbuddy/memory/2026-07-18.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# 2026-07-18 工作日志
|
||||
|
||||
## 手机号登录改用 loginBySuperAdminSms 接口
|
||||
|
||||
### 改动文件
|
||||
1. `src/api/passport/login/index.ts`
|
||||
- 新增 `loginBySuperAdminSms()` 方法,调用 `/loginBySuperAdminSms` 接口
|
||||
- 保留原有 `loginBySms()` 方法(其他页面如 register/dealer 仍在使用)
|
||||
- 新方法逻辑与 `loginBySms` 一致:成功后 setToken + 存 TenantId/UserId
|
||||
|
||||
2. `src/views/passport/login/index.vue`
|
||||
- import 替换:`loginBySms` → `loginBySuperAdminSms`
|
||||
- `onLoginBySms()` 函数中调用替换:`loginBySms(form)` → `loginBySuperAdminSms(form)`
|
||||
- 多租户选择逻辑(`listAdminsByPhoneAll`)保持不变
|
||||
|
||||
### 注意
|
||||
- 仅改了管理后台登录页,注册页面(register/dealer)仍用 `loginBySms`
|
||||
|
||||
## 账号登录合并邮箱/用户ID登录
|
||||
|
||||
### 需求
|
||||
账号登录输入框同时支持「邮箱」和「用户ID」:邮箱 → `https://server.websoft.top/api/loginByEmail`,纯数字 → `https://server.websoft.top/api/loginByUserId`。
|
||||
|
||||
### 改动文件
|
||||
1. `src/api/passport/login/model/index.ts`
|
||||
- `LoginParam` 新增 `email?: string` 和 `userId?: string | number`
|
||||
|
||||
2. `src/api/passport/login/index.ts`
|
||||
- 新增 `loginByEmail()` / `loginByUserId()`,逻辑同 `login()`(setToken + 存 TenantId/UserId)
|
||||
|
||||
3. `src/views/passport/login/index.vue`
|
||||
- 表单字段 `userId` → `account`(新增 `LoginForm = User & { account?: string }` 类型)
|
||||
- 输入框 placeholder 改为「邮箱 / 用户ID」,form-item name 改为 `account`
|
||||
- 校验规则 `userId` → `account`
|
||||
- `submit()` 用正则判断邮箱(`/^[^\s@]+@[^\s@]+\.[^\s@]+$/`) / 纯数字(`/^\d+$/`),路由到对应接口;格式不符提示「请输入正确的邮箱或用户ID」
|
||||
- 移除未使用的 `login` 导入
|
||||
|
||||
### 注意
|
||||
- 外部接口用绝对 URL(`https://server.websoft.top/api/...`),未走 SERVER_API_URL 代理
|
||||
- `vue-tsc` 全量检查仍有大量历史错误(ByteMdEditor、shopActivity 等),本次改动无新增错误
|
||||
@@ -31,6 +31,48 @@ export async function login(data: LoginParam) {
|
||||
return Promise.reject(new Error(res.data.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮箱登录
|
||||
*/
|
||||
export async function loginByEmail(data: LoginParam) {
|
||||
const res = await request.post<ApiResult<LoginResult>>(
|
||||
'https://server.websoft.top/api/loginByEmail',
|
||||
data
|
||||
);
|
||||
if (res.data.code === 0) {
|
||||
setToken(res.data.data?.access_token, data.remember);
|
||||
if (res.data.data?.user) {
|
||||
const user = res.data.data?.user;
|
||||
localStorage.setItem('TenantId', String(user.tenantId));
|
||||
localStorage.setItem('UserId', String(user.userId));
|
||||
}
|
||||
|
||||
return res.data.message;
|
||||
}
|
||||
return Promise.reject(new Error(res.data.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户ID登录
|
||||
*/
|
||||
export async function loginByUserId(data: LoginParam) {
|
||||
const res = await request.post<ApiResult<LoginResult>>(
|
||||
'https://server.websoft.top/api/loginByUserId',
|
||||
data
|
||||
);
|
||||
if (res.data.code === 0) {
|
||||
setToken(res.data.data?.access_token, data.remember);
|
||||
if (res.data.data?.user) {
|
||||
const user = res.data.data?.user;
|
||||
localStorage.setItem('TenantId', String(user.tenantId));
|
||||
localStorage.setItem('UserId', String(user.userId));
|
||||
}
|
||||
|
||||
return res.data.message;
|
||||
}
|
||||
return Promise.reject(new Error(res.data.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取验证码
|
||||
*/
|
||||
@@ -62,6 +104,27 @@ export async function loginBySms(data: LoginParam) {
|
||||
return Promise.reject(new Error(res.data.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 超管手机号短信登录
|
||||
*/
|
||||
export async function loginBySuperAdminSms(data: LoginParam) {
|
||||
const res = await request.post<ApiResult<LoginResult>>(
|
||||
SERVER_API_URL + '/loginBySuperAdminSms',
|
||||
data
|
||||
);
|
||||
if (res.data.code === 0) {
|
||||
setToken(res.data.data?.access_token, data.remember);
|
||||
if (res.data.data?.user) {
|
||||
const user = res.data.data?.user;
|
||||
localStorage.setItem('TenantId', String(user.tenantId));
|
||||
localStorage.setItem('UserId', String(user.userId));
|
||||
}
|
||||
|
||||
return res.data.message;
|
||||
}
|
||||
return Promise.reject(new Error(res.data.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送短信验证码
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,10 @@ import type { User } from '@/api/system/user/model';
|
||||
export interface LoginParam {
|
||||
// 账号
|
||||
username?: string;
|
||||
// 邮箱
|
||||
email?: string;
|
||||
// 用户ID
|
||||
userId?: string | number;
|
||||
// 密码
|
||||
password?: string;
|
||||
// 租户id
|
||||
|
||||
@@ -77,12 +77,12 @@
|
||||
<!-- </template>-->
|
||||
<!-- </a-input>-->
|
||||
<!-- </a-form-item>-->
|
||||
<a-form-item name="username">
|
||||
<a-form-item name="account">
|
||||
<a-input
|
||||
allow-clear
|
||||
size="large"
|
||||
v-model:value="form.userId"
|
||||
:placeholder="`用户ID`"
|
||||
v-model:value="form.account"
|
||||
placeholder="邮箱 / 用户ID"
|
||||
>
|
||||
<template #prefix>
|
||||
<UserOutlined />
|
||||
@@ -278,7 +278,12 @@
|
||||
RightOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import { goHomeRoute, cleanPageTabs } from '@/utils/page-tab-util';
|
||||
import { login, loginBySms, getCaptcha } from '@/api/passport/login';
|
||||
import {
|
||||
loginBySuperAdminSms,
|
||||
getCaptcha,
|
||||
loginByEmail,
|
||||
loginByUserId
|
||||
} from '@/api/passport/login';
|
||||
import QrLogin from '@/components/QrLogin/index.vue';
|
||||
|
||||
import { User } from '@/api/system/user/model';
|
||||
@@ -346,8 +351,10 @@
|
||||
console.warn('获取网站配置失败,使用默认配置:', e.message);
|
||||
}
|
||||
};
|
||||
const { form } = useFormData<User>({
|
||||
userId: undefined,
|
||||
type LoginForm = User & { account?: string };
|
||||
|
||||
const { form } = useFormData<LoginForm>({
|
||||
account: '',
|
||||
username: '',
|
||||
phone: '',
|
||||
password: '',
|
||||
@@ -383,7 +390,7 @@
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
userId: [
|
||||
account: [
|
||||
{
|
||||
required: true,
|
||||
message: t('login.username'),
|
||||
@@ -479,7 +486,7 @@
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
form.code = form.smsCode?.toLowerCase();
|
||||
loginBySms(form)
|
||||
loginBySuperAdminSms(form)
|
||||
.then((msg) => {
|
||||
if (msg == '请选择登录用户') {
|
||||
showSelectLoginUser.value = true;
|
||||
@@ -524,10 +531,25 @@
|
||||
// changeCaptcha();
|
||||
// return;
|
||||
// }
|
||||
const account = (form.account || '').trim();
|
||||
// 邮箱格式判断
|
||||
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(account);
|
||||
// 纯数字判断(用户ID)
|
||||
const isPureNumber = /^\d+$/.test(account);
|
||||
if (!isEmail && !isPureNumber) {
|
||||
message.error('请输入正确的邮箱或用户ID');
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
form.code = form.code?.toLowerCase();
|
||||
form.phone = undefined;
|
||||
login(form)
|
||||
const payload = {
|
||||
password: form.password,
|
||||
code: form.code?.toLowerCase(),
|
||||
remember: form.remember
|
||||
};
|
||||
const loginApi = isEmail
|
||||
? loginByEmail({ ...payload, email: account })
|
||||
: loginByUserId({ ...payload, userId: account });
|
||||
loginApi
|
||||
.then((msg) => {
|
||||
if (msg == '请选择登录用户') {
|
||||
showSelectLoginUser.value = true;
|
||||
|
||||
119
今日改动总结-2026-07-17.txt
Normal file
119
今日改动总结-2026-07-17.txt
Normal file
@@ -0,0 +1,119 @@
|
||||
=========================================================================
|
||||
2026-07-17 今日改动问题点总结
|
||||
=========================================================================
|
||||
|
||||
【一】管理后台(guilixu-admin)
|
||||
|
||||
1. 发货弹窗新增「发货门店」「配送店员」选择功能
|
||||
- 文件:src/views/shop/shopOrder/components/deliveryModal.vue
|
||||
- 新增发货门店下拉(复用 listShopStore),选中后自动回填
|
||||
发货人/电话/地址
|
||||
- 商家送货(deliveryType=2)新增配送店员二级联动下拉
|
||||
- 新增校验:发货门店必填(deliveryType≠1)、配送店员必填(deliveryType=2)
|
||||
- 提交时附带 sendStoreId / deliveryUserId
|
||||
|
||||
2. 发货弹窗文案优化
|
||||
- 文件:src/views/shop/shopOrder/components/deliveryModal.vue
|
||||
- 「发货门店」标签动态化:快递配送→发货门店,商家送货→配送门店
|
||||
- 「发货人」标签动态化:快递配送→寄件人,商家送货→发货人
|
||||
- 提示文案、验证规则文案同步动态化
|
||||
- 快递配送时增加"寄件人信息将同步至快递面单"说明
|
||||
|
||||
3. 订单模型字段补充
|
||||
- 文件:src/api/shop/shopOrder/model/index.ts
|
||||
- 新增 sendStoreId、deliveryUserId 字段
|
||||
|
||||
4. 订单详情页展示发货门店/配送店员
|
||||
- 文件:src/views/shop/shopOrder/components/orderInfo.vue
|
||||
- 发货信息卡片增加「发货门店」「配送店员」展示
|
||||
- 支付状态标签新增「已发货待收款」(payType=9 && payStatus=0 && deliveryStatus=20)
|
||||
- 步骤条逻辑:线下付款未付款但已发货时显示「下单→待收款→已发货」
|
||||
|
||||
5. 线下付款先发货后结款流程
|
||||
- 文件:src/views/shop/shopOrder/index.vue
|
||||
- 线下付款未付款订单按发货状态区分操作按钮:
|
||||
· deliveryStatus=10:显示「确认收款」+「发货」+「关闭」
|
||||
· deliveryStatus=20:仅显示「确认收款」
|
||||
- 文件:src/views/shop/shopOrder/components/OfflinePaymentModal.vue
|
||||
- 新增 deliveryStatus 字段及动态提示文案
|
||||
- 成功消息动态化:已发货→「已自动完成」,未发货→「已进入待发货状态」
|
||||
|
||||
6. 配送方式排序调整
|
||||
- 文件:src/views/shop/shopOrder/components/deliveryModal.vue
|
||||
- radio 顺序改为:快递配送→商家送货→无需发货
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
【二】后端 Java(guilixu-java)
|
||||
|
||||
1. shop_order 主表新增字段
|
||||
- ShopOrder.java:新增 sendStoreId、deliveryUserId 持久化字段
|
||||
及 sendStoreName、deliveryUserName 虚拟展示字段
|
||||
- ShopOrderMapper.xml:LEFT JOIN shop_store / shop_store_user 联带名称
|
||||
- SQL:ALTER TABLE shop_order ADD send_store_id INT, delivery_user_id INT
|
||||
|
||||
2. shop_order_delivery 发货单表新增字段
|
||||
- ShopOrderDelivery.java:新增 sendStoreId、deliveryUserId
|
||||
- ShopOrderController.update():发货写入分支(无需物流/实物快递/补录运单号)
|
||||
均 setSendStoreId / setDeliveryUserId
|
||||
- SQL:ALTER TABLE shop_order_delivery ADD send_store_id INT, delivery_user_id INT
|
||||
|
||||
3. 线下付款确认收款逻辑调整
|
||||
- ShopOrderServiceImpl.confirmOfflinePayment():移除订单状态=0约束,
|
||||
允许已发货订单确认收款;已发货(deliveryStatus=20)时确认后自动完成订单
|
||||
- ShopOrderController / ShopOrderService:更新接口描述和成功消息
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
【三】商家端小程序(xinlong-shop-taro)
|
||||
|
||||
1. 修复 storeId=0 导致发货人员列表为空的 Bug
|
||||
- 文件:src/pages/store/orders/index.tsx
|
||||
- 问题根因:openShipModal 调 listShopStoreUser() 未传 storeId(默认0)
|
||||
- 修复:先 getMyClerk() 取 storeId,再 listShopStoreUser({storeId})
|
||||
- 默认选中当前登录人对应的店员
|
||||
|
||||
2. 修复订单详情页配送方式判断逻辑
|
||||
- 文件:src/pages/order/detail.tsx
|
||||
- 问题:原 isExpress = deliveryType === 0 || undefined,无法区分商家送货
|
||||
- 修复:isExpress 改为 deliveryType === 0 || 2 || undefined
|
||||
- 新增 DELIVERY_TYPE_MAP:0=快递配送, 1=自提, 2=商家送货
|
||||
- 收货信息卡片:商家送货显示🛵+配送门店名,快递配送显示📦
|
||||
- 订单信息区新增「配送方式」字段展示
|
||||
|
||||
3. 支持线下付款先发货后结款
|
||||
- 文件:src/pages/store/orders/index.tsx
|
||||
- getStatusText():新增「已发货待收款」状态
|
||||
- getOrderActions():线下付款未付款(payType=9)也能显示发货按钮
|
||||
- OP_DESC:确认收款描述移除"订单将进入待发货状态"
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
【四】跨项目误改纠正(教训记录)
|
||||
|
||||
1. 误将商家端功能改到 guilixu-taro(用户端)
|
||||
- 错误改动:useClerk 全局上下文、订单详情 deliveryType 修复
|
||||
- 已用 git checkout 还原 guilixu-taro 的 5 个跟踪文件
|
||||
- 已删除 guilixu-taro 新建的 2 个文件(ClerkContext.tsx / useClerk.ts)
|
||||
- 正确项目:xinlong-shop-taro(商家端)
|
||||
|
||||
2. 教训:跨项目改动前,先在多个候选项目里确认"哪个项目有该功能源码"
|
||||
商家端发货/门店/订单 → xinlong-shop-taro
|
||||
用户端订单详情等 → guilixu-taro
|
||||
|
||||
=========================================================================
|
||||
今日 Git 提交记录
|
||||
=========================================================================
|
||||
|
||||
bef50c2 feat(order): 支持线下付款先发货后结款流程
|
||||
57be388 fix(xinlong-shop-taro): 修复订单详情页配送方式判断逻辑
|
||||
bd814d0 feat(shop): 优化发货弹窗文案及修复小程序配送方式判断
|
||||
3edbb13 fix(orders): 修正发货功能关联的项目错误导致 storeId 为 0
|
||||
b406973 feat(store): 修正 storeId 获取并新增发货人员选择功能
|
||||
2745f4b feat(shopOrder): 增加发货门店与配送店员选择功能
|
||||
e9249c9 feat(shopOrder): 增加发货门店与配送店员选择功能
|
||||
6b57dd2 fix(shopOrder): 修正确认收货状态码
|
||||
|
||||
=========================================================================
|
||||
生成时间:2026-07-17 18:18
|
||||
=========================================================================
|
||||
Reference in New Issue
Block a user