refactor: enforce 800 line source limits

This commit is contained in:
caoxiaozhu
2026-06-22 11:58:53 +08:00
parent 08a4fa3577
commit 6d33ba5742
150 changed files with 27413 additions and 23791 deletions

View File

@@ -2,112 +2,18 @@
<section class="approval-page">
<div class="approval-detail">
<div class="detail-scroll">
<article class="detail-hero panel">
<div class="hero-banner">
<div class="hero-banner-main">
<div class="applicant-card">
<div class="portrait">
<img src="/assets/person.png" alt="" />
</div>
<div class="applicant-copy">
<div class="applicant-name-row">
<h2>{{ profile.name }}</h2>
<span class="identity-badge">{{ profile.identity }}</span>
</div>
<div class="applicant-profile-meta">
<div class="applicant-profile-meta__org">
<span class="applicant-meta-item">
<em>部门</em>
<strong>{{ profile.department }}</strong>
</span>
<span class="applicant-meta-item applicant-meta-item--sub">
<em>直属上司</em>
<strong>{{ profile.manager }}</strong>
</span>
</div>
<div class="applicant-profile-meta__role">
<span class="applicant-meta-item">
<em>职级</em>
<strong>{{ profile.grade }}</strong>
</span>
<span class="applicant-meta-item">
<em>岗位</em>
<strong>{{ profile.position }}</strong>
</span>
</div>
</div>
</div>
</div>
<div class="hero-fact-grid">
<div v-for="item in heroFactItems" :key="item.key" class="hero-fact">
<div class="hero-fact-label">
<i v-if="item.icon" :class="item.icon"></i>
<span>{{ item.label }}</span>
</div>
<strong :class="item.valueClass">{{ item.value }}</strong>
</div>
</div>
</div>
</div>
</article>
<article class="progress-card panel">
<div class="progress-block">
<div class="progress-head">
<h3>{{ isApplicationDocument ? '申请进度' : '报销进度' }}</h3>
</div>
<div class="progress-line" :style="{ '--progress-columns': progressSteps.length }">
<div
v-for="step in progressSteps"
:key="step.label"
class="progress-step"
:class="{ active: step.active, current: step.current, done: step.done }"
>
<span>
<i
v-if="step.current"
v-motion
class="current-progress-ring"
:initial="currentProgressRingMotion.initial"
:enter="currentProgressRingMotion.enter"
aria-hidden="true"
></i>
<i v-if="step.done" class="mdi mdi-check"></i>
<template v-else>{{ step.index }}</template>
</span>
<div class="progress-step-copy" :title="step.title || step.detail || step.time">
<strong>{{ step.label }}</strong>
<small class="progress-step-status">{{ step.time }}</small>
<em v-if="step.detail" class="progress-step-meta">{{ step.detail }}</em>
</div>
</div>
</div>
</div>
</article>
<TravelRequestDetailHero :profile="profile" :hero-fact-items="heroFactItems" />
<TravelRequestProgressCard
:is-application-document="isApplicationDocument"
:progress-steps="progressSteps"
:current-progress-ring-motion="currentProgressRingMotion"
/>
<div class="detail-grid">
<section class="detail-left">
<article v-if="!isApplicationDocument" class="detail-card panel">
<div class="detail-card-head">
<div>
<h3>关联单据信息</h3>
<p>展示本次报销关联的前置申请便于核对申请内容天数事由和预计金额</p>
</div>
</div>
<div v-if="relatedApplicationFactItems.length" class="application-detail-facts related-application-facts">
<div
v-for="item in relatedApplicationFactItems"
:key="item.key"
class="application-detail-fact related-application-fact"
:class="{ highlight: item.highlight, emphasis: item.emphasis }"
>
<span>{{ item.label }}</span>
<strong>{{ item.value }}</strong>
</div>
</div>
<div v-else class="related-application-empty">
<strong>暂未识别到关联申请单</strong>
<p>差旅报销应先关联已审批的申请单请核对本单据是否由申请单生成或已在智能录入中完成关联</p>
</div>
</article>
<TravelRequestRelatedApplicationCard
:is-application-document="isApplicationDocument"
:related-application-fact-items="relatedApplicationFactItems"
/>
<article class="detail-card panel">
<div class="detail-card-head">
<div>
@@ -674,12 +580,7 @@
</div>
</ConfirmDialog>
<Transition name="shared-confirm">
<div
v-if="attachmentPreviewOpen"
class="attachment-preview-mask"
role="presentation"
@click.self="closeAttachmentPreview"
>
<div v-if="attachmentPreviewOpen" class="attachment-preview-mask" role="presentation" @click.self="closeAttachmentPreview">
<section class="attachment-preview-card" role="dialog" aria-modal="true" @click.stop>
<div class="attachment-preview-head">
<div>
@@ -723,18 +624,8 @@
<i class="mdi mdi-alert-circle-outline"></i>
<span>{{ attachmentPreviewError }}</span>
</div>
<img
v-else-if="attachmentPreviewUrl && attachmentPreviewMediaType.startsWith('image/')"
:src="attachmentPreviewUrl"
:alt="attachmentPreviewName || '附件图片'"
class="attachment-preview-image"
/>
<iframe
v-else-if="attachmentPreviewUrl && attachmentPreviewMediaType === 'application/pdf'"
:src="attachmentPreviewUrl"
class="attachment-preview-frame"
title="附件预览"
></iframe>
<img v-else-if="attachmentPreviewUrl && attachmentPreviewMediaType.startsWith('image/')" :src="attachmentPreviewUrl" :alt="attachmentPreviewName || '附件图片'" class="attachment-preview-image" />
<iframe v-else-if="attachmentPreviewUrl && attachmentPreviewMediaType === 'application/pdf'" :src="attachmentPreviewUrl" class="attachment-preview-frame" title="附件预览"></iframe>
<div v-else class="attachment-preview-state">
<i class="mdi mdi-file-outline"></i>
<span>当前附件暂不支持直接预览</span>
@@ -747,32 +638,20 @@
</div>
<div v-if="currentAttachmentPreviewInsight" class="attachment-insight-content">
<div class="attachment-insight-pills">
<span :class="['attachment-recognition-pill', currentAttachmentPreviewInsight.requirementTone]">
{{ currentAttachmentPreviewInsight.requirementLabel }}
</span>
<span :class="['attachment-recognition-pill', currentAttachmentPreviewInsight.requirementTone]">{{ currentAttachmentPreviewInsight.requirementLabel }}</span>
</div>
<p v-if="currentAttachmentPreviewInsight.message" class="attachment-recognition-message">
{{ currentAttachmentPreviewInsight.message }}
</p>
<p v-if="currentAttachmentPreviewInsight.message" class="attachment-recognition-message">{{ currentAttachmentPreviewInsight.message }}</p>
<div v-if="currentAttachmentPreviewInsight.fields.length" class="attachment-insight-section">
<span>字段结果</span>
<ul>
<li v-for="field in currentAttachmentPreviewInsight.fields" :key="field">{{ field }}</li>
</ul>
<ul><li v-for="field in currentAttachmentPreviewInsight.fields" :key="field">{{ field }}</li></ul>
</div>
<div v-if="currentAttachmentPreviewInsight.ruleBasis.length" class="attachment-insight-section">
<span>规则依据</span>
<ul>
<li v-for="basis in currentAttachmentPreviewInsight.ruleBasis" :key="basis">{{ basis }}</li>
</ul>
<ul><li v-for="basis in currentAttachmentPreviewInsight.ruleBasis" :key="basis">{{ basis }}</li></ul>
</div>
<div v-if="currentAttachmentPreviewRiskCards.length" class="attachment-insight-section risk">
<span>风险点</span>
<article
v-for="card in currentAttachmentPreviewRiskCards"
:key="card.id"
:class="['attachment-risk-card', card.tone]"
>
<article v-for="card in currentAttachmentPreviewRiskCards" :key="card.id" :class="['attachment-risk-card', card.tone]">
<strong>{{ card.risk }}</strong>
<p>{{ card.suggestion }}</p>
</article>
@@ -808,22 +687,10 @@
@confirm="confirmSubmitRequest"
>
<div class="submit-confirm-summary" aria-label="提交前核对摘要">
<div class="submit-confirm-row">
<span>单据编号</span>
<strong>{{ request.documentNo || request.id }}</strong>
</div>
<div class="submit-confirm-row">
<span>{{ isApplicationDocument ? '申请类型' : '报销类型' }}</span>
<strong>{{ request.typeLabel }}</strong>
</div>
<div class="submit-confirm-row">
<span>{{ isApplicationDocument ? '预计金额' : '报销金额' }}</span>
<strong>{{ submitConfirmAmountDisplay }}</strong>
</div>
<div v-if="!isApplicationDocument" class="submit-confirm-row">
<span>费用明细</span>
<strong>{{ expenseItems.length }} / {{ uploadedExpenseCount }} 张单据</strong>
</div>
<div class="submit-confirm-row"><span>单据编号</span><strong>{{ request.documentNo || request.id }}</strong></div>
<div class="submit-confirm-row"><span>{{ isApplicationDocument ? '申请类型' : '报销类型' }}</span><strong>{{ request.typeLabel }}</strong></div>
<div class="submit-confirm-row"><span>{{ isApplicationDocument ? '预计金额' : '报销金额' }}</span><strong>{{ submitConfirmAmountDisplay }}</strong></div>
<div v-if="!isApplicationDocument" class="submit-confirm-row"><span>费用明细</span><strong>{{ expenseItems.length }} / {{ uploadedExpenseCount }} 张单据</strong></div>
</div>
</ConfirmDialog>
<ConfirmDialog
@@ -924,223 +791,4 @@
<style scoped src="../assets/styles/views/travel-request-detail-view-part2.css"></style>
<style scoped src="../assets/styles/views/travel-request-detail-responsive.css"></style>
<style>
/* 强力锁定表格中输入框的高度,解决 scoped 模式下有前缀的 Element Plus 子组件无法被 :deep 成功匹配的局限性 */
.detail-expense-table .editor-control .el-input__wrapper,
.detail-expense-table .editor-control .el-select__wrapper,
.detail-expense-table .editor-select .el-select__wrapper,
.detail-expense-table .editor-date-picker .el-input__wrapper {
box-sizing: border-box !important;
min-height: var(--expense-editor-control-height, 34px) !important;
height: var(--expense-editor-control-height, 34px) !important;
line-height: var(--expense-editor-control-line-height, 16px) !important;
}
.detail-expense-table .editor-control:not(.risk-note-editor-input),
.detail-expense-table .editor-date-picker.editor-control,
.detail-expense-table .editor-select {
min-height: var(--expense-editor-control-height, 34px) !important;
height: var(--expense-editor-control-height, 34px) !important;
}
.detail-expense-table .editor-date-picker.editor-control {
display: flex !important;
align-items: center !important;
}
.detail-expense-table .editor-date-picker.editor-control .el-input__wrapper {
gap: 4px !important;
padding-right: 7px !important;
padding-left: 7px !important;
}
.detail-expense-table .editor-date-picker.editor-control .el-input__inner,
.detail-expense-table .editor-input-control.editor-control .el-input__inner,
.detail-expense-table .editor-select .el-select__selected-item,
.detail-expense-table .editor-select .el-select__placeholder {
height: var(--expense-editor-control-line-height, 16px) !important;
line-height: var(--expense-editor-control-line-height, 16px) !important;
font-size: 12px !important;
}
.detail-expense-table .editor-date-picker.editor-control .el-input__prefix,
.detail-expense-table .editor-date-picker.editor-control .el-input__suffix,
.detail-expense-table .editor-date-picker.editor-control .el-input__prefix-inner,
.detail-expense-table .editor-date-picker.editor-control .el-input__suffix-inner {
display: inline-flex !important;
align-items: center !important;
}
.detail-expense-table .editor-date-picker.editor-control .el-input__prefix,
.detail-expense-table .editor-date-picker.editor-control .el-input__suffix {
min-height: var(--expense-editor-control-height, 34px) !important;
height: var(--expense-editor-control-height, 34px) !important;
}
.detail-expense-table .editor-date-picker.editor-control .el-input__prefix {
flex: 0 0 14px !important;
width: 14px !important;
min-width: 14px !important;
margin: 0 !important;
color: #94a3b8 !important;
font-size: 13px !important;
}
.detail-expense-table .editor-date-picker.editor-control .el-input__suffix {
display: none !important;
}
.detail-expense-table .editor-date-picker.editor-control .el-input__prefix-inner,
.detail-expense-table .editor-date-picker.editor-control .el-input__suffix-inner {
height: var(--expense-editor-control-line-height, 16px) !important;
line-height: var(--expense-editor-control-line-height, 16px) !important;
}
.detail-expense-table .editor-date-picker.editor-control .el-input__prefix-inner {
width: 14px !important;
font-size: 13px !important;
}
.detail-expense-table .editor-amount-input.editor-control {
display: flex !important;
align-items: center !important;
}
.detail-expense-table .editor-amount-input.editor-control .el-input__wrapper {
display: flex !important;
align-items: center !important;
min-height: var(--expense-editor-control-height, 34px) !important;
height: var(--expense-editor-control-height, 34px) !important;
padding-top: 0 !important;
padding-bottom: 0 !important;
}
.detail-expense-table .editor-amount-input.editor-control .el-input__inner {
height: var(--expense-editor-control-line-height, 16px) !important;
line-height: var(--expense-editor-control-line-height, 16px) !important;
}
.detail-expense-table .editor-amount-input.editor-control .el-input__prefix,
.detail-expense-table .editor-amount-input.editor-control .el-input__prefix-inner {
display: inline-flex !important;
align-items: center !important;
}
.detail-expense-table .editor-amount-input.editor-control .el-input__prefix {
min-height: var(--expense-editor-control-height, 34px) !important;
height: var(--expense-editor-control-height, 34px) !important;
}
.detail-expense-table .editor-amount-input.editor-control .el-input__prefix-inner {
height: var(--expense-editor-control-line-height, 16px) !important;
line-height: var(--expense-editor-control-line-height, 16px) !important;
}
.detail-editor-date-popper.el-popper {
border: 1px solid rgba(148, 163, 184, .32) !important;
border-radius: 4px !important;
background: #ffffff !important;
box-shadow: 0 18px 42px rgba(15, 23, 42, .14) !important;
}
.detail-editor-date-popper .el-picker-panel {
border: 0 !important;
border-radius: 4px !important;
background: #ffffff !important;
color: #334155 !important;
}
.detail-editor-date-popper .el-date-picker__header {
height: 38px !important;
margin: 0 !important;
padding: 0 10px !important;
border-bottom: 1px solid #e2e8f0 !important;
display: flex !important;
align-items: center !important;
}
.detail-editor-date-popper .el-picker-panel__icon-btn {
appearance: none !important;
width: 24px !important;
height: 24px !important;
margin: 0 1px !important;
padding: 0 !important;
border: 0 !important;
border-radius: 4px !important;
background: transparent !important;
color: #64748b !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
transition: background-color 160ms var(--ease), color 160ms var(--ease) !important;
}
.detail-editor-date-popper .el-picker-panel__icon-btn:hover {
background: var(--theme-primary-soft) !important;
color: var(--theme-primary-active) !important;
}
.detail-editor-date-popper .el-date-picker__header-label {
color: #0f172a !important;
font-size: 13px !important;
font-weight: 800 !important;
}
.detail-editor-date-popper .el-picker-panel__content {
margin: 8px 10px 10px !important;
}
.detail-editor-date-popper .el-date-table th {
border-bottom: 1px solid #edf2f7 !important;
color: #64748b !important;
font-size: 11px !important;
font-weight: 800 !important;
}
.detail-editor-date-popper .el-date-table td {
width: 32px !important;
height: 30px !important;
padding: 2px !important;
}
.detail-editor-date-popper .el-date-table td .el-date-table-cell {
height: 28px !important;
padding: 0 !important;
}
.detail-editor-date-popper .el-date-table td .el-date-table-cell__text {
width: 26px !important;
height: 26px !important;
border-radius: 4px !important;
color: #334155 !important;
font-size: 12px !important;
line-height: 26px !important;
}
.detail-editor-date-popper .el-date-table td.available:hover .el-date-table-cell__text {
background: var(--theme-primary-soft) !important;
color: var(--theme-primary-active) !important;
}
.detail-editor-date-popper .el-date-table td.today .el-date-table-cell__text {
color: var(--theme-primary-active) !important;
font-weight: 850 !important;
}
.detail-editor-date-popper .el-date-table td.current .el-date-table-cell__text,
.detail-editor-date-popper .el-date-table td.selected .el-date-table-cell__text {
background: var(--theme-primary) !important;
color: #ffffff !important;
font-weight: 850 !important;
}
.detail-editor-date-popper .el-date-table td.prev-month .el-date-table-cell__text,
.detail-editor-date-popper .el-date-table td.next-month .el-date-table-cell__text {
color: #cbd5e1 !important;
}
.detail-editor-date-popper .el-date-table td.disabled .el-date-table-cell__text {
background: #f8fafc !important;
color: #cbd5e1 !important;
}
</style>
<style src="../assets/styles/views/travel-request-detail-date-popper.css"></style>