Files
shanxia2.0/miniprogram/utils/bxFormat.js
wuzilongandCursor f13eba5623 feat(miniprogram): migrate expense items and workflow admin from bx-mobile.
Enable mobile config of expense tree and advance/reimburse approval nodes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-11 23:42:16 +08:00

172 lines
4.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/** 对齐 bx-mobile/src/utils/format.ts(Batch2 所需子集) */
export function statusLabel(status) {
if (status == null || status === '') return '-'
const map = {
1: '启用',
0: '禁用',
draft: '待提交',
pending: '审批中',
approved: '已通过',
rejected: '已驳回',
withdrawn: '已撤回',
issued: '已发放',
paid: '已支付',
offset: '已冲抵',
partial: '部分冲抵',
processed: '已处理'
}
return map[status] ?? String(status)
}
export function statusTone(status) {
if (status == null) return 'info'
const map = {
1: 'done',
0: 'error',
draft: 'info',
pending: 'warn',
approved: 'done',
rejected: 'error',
withdrawn: 'warn',
issued: 'done',
paid: 'done',
offset: 'done',
partial: 'warn',
processed: 'done'
}
return map[status] ?? 'info'
}
/** StatusTag variant(对齐 bx-mobile statusTagClass) */
export function statusTagClass(status) {
const tone = statusTone(status)
const map = {
info: 'info',
warn: 'warning',
done: 'success',
error: 'danger',
processing: 'processing'
}
return map[tone] || 'info'
}
/** 小程序 status-tag class:启用/禁用或工作流状态 */
export function adminStatusTagClass(status) {
if (status === 1 || status === '1') return 's-approved'
if (status === 0 || status === '0') return 's-draft'
return workflowListStatusTagClass(status)
}
export function workflowListStatusTagClass(status) {
const raw = status == null || status === '' ? 'draft' : String(status)
return `s-${raw}`
}
export function ticketHeaderStatusToneClass(status) {
const tone = statusTone(status)
const map = {
info: 'advance-ticket-status--info',
warn: 'advance-ticket-status--warn',
done: 'advance-ticket-status--done',
error: 'advance-ticket-status--err',
processing: 'advance-ticket-status--processing'
}
return map[tone] || 'advance-ticket-status--info'
}
export function formatAmount(amount) {
const n = typeof amount === 'string' ? parseFloat(amount) : amount
if (Number.isNaN(n)) return '0.00'
return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
}
export function formatDate(dateStr) {
if (!dateStr) return '-'
return String(dateStr).substring(0, 10)
}
export function formatDateTime(dateStr) {
if (!dateStr) return '-'
return String(dateStr).substring(0, 16).replace('T', ' ')
}
export function pickApplyTime(row) {
if (!row || typeof row !== 'object') return undefined
const v = row.applyTime ?? row.createTime ?? row.apply_time ?? row.create_time
if (v == null || v === '') return undefined
return String(v)
}
export function formatApplyDateTime(row) {
return formatDateTime(pickApplyTime(row))
}
export function formatApplyDate(row) {
return formatDate(pickApplyTime(row))
}
/** 费用树扁平化(tree → flatList) */
export function flattenExpenseTree(tree) {
const result = []
for (const node of tree || []) {
result.push(node)
if (node.children?.length) result.push(...flattenExpenseTree(node.children))
}
return result
}
export function normalizeExpenseItem(raw) {
const children = Array.isArray(raw?.children)
? raw.children.map(normalizeExpenseItem)
: undefined
return {
id: String(raw?.id ?? ''),
parentId: raw?.parentId == null || raw?.parentId === '' ? '0' : String(raw.parentId),
itemName: raw?.itemName ?? '',
itemCode: raw?.itemCode ?? '',
level: Number(raw?.level ?? 0),
sortOrder: Number(raw?.sortOrder ?? 0),
status: raw?.status,
childCount: Number(raw?.childCount ?? children?.length ?? 0),
children
}
}
export function formatExpenseName(id, flatList) {
if (id == null || id === '') return '-'
const sid = String(id)
const parts = []
let cur = (flatList || []).find((i) => String(i.id) === sid)
const guard = new Set()
while (cur && !guard.has(cur.id)) {
guard.add(cur.id)
parts.unshift(cur.itemName)
const pid = cur.parentId
cur =
pid != null && pid !== '' && pid !== '0'
? (flatList || []).find((i) => String(i.id) === pid)
: undefined
}
return parts.length ? parts.join('/') : '-'
}
export function pickExpenseItemId(row) {
if (!row || typeof row !== 'object') return null
const raw = row.expenseId ?? row.expense_id ?? row.expenseItemId ?? row.expense_item_id
if (raw == null || raw === '') return null
return String(raw)
}
export function resolveExpenseDisplay(row, flatList) {
if (!row) return '-'
const id = pickExpenseItemId(row)
const nameFb = row.expenseName ?? row.expense_name
if (id != null && flatList && flatList.length) {
const p = formatExpenseName(id, flatList)
if (p && p !== '-') return p
}
const fb = nameFb != null ? String(nameFb).trim() : ''
return fb || '-'
}