feat(weibo): 优化外部单协作建单界面

This commit is contained in:
yml2213
2026-11-08 14:53:27 +08:00
parent 0285fc80bb
commit a927be36f2
2 changed files with 167 additions and 84 deletions
@@ -4,6 +4,7 @@ import { PlusOutlined } from '@ant-design/icons';
import type { HuyaCollabShop } from '../api/modules';
const { Text } = Typography;
type ShopOption = Pick<HuyaCollabShop, 'name' | 'is_active'>;
/**
* 店铺选择器:**一个店铺一个独立按钮**(中间留白),不做下拉。
@@ -27,7 +28,7 @@ export default function HuyaCollabShopPicker({
onChange,
}: {
value?: string | null;
shops: HuyaCollabShop[];
shops: ShopOption[];
disabled?: boolean;
includeInactive?: boolean;
allowCustom?: boolean;
+165 -83
View File
@@ -4,6 +4,7 @@ import {
AutoComplete,
Button,
Checkbox,
Col,
Descriptions,
Drawer,
Form,
@@ -11,6 +12,7 @@ import {
InputNumber,
Modal,
Popconfirm,
Row,
Select,
Space,
Statistic,
@@ -35,6 +37,7 @@ import {
UndoOutlined,
} from '@ant-design/icons';
import HuyaCollabHomeImageUploader from '../components/HuyaCollabHomeImageUploader';
import HuyaCollabShopPicker from '../components/HuyaCollabShopPicker';
import {
weiboCollabApi,
type WeiboCollabAccountLookup,
@@ -71,6 +74,12 @@ const STATUS_META: Record<WeiboCollabStatus, { label: string; color: string }> =
void: { label: '已作废', color: 'default' },
};
const ACCOUNT_CK_LABELS: Record<string, string> = {
valid: '有效',
invalid: '失效',
error: '查询失败',
};
const STATUS_ORDER: WeiboCollabStatus[] = [
'incomplete',
'to_recharge',
@@ -247,6 +256,7 @@ export default function WeiboCollabPage() {
const accountOptions = accounts.map((item) => ({
value: item.id,
label: `${item.nickname || item.uid} · UID ${item.uid}${item.game_role_name ? ` · ${item.game_role_name}` : ''}`,
title: item.nickname || `UID ${item.uid}`,
}));
const liveGoodsOptions = (lookup?.goods || []).map((item) => ({
@@ -263,7 +273,7 @@ export default function WeiboCollabPage() {
.filter((item) => item.is_active)
.map((item) => ({
value: item.name,
label: `${item.name} · ${item.price} 微豆(字典)`,
label: `${item.name} · ${item.price} 微豆(自定义)`,
goods: {
name: item.name,
price: item.price,
@@ -280,8 +290,8 @@ export default function WeiboCollabPage() {
goods_id: number | null;
goods_image: string;
};
}> = [...liveGoodsOptions];
for (const option of catalogGoodsOptions) {
}> = [...catalogGoodsOptions];
for (const option of liveGoodsOptions) {
if (!goodsOptions.some((item) => item.value === option.value)) goodsOptions.push(option);
}
@@ -569,6 +579,14 @@ export default function WeiboCollabPage() {
);
const columns: TableProps<WeiboCollabOrder>['columns'] = [
{
title: '序号',
key: 'index',
width: 72,
align: 'center',
fixed: 'left',
render: (_, __, index) => (page - 1) * pageSize + index + 1,
},
{
title: '订单编号',
dataIndex: 'order_no',
@@ -748,11 +766,6 @@ export default function WeiboCollabPage() {
<Button icon={<ReloadOutlined />} onClick={refreshAll}>
刷新
</Button>
{canEdit && (
<Button type="primary" icon={<PlusOutlined />} onClick={openCreate}>
新建协作单
</Button>
)}
</Space>
</div>
@@ -877,6 +890,11 @@ export default function WeiboCollabPage() {
<Button icon={<FileExcelOutlined />} onClick={() => setGoodsOpen(true)}>
商品管理
</Button>
{canEdit && (
<Button type="primary" icon={<PlusOutlined />} onClick={openCreate}>
新建协作单
</Button>
)}
</Space>
</div>
@@ -944,66 +962,82 @@ export default function WeiboCollabPage() {
<Modal
title={editing ? `编辑协作单 · ${editing.order_no}` : '新建微博外部单'}
open={editOpen}
width={760}
width={920}
confirmLoading={saving}
okText={editing ? '保存' : form.getFieldValue('draft') ? '保存草稿' : '创建并校验'}
cancelText="取消"
onOk={() => void saveOrder()}
onCancel={() => setEditOpen(false)}
styles={{ body: { maxHeight: '78vh', overflowY: 'auto', paddingRight: 12 } }}
destroyOnHidden
>
<Form form={form} layout="vertical">
<Space size={12} style={{ width: '100%' }} align="start">
<Form.Item
name="order_no"
label="订单编号"
rules={[{ required: true, message: '请填写订单编号' }]}
style={{ flex: 1 }}
>
<Input maxLength={64} />
</Form.Item>
<Form.Item name="shop" label="店铺" style={{ flex: 1 }}>
<AutoComplete
options={shops.map((item) => ({ value: item.name }))}
placeholder="可输入新店铺"
filterOption
/>
</Form.Item>
<Form.Item name="owner_id" label="负责人" style={{ width: 150 }}>
<Select
allowClear
options={owners.map((item) => ({ value: item.id, label: item.username }))}
/>
</Form.Item>
</Space>
<Space size={12} style={{ width: '100%' }} align="start">
<Form.Item name="account_id" label="微博账号" style={{ flex: 1 }}>
<Select
allowClear
showSearch
optionFilterProp="label"
options={accountOptions}
loading={lookupLoading}
onChange={(value) => void lookupAccount(value)}
/>
</Form.Item>
<Form.Item name="goods_name" label="商品" style={{ flex: 1 }}>
<AutoComplete
options={goodsOptions}
onChange={handleGoodsChange}
placeholder={lookup ? '选择当前账号商城商品' : '先选账号获取实时商品'}
filterOption
/>
</Form.Item>
<Form.Item
name="required_weidou"
label="所需微豆"
rules={[{ required: true, message: '请填写所需微豆' }]}
style={{ width: 150 }}
>
<InputNumber min={0} precision={0} style={{ width: '100%' }} />
</Form.Item>
</Space>
<Row gutter={16}>
<Col xs={24} md={12}>
<Form.Item
name="order_no"
label="订单编号"
rules={[{ required: true, message: '请填写订单编号' }]}
>
<Input maxLength={64} />
</Form.Item>
</Col>
<Col xs={24} md={12}>
<Form.Item name="owner_id" label="负责人">
<Select
allowClear
options={owners.map((item) => ({ value: item.id, label: item.username }))}
/>
</Form.Item>
</Col>
</Row>
<Form.Item name="shop" label="店铺">
<HuyaCollabShopPicker
shops={shops}
allowClear={false}
allowCustom
size="large"
/>
</Form.Item>
<Row gutter={16}>
<Col xs={24} md={12}>
<Form.Item name="account_id" label="微博账号">
<Select
allowClear
showSearch
optionFilterProp="label"
optionLabelProp="title"
options={accountOptions}
loading={lookupLoading}
placeholder="搜索并选择微博账号"
onChange={(value) => void lookupAccount(value)}
/>
</Form.Item>
</Col>
<Col xs={24} md={8}>
<Form.Item name="goods_name" label="商品">
<AutoComplete
options={goodsOptions}
onChange={handleGoodsChange}
placeholder={
lookup
? '选择当前账号商城商品'
: '选择自定义商品,或先选账号加载实时商品'
}
filterOption
/>
</Form.Item>
</Col>
<Col xs={24} md={4}>
<Form.Item
name="required_weidou"
label="所需微豆"
rules={[{ required: true, message: '请填写所需微豆' }]}
>
<InputNumber min={0} precision={0} style={{ width: '100%' }} />
</Form.Item>
</Col>
</Row>
<Form.Item name="goods_id" hidden>
<InputNumber />
</Form.Item>
@@ -1011,30 +1045,78 @@ export default function WeiboCollabPage() {
<Input />
</Form.Item>
{lookup && (
<Alert
type={lookup.ok ? 'success' : 'warning'}
showIcon
style={{ marginBottom: 16 }}
message={
lookup.ok
? `${lookup.nickname || lookup.uid} · 当前 ${lookup.weidou_balance?.toLocaleString() ?? '-'} 微豆`
: lookup.message || '账号不可用'
}
description={
lookup.orders_using_account.length > 0
? `同账号已有 ${lookup.orders_using_account.length} 单:${lookup.orders_using_account
.map((item) => item.order_no)
.join('、')}`
: undefined
}
/>
<>
<Alert
type={lookup.ok ? 'success' : 'warning'}
showIcon
style={{ marginBottom: 12 }}
message={
lookup.ok
? `${lookup.nickname || lookup.uid} · 当前 ${lookup.weidou_balance?.toLocaleString() ?? '-'} 微豆`
: lookup.message || '账号不可用'
}
/>
{lookup.ok && (
<Descriptions
size="small"
column={3}
style={{ marginBottom: 16 }}
items={[
{ key: 'uid', label: 'UID', children: lookup.uid || '-' },
{
key: 'role',
label: '绑定角色',
children: lookup.game_role_name || '未读取到角色',
},
{
key: 'bind',
label: '绑定状态',
children:
lookup.is_bound === true
? '已绑定'
: lookup.is_bound === false
? '未绑定'
: '未知',
},
{
key: 'ck',
label: 'CK 状态',
children:
ACCOUNT_CK_LABELS[lookup.ck_check_status] ||
lookup.ck_check_status ||
'未检测',
},
{
key: 'orders',
label: '同账号订单',
span: 2,
children:
lookup.orders_using_account.length > 0
? lookup.orders_using_account
.map(
(item) =>
`${item.order_no}(${item.status_label || item.status})`,
)
.join('、')
: '暂无',
},
]}
/>
)}
</>
)}
<Form.Item name="home_images" label="主页截图">
<HuyaCollabHomeImageUploader optional />
</Form.Item>
<Form.Item name="remark" label="备注">
<TextArea rows={3} maxLength={512} showCount />
</Form.Item>
<Row gutter={16}>
<Col xs={24} md={14}>
<Form.Item name="home_images" label="主页截图">
<HuyaCollabHomeImageUploader optional />
</Form.Item>
</Col>
<Col xs={24} md={10}>
<Form.Item name="remark" label="备注">
<TextArea rows={6} maxLength={512} showCount />
</Form.Item>
</Col>
</Row>
{!editing && (
<Form.Item name="draft" valuePropName="checked">
<Checkbox>先保存草稿,不校验账号</Checkbox>