feat(huya): 协作台账支持待补资料一键建单与表单暂存
This commit is contained in:
@@ -1200,6 +1200,8 @@ export interface AccountExchangeRecords {
|
||||
|
||||
/** 业务状态:一单卡在哪一步(void 是旁路) */
|
||||
export type HuyaCollabStatus =
|
||||
/** 只登记了订单号 + 店铺,CK / 礼包 / 主页截图等客户资料还没到 */
|
||||
| 'incomplete'
|
||||
| 'pending'
|
||||
| 'bound'
|
||||
| 'recharged'
|
||||
@@ -1473,6 +1475,8 @@ export interface HuyaCollabOrderCreate {
|
||||
remark?: string;
|
||||
/** 严格模式(默认 true):店铺/CK/礼包名/主页截图必填,且 CK 必须读到绑定角色 */
|
||||
require_verified?: boolean;
|
||||
/** 先建单后补资料:只填订单号 + 店铺,状态进「待补资料」 */
|
||||
draft?: boolean;
|
||||
}
|
||||
|
||||
export interface HuyaCollabOrderUpdate {
|
||||
|
||||
@@ -41,11 +41,14 @@ export default function HuyaCollabHomeImageUploader({
|
||||
value = [],
|
||||
max = 20,
|
||||
disabled,
|
||||
optional = false,
|
||||
onChange,
|
||||
}: {
|
||||
value?: string[];
|
||||
max?: number;
|
||||
disabled?: boolean;
|
||||
/** 草稿建单:主页截图可以先空着 */
|
||||
optional?: boolean;
|
||||
onChange?: (value: string[]) => void;
|
||||
}) {
|
||||
const [busy, setBusy] = useState(false);
|
||||
@@ -138,7 +141,9 @@ export default function HuyaCollabHomeImageUploader({
|
||||
return (
|
||||
<Space direction="vertical" size={8} style={{ width: '100%' }}>
|
||||
{keys.length === 0 ? (
|
||||
<Text type="secondary">还没有图(必填:至少 1 张,第一张作封面)</Text>
|
||||
<Text type="secondary">
|
||||
{optional ? '还没有图(可稍后补,第一张作封面)' : '还没有图(必填:至少 1 张,第一张作封面)'}
|
||||
</Text>
|
||||
) : (
|
||||
<Image.PreviewGroup
|
||||
items={keys.map((key) => previews[key]?.url || `/api/files/object?key=${encodeURIComponent(key)}`)}
|
||||
|
||||
@@ -55,6 +55,8 @@ function hasTextInputFocus(): boolean {
|
||||
}
|
||||
|
||||
const STATUS_META: Record<HuyaCollabStatus, { label: string; color: string }> = {
|
||||
// 只登记了订单号 + 店铺,客户资料(CK / 礼包 / 主页截图)到了再补
|
||||
incomplete: { label: '待补资料', color: 'gold' },
|
||||
pending: { label: '待处理', color: 'default' },
|
||||
// 人工核对过「探针读到的绑定角色」与「主页截图」一致
|
||||
bound: { label: '已确认绑定', color: 'blue' },
|
||||
@@ -74,7 +76,8 @@ const VERDICT_META: Record<string, { label: string; color: string }> = {
|
||||
unknown: { label: '无法判定', color: 'default' },
|
||||
};
|
||||
|
||||
/** 「改状态」能选的目标(顺序 = 业务流程顺序,回退要显式勾选) */
|
||||
/** 「改状态」能选的目标(顺序 = 业务流程顺序,回退要显式勾选)
|
||||
* 「待补资料」只作为新建起点,不放进「改状态」:它只能通过「回退状态」进入。 */
|
||||
const STATUS_ORDER_OPTIONS: { value: HuyaCollabStatus; label: string }[] = [
|
||||
{ value: 'pending', label: '待处理' },
|
||||
{ value: 'bound', label: '已确认绑定' },
|
||||
@@ -85,10 +88,15 @@ const STATUS_ORDER_OPTIONS: { value: HuyaCollabStatus; label: string }[] = [
|
||||
{ value: 'void', label: '已作废' },
|
||||
];
|
||||
|
||||
/** 「回退」能选的目标:只在流程链里选(要进「已作废 / 抢购失败」走「改状态」或「作废」入口) */
|
||||
const FLOW_STATUS_OPTIONS = STATUS_ORDER_OPTIONS.filter(
|
||||
(option) => option.value !== 'failed' && option.value !== 'void',
|
||||
);
|
||||
/** 「回退」能选的目标:流程链(含「待补资料」;要进「已作废 / 抢购失败」走「改状态」或「作废」入口) */
|
||||
const FLOW_STATUS_OPTIONS: { value: HuyaCollabStatus; label: string }[] = [
|
||||
{ value: 'incomplete', label: '待补资料' },
|
||||
{ value: 'pending', label: '待处理' },
|
||||
{ value: 'bound', label: '已确认绑定' },
|
||||
{ value: 'recharged', label: '已充值' },
|
||||
{ value: 'scripted', label: '已上脚本' },
|
||||
{ value: 'done', label: '抢购成功' },
|
||||
];
|
||||
|
||||
const CK_META: Record<string, { label: string; color: string }> = {
|
||||
unverified: { label: '未验证', color: 'default' },
|
||||
@@ -145,6 +153,94 @@ function writeGiftCache(gifts: HuyaCollabGift[]): void {
|
||||
}
|
||||
}
|
||||
|
||||
// 「新建协作单」草稿:填一半关掉 / 刷新页面后再打开不能清空(2026-10-17 用户需求)。
|
||||
// 按登录用户分键,避免同一台电脑换账号后看到上一个人的 CK。
|
||||
const CREATE_DRAFT_KEY_PREFIX = 'huya.collab.createDraft';
|
||||
// 「只填订单号 + 店铺直接建单」的首次提示只弹一次(按浏览器记,不再打扰)
|
||||
const CREATE_DRAFT_HINT_KEY = 'huya.collab.draftHintShown';
|
||||
|
||||
interface CreateDraft {
|
||||
order_no: string;
|
||||
shop: string;
|
||||
ck_text: string;
|
||||
gift_name: string;
|
||||
remark: string;
|
||||
home_images: string[];
|
||||
saved_at: number;
|
||||
}
|
||||
|
||||
function createDraftKey(userId?: number | null): string {
|
||||
return userId ? `${CREATE_DRAFT_KEY_PREFIX}.${userId}` : '';
|
||||
}
|
||||
|
||||
/** 读草稿(读不到 / 解析坏都当没有) */
|
||||
function readCreateDraft(userId?: number | null): CreateDraft | null {
|
||||
const key = createDraftKey(userId);
|
||||
if (!key) return null;
|
||||
try {
|
||||
const raw = window.localStorage.getItem(key);
|
||||
if (!raw) return null;
|
||||
const parsed = JSON.parse(raw) as Partial<CreateDraft>;
|
||||
const savedAt = Number(parsed.saved_at) || 0;
|
||||
// 草稿只留 7 天:里面可能有一份 CK,不能无限期躺在浏览器里
|
||||
if (!savedAt || Date.now() - savedAt > 7 * 24 * 60 * 60 * 1000) {
|
||||
window.localStorage.removeItem(key);
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
order_no: typeof parsed.order_no === 'string' ? parsed.order_no : '',
|
||||
shop: typeof parsed.shop === 'string' ? parsed.shop : '',
|
||||
ck_text: typeof parsed.ck_text === 'string' ? parsed.ck_text : '',
|
||||
gift_name: typeof parsed.gift_name === 'string' ? parsed.gift_name : '',
|
||||
remark: typeof parsed.remark === 'string' ? parsed.remark : '',
|
||||
home_images: Array.isArray(parsed.home_images)
|
||||
? parsed.home_images.filter((item): item is string => typeof item === 'string')
|
||||
: [],
|
||||
saved_at: Number(parsed.saved_at) || 0,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function clearCreateDraft(userId?: number | null): void {
|
||||
const key = createDraftKey(userId);
|
||||
if (!key) return;
|
||||
try {
|
||||
window.localStorage.removeItem(key);
|
||||
} catch {
|
||||
// 忽略:清不掉也不影响当前表单
|
||||
}
|
||||
}
|
||||
|
||||
/** 「资料没填全时直接建单 → 待补资料」的首次提示是否已经展示过 */
|
||||
function draftHintShown(): boolean {
|
||||
try {
|
||||
return window.localStorage.getItem(CREATE_DRAFT_HINT_KEY) === '1';
|
||||
} catch {
|
||||
return true; // 存不了就不要再反复弹
|
||||
}
|
||||
}
|
||||
|
||||
function markDraftHintShown(): void {
|
||||
try {
|
||||
window.localStorage.setItem(CREATE_DRAFT_HINT_KEY, '1');
|
||||
} catch {
|
||||
// 忽略:提示只是体验
|
||||
}
|
||||
}
|
||||
|
||||
function hasDraftContent(draft: Omit<CreateDraft, 'saved_at'>): boolean {
|
||||
return Boolean(
|
||||
draft.order_no.trim()
|
||||
|| draft.shop.trim()
|
||||
|| draft.ck_text.trim()
|
||||
|| draft.gift_name.trim()
|
||||
|| draft.remark.trim()
|
||||
|| draft.home_images.length,
|
||||
);
|
||||
}
|
||||
|
||||
function formatTime(value: string | null | undefined): string {
|
||||
if (!value) return '-';
|
||||
const time = new Date(value);
|
||||
@@ -311,6 +407,8 @@ export default function HuyaCollabPage() {
|
||||
|
||||
const [createOpen, setCreateOpen] = useState(false);
|
||||
const [createForm] = Form.useForm<Record<string, unknown>>();
|
||||
const [draftRestoredAt, setDraftRestoredAt] = useState<number | null>(null);
|
||||
const draftSaveTimer = useRef<number | null>(null);
|
||||
const [ckPreview, setCkPreview] = useState<HuyaCollabCkPreview | null>(null);
|
||||
const [previewing, setPreviewing] = useState(false);
|
||||
// 这次预览有没有带「拉礼包」(没有就是纯探针 + 用本地礼包缓存),只影响提示文案
|
||||
@@ -934,28 +1032,120 @@ export default function HuyaCollabPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const submitCreate = async () => {
|
||||
if (!ckReady) {
|
||||
message.warning('这份 CK 没通过验证(或读不到绑定角色),不能提交');
|
||||
/** 立即把当前表单写进本地草稿(关闭弹窗 / 防抖到点时都走这里) */
|
||||
const writeCreateDraft = useCallback((values: Record<string, unknown>) => {
|
||||
const userId = user?.id;
|
||||
const key = createDraftKey(userId);
|
||||
if (!key) return;
|
||||
const payload = {
|
||||
order_no: String(values.order_no ?? ''),
|
||||
shop: String(values.shop ?? ''),
|
||||
ck_text: String(values.ck_text ?? ''),
|
||||
gift_name: String(values.gift_name ?? ''),
|
||||
remark: String(values.remark ?? ''),
|
||||
home_images: Array.isArray(values.home_images)
|
||||
? (values.home_images as unknown[]).filter((item): item is string => typeof item === 'string')
|
||||
: [],
|
||||
};
|
||||
if (!hasDraftContent(payload)) {
|
||||
clearCreateDraft(userId);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
window.localStorage.setItem(key, JSON.stringify({ ...payload, saved_at: Date.now() }));
|
||||
} catch {
|
||||
// 隐私模式 / 配额满:暂存失败不影响提交
|
||||
}
|
||||
}, [user?.id]);
|
||||
|
||||
/** 新建弹窗表单变化后写本地草稿(防抖 400ms) */
|
||||
const persistCreateDraft = useCallback((values: Record<string, unknown>) => {
|
||||
if (draftSaveTimer.current) window.clearTimeout(draftSaveTimer.current);
|
||||
draftSaveTimer.current = window.setTimeout(() => writeCreateDraft(values), 400);
|
||||
}, [writeCreateDraft]);
|
||||
|
||||
/** 关闭弹窗时立刻落盘一次,避免 400ms 内重新打开读不到最新输入 */
|
||||
const closeCreateModal = useCallback(() => {
|
||||
if (draftSaveTimer.current) {
|
||||
window.clearTimeout(draftSaveTimer.current);
|
||||
draftSaveTimer.current = null;
|
||||
}
|
||||
writeCreateDraft(createForm.getFieldsValue(true) as Record<string, unknown>);
|
||||
setCreateOpen(false);
|
||||
}, [createForm, writeCreateDraft]);
|
||||
|
||||
useEffect(() => () => {
|
||||
if (draftSaveTimer.current) window.clearTimeout(draftSaveTimer.current);
|
||||
}, []);
|
||||
|
||||
/** 清掉草稿并恢复空表单(「清空草稿」入口用) */
|
||||
const discardCreateDraft = useCallback(() => {
|
||||
if (draftSaveTimer.current) {
|
||||
window.clearTimeout(draftSaveTimer.current);
|
||||
draftSaveTimer.current = null;
|
||||
}
|
||||
clearCreateDraft(user?.id);
|
||||
setDraftRestoredAt(null);
|
||||
setCkPreview(null);
|
||||
setPreviewing(false);
|
||||
setGiftHint('');
|
||||
previewSeq.current += 1;
|
||||
createForm.resetFields();
|
||||
}, [createForm, user?.id]);
|
||||
|
||||
const submitCreate = async () => {
|
||||
try {
|
||||
// 只校验订单号 + 店铺:CK / 礼包 / 主页截图即使空着也能一键建单(自动进「待补资料」)
|
||||
const values = await createForm.validateFields();
|
||||
const orderNo = String(values.order_no ?? '').trim();
|
||||
const ckText = String(values.ck_text ?? '').trim();
|
||||
const giftName = String(values.gift_name ?? '').trim();
|
||||
const homeImages = (values.home_images as string[] | undefined) ?? [];
|
||||
const missing: string[] = [];
|
||||
if (!ckText) missing.push('外部 CK');
|
||||
if (!giftName) missing.push('礼包名');
|
||||
if (homeImages.length === 0) missing.push('主页截图');
|
||||
// 资料齐全且 CK 已验证通过才走完整建单;否则一律按「待补资料」保存
|
||||
const draft = missing.length > 0 || !ckReady;
|
||||
const created = await huyaApi.createCollabOrder({
|
||||
order_no: String(values.order_no ?? '').trim(),
|
||||
order_no: orderNo,
|
||||
shop: String(values.shop ?? ''),
|
||||
ck_text: String(values.ck_text ?? ''),
|
||||
ck_text: ckText,
|
||||
// 「绑定斗鱼号」不再录入:绑了谁由探针读(bind_game_*),人工那一列已下线
|
||||
gift_name: String(values.gift_name ?? ''),
|
||||
home_images: (values.home_images as string[] | undefined) ?? [],
|
||||
gift_name: giftName,
|
||||
home_images: homeImages,
|
||||
remark: String(values.remark ?? ''),
|
||||
require_verified: true, // 服务端再校验一次:CK 必须读到绑定角色才让建
|
||||
draft,
|
||||
require_verified: !draft, // 草稿单不跑探针;完整建单仍要求 CK 读到绑定角色
|
||||
});
|
||||
if (created.gift_name) window.localStorage.setItem(LAST_GIFT_KEY, created.gift_name);
|
||||
message.success(`已新建 ${created.order_no}`);
|
||||
if (draft) {
|
||||
const reason = missing.length > 0
|
||||
? `还缺 ${missing.join('、')}`
|
||||
: (previewing ? 'CK 还在验证中' : 'CK 还没验证通过');
|
||||
if (!draftHintShown()) {
|
||||
markDraftHintShown();
|
||||
// 首次建草稿单给一次明确提示:以后直接点「新建」就行,不用先勾任何东西
|
||||
message.info(
|
||||
`已按「待补资料」创建 ${created.order_no}:${reason}。`
|
||||
+ '之后在详情里补齐,再点「标记为待处理」即可。',
|
||||
8,
|
||||
);
|
||||
} else {
|
||||
message.success(`已新建 ${created.order_no}(待补资料,资料可稍后补)`);
|
||||
}
|
||||
} else {
|
||||
message.success(`已新建 ${created.order_no}`);
|
||||
}
|
||||
setCreateOpen(false);
|
||||
setCkPreview(null);
|
||||
setGiftHint('');
|
||||
setDraftRestoredAt(null);
|
||||
if (draftSaveTimer.current) {
|
||||
window.clearTimeout(draftSaveTimer.current);
|
||||
draftSaveTimer.current = null;
|
||||
}
|
||||
clearCreateDraft(user?.id);
|
||||
createForm.resetFields();
|
||||
void load();
|
||||
} catch (e: unknown) {
|
||||
@@ -1303,6 +1493,12 @@ export default function HuyaCollabPage() {
|
||||
{/* 卡片用 flex 平分:状态多了一个「抢购失败」,固定 span=4 会换行参差不齐 */}
|
||||
<Row gutter={12}>
|
||||
<Col flex="1"><Card size="small"><Statistic title="全部" value={summary?.total ?? 0} /></Card></Col>
|
||||
<Col flex="1">
|
||||
<Card size="small">
|
||||
<Statistic title={STATUS_META.incomplete.label} value={summary?.by_status.incomplete ?? 0}
|
||||
valueStyle={{ color: '#fa8c16' }} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col flex="1">
|
||||
<Card size="small">
|
||||
<Statistic title="待处理" value={summary?.by_status.pending ?? 0} valueStyle={{ color: '#faad14' }} />
|
||||
@@ -1456,6 +1652,16 @@ export default function HuyaCollabPage() {
|
||||
setGiftHint('');
|
||||
previewSeq.current += 1; // 丢掉在途的预览结论
|
||||
createForm.resetFields();
|
||||
const draft = readCreateDraft(user?.id);
|
||||
if (draft && hasDraftContent(draft)) {
|
||||
// 上次填了一半:原样恢复(CK / 礼包 / 截图 / 备注都在),并重新验证暂存的 CK
|
||||
createForm.setFieldsValue({ ...draft });
|
||||
setDraftRestoredAt(draft.saved_at || Date.now());
|
||||
setCreateOpen(true);
|
||||
if (draft.ck_text.trim()) scheduleCkPreview(draft.ck_text, true);
|
||||
return;
|
||||
}
|
||||
setDraftRestoredAt(null);
|
||||
// 记住最近选的礼包:同一个礼包连开几单时不用反复选
|
||||
const lastGift = window.localStorage.getItem(LAST_GIFT_KEY);
|
||||
if (lastGift) createForm.setFieldsValue({ gift_name: lastGift });
|
||||
@@ -1499,6 +1705,23 @@ export default function HuyaCollabPage() {
|
||||
>
|
||||
{detail && (
|
||||
<Space direction="vertical" size={12} style={{ width: '100%' }}>
|
||||
{detail.status === 'incomplete' && (
|
||||
<Alert
|
||||
type="warning"
|
||||
showIcon
|
||||
message="这单还在「待补资料」"
|
||||
description={(() => {
|
||||
const missing = [
|
||||
!detail.has_cookie ? '外部 CK' : '',
|
||||
!detail.gift_name ? '礼包名' : '',
|
||||
detail.home_images.length === 0 ? '主页截图' : '',
|
||||
].filter(Boolean);
|
||||
return missing.length > 0
|
||||
? `还缺:${missing.join('、')}。补齐后点下面的「标记为待处理」按钮即可进入正常流程。`
|
||||
: '资料已齐,点下面的「标记为待处理」按钮进入正常流程。';
|
||||
})()}
|
||||
/>
|
||||
)}
|
||||
<Descriptions size="small" column={2} bordered
|
||||
items={[
|
||||
{ key: 'uid', label: '虎牙号', children: detail.uid || '-' },
|
||||
@@ -1770,11 +1993,11 @@ export default function HuyaCollabPage() {
|
||||
title="新建协作单"
|
||||
open={createOpen}
|
||||
width={920}
|
||||
onCancel={() => setCreateOpen(false)}
|
||||
onCancel={closeCreateModal}
|
||||
onOk={() => void submitCreate()}
|
||||
confirmLoading={busy}
|
||||
okText="新建"
|
||||
okButtonProps={{ disabled: !ckReady || previewing }}
|
||||
// 一键建单:不再要求先勾「先建单」或等 CK 验证通过;资料没填全自动存成「待补资料」
|
||||
// 内容比一屏高:给个滚动区,别让底部按钮被顶出可视范围
|
||||
styles={{ body: { maxHeight: '78vh', overflowY: 'auto', paddingRight: 12 } }}
|
||||
destroyOnHidden
|
||||
@@ -1784,10 +2007,28 @@ export default function HuyaCollabPage() {
|
||||
form={createForm}
|
||||
layout="vertical"
|
||||
size="middle"
|
||||
onValuesChange={(changed: Record<string, unknown>) => {
|
||||
onValuesChange={(changed: Record<string, unknown>, allValues: Record<string, unknown>) => {
|
||||
if (typeof changed.ck_text === 'string') scheduleCkPreview(changed.ck_text);
|
||||
persistCreateDraft(allValues);
|
||||
}}
|
||||
>
|
||||
{draftRestoredAt && (
|
||||
<Alert
|
||||
type="info"
|
||||
showIcon
|
||||
style={{ marginBottom: 12 }}
|
||||
message={`已恢复上次未提交的草稿(${formatTime(new Date(draftRestoredAt).toISOString())} 暂存)`}
|
||||
action={(
|
||||
<Button size="small" type="link" onClick={discardCreateDraft}>
|
||||
清空草稿
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 12, fontSize: 12 }}>
|
||||
只填订单号 + 店铺也能直接点右下角「新建」:资料没填全会自动按「待补资料」创建,
|
||||
CK / 礼包 / 主页截图之后在详情里补即可。填写内容会自动暂存在本机,关闭 / 刷新后再打开会恢复。
|
||||
</Text>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Form.Item name="order_no" label="订单编号" rules={[{ required: true, message: '订单号不能为空' }]}>
|
||||
@@ -1811,9 +2052,8 @@ export default function HuyaCollabPage() {
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="ck_text"
|
||||
label="外部 CK"
|
||||
tooltip="必填:支持「纯CK」或「账号----密码----CK」。贴进来即自动探针验证 + 读绑定角色;礼包列表本地有缓存就不再重复拉,要更新点旁边的「强制刷新礼包」"
|
||||
rules={[{ required: true, message: '请贴一份外部 CK' }]}
|
||||
label="外部 CK(可稍后补)"
|
||||
tooltip="支持「纯CK」或「账号----密码----CK」。贴进来即自动探针验证 + 读绑定角色;不贴也可以先建单,之后在详情里补。礼包列表本地有缓存就不再重复拉,要更新点旁边的「强制刷新礼包」"
|
||||
>
|
||||
{/* 高度随内容走:短 CK 就 3 行,别固定 5 行把弹窗撑高 */}
|
||||
<Input.TextArea
|
||||
@@ -1857,10 +2097,10 @@ export default function HuyaCollabPage() {
|
||||
/>
|
||||
) : (
|
||||
<Alert
|
||||
type="error"
|
||||
type="warning"
|
||||
showIcon
|
||||
message="这份 CK 不能用,禁止提交"
|
||||
description={`${ckPreview?.message || ''}${ckPreview?.ok && !ckPreview.has_role ? '(探针通了但读不到绑定角色)' : ''}`}
|
||||
message="这份 CK 没验证通过;点「新建」会先按「待补资料」保存"
|
||||
description={`${ckPreview?.message || ''}${ckPreview?.ok && !ckPreview.has_role ? '(探针通了但读不到绑定角色)' : ''} 之后补 / 换 CK,再在详情里验证即可。`}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -1869,9 +2109,8 @@ export default function HuyaCollabPage() {
|
||||
<Col span={14}>
|
||||
<Form.Item
|
||||
name="gift_name"
|
||||
label="礼包名(用户购买的物品)"
|
||||
tooltip="必填:先贴有效 CK,再从礼包列表里点选(列表有本地缓存,不用每次重拉;拉不到时可以直接手输)"
|
||||
rules={[{ required: true, message: '请选一个礼包' }]}
|
||||
label="礼包名(用户购买的物品,可稍后补)"
|
||||
tooltip="先贴有效 CK,再从礼包列表里点选(列表有本地缓存,不用每次重拉;拉不到时可以直接手输)。不选也能先建单,之后在详情里补。"
|
||||
extra={giftHint || (giftsCachedAt && giftOptions.length > 0
|
||||
? `礼包列表缓存于 ${giftCacheLabel}(${giftOptions.length} 个)`
|
||||
: undefined)}
|
||||
@@ -1879,7 +2118,7 @@ export default function HuyaCollabPage() {
|
||||
>
|
||||
<AutoComplete
|
||||
allowClear
|
||||
placeholder={ckReady ? '从礼包里点选(可直接输)' : '先贴一份有效 CK'}
|
||||
placeholder={ckReady ? '从礼包里点选(可直接输)' : '可先空着,之后在详情里补'}
|
||||
options={giftOptions.map((gift) => ({
|
||||
value: gift.name,
|
||||
label: [
|
||||
@@ -1918,17 +2157,10 @@ export default function HuyaCollabPage() {
|
||||
<Col span={14}>
|
||||
<Form.Item
|
||||
name="home_images"
|
||||
label="主页截图(必填,第一张作封面)"
|
||||
tooltip="支持点击选择、拖拽或 Ctrl/Cmd+V 粘贴上传;第一张作封面,绑定图不用再传"
|
||||
rules={[{
|
||||
validator: (_rule, value: string[] | undefined) => (
|
||||
value && value.length > 0
|
||||
? Promise.resolve()
|
||||
: Promise.reject(new Error('请至少上传 1 张主页截图'))
|
||||
),
|
||||
}]}
|
||||
label="主页截图(可稍后补,第一张作封面)"
|
||||
tooltip="支持点击选择、拖拽或 Ctrl/Cmd+V 粘贴上传;第一张作封面,绑定图不用再传。不传也能先建单,之后在详情里补。"
|
||||
>
|
||||
<HuyaCollabHomeImageUploader max={MAX_IMAGES_PER_SLOT} />
|
||||
<HuyaCollabHomeImageUploader max={MAX_IMAGES_PER_SLOT} optional />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={10}>
|
||||
|
||||
Reference in New Issue
Block a user