增加工单首次查看标识
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
getWorkerUserById,
|
||||
getWorkOrderById,
|
||||
listWorkerWorkOrderNotes,
|
||||
listWorkerWorkOrderViews,
|
||||
listWorkOrderShares,
|
||||
sumPendingUnfreezeByOrderIds,
|
||||
} from '../../repositories/worker-platform/index.js'
|
||||
@@ -283,15 +284,26 @@ async function publishWorkOrderSnapshots(input: {
|
||||
)) {
|
||||
const worker = await getWorkerUserById(workerId)
|
||||
if (!worker) continue
|
||||
const notes = await listWorkerWorkOrderNotes(workerId, [workOrderId])
|
||||
const [notes, views] = await Promise.all([
|
||||
listWorkerWorkOrderNotes(workerId, [workOrderId]),
|
||||
listWorkerWorkOrderViews(workerId, [workOrderId]),
|
||||
])
|
||||
const note = notes.find((item) => Number(item.work_order_id) === workOrderId)?.note || ''
|
||||
const viewedAt =
|
||||
views.find((item) => Number(item.work_order_id) === workOrderId)?.viewed_at || null
|
||||
const share = shares.find((item) => Number(item.worker_id) === workerId)
|
||||
publishRealtimeEvent({
|
||||
type: 'work_order.changed',
|
||||
entityId: workOrderId,
|
||||
scopes: ['worker_my_orders'],
|
||||
operation: 'upsert',
|
||||
data: mapWorkOrderForWorker(workOrder, resolveWorkerPermissions(worker), share, note),
|
||||
data: mapWorkOrderForWorker(
|
||||
workOrder,
|
||||
resolveWorkerPermissions(worker),
|
||||
share,
|
||||
note,
|
||||
viewedAt,
|
||||
),
|
||||
workerIds: [workerId],
|
||||
})
|
||||
}
|
||||
|
||||
@@ -365,6 +365,7 @@ export function mapWorkOrderForWorker(
|
||||
permissions: { depositFreeAmount: number },
|
||||
myShare?: WorkOrderShareRow | null,
|
||||
workerNote = '',
|
||||
viewedAt?: string | null,
|
||||
) {
|
||||
const mapped = mapWorkOrderAdmin(workOrder)
|
||||
const {
|
||||
@@ -380,6 +381,7 @@ export function mapWorkOrderForWorker(
|
||||
freezeDepositAmount: resolveFreezeDepositAmount(workOrder, permissions),
|
||||
workerNote,
|
||||
myShare: myShare ? mapWorkOrderShare(myShare) : null,
|
||||
...(viewedAt === undefined ? {} : { isUnread: !viewedAt }),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
isWorkerPasswordStrong,
|
||||
normalizeWithdrawChannel,
|
||||
normalizeRequirementFields,
|
||||
mapWorkOrderForWorker,
|
||||
resolveCollectSubmitTargetWorkOrder,
|
||||
resolveWorkerPermissions,
|
||||
resolveSkuNameQuantity,
|
||||
@@ -197,6 +198,17 @@ function buildWorkOrderRow(overrides: Partial<WorkOrderRow> = {}): WorkOrderRow
|
||||
}
|
||||
}
|
||||
|
||||
test('mapWorkOrderForWorker reflects the personal first-view state', () => {
|
||||
const workOrder = buildWorkOrderRow({ assigned_worker_id: 1 })
|
||||
const permissions = resolveWorkerPermissions(buildWorkerUserRow())
|
||||
assert.equal(mapWorkOrderForWorker(workOrder, permissions, null, '', null).isUnread, true)
|
||||
assert.equal(
|
||||
mapWorkOrderForWorker(workOrder, permissions, null, '', '2026-08-17T00:00:00.000Z').isUnread,
|
||||
false,
|
||||
)
|
||||
assert.equal(mapWorkOrderForWorker(workOrder, permissions).isUnread, undefined)
|
||||
})
|
||||
|
||||
test('resolveCollectSubmitTargetWorkOrder returns the only pending work order when no id is provided', () => {
|
||||
const workOrder = buildWorkOrderRow()
|
||||
const selected = resolveCollectSubmitTargetWorkOrder('ORDER-001', [workOrder], '')
|
||||
|
||||
@@ -43,6 +43,7 @@ import {
|
||||
listWorkerSharesByWorker,
|
||||
listWorkerWalletLedgers,
|
||||
listWorkerWorkOrderNotes,
|
||||
listWorkerWorkOrderViews,
|
||||
listWorkerWithdrawalAccounts,
|
||||
listWorkCategories,
|
||||
listWorkOrders,
|
||||
@@ -60,6 +61,7 @@ import {
|
||||
updateWorkOrderShareAcceptanceRecord,
|
||||
updateWorkOrderShareDraftAcceptance,
|
||||
upsertWorkerWorkOrderNote,
|
||||
markWorkerWorkOrderViewed,
|
||||
updateWorkerPassword,
|
||||
upsertWorkCategory,
|
||||
upsertWorkerLevel,
|
||||
@@ -1335,13 +1337,17 @@ export async function listWorkerMyOrders(query: JsonObject = {}, session: Worker
|
||||
const permissions = resolveWorkerPermissions(worker)
|
||||
const myShares = await listWorkerSharesByWorker(worker.id)
|
||||
const myShareByOrderId = new Map(myShares.map((share) => [Number(share.work_order_id), share]))
|
||||
const notes = await listWorkerWorkOrderNotes(
|
||||
worker.id,
|
||||
items.map((item) => Number(item.id)),
|
||||
)
|
||||
const workOrderIds = items.map((item) => Number(item.id))
|
||||
const [notes, views] = await Promise.all([
|
||||
listWorkerWorkOrderNotes(worker.id, workOrderIds),
|
||||
listWorkerWorkOrderViews(worker.id, workOrderIds),
|
||||
])
|
||||
const noteByOrderId = new Map(
|
||||
notes.map((item) => [Number(item.work_order_id), String(item.note || '')]),
|
||||
)
|
||||
const viewedAtByOrderId = new Map(
|
||||
views.map((item) => [Number(item.work_order_id), String(item.viewed_at || '')]),
|
||||
)
|
||||
return {
|
||||
items: items.map((item) =>
|
||||
mapWorkOrderForWorker(
|
||||
@@ -1349,6 +1355,7 @@ export async function listWorkerMyOrders(query: JsonObject = {}, session: Worker
|
||||
permissions,
|
||||
myShareByOrderId.get(Number(item.id)),
|
||||
noteByOrderId.get(Number(item.id)) || '',
|
||||
viewedAtByOrderId.get(Number(item.id)) || null,
|
||||
),
|
||||
),
|
||||
pagination: { page, pageSize, total },
|
||||
@@ -1456,6 +1463,34 @@ export async function saveWorkerOrderNote(
|
||||
}
|
||||
}
|
||||
|
||||
/** 标记打手本人已查看工单,首次操作后不再展示“新”标识。 */
|
||||
export async function markWorkerOrderRead(workOrderId: number | string, session: WorkerSession) {
|
||||
requireActiveWorkerSession(session)
|
||||
const workOrder = await getRequiredWorkOrder(workOrderId)
|
||||
const workerId = Number(session.workerId)
|
||||
const sharingShare = await getWorkOrderShare(workOrder.id, workerId)
|
||||
const isOrderOwner =
|
||||
Number(workOrder.assigned_worker_id || 0) === workerId ||
|
||||
Number(workOrder.last_assigned_worker_id || 0) === workerId
|
||||
if (!sharingShare && !isOrderOwner) {
|
||||
throw createHttpError('只能标记自己的订单为已读', {
|
||||
statusCode: 403,
|
||||
errorCode: 'work_order_read_owner_required',
|
||||
})
|
||||
}
|
||||
|
||||
const viewedAt = await markWorkerWorkOrderViewed({
|
||||
workOrderId: Number(workOrder.id),
|
||||
workerId,
|
||||
now: nowIso(),
|
||||
})
|
||||
publishWorkOrderRealtimeChange({
|
||||
workOrderId: Number(workOrder.id),
|
||||
workerIds: [workerId],
|
||||
})
|
||||
return { viewedAt, isUnread: false }
|
||||
}
|
||||
|
||||
export async function joinWorkerSharingOrder(
|
||||
workOrderId: number | string,
|
||||
payload: JsonObject = {},
|
||||
|
||||
Reference in New Issue
Block a user