feat(v3.4.13): partner column, version release cascade, client UX fixes

- HQ stores: partner column uses companyName/name/phone via partnerOptionLabel

- Dev plan: version RELEASED auto-marks tasks RELEASED and tickets PUBLISHED with releasedVersionNo

- mini-user/h5-shop/h5-partner v3.4.13 UX fixes (store UI, iOS scan OAuth, partner login guard)

- Docs: v3.4.13 dev doc + status audit updates

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-06 01:02:07 +08:00
parent 3ef4432b2f
commit 4f363fa9e7
25 changed files with 658 additions and 421 deletions
+11 -4
View File
@@ -376,7 +376,7 @@ type StoreRow = {
visibilityWhitelistEnabled?: boolean;
visibilityPhones?: string[];
cityRef?: { name: string; code: string };
partner?: { companyName: string };
partner?: { id?: string; companyName?: string | null; name?: string | null; phone?: string | null };
account?: {
phone: string;
name: string;
@@ -394,13 +394,14 @@ type StoreRow = {
category?: { id: string; name: string; parentId?: string | null } | null;
};
type PartnerOption = { id: string; companyName: string; name?: string };
type PartnerOption = { id: string; companyName?: string | null; name?: string | null; phone?: string | null };
function partnerOptionLabel(p: PartnerOption): string {
const company = (p.companyName || '').trim();
const person = (p.name || '').trim();
const phone = (p.phone || '').trim();
if (company && person) return `${company}-${person}`;
return company || person || p.id;
return company || person || phone || p.id;
}
type CityOption = {
id: string;
@@ -867,7 +868,13 @@ export default function StoresPage() {
);
},
},
{ title: '开城合伙人', dataIndex: ['partner', 'companyName'], width: 120 },
{
title: '开城合伙人',
dataIndex: 'partner',
width: 140,
render: (partner: StoreRow['partner']) =>
partner ? partnerOptionLabel({ id: partner.id ?? '', ...partner }) : '—',
},
{
title: '可见',
dataIndex: 'visibilityWhitelistEnabled',
@@ -56,6 +56,7 @@ const STATUS_COLOR: Record<SupportTicketStatusDto, string> = {
DEVELOPING: 'blue',
TESTING: 'purple',
PASSED: 'green',
PUBLISHED: 'cyan',
};
const TYPE_OPTIONS = (Object.keys(SUPPORT_TICKET_TYPE_LABELS) as SupportTicketTypeDto[]).map(
@@ -482,8 +483,15 @@ export default function SupportTicketsPage() {
title: '状态',
dataIndex: 'status',
width: 100,
render: (s: SupportTicketStatusDto) => (
<Tag color={STATUS_COLOR[s]}>{SUPPORT_TICKET_STATUS_LABELS[s] ?? s}</Tag>
render: (s: SupportTicketStatusDto, row) => (
<Space size={4} direction="vertical" style={{ lineHeight: 1.2 }}>
<Tag color={STATUS_COLOR[s]}>{SUPPORT_TICKET_STATUS_LABELS[s] ?? s}</Tag>
{row.releasedVersionNo ? (
<Typography.Text type="secondary" style={{ fontSize: 11 }}>
{row.releasedVersionNo}
</Typography.Text>
) : null}
</Space>
),
},
{ title: '标题', dataIndex: 'title', ellipsis: true },
@@ -666,6 +674,11 @@ export default function SupportTicketsPage() {
{detail.status === 'PASSED' && (
<Typography.Text type="success"></Typography.Text>
)}
{detail.status === 'PUBLISHED' && (
<Typography.Text type="success">
{detail.releasedVersionNo ? ` · ${detail.releasedVersionNo}` : ''}
</Typography.Text>
)}
</Space>
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
{fmtTime(detail.createdAt)}
@@ -689,6 +702,7 @@ export default function SupportTicketsPage() {
{ key: 'DEVELOPING' as SupportTicketStatusDto, label: '开发中', time: detail.reviewedAt },
{ key: 'TESTING' as SupportTicketStatusDto, label: '测试中', time: null },
{ key: 'PASSED' as SupportTicketStatusDto, label: '已通过', time: detail.completedAt },
{ key: 'PUBLISHED' as SupportTicketStatusDto, label: '已发布', time: detail.publishedAt },
]
: [{ key: 'REJECTED' as SupportTicketStatusDto, label: '已驳回', time: detail.reviewedAt }]),
];