| | |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="创建时间" |
| | | :span="2"> |
| | | {{ formatDisplayTime(row.createTime) }} |
| | | {{ formatDisplayDate(row.createTime) }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | |
| | | <script setup> |
| | | import { computed } from "vue"; |
| | | import { Paperclip } from "@element-plus/icons-vue"; |
| | | import { formatDisplayTime } from "../../approve-template/approveTemplateConstants.js"; |
| | | import { formatDisplayDate } from "../../approve-template/approveTemplateConstants.js"; |
| | | import { |
| | | approvalTypeLabel, |
| | | approvalTypeStyle, |
| | |
| | | } from "../../ReimburseManage/shared/reimburseApproveBridge.js"; |
| | | import { |
| | | fetchBusinessTypeOptions, |
| | | formatDisplayTime, |
| | | formatDisplayDate, |
| | | mapEnabledFromApi, |
| | | unwrapTemplateList, |
| | | } from "../approve-template/approveTemplateConstants.js"; |
| | |
| | | label: "创建时间", |
| | | prop: "createTime", |
| | | width: 170, |
| | | formatData: (v) => formatDisplayTime(v), |
| | | formatData: (v) => formatDisplayDate(v), |
| | | }, |
| | | { |
| | | dataType: "action", |
| | |
| | | import { computed } from "vue"; |
| | | import { businessApprovalStatusLabel, businessApprovalStatusTagType, formatFieldDisplayValue, resolveInstanceFormFields } from "../approve-list/approveListConstants.js"; |
| | | import { formatDisplayDate } from "../approve-template/approveTemplateConstants.js"; |
| | | import { INSTANCE_NO_SEARCH_MODULE_KEYS, INSTANCE_NO_TABLE_COLUMN } from "./approvalInstanceListSearch.js"; |
| | | |
| | | /** 列表/详情不回显为独立列的填报项 key(避免覆盖实例系统字段) */ |
| | |
| | | ...formCols, |
| | | ...extraColumns, |
| | | ...afterFormColumns, |
| | | { label: "创建时间", prop: "createTime", width: 170 }, |
| | | { label: "创建时间", prop: "createTime", width: 120, formatData: v => formatDisplayDate(v) }, |
| | | { |
| | | label: "审批状态", |
| | | prop: "approvalStatus", |
| | |
| | | return t || "—"; |
| | | } |
| | | |
| | | /** 仅展示日期(抹掉时分秒) */ |
| | | export function formatDisplayDate(val) { |
| | | const t = normalizeTimeValue(val); |
| | | if (!t) return "—"; |
| | | const parsed = dayjs(t.replace(/-/g, "/")); |
| | | return parsed.isValid() ? parsed.format("YYYY-MM-DD") : t; |
| | | } |
| | | |
| | | /** 详情接口 data 解包 */ |
| | | export function unwrapTemplateDetail(res) { |
| | | const data = res?.data ?? res; |
| | |
| | | |
| | | <el-descriptions-item label="创建时间">{{ formatDisplayTime(detailRow.createdTime) }}</el-descriptions-item> |
| | | |
| | | <el-descriptions-item label="更新时间">{{ formatDisplayTime(detailRow.updatedTime) }}</el-descriptions-item> |
| | | |
| | | </el-descriptions> |
| | | |
| | | <el-divider content-position="left">填报项({{ detailFormConfig.fields?.length || 0 }} 项)</el-divider> |
| | |
| | | formatData: (v) => formatDisplayTime(v), |
| | | }, |
| | | { |
| | | label: "更新时间", |
| | | prop: "updatedTime", |
| | | width: 170, |
| | | showOverflowTooltip: true, |
| | | formatData: (v) => formatDisplayTime(v), |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "操作", |
| | | align: "center", |
| | |
| | | <el-tag :type="statusTagType(row.approvalResult)" size="small">{{ statusLabel(row.approvalResult) }}</el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="费用类型">{{ expenseCategoryLabel(row.expenseCategory) }}</el-descriptions-item> |
| | | <el-descriptions-item label="申请时间">{{ row.applyTime || row.createTime || "—" }}</el-descriptions-item> |
| | | <el-descriptions-item label="申请时间">{{ dateOnly(row.applyTime || row.createTime) }}</el-descriptions-item> |
| | | <el-descriptions-item label="员工编号">{{ row.employeeNo || row.applicantNo || "—" }}</el-descriptions-item> |
| | | <el-descriptions-item label="员工姓名">{{ row.employeeName || row.applicantName || "—" }}</el-descriptions-item> |
| | | <el-descriptions-item label="报销原因" :span="2">{{ row.reimburseReason || "—" }}</el-descriptions-item> |
| | |
| | | <el-descriptions-item v-if="row.rejectReason" label="驳回原因" :span="2"> |
| | | <span class="reject-text">{{ row.rejectReason }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="创建时间" :span="2">{{ row.createTime || "—" }}</el-descriptions-item> |
| | | <el-descriptions-item label="创建时间" :span="2">{{ dateOnly(row.createTime) }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <el-divider content-position="left">报销明细</el-divider> |
| | |
| | | |
| | | <script setup> |
| | | import { computed } from "vue"; |
| | | import { formatReimbursementDate } from "../../shared/finReimbursementMappers.js"; |
| | | import { expenseCategoryLabel, expenseSubjectLabel, statusLabel, statusTagType } from "../costReimburseUtils.js"; |
| | | |
| | | const props = defineProps({ |
| | | row: { type: Object, default: () => ({}) }, |
| | | }); |
| | | |
| | | function dateOnly(val) { |
| | | return formatReimbursementDate(val) || "—"; |
| | | } |
| | | |
| | | const attachmentFiles = computed(() => { |
| | | const list = |
| | | props.row?.attachmentList || |
| | |
| | | enrichReimbursementListRowsWithApprovalFlow, |
| | | filterRowsByReimbursementType, |
| | | FIN_REIMBURSEMENT_TYPE, |
| | | formatReimbursementDate, |
| | | mapCostReimbursementRow, |
| | | mapFinReimbursementDetailRow, |
| | | resolveReimbursementDeleteId, |
| | |
| | | { label: "申请人", prop: "applicantName", minWidth: 90 }, |
| | | { label: "报销金额(元)", prop: "applyAmount", width: 110 }, |
| | | { label: "报销原因", prop: "reimburseReason", minWidth: 160, showOverflowTooltip: true }, |
| | | { label: "申请时间", prop: "applyTime", width: 165 }, |
| | | { label: "创建时间", prop: "createTime", width: 165 }, |
| | | { label: "申请时间", prop: "applyTime", width: 120, formatData: (v) => formatReimbursementDate(v) }, |
| | | { label: "创建时间", prop: "createTime", width: 120, formatData: (v) => formatReimbursementDate(v) }, |
| | | { |
| | | label: "报销状态", |
| | | prop: "approvalResult", |
| | |
| | | return hasTime ? d.format("YYYY-MM-DD HH:mm:ss") : d.format("YYYY-MM-DD"); |
| | | } |
| | | |
| | | /** 列表/详情仅展示日期(抹掉时分秒) */ |
| | | export function formatReimbursementDate(val) { |
| | | if (val == null || val === "") return ""; |
| | | const d = dayjs(val); |
| | | return d.isValid() ? d.format("YYYY-MM-DD") : String(val); |
| | | } |
| | | |
| | | /** 接口行 → 差旅报销列表行(兼容 useTravelReimburse 字段) */ |
| | | export function mapTravelReimbursementRow(row) { |
| | | if (!row) return {}; |
| | |
| | | <el-descriptions-item label="员工编号">{{ row.employeeNo || row.applicantNo || "—" }}</el-descriptions-item> |
| | | <el-descriptions-item label="员工姓名">{{ row.employeeName || row.applicantName || "—" }}</el-descriptions-item> |
| | | <el-descriptions-item label="报销原因" :span="2">{{ row.reimburseReason || "—" }}</el-descriptions-item> |
| | | <el-descriptions-item label="出差开始">{{ row.travelStartTime || "—" }}</el-descriptions-item> |
| | | <el-descriptions-item label="出差结束">{{ row.travelEndTime || "—" }}</el-descriptions-item> |
| | | <el-descriptions-item label="出差开始">{{ dateOnly(row.travelStartTime) }}</el-descriptions-item> |
| | | <el-descriptions-item label="出差结束">{{ dateOnly(row.travelEndTime) }}</el-descriptions-item> |
| | | <el-descriptions-item label="出差地">{{ row.departurePlace || "—" }}</el-descriptions-item> |
| | | <el-descriptions-item label="目的地">{{ row.destination || "—" }}</el-descriptions-item> |
| | | <el-descriptions-item label="酒店标准">{{ row.hotelStandard != null ? `${row.hotelStandard} 元/晚` : "—" }}</el-descriptions-item> |
| | |
| | | <el-descriptions-item v-if="row.rejectReason" label="驳回原因" :span="2"> |
| | | <span class="reject-text">{{ row.rejectReason }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="创建时间" :span="2">{{ row.createTime || "—" }}</el-descriptions-item> |
| | | <el-descriptions-item label="创建时间" :span="2">{{ dateOnly(row.createTime) }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <el-divider content-position="left">报销明细</el-divider> |
| | |
| | | |
| | | <script setup> |
| | | import { computed } from "vue"; |
| | | import { formatReimbursementDate } from "../../shared/finReimbursementMappers.js"; |
| | | import { expenseSubjectLabel, statusLabel, statusTagType } from "../travelReimburseUtils.js"; |
| | | |
| | | const props = defineProps({ |
| | | row: { type: Object, default: () => ({}) }, |
| | | }); |
| | | |
| | | function dateOnly(val) { |
| | | return formatReimbursementDate(val) || "—"; |
| | | } |
| | | |
| | | const attachmentFiles = computed(() => { |
| | | const list = |
| | | props.row?.attachmentList || |
| | |
| | | enrichReimbursementListRowsWithApprovalFlow, |
| | | filterRowsByReimbursementType, |
| | | FIN_REIMBURSEMENT_TYPE, |
| | | formatReimbursementDate, |
| | | mapFinReimbursementDetailRow, |
| | | mapTravelReimbursementRow, |
| | | resolveReimbursementDeleteId, |
| | |
| | | { label: "报销单号", prop: "reimburseNo", width: 150 }, |
| | | { label: "申请人编号", prop: "applicantNo", width: 110 }, |
| | | { label: "申请人", prop: "applicantName", minWidth: 90 }, |
| | | { label: "出差开始", prop: "travelStartTime", width: 165 }, |
| | | { label: "出差结束", prop: "travelEndTime", width: 165 }, |
| | | { label: "创建时间", prop: "createTime", width: 165 }, |
| | | { label: "出差开始", prop: "travelStartTime", width: 120, formatData: (v) => formatReimbursementDate(v) }, |
| | | { label: "出差结束", prop: "travelEndTime", width: 120, formatData: (v) => formatReimbursementDate(v) }, |
| | | { label: "创建时间", prop: "createTime", width: 120, formatData: (v) => formatReimbursementDate(v) }, |
| | | { |
| | | label: "状态", |
| | | prop: "approvalResult", |