feat(weibo): 增加外部单协作台账
This commit is contained in:
@@ -32,6 +32,7 @@ const HuyaElitePage = lazy(() => import('./pages/HuyaElitePage'));
|
||||
const HuyaCollabPage = lazy(() => import('./pages/HuyaCollabPage'));
|
||||
const HuyaBrowserExchangePage = lazy(() => import('./pages/HuyaBrowserExchangePage'));
|
||||
const WeiboAccountsPage = lazy(() => import('./pages/WeiboAccountsPage'));
|
||||
const WeiboCollabPage = lazy(() => import('./pages/WeiboCollabPage'));
|
||||
const YybRechargePage = lazy(() => import('./pages/YybRechargePage'));
|
||||
const AuditLogsPage = lazy(() => import('./pages/AuditLogsPage'));
|
||||
|
||||
@@ -107,6 +108,7 @@ function AppContent() {
|
||||
<Route path="huya/collab" element={lazyRoute(<HuyaCollabPage />)} />
|
||||
<Route path="huya/browser-exchange" element={lazyRoute(<HuyaBrowserExchangePage />)} />
|
||||
<Route path="weibo/accounts" element={lazyRoute(<WeiboAccountsPage />)} />
|
||||
<Route path="weibo/collab" element={lazyRoute(<WeiboCollabPage />)} />
|
||||
<Route path="yyb/recharge" element={lazyRoute(<YybRechargePage />)} />
|
||||
<Route path="proxy" element={lazyRoute(<ProxyPage />)} />
|
||||
<Route path="automation" element={lazyRoute(<AutomationPage />)} />
|
||||
|
||||
@@ -15,4 +15,28 @@ export { loginApi } from './login';
|
||||
export { proxyApi } from './proxy';
|
||||
export { userApi } from './users';
|
||||
export { weiboApi } from './weibo';
|
||||
export { weiboCollabApi } from './weiboCollab';
|
||||
export type {
|
||||
WeiboCollabAccountLookup,
|
||||
WeiboCollabAccountOption,
|
||||
WeiboCollabArchiveResult,
|
||||
WeiboCollabArchiveScope,
|
||||
WeiboCollabBalanceCheckResult,
|
||||
WeiboCollabExchangeCheckResult,
|
||||
WeiboCollabGoods,
|
||||
WeiboCollabLiveGoods,
|
||||
WeiboCollabMetric,
|
||||
WeiboCollabOrder,
|
||||
WeiboCollabOrderCreate,
|
||||
WeiboCollabOrderList,
|
||||
WeiboCollabOrderUpdate,
|
||||
WeiboCollabOwner,
|
||||
WeiboCollabShop,
|
||||
WeiboCollabStatus,
|
||||
WeiboCollabSummary,
|
||||
WeiboCollabTimeline,
|
||||
WeiboCollabUnarchiveResult,
|
||||
WeiboCollabVerdict,
|
||||
WeiboCollabVerifyBatchResult,
|
||||
} from './weiboCollab';
|
||||
export { yybApi } from './yyb';
|
||||
|
||||
@@ -0,0 +1,408 @@
|
||||
import api from './client';
|
||||
|
||||
export type WeiboCollabStatus =
|
||||
| 'incomplete'
|
||||
| 'to_recharge'
|
||||
| 'recharged'
|
||||
| 'exchange_pending'
|
||||
| 'done'
|
||||
| 'weidou_error'
|
||||
| 'failed'
|
||||
| 'void';
|
||||
|
||||
export type WeiboCollabArchiveScope = 'active' | 'archived' | 'all';
|
||||
export type WeiboCollabVerdict = 'success' | 'failed' | 'unknown' | '';
|
||||
|
||||
export interface WeiboCollabShop {
|
||||
id: number;
|
||||
name: string;
|
||||
sort_order: number;
|
||||
is_active: boolean;
|
||||
remark: string;
|
||||
created_by: number | null;
|
||||
updated_by: number | null;
|
||||
created_at: string | null;
|
||||
updated_at: string | null;
|
||||
}
|
||||
|
||||
export interface WeiboCollabGoods {
|
||||
id: number;
|
||||
name: string;
|
||||
price: number;
|
||||
goods_id: number | null;
|
||||
goods_image: string;
|
||||
sort_order: number;
|
||||
is_active: boolean;
|
||||
remark: string;
|
||||
created_by: number | null;
|
||||
updated_by: number | null;
|
||||
created_at: string | null;
|
||||
updated_at: string | null;
|
||||
}
|
||||
|
||||
export interface WeiboCollabLiveGoods {
|
||||
id: number;
|
||||
goods_name: string;
|
||||
goods_image: string;
|
||||
price: number;
|
||||
remain_count: number | null;
|
||||
is_sold_out: boolean;
|
||||
}
|
||||
|
||||
export interface WeiboCollabAccountLookup {
|
||||
ok: boolean;
|
||||
message: string;
|
||||
account_id: number;
|
||||
uid: string;
|
||||
nickname: string;
|
||||
is_enabled: boolean;
|
||||
ck_check_status: string;
|
||||
ck_check_message: string;
|
||||
is_bound: boolean | null;
|
||||
game_role_name: string;
|
||||
weidou_balance: number | null;
|
||||
goods: WeiboCollabLiveGoods[];
|
||||
orders_using_account: Array<{
|
||||
id: number;
|
||||
order_no: string;
|
||||
status: WeiboCollabStatus;
|
||||
status_label: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface WeiboCollabAccountOption {
|
||||
id: number;
|
||||
uid: string;
|
||||
nickname: string;
|
||||
game_role_name: string;
|
||||
weidou_balance: number | null;
|
||||
ck_check_status: string;
|
||||
}
|
||||
|
||||
export interface WeiboCollabOrder {
|
||||
id: number;
|
||||
order_no: string;
|
||||
shop: string;
|
||||
owner_id: number | null;
|
||||
owner_name: string;
|
||||
account_id: number | null;
|
||||
account_uid: string;
|
||||
account_nickname: string;
|
||||
account_exists: boolean;
|
||||
account_enabled: boolean;
|
||||
account_ck_status: string;
|
||||
account_ck_message: string;
|
||||
account_is_bound: boolean | null;
|
||||
game_role_name: string;
|
||||
bind_snapshot_at: string | null;
|
||||
goods_id: number | null;
|
||||
goods_name: string;
|
||||
goods_image: string;
|
||||
required_weidou: number | null;
|
||||
home_images: string[];
|
||||
remark: string;
|
||||
status: WeiboCollabStatus;
|
||||
status_label: string;
|
||||
next_status: WeiboCollabStatus | null;
|
||||
missing_fields: string[];
|
||||
weidou_balance: number | null;
|
||||
weidou_required_total: number | null;
|
||||
weidou_surplus: number | null;
|
||||
weidou_threshold: number | null;
|
||||
weidou_checked_at: string | null;
|
||||
weidou_check_reason: string;
|
||||
weidou_check_message: string;
|
||||
weidou_check_detail: Record<string, unknown> | null;
|
||||
exchange_started_at: string | null;
|
||||
exchange_checked_at: string | null;
|
||||
exchange_record_key: string;
|
||||
exchange_record_snapshot: Record<string, unknown> | null;
|
||||
exchange_verdict: WeiboCollabVerdict;
|
||||
exchange_message: string;
|
||||
recharged_at: string | null;
|
||||
done_at: string | null;
|
||||
void_reason: string;
|
||||
is_archived: boolean;
|
||||
archived_at: string | null;
|
||||
archived_by: number | null;
|
||||
archived_by_name: string;
|
||||
archive_reason: string;
|
||||
created_by: number | null;
|
||||
created_by_name: string;
|
||||
updated_by: number | null;
|
||||
updated_by_name: string;
|
||||
version: number;
|
||||
created_at: string | null;
|
||||
updated_at: string | null;
|
||||
account_cluster: {
|
||||
total: number;
|
||||
orders: Array<{
|
||||
id: number;
|
||||
order_no: string;
|
||||
status: WeiboCollabStatus;
|
||||
status_label: string;
|
||||
goods_name: string;
|
||||
}>;
|
||||
} | null;
|
||||
last_metric_at: string | null;
|
||||
last_metric_message: string;
|
||||
}
|
||||
|
||||
export interface WeiboCollabOrderList {
|
||||
items: WeiboCollabOrder[];
|
||||
total: number;
|
||||
page: number;
|
||||
page_size: number;
|
||||
}
|
||||
|
||||
export interface WeiboCollabSummary {
|
||||
total: number;
|
||||
by_status: Record<string, number>;
|
||||
account_missing: number;
|
||||
account_disabled: number;
|
||||
ck_invalid: number;
|
||||
archived_total: number;
|
||||
}
|
||||
|
||||
export interface WeiboCollabOwner {
|
||||
id: number;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface WeiboCollabMetric {
|
||||
id: number;
|
||||
order_id: number;
|
||||
order_no: string;
|
||||
account_uid: string;
|
||||
weidou_balance: number | null;
|
||||
weidou_required_total: number | null;
|
||||
weidou_surplus: number | null;
|
||||
records_total: number;
|
||||
records_matched: number;
|
||||
verdict: WeiboCollabVerdict;
|
||||
verdict_label: string;
|
||||
message: string;
|
||||
source: string;
|
||||
created_at: string | null;
|
||||
}
|
||||
|
||||
export interface WeiboCollabTimeline {
|
||||
id: number;
|
||||
action: string;
|
||||
username: string;
|
||||
detail: string;
|
||||
success: boolean | null;
|
||||
created_at: string | null;
|
||||
}
|
||||
|
||||
export interface WeiboCollabOrderCreate {
|
||||
order_no: string;
|
||||
shop?: string;
|
||||
owner_id?: number | null;
|
||||
account_id?: number | null;
|
||||
goods_id?: number | null;
|
||||
goods_name?: string;
|
||||
goods_image?: string;
|
||||
required_weidou?: number | null;
|
||||
home_images?: string[];
|
||||
remark?: string;
|
||||
draft?: boolean;
|
||||
require_verified?: boolean;
|
||||
}
|
||||
|
||||
export interface WeiboCollabOrderUpdate {
|
||||
order_no?: string;
|
||||
shop?: string;
|
||||
owner_id?: number | null;
|
||||
goods_id?: number | null;
|
||||
goods_name?: string;
|
||||
goods_image?: string;
|
||||
required_weidou?: number | null;
|
||||
home_images?: string[];
|
||||
remark?: string;
|
||||
expected_version?: number;
|
||||
}
|
||||
|
||||
export interface WeiboCollabBalanceCheckResult {
|
||||
total: number;
|
||||
updated: number;
|
||||
threshold: number;
|
||||
groups: Array<{
|
||||
account_id: number;
|
||||
uid: string;
|
||||
status: string;
|
||||
status_label: string;
|
||||
balance: number | null;
|
||||
required_total: number;
|
||||
surplus: number | null;
|
||||
threshold: number;
|
||||
reason: string;
|
||||
message: string;
|
||||
order_ids: number[];
|
||||
}>;
|
||||
failures: Array<{ id: number; order_no: string; message: string }>;
|
||||
skipped: Array<{ id: number; order_no: string; message: string }>;
|
||||
}
|
||||
|
||||
export interface WeiboCollabExchangeCheckResult {
|
||||
total: number;
|
||||
success: number;
|
||||
failed: number;
|
||||
unknown: number;
|
||||
results: Array<{
|
||||
id: number;
|
||||
order_no: string;
|
||||
ok: boolean;
|
||||
verdict: WeiboCollabVerdict;
|
||||
verdict_label: string;
|
||||
message: string;
|
||||
records_total: number;
|
||||
records_matched: number;
|
||||
status: WeiboCollabStatus;
|
||||
status_label: string;
|
||||
metric_id: number;
|
||||
}>;
|
||||
failures: Array<{ id: number; order_no: string; message: string }>;
|
||||
}
|
||||
|
||||
export interface WeiboCollabVerifyBatchResult {
|
||||
success: boolean;
|
||||
results: Array<{
|
||||
id: number;
|
||||
order_no: string;
|
||||
success: boolean;
|
||||
message: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface WeiboCollabArchiveResult {
|
||||
total: number;
|
||||
archived: number;
|
||||
skipped: number;
|
||||
results: Array<{ id: number; order_no: string; ok: boolean; message: string }>;
|
||||
}
|
||||
|
||||
export interface WeiboCollabUnarchiveResult {
|
||||
total: number;
|
||||
unarchived: number;
|
||||
skipped: number;
|
||||
results: Array<{ id: number; order_no: string; ok: boolean; message: string }>;
|
||||
}
|
||||
|
||||
export const weiboCollabApi = {
|
||||
accounts: () =>
|
||||
api.get<WeiboCollabAccountOption[], WeiboCollabAccountOption[]>(
|
||||
'/weibo/external-orders/accounts/options',
|
||||
),
|
||||
summary: (params: { include_void?: boolean; archive_scope?: WeiboCollabArchiveScope }) =>
|
||||
api.get<WeiboCollabSummary, WeiboCollabSummary>('/weibo/external-orders/summary', {
|
||||
params,
|
||||
}),
|
||||
owners: () =>
|
||||
api.get<WeiboCollabOwner[], WeiboCollabOwner[]>('/weibo/external-orders/owners'),
|
||||
listOrders: (params: Record<string, unknown>) =>
|
||||
api.get<WeiboCollabOrderList, WeiboCollabOrderList>('/weibo/external-orders', {
|
||||
params,
|
||||
}),
|
||||
getOrder: (id: number) =>
|
||||
api.get<WeiboCollabOrder, WeiboCollabOrder>(`/weibo/external-orders/${id}`),
|
||||
createOrder: (data: WeiboCollabOrderCreate) =>
|
||||
api.post<WeiboCollabOrder, WeiboCollabOrder>('/weibo/external-orders', data, {
|
||||
timeout: 120000,
|
||||
}),
|
||||
updateOrder: (id: number, data: WeiboCollabOrderUpdate) =>
|
||||
api.put<WeiboCollabOrder, WeiboCollabOrder>(`/weibo/external-orders/${id}`, data),
|
||||
setAccount: (id: number, accountId: number, expectedVersion?: number) =>
|
||||
api.post<WeiboCollabOrder, WeiboCollabOrder>(
|
||||
`/weibo/external-orders/${id}/account`,
|
||||
{ account_id: accountId, expected_version: expectedVersion },
|
||||
{ timeout: 120000 },
|
||||
),
|
||||
verifyOrder: (id: number) =>
|
||||
api.post<WeiboCollabOrder, WeiboCollabOrder>(
|
||||
`/weibo/external-orders/${id}/verify`,
|
||||
undefined,
|
||||
{ timeout: 120000 },
|
||||
),
|
||||
updateStatus: (
|
||||
id: number,
|
||||
data: {
|
||||
status: WeiboCollabStatus;
|
||||
reason?: string;
|
||||
rollback?: boolean;
|
||||
expected_version?: number;
|
||||
},
|
||||
) =>
|
||||
api.post<WeiboCollabOrder, WeiboCollabOrder>(
|
||||
`/weibo/external-orders/${id}/status`,
|
||||
data,
|
||||
),
|
||||
batchStatus: (data: {
|
||||
ids: number[];
|
||||
status: WeiboCollabStatus;
|
||||
reason?: string;
|
||||
rollback?: boolean;
|
||||
}) => api.post('/weibo/external-orders/status/batch', data),
|
||||
verifyBatch: (ids: number[]) =>
|
||||
api.post<WeiboCollabVerifyBatchResult, WeiboCollabVerifyBatchResult>(
|
||||
'/weibo/external-orders/verify/batch',
|
||||
ids,
|
||||
{ timeout: 120000 },
|
||||
),
|
||||
checkBalance: (ids: number[], threshold: number) =>
|
||||
api.post<WeiboCollabBalanceCheckResult, WeiboCollabBalanceCheckResult>(
|
||||
'/weibo/external-orders/balances/check',
|
||||
{ ids, threshold },
|
||||
{ timeout: 120000 },
|
||||
),
|
||||
checkExchangeRecords: (ids: number[]) =>
|
||||
api.post<WeiboCollabExchangeCheckResult, WeiboCollabExchangeCheckResult>(
|
||||
'/weibo/external-orders/exchange-records/check',
|
||||
{ ids },
|
||||
{ timeout: 120000 },
|
||||
),
|
||||
archive: (ids: number[], reason = '') =>
|
||||
api.post<WeiboCollabArchiveResult, WeiboCollabArchiveResult>(
|
||||
'/weibo/external-orders/archive',
|
||||
{ ids, reason },
|
||||
),
|
||||
unarchive: (ids: number[]) =>
|
||||
api.post<WeiboCollabUnarchiveResult, WeiboCollabUnarchiveResult>(
|
||||
'/weibo/external-orders/unarchive',
|
||||
ids,
|
||||
),
|
||||
deleteOrder: (id: number) => api.delete(`/weibo/external-orders/${id}`),
|
||||
metrics: (id: number) =>
|
||||
api.get<WeiboCollabMetric[], WeiboCollabMetric[]>(
|
||||
`/weibo/external-orders/${id}/metrics`,
|
||||
),
|
||||
timeline: (id: number) =>
|
||||
api.get<WeiboCollabTimeline[], WeiboCollabTimeline[]>(
|
||||
`/weibo/external-orders/${id}/timeline`,
|
||||
),
|
||||
lookupAccount: (accountId: number, withGoods = true) =>
|
||||
api.post<WeiboCollabAccountLookup, WeiboCollabAccountLookup>(
|
||||
'/weibo/external-orders/accounts/lookup',
|
||||
{ account_id: accountId, with_goods: withGoods },
|
||||
{ timeout: 120000 },
|
||||
),
|
||||
listShops: () =>
|
||||
api.get<WeiboCollabShop[], WeiboCollabShop[]>('/weibo/collab-shops'),
|
||||
createShop: (data: { name: string; remark?: string }) =>
|
||||
api.post<WeiboCollabShop, WeiboCollabShop>('/weibo/collab-shops', data),
|
||||
updateShop: (id: number, data: Partial<Omit<WeiboCollabShop, 'id'>>) =>
|
||||
api.put<WeiboCollabShop, WeiboCollabShop>(`/weibo/collab-shops/${id}`, data),
|
||||
deleteShop: (id: number) => api.delete(`/weibo/collab-shops/${id}`),
|
||||
listGoods: () =>
|
||||
api.get<WeiboCollabGoods[], WeiboCollabGoods[]>('/weibo/collab-goods'),
|
||||
createGoods: (data: {
|
||||
name: string;
|
||||
price: number;
|
||||
goods_id?: number | null;
|
||||
goods_image?: string;
|
||||
remark?: string;
|
||||
}) => api.post<WeiboCollabGoods, WeiboCollabGoods>('/weibo/collab-goods', data),
|
||||
updateGoods: (id: number, data: Partial<Omit<WeiboCollabGoods, 'id'>>) =>
|
||||
api.put<WeiboCollabGoods, WeiboCollabGoods>(`/weibo/collab-goods/${id}`, data),
|
||||
deleteGoods: (id: number) => api.delete(`/weibo/collab-goods/${id}`),
|
||||
};
|
||||
@@ -129,6 +129,9 @@ export default function MainLayout({ onLogout }: { onLogout?: () => void }) {
|
||||
if (can('weibo:view')) {
|
||||
weiboItems.push({ key: '/weibo/accounts', label: '账号与绑定', icon: <MessageOutlined /> });
|
||||
}
|
||||
if (can('weibo:collab:view')) {
|
||||
weiboItems.push({ key: '/weibo/collab', label: '外部单协作', icon: <FileExcelOutlined /> });
|
||||
}
|
||||
|
||||
if (douyuItems.length > 0) {
|
||||
menuItems.push({ key: 'group-douyu', type: 'group', label: '斗鱼', children: douyuItems });
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user