fix:完善门店和总部管理端

This commit is contained in:
ljy
2026-07-06 20:58:38 +08:00
parent 67b5a580c5
commit fcf1d45522
25 changed files with 1273 additions and 118 deletions
+7 -27
View File
@@ -1,4 +1,5 @@
import type { WechatLoginResult } from '@dukang/shared-types';
import { WECHAT_INAPP_REQUIRED_MSG } from '@dukang/weixin-sdk';
import { isWechatEnv, weixinSdk } from './weixin';
import { request, saveAuth } from './api';
@@ -31,37 +32,16 @@ export async function handlePartnerWechatCallback(): Promise<WechatLoginResult |
return weixinSdk.handleOAuthCallback();
}
let clientConfigCache: { mockWechat?: boolean } | null = null;
async function fetchClientConfig(): Promise<{ mockWechat?: boolean }> {
if (clientConfigCache) return clientConfigCache;
try {
clientConfigCache = await request<{ mockWechat?: boolean }>('PARTNER_H5', '/common/client-config');
} catch {
clientConfigCache = {};
}
return clientConfigCache;
}
/**
* 微信授权登录( C 端一致:微信内走公众号 OAuth)。
* 微信授权登录(对齐 C 端:仅微信内置浏览器走 OAuth)。
* 返回 true = 已登录;void = 已跳转授权页等待回调。
*/
export async function loginPartnerWithWechat(): Promise<boolean | void> {
if (isWechatEnv()) {
const result = await weixinSdk.login();
if (result) return handlePartnerWechatLoginResult(result);
return;
if (!isWechatEnv()) {
throw new Error(WECHAT_INAPP_REQUIRED_MSG);
}
const cfg = await fetchClientConfig();
if (!cfg.mockWechat) {
throw new Error('请在微信内打开以使用微信一键授权');
}
const result = await request<WechatLoginResult>('PARTNER_H5', '/partner/auth/login/wechat', {
method: 'POST',
body: JSON.stringify({ code: `mockcode_${Date.now()}`, platform: 'h5' }),
});
return handlePartnerWechatLoginResult(result);
const result = await weixinSdk.login();
if (result) return handlePartnerWechatLoginResult(result);
}
/**
@@ -74,7 +54,7 @@ export async function bindPartnerWechatAfterSmsLogin(): Promise<void> {
export async function authorizePartnerWechat(): Promise<WechatLoginResult | void> {
if (!isWechatEnv()) {
throw new Error('请在微信内打开以完成授权');
throw new Error(WECHAT_INAPP_REQUIRED_MSG);
}
return weixinSdk.login();
}
+6 -1
View File
@@ -8,6 +8,7 @@ import {
loginPartnerWithWechat,
} from '../lib/wechat-auth';
import { isWechatEnv } from '../lib/weixin';
import { WECHAT_INAPP_REQUIRED_MSG } from '@dukang/weixin-sdk';
const REMEMBER_PHONE_KEY = 'partner_remember_phone';
const REMEMBER_FLAG_KEY = 'partner_remember_account';
@@ -132,6 +133,10 @@ export default function LoginPage() {
async function wechatLogin() {
if (!ensureAgreed()) return;
setMsg('');
if (!isWechatEnv()) {
setMsg(WECHAT_INAPP_REQUIRED_MSG);
return;
}
setWxLoading(true);
try {
const ok = await loginPartnerWithWechat();
@@ -230,7 +235,7 @@ export default function LoginPage() {
<svg viewBox="0 0 24 24" fill="#07C160" aria-hidden>
<path d="M8.25 4.5C4.52 4.5 1.5 7.04 1.5 10.17c0 1.78.98 3.37 2.5 4.48l-.63 1.88 2.19-1.09c.84.24 1.74.38 2.69.38.25 0 .5 0 .75-.03-.16-.53-.25-1.09-.25-1.66 0-3.13 3.02-5.67 6.75-5.67.57 0 1.13.06 1.66.17C15.17 6.13 12 4.5 8.25 4.5zm10.5 6.33c-3.11 0-5.62 2.12-5.62 4.73 0 2.61 2.51 4.73 5.62 4.73.79 0 1.54-.14 2.24-.38l1.83.91-.53-1.57c1.27-.92 2.08-2.25 2.08-3.73 0-2.61-2.51-4.73-5.62-4.73z" />
</svg>
<span>{wxLoading ? '登录中...' : '微信一键登录'}</span>
<span>{wxLoading ? '登录中...' : '微信一键授权'}</span>
</button>
<label className="partner-checkbox-row">
<input type="checkbox" checked={agreed} onChange={(e) => setAgreed(e.target.checked)} />
+61 -12
View File
@@ -6,6 +6,10 @@ html, body, #root {
max-width: 100%;
}
html {
scrollbar-gutter: stable;
}
/* ── Partner auth ── */
.partner-auth-page {
min-height: 100vh;
@@ -733,30 +737,75 @@ html, body, #root {
flex-shrink: 0;
}
/* ── Partner bottom tabbar ── */
.app-tabbar {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* ── Partner bottom tabbar(锁定尺寸,仅切换颜色)── */
nav.app-tabbar {
display: flex;
flex-direction: row;
align-items: stretch;
justify-items: stretch;
padding: 8px 0 calc(8px + env(safe-area-inset-bottom, 0px));
justify-content: stretch;
padding: 0;
padding-bottom: env(safe-area-inset-bottom, 0px);
height: calc(56px + env(safe-area-inset-bottom, 0px));
box-sizing: border-box;
}
.app-tabbar-item {
flex: 1;
nav.app-tabbar .app-tabbar-item {
flex: 1 1 0;
min-width: 0;
width: 100%;
padding: 4px 2px;
max-width: 33.333%;
height: 56px;
padding: 6px 0 4px;
border-radius: 0;
gap: 2px;
color: var(--color-subtle-gray);
text-decoration: none;
transition: color 0.15s ease;
transform: none;
-webkit-tap-highlight-color: transparent;
touch-action: manipulation;
user-select: none;
}
nav.app-tabbar .app-tabbar-item.active {
color: var(--color-heritage-red);
}
nav.app-tabbar .app-tabbar-item:active,
nav.app-tabbar .app-tabbar-item:focus,
nav.app-tabbar .app-tabbar-item:focus-visible {
transform: none;
outline: none;
}
nav.app-tabbar .app-tabbar-icon {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: 24px;
height: 24px;
font-size: 24px;
line-height: 1;
overflow: hidden;
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
.app-tabbar-label {
max-width: 100%;
nav.app-tabbar .app-tabbar-label {
display: block;
flex-shrink: 0;
width: 100%;
height: 14px;
line-height: 14px;
margin: 0;
padding: 0 1px;
font-size: 11px;
font-weight: 500;
letter-spacing: 0;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
box-sizing: border-box;
}
/* ── Store create stepper ── */