import { computed, ref, watch } from 'vue' import { normalizeRequestForUi } from '../../utils/requestViewModel.js' function extractRowDate(value) { const matched = String(value || '').match(/\d{4}-\d{2}-\d{2}/) return matched ? matched[0] : '' } export default { name: 'RequestsView', props: { filteredRequests: { type: Array, required: true }, hasData: { type: Boolean, default: false }, loading: { type: Boolean, default: false }, error: { type: String, default: '' } }, emits: ['ask', 'approve', 'reject', 'create-request', 'reload'], setup(props, { emit }) { const activeTab = ref('全部') const tabs = ['全部', '草稿', '审批中', '待补充', '已完成'] const filters = ['报销状态', '报销类型', '所属主体'] const listKeyword = ref('') const datePopover = ref(false) const rangeStart = ref('') const rangeEnd = ref('') const appliedStart = ref('') const appliedEnd = ref('') const dateRangeLabel = computed(() => { if (appliedStart.value && appliedEnd.value) { return `${appliedStart.value} ~ ${appliedEnd.value}` } return '选择时间段' }) function applyDateRange() { if (!rangeStart.value || !rangeEnd.value) { return } appliedStart.value = rangeStart.value appliedEnd.value = rangeEnd.value datePopover.value = false } const rows = computed(() => props.filteredRequests .map((item) => normalizeRequestForUi(item)) .filter(Boolean) ) const currentPage = ref(1) const pageSize = ref(10) const pageSizes = [10, 20, 50] const pageSizeOpen = ref(false) function changePageSize(size) { pageSize.value = size pageSizeOpen.value = false currentPage.value = 1 } const filteredRows = computed(() => { const keyword = listKeyword.value.trim().toLowerCase() return rows.value.filter((row) => { const matchesKeyword = !keyword || [ row.id, row.documentNo, row.typeLabel, row.reason, row.sceneTarget, row.relatedCustomer, row.riskSummary ] .filter(Boolean) .join('') .toLowerCase() .includes(keyword) const applyDate = extractRowDate(row.applyTime) const matchesDateRange = !appliedStart.value || !appliedEnd.value || (applyDate && applyDate >= appliedStart.value && applyDate <= appliedEnd.value) const matchesTab = activeTab.value === '全部' || (activeTab.value === '草稿' && row.approvalKey === 'draft') || (activeTab.value === '审批中' && row.approvalKey === 'in_progress') || (activeTab.value === '待补充' && row.approvalKey === 'supplement') || (activeTab.value === '已完成' && row.approvalKey === 'completed') return matchesKeyword && matchesDateRange && matchesTab }) }) const totalCount = computed(() => filteredRows.value.length) const totalPages = computed(() => Math.max(1, Math.ceil(totalCount.value / pageSize.value))) const visibleRows = computed(() => { const start = (currentPage.value - 1) * pageSize.value return filteredRows.value.slice(start, start + pageSize.value) }) const showTable = computed(() => !props.loading && !props.error && visibleRows.value.length > 0) const showEmpty = computed(() => !props.loading && !props.error && visibleRows.value.length === 0) const emptyState = computed(() => { if (!props.hasData) { return { title: '暂无真实报销单据', desc: '数据库里还没有可见的个人报销数据。保存草稿或提交报销后,会显示在这里。' } } return { title: '没有匹配结果', desc: '当前筛选条件下没有可展示的报销单据。' } }) watch([activeTab, rows, listKeyword, appliedStart, appliedEnd], () => { currentPage.value = 1 }) return { emit, activeTab, tabs, filters, listKeyword, datePopover, rangeStart, rangeEnd, appliedStart, appliedEnd, dateRangeLabel, applyDateRange, rows, currentPage, pageSize, pageSizes, pageSizeOpen, changePageSize, filteredRows, totalCount, totalPages, visibleRows, showTable, showEmpty, emptyState } } }