Compare commits
2 Commits
a49d8d99b6
...
e2fd28a35b
| Author | SHA1 | Date | |
|---|---|---|---|
| e2fd28a35b | |||
| 15c35c49de |
@@ -6,7 +6,6 @@ export type StoreDraftForm = {
|
|||||||
district: string;
|
district: string;
|
||||||
name: string;
|
name: string;
|
||||||
phone: string;
|
phone: string;
|
||||||
storeSmsCode: string;
|
|
||||||
address: string;
|
address: string;
|
||||||
/** 门店坐标(定位或地理编码) */
|
/** 门店坐标(定位或地理编码) */
|
||||||
latitude: string;
|
latitude: string;
|
||||||
@@ -50,7 +49,6 @@ export const defaultStoreForm = (): StoreDraftForm => ({
|
|||||||
cityId: '',
|
cityId: '',
|
||||||
name: '',
|
name: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
storeSmsCode: '',
|
|
||||||
address: '',
|
address: '',
|
||||||
latitude: '',
|
latitude: '',
|
||||||
longitude: '',
|
longitude: '',
|
||||||
@@ -218,7 +216,7 @@ export function patchEnvPhotoAt(urls: string[], index: number, url: string): str
|
|||||||
export function validateStoreStep3(
|
export function validateStoreStep3(
|
||||||
form: Pick<
|
form: Pick<
|
||||||
StoreDraftForm,
|
StoreDraftForm,
|
||||||
'bankAccountName' | 'bankAccountNo' | 'bankBranch' | 'phone' | 'storeSmsCode'
|
'bankAccountName' | 'bankAccountNo' | 'bankBranch' | 'phone'
|
||||||
>,
|
>,
|
||||||
): string | null {
|
): string | null {
|
||||||
if (!form.bankAccountName.trim()) return '请填写户主姓名';
|
if (!form.bankAccountName.trim()) return '请填写户主姓名';
|
||||||
@@ -227,7 +225,5 @@ export function validateStoreStep3(
|
|||||||
if (!form.bankBranch.trim()) return '请填写开户支行';
|
if (!form.bankBranch.trim()) return '请填写开户支行';
|
||||||
if (!form.phone.trim()) return '请填写联系电话';
|
if (!form.phone.trim()) return '请填写联系电话';
|
||||||
if (!PHONE_RE.test(form.phone.trim())) return '联系电话须为11位手机号';
|
if (!PHONE_RE.test(form.phone.trim())) return '联系电话须为11位手机号';
|
||||||
if (!form.storeSmsCode.trim()) return '请输入门店手机号验证码';
|
|
||||||
if (!/^\d{4,6}$/.test(form.storeSmsCode.trim())) return '验证码格式不正确';
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,4 @@ export function checkStorePhoneAvailable(phone: string) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sendStorePhoneSms(phone: string) {
|
|
||||||
return request<{ ok: boolean; maskedPhone: string }>('PARTNER_H5', '/partner/stores/send-phone-sms', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({ phone: phone.trim() }),
|
|
||||||
silent: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export type { PartnerStorePhoneAvailableResponse };
|
export type { PartnerStorePhoneAvailableResponse };
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { toastError, toastSuccess } from '../lib/toast';
|
|||||||
|
|
||||||
import { resolveRegionBinding } from '../lib/china-region';
|
import { resolveRegionBinding } from '../lib/china-region';
|
||||||
|
|
||||||
import { checkStorePhoneAvailable, sendStorePhoneSms } from '../lib/storePhone';
|
import { checkStorePhoneAvailable } from '../lib/storePhone';
|
||||||
|
|
||||||
import { formatStoreCoords, locateStorePosition } from '../lib/storeLocate';
|
import { formatStoreCoords, locateStorePosition } from '../lib/storeLocate';
|
||||||
|
|
||||||
@@ -55,7 +55,6 @@ type StoreCategoryNode = {
|
|||||||
|
|
||||||
type FieldErrors = {
|
type FieldErrors = {
|
||||||
phone?: string;
|
phone?: string;
|
||||||
storeSmsCode?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -70,7 +69,7 @@ function isPhoneConflictMessage(message: string) {
|
|||||||
|
|
||||||
function isPhoneValidationMessage(message: string) {
|
function isPhoneValidationMessage(message: string) {
|
||||||
|
|
||||||
return message.includes('联系电话') || message.includes('手机号') || message.includes('验证码');
|
return message.includes('联系电话') || message.includes('手机号');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,10 +99,6 @@ export default function StoreCreatePage() {
|
|||||||
|
|
||||||
const [citiesError, setCitiesError] = useState('');
|
const [citiesError, setCitiesError] = useState('');
|
||||||
|
|
||||||
const [smsCooldown, setSmsCooldown] = useState(0);
|
|
||||||
|
|
||||||
const [smsHint, setSmsHint] = useState('');
|
|
||||||
|
|
||||||
const [categoryTree, setCategoryTree] = useState<StoreCategoryNode[]>([]);
|
const [categoryTree, setCategoryTree] = useState<StoreCategoryNode[]>([]);
|
||||||
|
|
||||||
const [locating, setLocating] = useState(false);
|
const [locating, setLocating] = useState(false);
|
||||||
@@ -230,25 +225,13 @@ export default function StoreCreatePage() {
|
|||||||
|
|
||||||
setSubmitError('');
|
setSubmitError('');
|
||||||
|
|
||||||
let nextPatch = patch;
|
|
||||||
|
|
||||||
if ('phone' in patch) {
|
if ('phone' in patch) {
|
||||||
|
|
||||||
setFieldErrors((prev) => ({ ...prev, phone: undefined, storeSmsCode: undefined }));
|
setFieldErrors((prev) => ({ ...prev, phone: undefined }));
|
||||||
|
|
||||||
setSmsHint('');
|
|
||||||
|
|
||||||
nextPatch = { ...patch, storeSmsCode: '' };
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('storeSmsCode' in patch) {
|
setForm((prev) => ({ ...prev, ...patch }));
|
||||||
|
|
||||||
setFieldErrors((prev) => ({ ...prev, storeSmsCode: undefined }));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
setForm((prev) => ({ ...prev, ...nextPatch }));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,72 +291,6 @@ export default function StoreCreatePage() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function sendStorePhoneCode() {
|
|
||||||
|
|
||||||
const phone = form.phone.trim();
|
|
||||||
|
|
||||||
if (!/^1\d{10}$/.test(phone)) {
|
|
||||||
|
|
||||||
setFieldErrors({ phone: '请先填写正确的11位手机号' });
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
setSmsHint('');
|
|
||||||
|
|
||||||
setFieldErrors((prev) => ({ ...prev, phone: undefined }));
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
const phoneCheck = await checkStorePhoneAvailable(phone);
|
|
||||||
|
|
||||||
if (!phoneCheck.available) {
|
|
||||||
|
|
||||||
setFieldErrors({ phone: phoneCheck.message ?? '该手机号不可用于门店账号' });
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await sendStorePhoneSms(phone);
|
|
||||||
|
|
||||||
setSmsHint(`验证码已发送至 ${res.maskedPhone}`);
|
|
||||||
|
|
||||||
setSmsCooldown(60);
|
|
||||||
|
|
||||||
const timer = setInterval(() => {
|
|
||||||
|
|
||||||
setSmsCooldown((s) => {
|
|
||||||
|
|
||||||
if (s <= 1) {
|
|
||||||
|
|
||||||
clearInterval(timer);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return s - 1;
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
|
|
||||||
const msg = e instanceof Error ? e.message : '验证码发送失败';
|
|
||||||
|
|
||||||
setFieldErrors({ phone: msg });
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function handleNext() {
|
async function handleNext() {
|
||||||
|
|
||||||
if (step === 1) {
|
if (step === 1) {
|
||||||
@@ -410,11 +327,7 @@ export default function StoreCreatePage() {
|
|||||||
|
|
||||||
if (msg) {
|
if (msg) {
|
||||||
if (isPhoneValidationMessage(msg)) {
|
if (isPhoneValidationMessage(msg)) {
|
||||||
if (msg.includes('验证码')) {
|
setFieldErrors({ phone: msg });
|
||||||
setFieldErrors({ storeSmsCode: msg });
|
|
||||||
} else {
|
|
||||||
setFieldErrors({ phone: msg });
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
reportFormError(msg);
|
reportFormError(msg);
|
||||||
@@ -510,8 +423,6 @@ export default function StoreCreatePage() {
|
|||||||
|
|
||||||
phone: form.phone.trim(),
|
phone: form.phone.trim(),
|
||||||
|
|
||||||
smsCode: form.storeSmsCode.trim(),
|
|
||||||
|
|
||||||
district: form.district.trim(),
|
district: form.district.trim(),
|
||||||
|
|
||||||
address: form.address.trim(),
|
address: form.address.trim(),
|
||||||
@@ -561,7 +472,6 @@ export default function StoreCreatePage() {
|
|||||||
setForm(defaultStoreForm());
|
setForm(defaultStoreForm());
|
||||||
setFieldErrors({});
|
setFieldErrors({});
|
||||||
setSubmitError('');
|
setSubmitError('');
|
||||||
setSmsHint('');
|
|
||||||
setParams({ step: '1' }, { replace: true });
|
setParams({ step: '1' }, { replace: true });
|
||||||
toastSuccess('门店录入成功');
|
toastSuccess('门店录入成功');
|
||||||
navigate(`/stores/${result.store.id}`);
|
navigate(`/stores/${result.store.id}`);
|
||||||
@@ -571,11 +481,6 @@ export default function StoreCreatePage() {
|
|||||||
setFieldErrors({ phone: message });
|
setFieldErrors({ phone: message });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (/验证码/.test(message)) {
|
|
||||||
setFieldErrors({ storeSmsCode: message });
|
|
||||||
goStep(3);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setSubmitError(message);
|
setSubmitError(message);
|
||||||
toastError(message);
|
toastError(message);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1201,74 +1106,11 @@ export default function StoreCreatePage() {
|
|||||||
|
|
||||||
<p className="label-md text-muted" style={{ marginTop: 8 }}>
|
<p className="label-md text-muted" style={{ marginTop: 8 }}>
|
||||||
|
|
||||||
该手机号将作为门店端登录账号,验证码发送至该号确认后方可提交。
|
该手机号将作为门店端登录账号。
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="partner-field">
|
|
||||||
|
|
||||||
<label>门店账号验证码 <span className="text-primary">*</span></label>
|
|
||||||
|
|
||||||
<div className="partner-input-row">
|
|
||||||
|
|
||||||
<div className="partner-input-wrap" style={{ flex: 1 }}>
|
|
||||||
|
|
||||||
<span className="material-symbols-outlined partner-input-icon">shield</span>
|
|
||||||
|
|
||||||
<input
|
|
||||||
|
|
||||||
className="partner-input"
|
|
||||||
|
|
||||||
type="text"
|
|
||||||
|
|
||||||
inputMode="numeric"
|
|
||||||
|
|
||||||
maxLength={6}
|
|
||||||
|
|
||||||
placeholder="请输入短信验证码"
|
|
||||||
|
|
||||||
value={form.storeSmsCode}
|
|
||||||
|
|
||||||
onChange={(e) => patchForm({ storeSmsCode: e.target.value.replace(/\D/g, '') })}
|
|
||||||
|
|
||||||
/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
|
||||||
|
|
||||||
type="button"
|
|
||||||
|
|
||||||
className="partner-code-btn"
|
|
||||||
|
|
||||||
disabled={smsCooldown > 0 || submitting}
|
|
||||||
|
|
||||||
onClick={() => void sendStorePhoneCode()}
|
|
||||||
|
|
||||||
>
|
|
||||||
|
|
||||||
{smsCooldown > 0 ? `${smsCooldown}s` : '获取验证码'}
|
|
||||||
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{smsHint && (
|
|
||||||
|
|
||||||
<p className="label-md text-muted" style={{ marginTop: 8 }}>{smsHint}</p>
|
|
||||||
|
|
||||||
)}
|
|
||||||
|
|
||||||
{fieldErrors.storeSmsCode && (
|
|
||||||
|
|
||||||
<p className="partner-field-error" role="alert">{fieldErrors.storeSmsCode}</p>
|
|
||||||
|
|
||||||
)}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</>
|
</>
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 518 KiB |
@@ -2,4 +2,6 @@ export default definePageConfig({
|
|||||||
navigationBarTitleText: '我的',
|
navigationBarTitleText: '我的',
|
||||||
enablePullDownRefresh: true,
|
enablePullDownRefresh: true,
|
||||||
backgroundTextStyle: 'dark',
|
backgroundTextStyle: 'dark',
|
||||||
|
enableShareAppMessage: true,
|
||||||
|
enableShareTimeline: true,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { View, Text, Image, Button, Input, ScrollView } from '@tarojs/components';
|
import { View, Text, Image, Button, Input, ScrollView } from '@tarojs/components';
|
||||||
import Taro, { useDidShow, usePullDownRefresh } from '@tarojs/taro';
|
import Taro, { useDidShow, usePullDownRefresh, useShareAppMessage, useShareTimeline } from '@tarojs/taro';
|
||||||
import {
|
import {
|
||||||
BRAND_LOGO_MARK_URL,
|
BRAND_LOGO_MARK_URL,
|
||||||
QUALIFICATION_DISCLOSURE_URL,
|
QUALIFICATION_DISCLOSURE_URL,
|
||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
} from '@dukang/shared-types';
|
} from '@dukang/shared-types';
|
||||||
import PageShell from '../../components/PageShell';
|
import PageShell from '../../components/PageShell';
|
||||||
import TabMainHeader from '../../components/TabMainHeader';
|
import TabMainHeader from '../../components/TabMainHeader';
|
||||||
|
import WechatShareReady from '../../components/WechatShareReady';
|
||||||
import UserTabBar, { shouldRenderPageTabBar, syncTabBarSelected } from '../../components/UserTabBar';
|
import UserTabBar, { shouldRenderPageTabBar, syncTabBarSelected } from '../../components/UserTabBar';
|
||||||
import { goLogin } from '../../lib/auth-nav';
|
import { goLogin } from '../../lib/auth-nav';
|
||||||
import { bindWechatForUser } from '../../lib/wechat-auth';
|
import { bindWechatForUser } from '../../lib/wechat-auth';
|
||||||
@@ -22,6 +23,11 @@ import {
|
|||||||
} from '../../lib/mini-wechat-profile';
|
} from '../../lib/mini-wechat-profile';
|
||||||
import { isLoggedIn, logout, request, toast, type UserProfile } from '../../lib/api';
|
import { isLoggedIn, logout, request, toast, type UserProfile } from '../../lib/api';
|
||||||
import { isWechatEnv } from '../../lib/weixin';
|
import { isWechatEnv } from '../../lib/weixin';
|
||||||
|
import {
|
||||||
|
DEFAULT_SHARE_DESC,
|
||||||
|
DEFAULT_SHARE_TITLE,
|
||||||
|
toWeappShareMessage,
|
||||||
|
} from '../../lib/wechat-share';
|
||||||
|
|
||||||
const ORDER_SHORTCUTS = [
|
const ORDER_SHORTCUTS = [
|
||||||
{ tab: 'pending_pay', icon: '付', label: '待付款' },
|
{ tab: 'pending_pay', icon: '付', label: '待付款' },
|
||||||
@@ -132,6 +138,21 @@ export default function MinePage() {
|
|||||||
.catch(() => setWxAuthorize(true));
|
.catch(() => setWxAuthorize(true));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const sharePayload = useMemo(
|
||||||
|
() => ({
|
||||||
|
title: '杜康好客 · 我的',
|
||||||
|
desc: DEFAULT_SHARE_DESC,
|
||||||
|
path: '/pages/mine/index',
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
useShareAppMessage(() => toWeappShareMessage(sharePayload));
|
||||||
|
useShareTimeline(() => ({
|
||||||
|
title: sharePayload.title || DEFAULT_SHARE_TITLE,
|
||||||
|
query: '',
|
||||||
|
}));
|
||||||
|
|
||||||
async function ensureWechatBound(): Promise<boolean> {
|
async function ensureWechatBound(): Promise<boolean> {
|
||||||
if (profile?.hasWechat) return true;
|
if (profile?.hasWechat) return true;
|
||||||
if (!wxAuthorize) {
|
if (!wxAuthorize) {
|
||||||
@@ -279,6 +300,7 @@ export default function MinePage() {
|
|||||||
if (!authed) {
|
if (!authed) {
|
||||||
return (
|
return (
|
||||||
<PageShell variant="tab" className="mine-page no-tab-header">
|
<PageShell variant="tab" className="mine-page no-tab-header">
|
||||||
|
<WechatShareReady payload={sharePayload} />
|
||||||
<TabMainHeader title="我的" />
|
<TabMainHeader title="我的" />
|
||||||
<View className="mine-header">
|
<View className="mine-header">
|
||||||
<View className="mine-header-texture" />
|
<View className="mine-header-texture" />
|
||||||
@@ -331,6 +353,7 @@ export default function MinePage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<PageShell variant="tab" className="mine-page no-tab-header">
|
<PageShell variant="tab" className="mine-page no-tab-header">
|
||||||
|
<WechatShareReady payload={sharePayload} />
|
||||||
<TabMainHeader title="我的" />
|
<TabMainHeader title="我的" />
|
||||||
<View className="mine-header">
|
<View className="mine-header">
|
||||||
<View className="mine-header-texture" />
|
<View className="mine-header-texture" />
|
||||||
@@ -533,7 +556,13 @@ export default function MinePage() {
|
|||||||
className="mine-qualification-mask"
|
className="mine-qualification-mask"
|
||||||
onClick={() => setQualificationOpen(false)}
|
onClick={() => setQualificationOpen(false)}
|
||||||
>
|
>
|
||||||
<ScrollView scrollY className="mine-qualification-scroll" enhanced showScrollbar>
|
<ScrollView
|
||||||
|
scrollY
|
||||||
|
className="mine-qualification-scroll"
|
||||||
|
style={{ height: '100%' }}
|
||||||
|
enhanced
|
||||||
|
showScrollbar
|
||||||
|
>
|
||||||
<Image
|
<Image
|
||||||
className="mine-qualification-img"
|
className="mine-qualification-img"
|
||||||
src={QUALIFICATION_DISCLOSURE_URL}
|
src={QUALIFICATION_DISCLOSURE_URL}
|
||||||
|
|||||||
@@ -2,4 +2,6 @@ export default definePageConfig({
|
|||||||
navigationBarTitleText: '门店',
|
navigationBarTitleText: '门店',
|
||||||
enablePullDownRefresh: true,
|
enablePullDownRefresh: true,
|
||||||
backgroundTextStyle: 'dark',
|
backgroundTextStyle: 'dark',
|
||||||
|
enableShareAppMessage: true,
|
||||||
|
enableShareTimeline: true,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { View, Text, Image, Input } from '@tarojs/components';
|
import { View, Text, Image, Input } from '@tarojs/components';
|
||||||
import Taro, { useDidShow, usePullDownRefresh } from '@tarojs/taro';
|
import Taro, { useDidShow, usePullDownRefresh, useShareAppMessage, useShareTimeline } from '@tarojs/taro';
|
||||||
import PageShell from '../../components/PageShell';
|
import PageShell from '../../components/PageShell';
|
||||||
import TabMainHeader from '../../components/TabMainHeader';
|
import TabMainHeader from '../../components/TabMainHeader';
|
||||||
|
import WechatShareReady from '../../components/WechatShareReady';
|
||||||
import RegionPicker from '../../components/RegionPicker';
|
import RegionPicker from '../../components/RegionPicker';
|
||||||
import CategoryPicker, {
|
import CategoryPicker, {
|
||||||
EMPTY_CATEGORY,
|
EMPTY_CATEGORY,
|
||||||
@@ -27,6 +28,11 @@ import {
|
|||||||
import { FALLBACK_CITY_CODE } from '../../lib/product-images';
|
import { FALLBACK_CITY_CODE } from '../../lib/product-images';
|
||||||
import { formatDistanceMeters } from '../../lib/geo';
|
import { formatDistanceMeters } from '../../lib/geo';
|
||||||
import { request, toast } from '../../lib/api';
|
import { request, toast } from '../../lib/api';
|
||||||
|
import {
|
||||||
|
DEFAULT_SHARE_DESC,
|
||||||
|
DEFAULT_SHARE_TITLE,
|
||||||
|
toWeappShareMessage,
|
||||||
|
} from '../../lib/wechat-share';
|
||||||
|
|
||||||
type Store = {
|
type Store = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -176,8 +182,24 @@ export default function StoresPage() {
|
|||||||
return parts.length ? `营业时间: ${parts.join(',')}` : '营业时间: 10:00-22:00';
|
return parts.length ? `营业时间: ${parts.join(',')}` : '营业时间: 10:00-22:00';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sharePayload = useMemo(
|
||||||
|
() => ({
|
||||||
|
title: '杜康好客门店',
|
||||||
|
desc: DEFAULT_SHARE_DESC,
|
||||||
|
path: '/pages/stores/index',
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
useShareAppMessage(() => toWeappShareMessage(sharePayload));
|
||||||
|
useShareTimeline(() => ({
|
||||||
|
title: sharePayload.title || DEFAULT_SHARE_TITLE,
|
||||||
|
query: '',
|
||||||
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageShell variant="tab" className="store-page no-tab-header">
|
<PageShell variant="tab" className="store-page no-tab-header">
|
||||||
|
<WechatShareReady payload={sharePayload} />
|
||||||
<TabMainHeader title="门店" />
|
<TabMainHeader title="门店" />
|
||||||
|
|
||||||
<View className="store-filter">
|
<View className="store-filter">
|
||||||
|
|||||||
@@ -505,31 +505,40 @@
|
|||||||
z-index: 1200;
|
z-index: 1200;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
width: 100%;
|
||||||
justify-content: center;
|
height: 100%;
|
||||||
gap: 10px;
|
padding: 0;
|
||||||
padding: 24px 16px;
|
margin: 0;
|
||||||
background: rgba(0, 0, 0, 0.72);
|
background: #000;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mine-qualification-scroll {
|
.mine-qualification-scroll {
|
||||||
|
flex: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 420px;
|
height: 100%;
|
||||||
max-height: calc(86vh - 36px);
|
max-width: none;
|
||||||
border-radius: 8px;
|
max-height: none;
|
||||||
|
border-radius: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #fff;
|
background: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mine-qualification-img {
|
.mine-qualification-img {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mine-qualification-hint {
|
.mine-qualification-hint {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: calc(12px + env(safe-area-inset-bottom, 0px));
|
||||||
|
z-index: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: rgba(255, 255, 255, 0.82);
|
color: rgba(255, 255, 255, 0.82);
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* 上传小程序「资质公示」静态图到 OSS:static/mini-user/qualification-disclosure.png
|
* 上传小程序「资质公示」静态图到 OSS:static/mini-user/qualification-disclosure.png
|
||||||
* 用法(在 server/dukang-api): node scripts/upload-qualification-disclosure.mjs
|
* 用法(在 server/dukang-api):
|
||||||
|
* node scripts/upload-qualification-disclosure.mjs [本地 png 路径]
|
||||||
|
* 也可设环境变量 QUALIFICATION_DISCLOSURE_LOCAL。
|
||||||
*/
|
*/
|
||||||
import { readFileSync, existsSync } from 'fs';
|
import { readFileSync, existsSync } from 'fs';
|
||||||
import { resolve, dirname } from 'path';
|
import { resolve, dirname, isAbsolute } from 'path';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { createRequire } from 'module';
|
import { createRequire } from 'module';
|
||||||
|
|
||||||
@@ -12,7 +14,6 @@ const OSS = require('ali-oss');
|
|||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
const apiRoot = resolve(__dirname, '..');
|
const apiRoot = resolve(__dirname, '..');
|
||||||
const repoRoot = resolve(apiRoot, '../..');
|
|
||||||
|
|
||||||
function loadEnvFile(path) {
|
function loadEnvFile(path) {
|
||||||
if (!existsSync(path)) return {};
|
if (!existsSync(path)) return {};
|
||||||
@@ -49,10 +50,15 @@ if (!accessKeyId || !accessKeySecret || !bucket) {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const localFile = resolve(
|
const argPath = process.argv[2]?.trim() || env.QUALIFICATION_DISCLOSURE_LOCAL?.trim() || '';
|
||||||
repoRoot,
|
if (!argPath) {
|
||||||
'apps/mini-user/src/assets/qualification-disclosure.png',
|
console.error(
|
||||||
);
|
'请传入本地 png 路径,例如:\n node scripts/upload-qualification-disclosure.mjs D:/tmp/qualification-disclosure.png',
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const localFile = isAbsolute(argPath) ? argPath : resolve(process.cwd(), argPath);
|
||||||
if (!existsSync(localFile)) {
|
if (!existsSync(localFile)) {
|
||||||
console.error('本地文件不存在:', localFile);
|
console.error('本地文件不存在:', localFile);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
@@ -260,9 +260,6 @@ export class StoreService {
|
|||||||
async createStore(partnerAccountId: bigint, body: Record<string, unknown>) {
|
async createStore(partnerAccountId: bigint, body: Record<string, unknown>) {
|
||||||
const { primaryId } = await this.resolvePartnerScope(partnerAccountId);
|
const { primaryId } = await this.resolvePartnerScope(partnerAccountId);
|
||||||
const normalizedPhone = String(body.phone).trim();
|
const normalizedPhone = String(body.phone).trim();
|
||||||
const smsCode = body.smsCode ? String(body.smsCode).trim() : '';
|
|
||||||
if (!smsCode) throw new BadRequestException('请输入门店手机号验证码');
|
|
||||||
await this.authService.verifySmsCode(normalizedPhone, smsCode, SmsScene.PARTNER_STORE_OPEN);
|
|
||||||
const confirmBindExisting = body.confirmBindExisting === true || body.confirmBindExisting === 'true';
|
const confirmBindExisting = body.confirmBindExisting === true || body.confirmBindExisting === 'true';
|
||||||
await this.assertStorePhoneAvailable(normalizedPhone, confirmBindExisting);
|
await this.assertStorePhoneAvailable(normalizedPhone, confirmBindExisting);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user