手机号核销确认

This commit is contained in:
2026-07-12 10:34:58 +08:00
parent 7f031cc4c2
commit d949301bc1
17 changed files with 1285 additions and 215 deletions
+316 -114
View File
@@ -22,16 +22,25 @@ export default function RedeemDebugPage() {
const [createForm] = Form.useForm();
const [previewForm] = Form.useForm();
const [confirmForm] = Form.useForm();
const [phoneLookupForm] = Form.useForm();
const [phoneBalanceForm] = Form.useForm();
const [phonePrepareForm] = Form.useForm();
const [phoneConfirmForm] = Form.useForm();
const [loading, setLoading] = useState(false);
const [createResult, setCreateResult] = useState<ApiResult | null>(null);
const [previewResult, setPreviewResult] = useState<ApiResult | null>(null);
const [confirmResult, setConfirmResult] = useState<ApiResult | null>(null);
const [phoneLookupResult, setPhoneLookupResult] = useState<ApiResult | null>(null);
const [phoneBalanceResult, setPhoneBalanceResult] = useState<ApiResult | null>(null);
const [phonePrepareResult, setPhonePrepareResult] = useState<ApiResult | null>(null);
const [phoneConfirmResult, setPhoneConfirmResult] = useState<ApiResult | null>(null);
async function invoke(
path: string,
body: unknown,
setResult: (v: ApiResult | null) => void,
successMsg: string,
onSuccess?: (res: ApiResult) => void,
) {
setLoading(true);
setResult(null);
@@ -42,10 +51,21 @@ export default function RedeemDebugPage() {
});
setResult(res);
message.success(successMsg);
onSuccess?.(res);
if (path.includes('create-token') && res.token) {
previewForm.setFieldsValue({ token: res.token });
confirmForm.setFieldsValue({ token: res.token });
}
if (path.includes('phone/balance') && res.sessionId) {
phonePrepareForm.setFieldsValue({
storeId: phoneBalanceForm.getFieldValue('storeId'),
sessionId: res.sessionId,
});
phoneConfirmForm.setFieldsValue({
storeId: phoneBalanceForm.getFieldValue('storeId'),
sessionId: res.sessionId,
});
}
} catch (e) {
message.error(e instanceof Error ? e.message : '调用失败');
} finally {
@@ -53,129 +73,311 @@ export default function RedeemDebugPage() {
}
}
const tokenTabItems = [
{
key: 'create',
label: '1. 生成核销码',
children: (
<Row gutter={16}>
<Col xs={24} lg={10}>
<Card size="small" title="参数">
<Form form={createForm} layout="vertical">
<Form.Item
name="userId"
label="用户"
rules={[{ required: true, message: '请填写用户 ID、编号或手机号' }]}
>
<Input placeholder="数据库 ID / 用户编号 / 手机号" />
</Form.Item>
<Form.Item name="amount" label="核销金额" rules={[{ required: true }]}>
<InputNumber min={0.01} max={500} step={1} style={{ width: '100%' }} />
</Form.Item>
<Form.Item name="couponId" label="指定券 ID(可选)">
<Input placeholder="不填则自动分摊" />
</Form.Item>
<Form.Item name="storeId" label="绑定门店 ID(可选)">
<Input placeholder="绑定后仅该门店可核销" />
</Form.Item>
<Button
type="primary"
loading={loading}
onClick={() => {
void createForm.validateFields().then((values) => {
void invoke('/admin/redeem/debug/create-token', values, setCreateResult, '核销码已生成');
});
}}
>
</Button>
</Form>
</Card>
</Col>
<Col xs={24} lg={14}>
<Card size="small" title="响应">
<ResultBox data={createResult} />
</Card>
</Col>
</Row>
),
},
{
key: 'preview',
label: '2. 预览核销',
children: (
<Row gutter={16}>
<Col xs={24} lg={10}>
<Card size="small" title="参数">
<Form form={previewForm} layout="vertical">
<Form.Item name="storeId" label="门店 ID" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name="token" label="核销码" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Button
loading={loading}
onClick={() => {
const values = previewForm.getFieldsValue();
void invoke('/admin/redeem/debug/preview', values, setPreviewResult, '预览成功');
}}
>
</Button>
</Form>
</Card>
</Col>
<Col xs={24} lg={14}>
<Card size="small" title="响应">
<ResultBox data={previewResult} />
</Card>
</Col>
</Row>
),
},
{
key: 'confirm',
label: '3. 确认核销',
children: (
<Row gutter={16}>
<Col xs={24} lg={10}>
<Card size="small" title="参数">
<Form form={confirmForm} layout="vertical">
<Form.Item name="storeId" label="门店 ID" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name="token" label="核销码" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Space>
<Button
type="primary"
danger
loading={loading}
onClick={() => {
const values = confirmForm.getFieldsValue();
void invoke('/admin/redeem/debug/confirm', values, setConfirmResult, '核销成功');
}}
>
</Button>
</Space>
</Form>
</Card>
</Col>
<Col xs={24} lg={14}>
<Card size="small" title="响应">
<ResultBox data={confirmResult} />
</Card>
</Col>
</Row>
),
},
];
const phoneTabItems = [
{
key: 'phone-lookup',
label: '1. 发送查权益验证码',
children: (
<Row gutter={16}>
<Col xs={24} lg={10}>
<Card size="small" title="参数">
<Form form={phoneLookupForm} layout="vertical">
<Form.Item name="storeId" label="门店 ID" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name="phone" label="用户手机号" rules={[{ required: true }]}>
<Input placeholder="11 位手机号" />
</Form.Item>
<Button
type="primary"
loading={loading}
onClick={() => {
void phoneLookupForm.validateFields().then((values) => {
phoneBalanceForm.setFieldsValue({
storeId: values.storeId,
phone: values.phone,
});
void invoke(
'/admin/redeem/debug/phone/send-lookup-sms',
values,
setPhoneLookupResult,
'查权益验证码已发送',
);
});
}}
>
</Button>
</Form>
</Card>
</Col>
<Col xs={24} lg={14}>
<Card size="small" title="响应">
<ResultBox data={phoneLookupResult} />
</Card>
</Col>
</Row>
),
},
{
key: 'phone-balance',
label: '2. 验证并查权益',
children: (
<Row gutter={16}>
<Col xs={24} lg={10}>
<Card size="small" title="参数">
<Form form={phoneBalanceForm} layout="vertical">
<Form.Item name="storeId" label="门店 ID" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name="phone" label="用户手机号" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name="code" label="验证码" rules={[{ required: true }]}>
<Input placeholder="Mock 默认 123456" />
</Form.Item>
<Button
loading={loading}
onClick={() => {
void phoneBalanceForm.validateFields().then((values) => {
void invoke('/admin/redeem/debug/phone/balance', values, setPhoneBalanceResult, '权益查询成功');
});
}}
>
</Button>
</Form>
</Card>
</Col>
<Col xs={24} lg={14}>
<Card size="small" title="响应">
<ResultBox data={phoneBalanceResult} />
</Card>
</Col>
</Row>
),
},
{
key: 'phone-prepare',
label: '3. 发送核销确认码',
children: (
<Row gutter={16}>
<Col xs={24} lg={10}>
<Card size="small" title="参数">
<Form form={phonePrepareForm} layout="vertical">
<Form.Item name="storeId" label="门店 ID" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name="sessionId" label="会话 ID" rules={[{ required: true }]}>
<Input placeholder="上一步返回的 sessionId" />
</Form.Item>
<Form.Item name="amount" label="核销金额" rules={[{ required: true }]}>
<InputNumber min={0.01} max={500} step={1} style={{ width: '100%' }} />
</Form.Item>
<Button
loading={loading}
onClick={() => {
void phonePrepareForm.validateFields().then((values) => {
phoneConfirmForm.setFieldsValue({
storeId: values.storeId,
sessionId: values.sessionId,
});
void invoke('/admin/redeem/debug/phone/prepare', values, setPhonePrepareResult, '核销确认码已发送');
});
}}
>
</Button>
</Form>
</Card>
</Col>
<Col xs={24} lg={14}>
<Card size="small" title="响应">
<ResultBox data={phonePrepareResult} />
</Card>
</Col>
</Row>
),
},
{
key: 'phone-confirm',
label: '4. 确认核销',
children: (
<Row gutter={16}>
<Col xs={24} lg={10}>
<Card size="small" title="参数">
<Form form={phoneConfirmForm} layout="vertical">
<Form.Item name="storeId" label="门店 ID" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name="sessionId" label="会话 ID" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name="code" label="核销确认验证码" rules={[{ required: true }]}>
<Input placeholder="Mock 默认 123456" />
</Form.Item>
<Button
type="primary"
danger
loading={loading}
onClick={() => {
void phoneConfirmForm.validateFields().then((values) => {
void invoke('/admin/redeem/debug/phone/confirm', values, setPhoneConfirmResult, '手机号核销成功');
});
}}
>
</Button>
</Form>
</Card>
</Col>
<Col xs={24} lg={14}>
<Card size="small" title="响应">
<ResultBox data={phoneConfirmResult} />
</Card>
</Col>
</Row>
),
},
];
return (
<div>
<Typography.Title level={4}></Typography.Title>
<Tabs
defaultActiveKey="token"
items={[
{
key: 'create',
label: '1. 生成核销',
children: (
<Row gutter={16}>
<Col xs={24} lg={10}>
<Card size="small" title="参数">
<Form form={createForm} layout="vertical">
<Form.Item
name="userId"
label="用户"
rules={[{ required: true, message: '请填写用户 ID、编号或手机号' }]}
>
<Input placeholder="数据库 ID / 用户编号 / 手机号" />
</Form.Item>
<Form.Item name="amount" label="核销金额" rules={[{ required: true }]}>
<InputNumber min={0.01} max={500} step={1} style={{ width: '100%' }} />
</Form.Item>
<Form.Item name="couponId" label="指定券 ID(可选)">
<Input placeholder="不填则自动分摊" />
</Form.Item>
<Form.Item name="storeId" label="绑定门店 ID(可选)">
<Input placeholder="绑定后仅该门店可核销" />
</Form.Item>
<Button
type="primary"
loading={loading}
onClick={() => {
void createForm.validateFields().then((values) => {
void invoke('/admin/redeem/debug/create-token', values, setCreateResult, '核销码已生成');
});
}}
>
</Button>
</Form>
</Card>
</Col>
<Col xs={24} lg={14}>
<Card size="small" title="响应">
<ResultBox data={createResult} />
</Card>
</Col>
</Row>
),
key: 'token',
label: '扫码核销',
children: <Tabs items={tokenTabItems} />,
},
{
key: 'preview',
label: '2. 预览核销',
children: (
<Row gutter={16}>
<Col xs={24} lg={10}>
<Card size="small" title="参数">
<Form form={previewForm} layout="vertical">
<Form.Item name="storeId" label="门店 ID" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name="token" label="核销码" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Button
loading={loading}
onClick={() => {
const values = previewForm.getFieldsValue();
void invoke('/admin/redeem/debug/preview', values, setPreviewResult, '预览成功');
}}
>
</Button>
</Form>
</Card>
</Col>
<Col xs={24} lg={14}>
<Card size="small" title="响应">
<ResultBox data={previewResult} />
</Card>
</Col>
</Row>
),
},
{
key: 'confirm',
label: '3. 确认核销',
children: (
<Row gutter={16}>
<Col xs={24} lg={10}>
<Card size="small" title="参数">
<Form form={confirmForm} layout="vertical">
<Form.Item name="storeId" label="门店 ID" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name="token" label="核销码" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Space>
<Button
type="primary"
danger
loading={loading}
onClick={() => {
const values = confirmForm.getFieldsValue();
void invoke('/admin/redeem/debug/confirm', values, setConfirmResult, '核销成功');
}}
>
</Button>
</Space>
</Form>
</Card>
</Col>
<Col xs={24} lg={14}>
<Card size="small" title="响应">
<ResultBox data={confirmResult} />
</Card>
</Col>
</Row>
),
key: 'phone',
label: '手机号核销',
children: <Tabs items={phoneTabItems} />,
},
]}
/>