Files
X-Financial/web/src/views/scripts/useApplicationPreviewEditor.js

178 lines
5.6 KiB
JavaScript
Raw Normal View History

import { ref } from 'vue'
import {
APPLICATION_TRANSPORT_MODE_OPTIONS,
buildApplicationPreviewRows,
buildLocalApplicationPreviewMessage,
normalizeApplicationPreview
} from '../../utils/expenseApplicationPreview.js'
import {
buildWorkbenchDateLabel,
canApplyWorkbenchDateSelection,
getTodayDateValue
} from '../../utils/workbenchComposerDate.js'
function parseEditorDateValue(value) {
const text = String(value || '').trim()
const matches = [...text.matchAll(/20\d{2}-\d{1,2}-\d{1,2}/g)].map((item) => item[0])
const startDate = matches[0] || getTodayDateValue()
const endDate = matches[1] || startDate
return {
dateMode: matches.length > 1 && startDate !== endDate ? 'range' : 'single',
singleDate: startDate,
rangeStartDate: startDate,
rangeEndDate: endDate
}
}
function buildEmptyEditor() {
return {
messageId: '',
fieldKey: '',
draftValue: '',
dateMode: 'single',
singleDate: getTodayDateValue(),
rangeStartDate: getTodayDateValue(),
rangeEndDate: getTodayDateValue()
}
}
export function useApplicationPreviewEditor({ persistSessionState, toast } = {}) {
const applicationPreviewEditor = ref(buildEmptyEditor())
function resolveApplicationPreviewRows(message) {
return buildApplicationPreviewRows(message?.applicationPreview || {})
}
function resolveApplicationPreviewEditorControl(fieldKey) {
if (fieldKey === 'transportMode') return 'select'
if (fieldKey === 'time') return 'date'
return 'text'
}
function resolveApplicationPreviewEditorOptions(fieldKey) {
return fieldKey === 'transportMode' ? APPLICATION_TRANSPORT_MODE_OPTIONS : []
}
function isApplicationPreviewEditing(message, fieldKey) {
return (
String(applicationPreviewEditor.value.messageId || '') === String(message?.id || '') &&
applicationPreviewEditor.value.fieldKey === fieldKey
)
}
function openApplicationPreviewEditor(message, fieldKey, value) {
if (!message?.applicationPreview || !fieldKey) return
const targetRow = buildApplicationPreviewRows(message.applicationPreview)
.find((row) => row.key === fieldKey)
if (targetRow && targetRow.editable === false) return
const normalizedValue = String(value || '').trim() === '待补充' ? '' : String(value || '')
const dateState = fieldKey === 'time' ? parseEditorDateValue(normalizedValue) : {}
applicationPreviewEditor.value = {
messageId: String(message.id || ''),
fieldKey,
draftValue: fieldKey === 'transportMode' && !APPLICATION_TRANSPORT_MODE_OPTIONS.includes(normalizedValue)
? ''
: normalizedValue,
...dateState
}
}
function cancelApplicationPreviewEditor() {
applicationPreviewEditor.value = buildEmptyEditor()
}
function isApplicationPreviewDateEditorOpen(message) {
return isApplicationPreviewEditing(message, 'time')
}
function setApplicationPreviewDateMode(mode) {
applicationPreviewEditor.value.dateMode = mode === 'range' ? 'range' : 'single'
}
function canApplyApplicationPreviewDateSelection() {
const editor = applicationPreviewEditor.value
return canApplyWorkbenchDateSelection({
mode: editor.dateMode,
singleDate: editor.singleDate,
rangeStartDate: editor.rangeStartDate,
rangeEndDate: editor.rangeEndDate
})
}
function buildApplicationPreviewDateDraftValue() {
const editor = applicationPreviewEditor.value
return buildWorkbenchDateLabel({
mode: editor.dateMode,
singleDate: editor.singleDate,
rangeStartDate: editor.rangeStartDate,
rangeEndDate: editor.rangeEndDate
})
}
function commitApplicationPreviewEditor(message) {
const editor = applicationPreviewEditor.value
if (!message?.applicationPreview || String(editor.messageId || '') !== String(message.id || '') || !editor.fieldKey) {
cancelApplicationPreviewEditor()
return false
}
const nextValue = editor.fieldKey === 'time'
? buildApplicationPreviewDateDraftValue()
: String(editor.draftValue || '').trim()
if (editor.fieldKey === 'time' && !nextValue) {
toast?.('请先选择有效日期。')
return false
}
const nextPreview = normalizeApplicationPreview({
...message.applicationPreview,
fields: {
...(message.applicationPreview.fields || {}),
[editor.fieldKey]: nextValue
}
})
message.applicationPreview = nextPreview
message.text = buildLocalApplicationPreviewMessage(nextPreview)
cancelApplicationPreviewEditor()
persistSessionState?.()
toast?.('已更新核对表内容。')
return true
}
function commitApplicationPreviewDateEditor(message) {
if (!canApplyApplicationPreviewDateSelection()) {
toast?.('请确认结束日期不早于开始日期。')
return false
}
return commitApplicationPreviewEditor(message)
}
function handleApplicationPreviewEditorKeydown(event, message) {
if (event.key === 'Enter') {
event.preventDefault()
commitApplicationPreviewEditor(message)
return
}
if (event.key === 'Escape') {
event.preventDefault()
cancelApplicationPreviewEditor()
}
}
return {
applicationPreviewEditor,
resolveApplicationPreviewRows,
resolveApplicationPreviewEditorControl,
resolveApplicationPreviewEditorOptions,
isApplicationPreviewEditing,
isApplicationPreviewDateEditorOpen,
openApplicationPreviewEditor,
commitApplicationPreviewEditor,
commitApplicationPreviewDateEditor,
cancelApplicationPreviewEditor,
setApplicationPreviewDateMode,
canApplyApplicationPreviewDateSelection,
handleApplicationPreviewEditorKeydown
}
}