feat(admin): 后台可配领取链接/发消息模板 + 可见买家账号 + 修正皮肤领取链接
**面板新增三项(抖音码速达接入配置)**
- 领取链接基址 (claimLinkBase):带实时预览「皮肤订单最终链接」,并拦截两类误配 ——
带 `#`(`#/claim` 是打手领取页,会把买家带进绑定 UID 流程)、缺 http(s) 协议
- 发消息模板 (messageTemplate):提示可用占位符;模板里没有 `{link}` 直接报错提示
- 付款后发领取消息开关 (claimMessageEnabled)
- 顺带把默认出网超时的展示值对齐后端(10s → 20s)
**后台可见买家提交的账号(运营发货依据)**
- `getAdminTaskDetail` 新增 `claimSubmission`,按 `canViewSensitiveTaskData` 门禁下发
(与 claimToken 明文同一门禁);任务详情新增「买家提交信息」卡片(可一键复制账号)
**修正:皮肤任务的领取链接**
- 详情接口原来用全局 `buildClaimUrl`(默认 hash 形式 `…/#/claim/…`),那是**打手**领取页;
皮肤任务改用 `claimLinkBase + '/' + token`,运营复制给买家的链接才是买家页
- 顺带把「履约渠道」筛选项加上「皮肤自动发货」、任务详情执行器标签加上它、
「来源渠道」加上「抖音码速达」(此前筛不出来抖音订单)
This commit is contained in:
@@ -361,6 +361,33 @@ export default function AdminTaskDetailPage() {
|
||||
</Card>
|
||||
) : null}
|
||||
|
||||
{/* 皮肤自动发货:买家在领取页提交的游戏账号是发货依据,单独成卡,避免被领取链接卡片挤掉 */}
|
||||
{resolvedDetail.claimSubmission ? (
|
||||
<Card title="买家提交信息">
|
||||
<Space direction="vertical" size={4}>
|
||||
<Typography.Text type="secondary">
|
||||
买家在领取页填写的游戏账号(发货依据,属买家隐私,请勿外传)
|
||||
</Typography.Text>
|
||||
<Space wrap size={8}>
|
||||
<Typography.Text strong style={{ fontSize: 15 }}>
|
||||
{resolvedDetail.claimSubmission.gameAccount}
|
||||
</Typography.Text>
|
||||
<Typography.Text
|
||||
type="secondary"
|
||||
copyable={{ text: resolvedDetail.claimSubmission.gameAccount }}
|
||||
>
|
||||
复制
|
||||
</Typography.Text>
|
||||
</Space>
|
||||
{resolvedDetail.claimSubmission.submittedAt ? (
|
||||
<Typography.Text type="secondary">
|
||||
提交时间:{formatAdminDateTime(resolvedDetail.claimSubmission.submittedAt)}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
</Space>
|
||||
</Card>
|
||||
) : null}
|
||||
|
||||
{resolvedDetail.task.executorKey === 'manual_dispatch' ||
|
||||
resolvedDetail.operations.canCompleteManualDispatch ||
|
||||
resolvedDetail.manualDispatch ? (
|
||||
@@ -856,6 +883,9 @@ function resolveTaskExecutorDisplay(value: unknown) {
|
||||
if (executorKey === 'kuaishou_feifei') {
|
||||
return { label: '飞飞(已下线)', color: 'default' }
|
||||
}
|
||||
if (executorKey === 'douyin_mashida_skin') {
|
||||
return { label: '皮肤自动发货', color: 'magenta' }
|
||||
}
|
||||
if (executorKey === 'manual_dispatch') {
|
||||
return { label: '人工履约', color: 'orange' }
|
||||
}
|
||||
|
||||
@@ -30,7 +30,10 @@ import {
|
||||
} from '@/services/admin/platform-config'
|
||||
import type { AdminDouyinMashidaConfig } from '@/types/admin/platform-config'
|
||||
import {
|
||||
buildDouyinMashidaClaimLinkPreview,
|
||||
buildDouyinMashidaMessageUrl,
|
||||
describeClaimLinkBaseWarning,
|
||||
describeMessageTemplateWarning,
|
||||
describeMissingConfigFields,
|
||||
isLocalDevBaseUrl,
|
||||
} from '@/utils/douyin-mashida'
|
||||
@@ -59,10 +62,13 @@ function createEmptyConfig(): AdminDouyinMashidaConfig {
|
||||
secretMasked: '',
|
||||
hasSecret: false,
|
||||
certLink: '',
|
||||
claimLinkBase: '',
|
||||
messageTemplate: '',
|
||||
claimMessageEnabled: true,
|
||||
afterVerifyLink: '',
|
||||
afterVerifyMessage: '您的订单已兑换成功',
|
||||
messageType: 2,
|
||||
timeoutMs: 10000,
|
||||
timeoutMs: 20000,
|
||||
handledTopics: [...DEFAULT_HANDLED_TOPICS],
|
||||
ready: false,
|
||||
}
|
||||
@@ -144,6 +150,9 @@ export function DouyinMashidaPanel() {
|
||||
})
|
||||
const isLocalDev = isLocalDevBaseUrl(config.baseUrl)
|
||||
const messageUrl = buildDouyinMashidaMessageUrl(window.location.origin)
|
||||
const claimLinkPreview = buildDouyinMashidaClaimLinkPreview(config.claimLinkBase)
|
||||
const claimLinkWarning = describeClaimLinkBaseWarning(config.claimLinkBase)
|
||||
const messageTemplateWarning = describeMessageTemplateWarning(config.messageTemplate)
|
||||
|
||||
return (
|
||||
<Card
|
||||
@@ -274,7 +283,65 @@ export function DouyinMashidaPanel() {
|
||||
placeholder="https://你的域名/redeem"
|
||||
/>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
卡券里下发给买家的固定兑换链接
|
||||
通用兜底兑换链接(皮肤订单解析不出领取链接时才用它)
|
||||
</Text>
|
||||
</Space>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} sm={12} md={8}>
|
||||
<Space direction="vertical" size={4} style={{ width: '100%' }}>
|
||||
<Text strong>领取链接基址 (claimLinkBase)</Text>
|
||||
<Input
|
||||
value={config.claimLinkBase}
|
||||
onChange={(event) => updateField('claimLinkBase', event.target.value)}
|
||||
placeholder="https://你的域名/claim"
|
||||
/>
|
||||
{claimLinkPreview ? (
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
皮肤订单最终链接:{claimLinkPreview}
|
||||
</Text>
|
||||
) : (
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
皮肤自动发货订单的领取页基址,留空则回退到上面的兑换链接
|
||||
</Text>
|
||||
)}
|
||||
{claimLinkWarning ? (
|
||||
<Text type="danger" style={{ fontSize: 12 }}>
|
||||
{claimLinkWarning}
|
||||
</Text>
|
||||
) : null}
|
||||
</Space>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} sm={12} md={8}>
|
||||
<Space direction="vertical" size={4} style={{ width: '100%' }}>
|
||||
<Text strong>发消息模板 (messageTemplate)</Text>
|
||||
<Input
|
||||
value={config.messageTemplate}
|
||||
onChange={(event) => updateField('messageTemplate', event.target.value)}
|
||||
placeholder="您的订单已发货,请点击链接领取:{link}"
|
||||
/>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
占位符:{'{link}'} 领取链接、{'{sku}'} 内部SKU、{'{orderNo}'} 订单号、
|
||||
{'{productTitle}'} 商品标题;留空用默认文案
|
||||
</Text>
|
||||
{messageTemplateWarning ? (
|
||||
<Text type="danger" style={{ fontSize: 12 }}>
|
||||
{messageTemplateWarning}
|
||||
</Text>
|
||||
) : null}
|
||||
</Space>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} sm={12} md={8}>
|
||||
<Space direction="vertical" size={4} style={{ width: '100%' }}>
|
||||
<Text strong>付款后发领取消息 (claimMessageEnabled)</Text>
|
||||
<Switch
|
||||
checked={config.claimMessageEnabled}
|
||||
onChange={(checked) => updateField('claimMessageEnabled', checked)}
|
||||
/>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
关闭后只把领取链接写进卡券,不发订单消息
|
||||
</Text>
|
||||
</Space>
|
||||
</Col>
|
||||
|
||||
Reference in New Issue
Block a user