bxFormat.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /** 对齐 bx-mobile/src/utils/format.ts(Batch2 所需子集) */
  2. export function statusLabel(status) {
  3. if (status == null || status === '') return '-'
  4. const map = {
  5. 1: '启用',
  6. 0: '禁用',
  7. draft: '待提交',
  8. pending: '审批中',
  9. approved: '已通过',
  10. rejected: '已驳回',
  11. withdrawn: '已撤回',
  12. issued: '已发放',
  13. paid: '已支付',
  14. offset: '已冲抵',
  15. partial: '部分冲抵',
  16. processed: '已处理'
  17. }
  18. return map[status] ?? String(status)
  19. }
  20. export function statusTone(status) {
  21. if (status == null) return 'info'
  22. const map = {
  23. 1: 'done',
  24. 0: 'error',
  25. draft: 'info',
  26. pending: 'warn',
  27. approved: 'done',
  28. rejected: 'error',
  29. withdrawn: 'warn',
  30. issued: 'done',
  31. paid: 'done',
  32. offset: 'done',
  33. partial: 'warn',
  34. processed: 'done'
  35. }
  36. return map[status] ?? 'info'
  37. }
  38. /** StatusTag variant(对齐 bx-mobile statusTagClass) */
  39. export function statusTagClass(status) {
  40. const tone = statusTone(status)
  41. const map = {
  42. info: 'info',
  43. warn: 'warning',
  44. done: 'success',
  45. error: 'danger',
  46. processing: 'processing'
  47. }
  48. return map[tone] || 'info'
  49. }
  50. /** 小程序 status-tag class:启用/禁用或工作流状态 */
  51. export function adminStatusTagClass(status) {
  52. if (status === 1 || status === '1') return 's-approved'
  53. if (status === 0 || status === '0') return 's-draft'
  54. return workflowListStatusTagClass(status)
  55. }
  56. export function workflowListStatusTagClass(status) {
  57. const raw = status == null || status === '' ? 'draft' : String(status)
  58. return `s-${raw}`
  59. }
  60. export function ticketHeaderStatusToneClass(status) {
  61. const tone = statusTone(status)
  62. const map = {
  63. info: 'advance-ticket-status--info',
  64. warn: 'advance-ticket-status--warn',
  65. done: 'advance-ticket-status--done',
  66. error: 'advance-ticket-status--err',
  67. processing: 'advance-ticket-status--processing'
  68. }
  69. return map[tone] || 'advance-ticket-status--info'
  70. }
  71. export function formatAmount(amount) {
  72. const n = typeof amount === 'string' ? parseFloat(amount) : amount
  73. if (Number.isNaN(n)) return '0.00'
  74. return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
  75. }
  76. export function formatDate(dateStr) {
  77. if (!dateStr) return '-'
  78. return String(dateStr).substring(0, 10)
  79. }
  80. export function formatDateTime(dateStr) {
  81. if (!dateStr) return '-'
  82. return String(dateStr).substring(0, 16).replace('T', ' ')
  83. }
  84. export function pickApplyTime(row) {
  85. if (!row || typeof row !== 'object') return undefined
  86. const v = row.applyTime ?? row.createTime ?? row.apply_time ?? row.create_time
  87. if (v == null || v === '') return undefined
  88. return String(v)
  89. }
  90. export function formatApplyDateTime(row) {
  91. return formatDateTime(pickApplyTime(row))
  92. }
  93. export function formatApplyDate(row) {
  94. return formatDate(pickApplyTime(row))
  95. }
  96. /** 费用树扁平化(tree → flatList) */
  97. export function flattenExpenseTree(tree) {
  98. const result = []
  99. for (const node of tree || []) {
  100. result.push(node)
  101. if (node.children?.length) result.push(...flattenExpenseTree(node.children))
  102. }
  103. return result
  104. }
  105. export function normalizeExpenseItem(raw) {
  106. const children = Array.isArray(raw?.children)
  107. ? raw.children.map(normalizeExpenseItem)
  108. : undefined
  109. return {
  110. id: String(raw?.id ?? ''),
  111. parentId: raw?.parentId == null || raw?.parentId === '' ? '0' : String(raw.parentId),
  112. itemName: raw?.itemName ?? '',
  113. itemCode: raw?.itemCode ?? '',
  114. level: Number(raw?.level ?? 0),
  115. sortOrder: Number(raw?.sortOrder ?? 0),
  116. status: raw?.status,
  117. childCount: Number(raw?.childCount ?? children?.length ?? 0),
  118. children
  119. }
  120. }
  121. export function formatExpenseName(id, flatList) {
  122. if (id == null || id === '') return '-'
  123. const sid = String(id)
  124. const parts = []
  125. let cur = (flatList || []).find((i) => String(i.id) === sid)
  126. const guard = new Set()
  127. while (cur && !guard.has(cur.id)) {
  128. guard.add(cur.id)
  129. parts.unshift(cur.itemName)
  130. const pid = cur.parentId
  131. cur =
  132. pid != null && pid !== '' && pid !== '0'
  133. ? (flatList || []).find((i) => String(i.id) === pid)
  134. : undefined
  135. }
  136. return parts.length ? parts.join('/') : '-'
  137. }
  138. export function pickExpenseItemId(row) {
  139. if (!row || typeof row !== 'object') return null
  140. const raw = row.expenseId ?? row.expense_id ?? row.expenseItemId ?? row.expense_item_id
  141. if (raw == null || raw === '') return null
  142. return String(raw)
  143. }
  144. export function resolveExpenseDisplay(row, flatList) {
  145. if (!row) return '-'
  146. const id = pickExpenseItemId(row)
  147. const nameFb = row.expenseName ?? row.expense_name
  148. if (id != null && flatList && flatList.length) {
  149. const p = formatExpenseName(id, flatList)
  150. if (p && p !== '-') return p
  151. }
  152. const fb = nameFb != null ? String(nameFb).trim() : ''
  153. return fb || '-'
  154. }