feat(semi-auto): 重构客户资料收集与虎牙绑定确认流程
- 客户资料页按设计稿重构,区服固定四项下拉,游戏编号/角色名校验 - 虎牙登录与绑定页统一深色样式,扫码页新增改用手机号登录 - 待确认角色 UID 改用 huyaUid,不再展示虎牙加密 roleId - 绑定确认新增两侧角色比对,不一致禁止确认,会话过期引导重新登录 - 新增迁移 168/169 与角色绑定单测,脚本换行符固定为 LF
This commit is contained in:
@@ -138,6 +138,21 @@ function applySessionExpiryHeaders(
|
||||
}
|
||||
}
|
||||
|
||||
/** HTTP 状态码兜底文案:避免把英文 statusText(如 Not Found)原样抛给用户 */
|
||||
const HTTP_STATUS_MESSAGES: Record<number, string> = {
|
||||
400: '请求参数有误',
|
||||
401: '登录状态已失效,请重新登录',
|
||||
403: '没有操作权限',
|
||||
404: '接口不存在,请刷新页面后重试',
|
||||
409: '数据已更新,请刷新后重试',
|
||||
422: '提交的数据不合法',
|
||||
429: '操作过于频繁,请稍后再试',
|
||||
500: '服务器开小差了,请稍后重试',
|
||||
502: '服务暂时不可用,请稍后重试',
|
||||
503: '服务维护中,请稍后重试',
|
||||
504: '请求超时,请稍后重试',
|
||||
}
|
||||
|
||||
function resolveFallbackHttpMessage(error: unknown) {
|
||||
const message = String((error as { message?: string })?.message ?? '')
|
||||
|
||||
@@ -149,6 +164,13 @@ function resolveFallbackHttpMessage(error: unknown) {
|
||||
return '网络连接错误'
|
||||
}
|
||||
|
||||
const status = Number((error as { response?: { status?: number } })?.response?.status || 0)
|
||||
const statusMessage = status > 0 ? HTTP_STATUS_MESSAGES[status] : ''
|
||||
|
||||
if (statusMessage) {
|
||||
return statusMessage
|
||||
}
|
||||
|
||||
if (typeof (error as { response?: { statusText?: string } })?.response?.statusText === 'string') {
|
||||
return String((error as { response: { statusText: string } }).response.statusText).trim()
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ const STATUS_COLORS: Record<string, string> = {
|
||||
login_scanned: 'cyan',
|
||||
waiting_binding: 'gold',
|
||||
binding_confirm: 'orange',
|
||||
binding_expired: 'red',
|
||||
binding_failed: 'red',
|
||||
waiting_operator: 'volcano',
|
||||
credential_expired: 'red',
|
||||
processing: 'processing',
|
||||
@@ -67,6 +69,16 @@ const PLATFORM_LABELS: Record<string, string> = {
|
||||
weibo: '微博',
|
||||
}
|
||||
|
||||
const BINDING_STATUS_LABELS: Record<string, string> = {
|
||||
not_started: '未开始',
|
||||
qr_pending: '待扫码',
|
||||
scanned: '已扫码',
|
||||
role_ready: '待确认角色',
|
||||
confirmed: '已确认',
|
||||
failed: '失败',
|
||||
expired: '已过期',
|
||||
}
|
||||
|
||||
type CompleteFormValues = {
|
||||
note?: string
|
||||
externalOrderNo?: string
|
||||
@@ -344,6 +356,16 @@ export default function AdminSemiAutoTasksPage() {
|
||||
<Space direction="vertical" size={2}>
|
||||
<Tag>{task.displayStatus.label}</Tag>
|
||||
<Text type="secondary">{task.huyaUid ? `UID ${task.huyaUid}` : '未获取 UID'}</Text>
|
||||
<Text type="secondary">
|
||||
{task.platform === 'huya'
|
||||
? `绑定:${BINDING_STATUS_LABELS[task.bindingStatus] || task.bindingStatus}`
|
||||
: '微博登录即授权'}
|
||||
</Text>
|
||||
{task.platform === 'huya' && (task.bindGameRole || task.bindGameRoleId) ? (
|
||||
<Text type="secondary">
|
||||
{`角色:${task.bindGameRole || '-'}${task.bindGameRoleId ? `(${task.bindGameRoleId})` : '(无角色ID)'}`}
|
||||
</Text>
|
||||
) : null}
|
||||
<Text type="secondary">
|
||||
CK:
|
||||
{task.credentialStatus === 'valid'
|
||||
@@ -616,6 +638,24 @@ export default function AdminSemiAutoTasksPage() {
|
||||
<Descriptions.Item label="登录状态">
|
||||
{detail.task.loginStatus === 'authenticated' ? 'CK 已获取' : '等待客户登录'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="绑定状态">
|
||||
{detail.task.platform === 'weibo'
|
||||
? '微博登录即授权'
|
||||
: BINDING_STATUS_LABELS[detail.task.bindingStatus] || detail.task.bindingStatus}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="绑定角色">
|
||||
{detail.task.bindGameRole
|
||||
? `${detail.task.bindGameRole}${detail.task.bindGameRoleId ? `(${detail.task.bindGameRoleId})` : '(无角色ID)'}`
|
||||
: '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="客户填写角色">
|
||||
{detail.task.customerGameRoleName
|
||||
? `${detail.task.customerGameRoleName}${detail.task.customerGameRoleId ? `(${detail.task.customerGameRoleId})` : ''}`
|
||||
: '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="区服">
|
||||
{detail.task.customerServerZone || '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="客服">
|
||||
{detail.task.assignedAdminName || '未领取'}
|
||||
</Descriptions.Item>
|
||||
@@ -765,6 +805,7 @@ function taskNeedsCustomerReauth(task: SemiAutoTask) {
|
||||
function taskCanUseCredential(task: SemiAutoTask) {
|
||||
return (
|
||||
task.loginStatus === 'authenticated' &&
|
||||
(task.platform === 'weibo' || task.bindingStatus === 'confirmed') &&
|
||||
task.credentialReady &&
|
||||
task.credentialStatus !== 'invalid' &&
|
||||
task.credentialStatus !== 'error'
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,9 @@
|
||||
import { apiGet, apiPost } from '@/lib/http'
|
||||
import type { CustomerLoginInfo, CustomerSemiAutoTask } from '@/types/customer-fulfillment'
|
||||
import type {
|
||||
CustomerBindingInfo,
|
||||
CustomerLoginInfo,
|
||||
CustomerSemiAutoTask,
|
||||
} from '@/types/customer-fulfillment'
|
||||
|
||||
export function fetchCustomerFulfillment(orderNo: string) {
|
||||
return apiGet<CustomerSemiAutoTask[]>(
|
||||
@@ -14,6 +18,17 @@ export function markCustomerFulfillmentOpened(orderNo: string, taskId: number) {
|
||||
)
|
||||
}
|
||||
|
||||
export function saveCustomerTaskProfile(
|
||||
orderNo: string,
|
||||
taskId: number,
|
||||
input: { roleName: string; roleId: string; serverZone: string },
|
||||
) {
|
||||
return apiPost<{ task: CustomerSemiAutoTask }>(
|
||||
`/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/profile`,
|
||||
input,
|
||||
)
|
||||
}
|
||||
|
||||
export function startCustomerLogin(orderNo: string, taskId: number) {
|
||||
return apiPost<{ task: CustomerSemiAutoTask; login: CustomerLoginInfo }>(
|
||||
`/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/login/start`,
|
||||
@@ -27,6 +42,30 @@ export function pollCustomerLogin(orderNo: string, taskId: number) {
|
||||
)
|
||||
}
|
||||
|
||||
export function startCustomerBinding(
|
||||
orderNo: string,
|
||||
taskId: number,
|
||||
options: { forceRebind?: boolean } = {},
|
||||
) {
|
||||
return apiPost<{ task: CustomerSemiAutoTask; binding: CustomerBindingInfo }>(
|
||||
`/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/binding/start`,
|
||||
options.forceRebind ? { forceRebind: true } : {},
|
||||
)
|
||||
}
|
||||
|
||||
export function pollCustomerBinding(orderNo: string, taskId: number) {
|
||||
return apiGet<{ task: CustomerSemiAutoTask; binding: CustomerBindingInfo | null }>(
|
||||
`/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/binding/status`,
|
||||
)
|
||||
}
|
||||
|
||||
export function confirmCustomerBinding(orderNo: string, taskId: number) {
|
||||
return apiPost<{ task: CustomerSemiAutoTask; binding: CustomerBindingInfo }>(
|
||||
`/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/binding/confirm`,
|
||||
{},
|
||||
)
|
||||
}
|
||||
|
||||
type CustomerHuyaChallengeBase = {
|
||||
image: string
|
||||
width: number
|
||||
|
||||
@@ -1437,54 +1437,47 @@
|
||||
}
|
||||
|
||||
.customer-auth-page {
|
||||
--auth-accent: #ff8a00;
|
||||
--auth-accent-hover: #ffa12f;
|
||||
--auth-panel: #07142e;
|
||||
--auth-panel-soft: #0d1d3d;
|
||||
--auth-line: rgba(255, 255, 255, 0.11);
|
||||
--auth-text: #f8fafc;
|
||||
--auth-muted: #a6b0c3;
|
||||
--auth-accent: #2f6fed;
|
||||
--auth-accent-hover: #4a83ff;
|
||||
--auth-panel: #232936;
|
||||
--auth-panel-soft: #2a3140;
|
||||
--auth-line: rgba(255, 255, 255, 0.08);
|
||||
--auth-text: #f5f7fa;
|
||||
--auth-muted: #9aa3b2;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
overflow-x: hidden;
|
||||
padding: clamp(20px, 4vw, 48px) 16px;
|
||||
padding: 0;
|
||||
color: var(--auth-text);
|
||||
background: #202124;
|
||||
background: #232936;
|
||||
}
|
||||
|
||||
.customer-auth-shell {
|
||||
width: min(760px, 100%);
|
||||
width: min(560px, 100%);
|
||||
min-width: 0;
|
||||
align-self: flex-start;
|
||||
align-self: stretch;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 8px;
|
||||
background: var(--auth-panel);
|
||||
box-shadow: 0 28px 70px rgba(0, 0, 0, 0.34);
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.customer-auth-hero {
|
||||
min-height: 176px;
|
||||
min-height: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 34px 38px;
|
||||
background-image:
|
||||
linear-gradient(
|
||||
90deg,
|
||||
rgba(3, 18, 55, 0.97) 0%,
|
||||
rgba(5, 23, 65, 0.83) 48%,
|
||||
rgba(7, 20, 43, 0.45) 100%
|
||||
),
|
||||
url('https://game.gtimg.cn/images/gp/web201908/inside_kv.jpg');
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
justify-content: center;
|
||||
padding: 38px 16px 10px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.customer-auth-brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 18px;
|
||||
justify-content: center;
|
||||
gap: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@@ -1505,28 +1498,30 @@
|
||||
.customer-auth-brand h1 {
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
font-size: clamp(18px, 2.3vw, 22px);
|
||||
line-height: 1.3;
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
line-height: 1.4;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.customer-auth-warning {
|
||||
padding: 19px 24px;
|
||||
padding: 6px 16px 10px;
|
||||
color: #ff6975;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
background: #06122b;
|
||||
border-bottom: 1px solid var(--auth-line);
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
background: transparent;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.customer-auth-main {
|
||||
min-width: 0;
|
||||
padding-bottom: 24px;
|
||||
color: var(--auth-text);
|
||||
background: var(--auth-panel);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.customer-auth-content-stack {
|
||||
@@ -1605,8 +1600,8 @@
|
||||
|
||||
.customer-auth-section {
|
||||
min-width: 0;
|
||||
padding: 28px 26px 30px;
|
||||
border-bottom: 1px solid var(--auth-line);
|
||||
padding: 16px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.customer-auth-section-heading {
|
||||
@@ -1616,24 +1611,24 @@
|
||||
}
|
||||
|
||||
.customer-auth-section-icon {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
flex: none;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||
border-radius: 7px;
|
||||
border-radius: 8px;
|
||||
color: var(--auth-accent);
|
||||
font-size: 22px;
|
||||
font-size: 18px;
|
||||
background: rgba(255, 255, 255, 0.035);
|
||||
}
|
||||
|
||||
.customer-auth-section-heading h2,
|
||||
.customer-auth-state h2 {
|
||||
margin: 0 0 8px;
|
||||
margin: 0 0 6px;
|
||||
color: #fff;
|
||||
font-size: 23px;
|
||||
line-height: 1.35;
|
||||
font-size: 18px;
|
||||
line-height: 1.4;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@@ -2081,6 +2076,607 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.customer-auth-binding {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.customer-auth-binding-tip {
|
||||
color: #ffb454;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.customer-auth-profile,
|
||||
.customer-auth-profile-summary {
|
||||
padding: 14px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.14);
|
||||
border-radius: 6px;
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
}
|
||||
|
||||
.customer-auth-profile > p {
|
||||
margin: 0 0 10px;
|
||||
color: var(--auth-muted);
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.customer-auth-profile-summary {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.customer-auth-profile-summary span {
|
||||
color: var(--auth-muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.customer-auth-profile-summary strong {
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.customer-auth-profile-summary em {
|
||||
color: var(--auth-muted);
|
||||
font-style: normal;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* 客户资料页(图 1) */
|
||||
.customer-collect-page {
|
||||
min-height: 100vh;
|
||||
background: #0b1220;
|
||||
color: #e5e7eb;
|
||||
}
|
||||
|
||||
.customer-collect-hero {
|
||||
position: relative;
|
||||
height: 210px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.customer-collect-hero-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: left center;
|
||||
filter: saturate(0.9) brightness(0.72);
|
||||
}
|
||||
|
||||
.customer-collect-hero-mask {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(180deg, rgba(11, 18, 32, 0.1), rgba(11, 18, 32, 0.96));
|
||||
}
|
||||
|
||||
.customer-collect-warning {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 22px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
color: #f87171;
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.customer-collect-body {
|
||||
max-width: 560px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 20px 48px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.customer-collect-label {
|
||||
margin-top: 8px;
|
||||
color: #e5e7eb;
|
||||
font-size: 15px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.customer-collect-label span {
|
||||
color: #f87171;
|
||||
}
|
||||
|
||||
.customer-collect-readonly {
|
||||
height: 56px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
border-radius: 12px;
|
||||
background: #1b2436;
|
||||
border: 1px solid #26344d;
|
||||
color: #94a3b8;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.customer-collect-card {
|
||||
margin: 10px 0;
|
||||
padding: 16px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #1e2f4a;
|
||||
background: #141d30;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.customer-collect-card > div {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
color: #cbd5e1;
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.customer-collect-card > div > span {
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.customer-collect-card > div strong {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
text-align: right;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.customer-collect-card > p {
|
||||
margin: 6px 0 0;
|
||||
color: #fbbf24;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.customer-collect-input.ant-input {
|
||||
height: 56px;
|
||||
border-radius: 12px;
|
||||
background: #1b2436;
|
||||
border-color: #26344d;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.customer-collect-input.ant-input::placeholder {
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.customer-collect-select.ant-select {
|
||||
width: 100%;
|
||||
height: 56px;
|
||||
padding-inline: 16px;
|
||||
align-items: center;
|
||||
font-size: 15px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #26344d;
|
||||
background: #1b2436;
|
||||
color: #fff;
|
||||
--ant-select-height: 56px;
|
||||
--ant-select-border-radius: 12px;
|
||||
--ant-select-border-color: #26344d;
|
||||
--ant-select-background-color: #1b2436;
|
||||
--ant-select-color: #fff;
|
||||
--ant-select-hover-border-color: #3b4d6b;
|
||||
--ant-select-active-border-color: #2563eb;
|
||||
--ant-select-active-outline-color: rgba(37, 99, 235, 0.2);
|
||||
}
|
||||
|
||||
.customer-collect-select.ant-select:hover {
|
||||
border-color: #3b4d6b;
|
||||
}
|
||||
|
||||
.customer-collect-select.ant-select.ant-select-focused {
|
||||
border-color: #2563eb;
|
||||
box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.2);
|
||||
}
|
||||
|
||||
.customer-collect-select .ant-select-content {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.customer-collect-select .ant-select-selection-item {
|
||||
color: #fff;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.customer-collect-select .ant-select-placeholder {
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.customer-collect-select .ant-select-suffix {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.ant-select-dropdown.customer-collect-dropdown {
|
||||
padding: 6px;
|
||||
border-radius: 12px;
|
||||
background: #141d30;
|
||||
box-shadow: 0 14px 34px rgba(2, 6, 23, 0.55);
|
||||
--ant-select-option-active-bg: #1b2436;
|
||||
--ant-select-option-selected-bg: #1e3a8a;
|
||||
--ant-select-option-selected-color: #fff;
|
||||
}
|
||||
|
||||
.customer-collect-dropdown .ant-select-item {
|
||||
border-radius: 8px;
|
||||
color: #cbd5e1;
|
||||
}
|
||||
|
||||
.customer-collect-dropdown .ant-select-item-option-active {
|
||||
background: #1b2436 !important;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.customer-collect-dropdown .ant-select-item-option-selected {
|
||||
background: #1e3a8a !important;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.customer-collect-page .customer-collect-submit.ant-btn {
|
||||
height: 56px;
|
||||
margin-top: 14px;
|
||||
border-radius: 14px;
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
--ant-btn-bg-color: #2563eb;
|
||||
--ant-btn-bg-color-hover: #1d4ed8;
|
||||
--ant-btn-bg-color-active: #1e40af;
|
||||
--ant-btn-text-color: #fff;
|
||||
--ant-btn-text-color-hover: #fff;
|
||||
--ant-btn-text-color-active: #fff;
|
||||
--ant-btn-border-color: #2563eb;
|
||||
--ant-btn-border-color-hover: #1d4ed8;
|
||||
--ant-btn-border-color-active: #1e40af;
|
||||
background: #2563eb !important;
|
||||
border-color: #2563eb !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.customer-collect-page .customer-collect-submit.ant-btn:hover,
|
||||
.customer-collect-page .customer-collect-submit.ant-btn:focus-visible {
|
||||
background: #1d4ed8 !important;
|
||||
border-color: #1d4ed8 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* 登录与绑定页(图 2-10) */
|
||||
.customer-login-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.customer-login-hint {
|
||||
margin: 0 0 2px;
|
||||
color: #d5dae3;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.customer-login-mobile-row {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.customer-login-mobile.ant-input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
height: 52px;
|
||||
padding: 0 16px;
|
||||
border-radius: 8px;
|
||||
border-color: #3a4150;
|
||||
background: #1b2130;
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.customer-login-mobile.ant-input::placeholder {
|
||||
color: #6b7482;
|
||||
}
|
||||
|
||||
.customer-login-code-button.ant-btn {
|
||||
flex: none;
|
||||
width: 118px;
|
||||
height: 52px;
|
||||
border-radius: 8px;
|
||||
background: #3b82f6 !important;
|
||||
border-color: #3b82f6 !important;
|
||||
color: #fff !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.customer-login-code-input.ant-input {
|
||||
height: 52px;
|
||||
border-radius: 8px;
|
||||
border-color: #3a4150;
|
||||
background: #1b2130;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
letter-spacing: 6px;
|
||||
}
|
||||
|
||||
.customer-login-code-input.ant-input::placeholder {
|
||||
color: #6b7482;
|
||||
}
|
||||
|
||||
.customer-login-submit.ant-btn {
|
||||
height: 52px;
|
||||
border-radius: 8px;
|
||||
background: #0aa53a !important;
|
||||
border-color: #0aa53a !important;
|
||||
color: #fff !important;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.customer-login-alt.ant-btn {
|
||||
height: 52px;
|
||||
border-radius: 8px;
|
||||
background: transparent !important;
|
||||
border-color: #3a4150 !important;
|
||||
color: #cbd5e1 !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.customer-order-card {
|
||||
margin: 10px 16px 0;
|
||||
padding: 16px;
|
||||
border: 1px solid #3a4150;
|
||||
border-radius: 12px;
|
||||
background: #212733;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.customer-order-card h3 {
|
||||
margin: 0 0 4px;
|
||||
color: #94a3b8;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.customer-order-card > div {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
color: #cbd5e1;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.customer-order-card > div > span {
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
color: #9aa3b2;
|
||||
}
|
||||
|
||||
.customer-order-card > div strong {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
color: #fff;
|
||||
text-align: right;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.customer-binding-stage {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.customer-binding-info {
|
||||
padding: 16px;
|
||||
border: 1px solid #3a4150;
|
||||
border-radius: 12px;
|
||||
background: #212733;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.customer-binding-info h3 {
|
||||
margin: 0 0 4px;
|
||||
color: #9aa3b2;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.customer-binding-info h3 small {
|
||||
color: #64748b;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.customer-binding-info > div {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
color: #cbd5e1;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.customer-binding-info > div > span {
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.customer-binding-info > div strong {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
color: #fff;
|
||||
text-align: right;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.customer-binding-alert {
|
||||
padding: 12px 14px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.customer-binding-alert.is-warning {
|
||||
color: #fbbf24;
|
||||
border-color: #78350f;
|
||||
background: rgba(120, 53, 15, 0.25);
|
||||
}
|
||||
|
||||
.customer-binding-alert.is-info {
|
||||
color: #93c5fd;
|
||||
border-color: #1e3a8a;
|
||||
background: rgba(30, 58, 138, 0.3);
|
||||
}
|
||||
|
||||
.customer-binding-qr-card {
|
||||
padding: 18px;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
color: #111827;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.customer-binding-qr-card h3 {
|
||||
margin: 0;
|
||||
color: #6b7280;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.customer-binding-qr-hint {
|
||||
margin: 0;
|
||||
color: #6b7280;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.customer-binding-qr-tip {
|
||||
margin: 0;
|
||||
color: #f59e0b;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.customer-binding-qr-countdown {
|
||||
margin: 0;
|
||||
color: #6b7280;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.customer-binding-qr-actions {
|
||||
width: 100%;
|
||||
margin-top: 4px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.customer-binding-qr-actions .ant-btn {
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.customer-binding-next.ant-btn {
|
||||
width: 100%;
|
||||
height: 46px;
|
||||
margin-top: 6px;
|
||||
border-radius: 8px;
|
||||
background: #2563eb !important;
|
||||
border-color: #2563eb !important;
|
||||
color: #fff !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.customer-binding-modal-footer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.customer-binding-modal-actions {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.customer-binding-modal-actions .ant-btn {
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.customer-binding-modal-error {
|
||||
margin: 0;
|
||||
color: #dc2626;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.customer-binding-modal-warning {
|
||||
margin: 0;
|
||||
color: #d97706;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.customer-binding-compare {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.customer-binding-compare-side {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding: 14px;
|
||||
border: 1px solid rgba(15, 23, 42, 0.12);
|
||||
border-radius: 6px;
|
||||
background: rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
|
||||
.customer-binding-compare-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.customer-binding-compare-side strong {
|
||||
color: #0f172a;
|
||||
font-size: 16px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.customer-binding-compare-side em {
|
||||
color: #64748b;
|
||||
font-style: normal;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.customer-binding-compare {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.customer-auth-button-stack {
|
||||
width: min(100%, 580px);
|
||||
display: flex;
|
||||
@@ -2190,49 +2786,43 @@
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.customer-auth-page {
|
||||
height: 100dvh;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
min-height: 100vh;
|
||||
overflow: visible;
|
||||
padding: 0;
|
||||
background: var(--auth-panel);
|
||||
}
|
||||
|
||||
.customer-auth-shell {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: auto;
|
||||
display: block;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.customer-auth-hero {
|
||||
min-height: 116px;
|
||||
flex: none;
|
||||
padding: 20px 22px;
|
||||
background-position: 58% center;
|
||||
min-height: auto;
|
||||
padding: 38px 16px 10px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.customer-auth-brand h1 {
|
||||
font-size: 18px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.customer-auth-warning {
|
||||
flex: none;
|
||||
padding: 12px 14px;
|
||||
font-size: 16px;
|
||||
padding: 6px 16px 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.customer-auth-main {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.customer-auth-content-stack {
|
||||
height: 100%;
|
||||
height: auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
@@ -2257,7 +2847,7 @@
|
||||
}
|
||||
|
||||
.customer-auth-section {
|
||||
padding: 14px 16px 10px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.customer-auth-section-copy h2,
|
||||
|
||||
@@ -13,6 +13,7 @@ export type SemiAutoTask = {
|
||||
platform: SemiAutoPlatform
|
||||
platformLabel: string
|
||||
loginStatus: string
|
||||
bindingStatus: string
|
||||
executionStatus: string
|
||||
connectorMode: 'embedded' | 'external' | 'mock'
|
||||
displayStatus: SemiAutoDisplayStatus
|
||||
@@ -23,6 +24,13 @@ export type SemiAutoTask = {
|
||||
credentialUpdatedAt: string | null
|
||||
huyaUid: string
|
||||
platformNickname: string
|
||||
bindGameAccount: string
|
||||
bindGameRole: string
|
||||
bindGameRoleId: string
|
||||
bindGameChannel: string
|
||||
customerGameRoleId: string
|
||||
customerGameRoleName: string
|
||||
customerServerZone: string
|
||||
targetQuantity: number
|
||||
completedQuantity: number
|
||||
assignedAdminUserId: number | null
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
export type CustomerBindingComparison = {
|
||||
verdict: 'match' | 'mismatch' | 'unknown'
|
||||
customerRoleName: string
|
||||
customerRoleId: string
|
||||
boundRoleName: string
|
||||
boundRoleId: string
|
||||
message: string
|
||||
}
|
||||
|
||||
export type CustomerSemiAutoTask = {
|
||||
id: number
|
||||
platform: 'huya' | 'weibo'
|
||||
@@ -8,10 +17,18 @@ export type CustomerSemiAutoTask = {
|
||||
skuCode: string
|
||||
quantity: number
|
||||
loginStatus: string
|
||||
bindingStatus: string
|
||||
executionStatus: string
|
||||
displayStatus: { key: string; label: string }
|
||||
huyaUid: string
|
||||
platformNickname: string
|
||||
bindGameAccount: string
|
||||
bindGameRole: string
|
||||
bindGameRoleId: string
|
||||
bindGameChannel: string
|
||||
customerGameRoleId: string
|
||||
customerGameRoleName: string
|
||||
customerServerZone: string
|
||||
completedAt: string | null
|
||||
completionNote: string
|
||||
semiAutoConfig: {
|
||||
@@ -28,3 +45,18 @@ export type CustomerLoginInfo = {
|
||||
expiresAt: string
|
||||
message: string
|
||||
}
|
||||
|
||||
export type CustomerBindingInfo = {
|
||||
status: string
|
||||
qrImage: string
|
||||
qrExpiresAt: string
|
||||
qrUrl: string
|
||||
bindGameAccount: string
|
||||
bindGameRole: string
|
||||
bindGameRoleId: string
|
||||
bindGameChannel: string
|
||||
hasExistingBinding: boolean
|
||||
rebindRequested: boolean
|
||||
message: string
|
||||
comparison: CustomerBindingComparison
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user