增加工单首次查看标识
This commit is contained in:
@@ -269,12 +269,24 @@ function applyWorkerDepositRule(queryClient: ReturnType<typeof useQueryClient>,
|
||||
}
|
||||
|
||||
function matchesWorkOrderKeyword(
|
||||
item: { productName?: unknown; platformOrderId?: unknown },
|
||||
item: { productName?: unknown; platformOrderId?: unknown; material?: unknown },
|
||||
keyword: string,
|
||||
) {
|
||||
const normalizedKeyword = keyword.trim().toLowerCase()
|
||||
if (!normalizedKeyword) return true
|
||||
return [item.productName, item.platformOrderId]
|
||||
const material = isRecord(item.material) ? item.material : {}
|
||||
const collect = isRecord(material.collect) ? material.collect : {}
|
||||
const fields = isRecord(collect.fields) ? collect.fields : {}
|
||||
return [
|
||||
item.productName,
|
||||
item.platformOrderId,
|
||||
fields.gameId,
|
||||
fields.gameNickname,
|
||||
fields.gameAccount,
|
||||
fields.roleName,
|
||||
material.gameId,
|
||||
material.gameNickname,
|
||||
]
|
||||
.map((value) => String(value || '').toLowerCase())
|
||||
.some((value) => value.includes(normalizedKeyword))
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
fetchWorkerMyOrderOverview,
|
||||
fetchWorkerMyOrders,
|
||||
fetchWorkerProfile,
|
||||
markWorkerOrderRead,
|
||||
remindWorkerAcceptance,
|
||||
saveWorkerAcceptanceDraft,
|
||||
saveWorkerOrderNote,
|
||||
@@ -231,7 +232,23 @@ export default function WorkerOrdersPage() {
|
||||
])
|
||||
}
|
||||
|
||||
function markOrderAsRead(order: WorkOrder) {
|
||||
if (!order.isUnread) return
|
||||
queryClient.setQueriesData({ queryKey: ['worker-my-orders'] }, (current: unknown) =>
|
||||
patchWorkOrderReadState(current, order.workOrderId),
|
||||
)
|
||||
void markWorkerOrderRead(order.workOrderId).catch(() => {
|
||||
void queryClient.invalidateQueries({ queryKey: ['worker-my-orders'] })
|
||||
})
|
||||
}
|
||||
|
||||
function openOrderDetail(order: WorkOrder) {
|
||||
markOrderAsRead(order)
|
||||
setDetailOrder(order)
|
||||
}
|
||||
|
||||
function copyOrderInfo(order: WorkOrder) {
|
||||
markOrderAsRead(order)
|
||||
const items = getCopyOrderInfoItems(order)
|
||||
if (items.length === 0) {
|
||||
message.warning('该订单暂无可复制信息')
|
||||
@@ -273,6 +290,7 @@ export default function WorkerOrdersPage() {
|
||||
}
|
||||
|
||||
function openAcceptanceModal(order: WorkOrder) {
|
||||
markOrderAsRead(order)
|
||||
setEditingOrder(order)
|
||||
// 已提交:以已提交的验收资料为初始内容;未提交:以暂存草稿为初始内容
|
||||
const source = hasSubmittedAcceptance(order)
|
||||
@@ -284,6 +302,7 @@ export default function WorkerOrdersPage() {
|
||||
}
|
||||
|
||||
function openNoteModal(order: WorkOrder) {
|
||||
markOrderAsRead(order)
|
||||
setNoteOrder(order)
|
||||
noteForm.setFieldsValue({ note: String(order.workerNote || '') })
|
||||
}
|
||||
@@ -388,14 +407,21 @@ export default function WorkerOrdersPage() {
|
||||
width: 270,
|
||||
render: (_, row) => (
|
||||
<div className="cell-stack">
|
||||
<Typography.Link
|
||||
strong
|
||||
onClick={() => setDetailOrder(row)}
|
||||
title={row.productName || '未命名商品'}
|
||||
ellipsis
|
||||
>
|
||||
{row.productName || '未命名商品'}
|
||||
</Typography.Link>
|
||||
<Space size={4} align="center">
|
||||
{row.isUnread ? (
|
||||
<Tag color="red" className="worker-order-unread-tag">
|
||||
新
|
||||
</Tag>
|
||||
) : null}
|
||||
<Typography.Link
|
||||
strong
|
||||
onClick={() => openOrderDetail(row)}
|
||||
title={row.productName || '未命名商品'}
|
||||
ellipsis
|
||||
>
|
||||
{row.productName || '未命名商品'}
|
||||
</Typography.Link>
|
||||
</Space>
|
||||
<Space size={[4, 4]} wrap>
|
||||
{row.categoryName ? <Tag color="blue">{row.categoryName}</Tag> : null}
|
||||
{row.myShare ? <Tag color="purple">拼单</Tag> : null}
|
||||
@@ -596,7 +622,7 @@ export default function WorkerOrdersPage() {
|
||||
<Button
|
||||
aria-label="查看详情"
|
||||
icon={<EyeOutlined />}
|
||||
onClick={() => setDetailOrder(row)}
|
||||
onClick={() => openOrderDetail(row)}
|
||||
/>
|
||||
</Tooltip>
|
||||
{canEditAcceptanceImages(row) ? (
|
||||
@@ -724,6 +750,11 @@ export default function WorkerOrdersPage() {
|
||||
{/* 卡片顶栏:分类 + 订单号 + 状态/倒计时 */}
|
||||
<div className="worker-order-mobile-header">
|
||||
<div className="worker-order-mobile-header-left">
|
||||
{order.isUnread ? (
|
||||
<Tag color="red" className="worker-order-unread-tag">
|
||||
新
|
||||
</Tag>
|
||||
) : null}
|
||||
{order.categoryName ? (
|
||||
<Tag color="blue" className="worker-order-mobile-tag">
|
||||
{order.categoryName}
|
||||
@@ -892,7 +923,7 @@ export default function WorkerOrdersPage() {
|
||||
<Button
|
||||
size="small"
|
||||
icon={<EyeOutlined />}
|
||||
onClick={() => setDetailOrder(order)}
|
||||
onClick={() => openOrderDetail(order)}
|
||||
>
|
||||
详情
|
||||
</Button>
|
||||
@@ -1304,6 +1335,27 @@ export default function WorkerOrdersPage() {
|
||||
)
|
||||
}
|
||||
|
||||
function patchWorkOrderReadState(current: unknown, workOrderId: number) {
|
||||
if (!isRecord(current) || !isRecord(current.data) || !Array.isArray(current.data.items)) {
|
||||
return current
|
||||
}
|
||||
return {
|
||||
...current,
|
||||
data: {
|
||||
...current.data,
|
||||
items: current.data.items.map((item) =>
|
||||
isRecord(item) && Number(item.workOrderId) === workOrderId
|
||||
? { ...item, isUnread: false }
|
||||
: item,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return Boolean(value && typeof value === 'object' && !Array.isArray(value))
|
||||
}
|
||||
|
||||
function canSubmitAcceptance(order: WorkOrder) {
|
||||
if (order.myShare) {
|
||||
return order.myShare.status === 'joined' && order.status !== 'accepted'
|
||||
|
||||
@@ -172,6 +172,10 @@ export function fetchWorkerMyOrderEvents(workOrderId: number) {
|
||||
return apiGet<{ items: WorkOrderEvent[] }>(`/api/v1/worker/orders/${workOrderId}/events`)
|
||||
}
|
||||
|
||||
export function markWorkerOrderRead(workOrderId: number) {
|
||||
return apiPost<{ viewedAt: string; isUnread: false }>(`/api/v1/worker/orders/${workOrderId}/read`)
|
||||
}
|
||||
|
||||
export function saveWorkerOrderNote(workOrderId: number, note: string) {
|
||||
return apiPost<{ order: WorkOrder }>(`/api/v1/worker/orders/${workOrderId}/note`, { note })
|
||||
}
|
||||
|
||||
@@ -1008,6 +1008,11 @@ body {
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.worker-order-unread-tag {
|
||||
margin: 0;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.worker-order-mobile-orderno-text {
|
||||
font-size: 12px;
|
||||
color: #64748b;
|
||||
|
||||
@@ -309,6 +309,8 @@ export type WorkOrder = {
|
||||
/** 暂存的验收草稿(未提交时保存于此,刷新不丢失;提交后清空) */
|
||||
draftAcceptance: WorkerAcceptance
|
||||
workerNote?: string
|
||||
/** 打手本人尚未点击查看或操作过该工单。 */
|
||||
isUnread?: boolean
|
||||
problemNote: string
|
||||
worker: null | {
|
||||
workerId: number
|
||||
|
||||
Reference in New Issue
Block a user