feat: 细化差旅票据费用明细分类并自动计算出差补贴
将差旅费用明细拆分为火车票、机票、住宿票、乘车等细分类 型,根据票据字段自动生成行程/事由描述,结合规则引擎自 动计算出差补贴金额,前端适配费用明细编辑和差旅票据审 核交互,补充单元测试覆盖。
This commit is contained in:
@@ -561,6 +561,46 @@
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.detail-note.readonly {
|
||||
background: #f8fafc;
|
||||
border-color: #e2e8f0;
|
||||
}
|
||||
|
||||
.detail-note-editor {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.detail-note-editor textarea {
|
||||
min-height: 92px;
|
||||
border-color: rgba(16, 185, 129, .28);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.detail-note-editor textarea:focus {
|
||||
border-color: #10b981;
|
||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, .12);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.detail-note-editor-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.detail-note-actions {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex-shrink: 0;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.leader-approval-card {
|
||||
border-color: rgba(5, 150, 105, .18);
|
||||
background: linear-gradient(180deg, #ffffff 0%, #f7fdfb 100%);
|
||||
@@ -633,6 +673,15 @@
|
||||
background: #fbfefd;
|
||||
}
|
||||
|
||||
.detail-expense-table tbody tr.system-generated-row td {
|
||||
background: #f0fdf4;
|
||||
border-bottom-color: #bbf7d0;
|
||||
}
|
||||
|
||||
.detail-expense-table tbody tr.system-generated-row:hover td {
|
||||
background: #ecfdf5;
|
||||
}
|
||||
|
||||
.detail-expense-table .col-time { width: 11%; }
|
||||
.detail-expense-table .col-filled-at { width: 15%; }
|
||||
.detail-expense-table .col-type { width: 13%; }
|
||||
@@ -756,6 +805,36 @@
|
||||
color: #ea580c;
|
||||
}
|
||||
|
||||
.over-tag.system {
|
||||
background: #dcfce7;
|
||||
color: #047857;
|
||||
}
|
||||
|
||||
.expense-total-under-table {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 12px;
|
||||
padding: 12px 14px;
|
||||
border: 1px solid #d1fae5;
|
||||
border-radius: 8px;
|
||||
background: #f0fdf4;
|
||||
color: #0f766e;
|
||||
}
|
||||
|
||||
.expense-total-under-table span {
|
||||
color: #475569;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.expense-total-under-table strong {
|
||||
color: #047857;
|
||||
font-size: 17px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.attachment-action-group {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@@ -932,6 +1011,36 @@
|
||||
min-width: 128px;
|
||||
}
|
||||
|
||||
.system-row-lock {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
min-height: 28px;
|
||||
padding: 0 9px;
|
||||
border-radius: 8px;
|
||||
background: #dcfce7;
|
||||
color: #047857;
|
||||
font-size: 11px;
|
||||
font-weight: 850;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.system-attachment-note {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
min-height: 28px;
|
||||
padding: 0 9px;
|
||||
border-radius: 8px;
|
||||
background: #ecfdf5;
|
||||
color: #047857;
|
||||
font-size: 11px;
|
||||
font-weight: 850;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.row-action-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -1332,8 +1441,9 @@
|
||||
}
|
||||
|
||||
.validation-card {
|
||||
border: 1px solid #e6f0eb;
|
||||
background: linear-gradient(180deg, #fcfffd 0%, #f7fbf9 100%);
|
||||
border: 1px solid #e5e7eb;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
|
||||
.validation-head {
|
||||
@@ -1341,11 +1451,14 @@
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.validation-head h3 {
|
||||
margin-bottom: 4px;
|
||||
color: #0f172a;
|
||||
font-size: 15px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.validation-head p {
|
||||
@@ -1356,28 +1469,32 @@
|
||||
}
|
||||
|
||||
.validation-pill {
|
||||
min-height: 26px;
|
||||
min-height: 24px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
border-radius: 999px;
|
||||
font-size: 12px;
|
||||
border: 1px solid transparent;
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.validation-pill.ready {
|
||||
background: #dcfce7;
|
||||
color: #047857;
|
||||
background: #f0fdf4;
|
||||
border-color: #bbf7d0;
|
||||
color: #166534;
|
||||
}
|
||||
|
||||
.validation-pill.pending {
|
||||
background: #fff7ed;
|
||||
border-color: #fed7aa;
|
||||
color: #c2410c;
|
||||
}
|
||||
|
||||
.validation-pill.warning {
|
||||
background: #fef2f2;
|
||||
color: #dc2626;
|
||||
border-color: #fecaca;
|
||||
color: #b91c1c;
|
||||
}
|
||||
|
||||
.validation-summary {
|
||||
@@ -1387,29 +1504,155 @@
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.validation-sections {
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.validation-section {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
padding-top: 14px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.validation-section:first-child {
|
||||
padding-top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.validation-section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 0;
|
||||
color: #0f172a;
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.validation-section-title::before {
|
||||
content: '';
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 999px;
|
||||
background: #10b981;
|
||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.12);
|
||||
}
|
||||
|
||||
.validation-section--risk .validation-section-title {
|
||||
color: #b91c1c;
|
||||
}
|
||||
|
||||
.validation-section--risk .validation-section-title::before {
|
||||
background: #ef4444;
|
||||
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1);
|
||||
}
|
||||
|
||||
.validation-list {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
margin-top: 12px;
|
||||
padding-left: 18px;
|
||||
color: #b45309;
|
||||
margin: 0;
|
||||
padding: 0 0 0 18px;
|
||||
color: #0f766e;
|
||||
font-size: 13px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.risk-advice-list {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
margin-top: 14px;
|
||||
.validation-list li::marker {
|
||||
color: #14b8a6;
|
||||
}
|
||||
|
||||
.risk-advice-card {
|
||||
.validation-section--risk .risk-advice-list {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
padding: 14px;
|
||||
border: 1px solid #fee2e2;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.validation-section--risk .risk-advice-card {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
padding: 12px 12px 11px;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 10px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 1px 1px rgba(15, 23, 42, 0.03);
|
||||
}
|
||||
|
||||
.validation-section--risk .risk-advice-card.medium {
|
||||
border-color: #f3e8d9;
|
||||
background: #fffcf7;
|
||||
}
|
||||
|
||||
.validation-section--risk .risk-advice-card-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.validation-section--risk .risk-advice-card-head span {
|
||||
min-height: 20px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0 8px;
|
||||
border-radius: 999px;
|
||||
background: #fef2f2;
|
||||
color: #b91c1c;
|
||||
font-size: 10px;
|
||||
font-weight: 800;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.validation-section--risk .risk-advice-card.medium .risk-advice-card-head span {
|
||||
background: #fff7ed;
|
||||
color: #c2410c;
|
||||
}
|
||||
|
||||
.validation-section--risk .risk-advice-card-head strong {
|
||||
min-width: 0;
|
||||
color: #0f172a;
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.validation-section--risk .risk-advice-point {
|
||||
margin: 0;
|
||||
color: #334155;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.validation-section--risk .risk-advice-meta {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.validation-section--risk .risk-advice-meta > div {
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
padding: 8px 9px;
|
||||
border-radius: 8px;
|
||||
background: #fffafa;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.validation-section--risk .risk-advice-meta span {
|
||||
color: #64748b;
|
||||
font-size: 10px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.validation-section--risk .risk-advice-meta ul,
|
||||
.validation-section--risk .risk-advice-meta p {
|
||||
margin: 0;
|
||||
color: #334155;
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.risk-advice-card.medium {
|
||||
|
||||
Reference in New Issue
Block a user