fix: 流程明细取消重复页面外壳 #635
@ -0,0 +1,412 @@
|
||||
<style>
|
||||
.process-details-page {
|
||||
color: var(--vip-content-ink, #171717);
|
||||
font-size: .8125rem;
|
||||
}
|
||||
|
||||
.process-details-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: .4rem .9rem;
|
||||
margin-bottom: .85rem;
|
||||
color: var(--vip-content-muted, #595959);
|
||||
font-size: .75rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.process-details-meta strong {
|
||||
color: var(--vip-content-ink, #171717);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.process-details-toolbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-end;
|
||||
gap: .75rem;
|
||||
padding: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-radius: .5rem;
|
||||
background: var(--vip-surface, #fff);
|
||||
}
|
||||
|
||||
.process-details-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .35rem;
|
||||
min-width: 10.5rem;
|
||||
}
|
||||
|
||||
.process-details-field.is-wide {
|
||||
min-width: 13.5rem;
|
||||
}
|
||||
|
||||
.process-details-field label {
|
||||
color: var(--vip-content-muted, #595959);
|
||||
font-size: .75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.process-details-field input,
|
||||
.process-details-field select {
|
||||
height: 2.25rem;
|
||||
padding: 0 .65rem;
|
||||
border: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-radius: .5rem;
|
||||
background: #fff;
|
||||
color: var(--vip-content-ink, #171717);
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.process-details-field input:focus,
|
||||
.process-details-field select:focus {
|
||||
border-color: var(--vip-content-accent-dark, #856632);
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px rgba(133, 102, 50, .2);
|
||||
}
|
||||
|
||||
.process-details-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: .5rem;
|
||||
}
|
||||
|
||||
.process-details-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: .35rem;
|
||||
height: 2.25rem;
|
||||
padding: 0 .85rem;
|
||||
border: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-radius: .5rem;
|
||||
background: #fff;
|
||||
color: var(--vip-content-ink, #171717);
|
||||
font: inherit;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.process-details-button:hover {
|
||||
border-color: var(--vip-content-accent, #B9954F);
|
||||
color: var(--vip-content-accent-dark, #856632);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.process-details-button.is-primary {
|
||||
border-color: var(--vip-content-accent-dark, #856632);
|
||||
background: var(--vip-content-accent-dark, #856632);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.process-details-button.is-primary:hover {
|
||||
background: #6A5129;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.process-details-alert {
|
||||
padding: .75rem 1rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid var(--vip-danger, #B80000);
|
||||
border-radius: .5rem;
|
||||
background: #fff5f5;
|
||||
color: var(--vip-danger, #B80000);
|
||||
}
|
||||
|
||||
.process-details-summary {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem 2rem;
|
||||
padding: .8rem 1rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-radius: .5rem;
|
||||
background: var(--vip-content-accent-soft, #F7F0DE);
|
||||
}
|
||||
|
||||
.process-details-summary .item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .15rem;
|
||||
}
|
||||
|
||||
.process-details-summary .item span {
|
||||
color: var(--vip-content-muted, #595959);
|
||||
font-size: .7rem;
|
||||
}
|
||||
|
||||
.process-details-summary .item b {
|
||||
font-size: .95rem;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.process-details-note {
|
||||
margin-bottom: .75rem;
|
||||
color: var(--vip-content-muted, #595959);
|
||||
font-size: .75rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.process-details-table-wrap {
|
||||
overflow: auto;
|
||||
max-height: min(68vh, 46rem);
|
||||
border: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-radius: .5rem;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.process-details-table {
|
||||
width: 100%;
|
||||
min-width: 112rem;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
font-size: .78rem;
|
||||
}
|
||||
|
||||
.process-details-table th,
|
||||
.process-details-table td {
|
||||
padding: .55rem .65rem;
|
||||
border-right: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-bottom: 1px solid var(--vip-border, #D8D2C7);
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.process-details-table th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
background: var(--vip-content-accent-soft, #F7F0DE);
|
||||
color: var(--vip-content-ink, #171717);
|
||||
font-size: .75rem;
|
||||
font-weight: 700;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.process-details-table tr:hover td {
|
||||
background: #fcfaf4;
|
||||
}
|
||||
|
||||
.process-details-table .num {
|
||||
text-align: right;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.process-details-table .center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.process-details-table .wide {
|
||||
max-width: 18rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.process-details-table .wide:hover {
|
||||
overflow: visible;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.process-details-status {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: .15rem .5rem;
|
||||
border-radius: 999px;
|
||||
font-size: .7rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.process-details-status.is-success {
|
||||
background: rgba(83, 121, 62, .12);
|
||||
color: var(--vip-success, #53793E);
|
||||
}
|
||||
|
||||
.process-details-status.is-warning {
|
||||
background: rgba(147, 95, 7, .12);
|
||||
color: var(--vip-warning, #935F07);
|
||||
}
|
||||
|
||||
.process-details-status.is-danger {
|
||||
background: rgba(184, 0, 0, .09);
|
||||
color: var(--vip-danger, #B80000);
|
||||
}
|
||||
|
||||
.process-details-status.is-neutral {
|
||||
background: #f1f1f1;
|
||||
color: var(--vip-content-muted, #595959);
|
||||
}
|
||||
|
||||
.process-details-empty {
|
||||
padding: 4rem 1rem;
|
||||
text-align: center;
|
||||
color: var(--vip-content-muted, #595959);
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.process-details-footer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: .75rem;
|
||||
padding: .8rem 1rem;
|
||||
color: var(--vip-content-muted, #595959);
|
||||
font-size: .75rem;
|
||||
}
|
||||
|
||||
.process-details-footer .pagination {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.process-details-toolbar {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.process-details-field,
|
||||
.process-details-field.is-wide {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.process-details-actions {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="process-details-page">
|
||||
<div class="process-details-meta">
|
||||
<span>数据范围:<strong>{{ $scopeLabel }}</strong></span>
|
||||
<span>镜像状态:<strong>{{ $mirrorStatus ?? 'unknown' }}</strong></span>
|
||||
@if (! empty($mirrorSyncedAt))
|
||||
<span>最近同步:<strong>{{ $mirrorSyncedAt }}</strong></span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if ($error)
|
||||
<div class="process-details-alert" role="alert">{{ $error }}</div>
|
||||
@endif
|
||||
|
||||
<form method="GET" action="{{ $pageUrl }}" class="process-details-toolbar" aria-label="流程明细筛选">
|
||||
<div class="process-details-field">
|
||||
<label for="process-details-month">月份</label>
|
||||
<input id="process-details-month" type="month" name="month" value="{{ $filters['month'] ?? '' }}">
|
||||
</div>
|
||||
<div class="process-details-field">
|
||||
<label for="process-details-type">单据类型</label>
|
||||
<select id="process-details-type" name="document_type">
|
||||
<option value="">全部类型</option>
|
||||
@foreach ($documentTypes as $option)
|
||||
<option value="{{ $option }}" @selected(($filters['document_type'] ?? '') === $option)>{{ $option }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="process-details-field">
|
||||
<label for="process-details-status">状态</label>
|
||||
<select id="process-details-status" name="status">
|
||||
<option value="">全部状态</option>
|
||||
@foreach ($statuses as $option)
|
||||
<option value="{{ $option }}" @selected(($filters['status'] ?? '') === $option)>{{ $option }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="process-details-field is-wide">
|
||||
<label for="process-details-business-id">审批编号</label>
|
||||
<input id="process-details-business-id" type="search" name="business_id" value="{{ $filters['business_id'] ?? '' }}" placeholder="支持包含查询">
|
||||
</div>
|
||||
<div class="process-details-field">
|
||||
<label for="process-details-originator">发起人</label>
|
||||
<input id="process-details-originator" type="search" name="originator_name" value="{{ $filters['originator_name'] ?? '' }}" placeholder="支持包含查询">
|
||||
</div>
|
||||
<div class="process-details-field is-wide">
|
||||
<label for="process-details-keyword">用途/摘要</label>
|
||||
<input id="process-details-keyword" type="search" name="keyword" value="{{ $filters['keyword'] ?? '' }}" placeholder="支持包含查询">
|
||||
</div>
|
||||
<div class="process-details-actions">
|
||||
<button class="process-details-button is-primary" type="submit">
|
||||
<span class="material-icons-outlined" aria-hidden="true">search</span>查询
|
||||
</button>
|
||||
<a class="process-details-button" href="{{ $pageUrl }}">
|
||||
<span class="material-icons-outlined" aria-hidden="true">refresh</span>重置
|
||||
</a>
|
||||
<a class="process-details-button" href="{{ $exportUrl }}" title="导出当前筛选结果(CSV,包含全部匹配行)">
|
||||
<span class="material-icons-outlined" aria-hidden="true">download</span>导出
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="process-details-summary">
|
||||
<div class="item"><span>明细行数</span><b>{{ number_format((int) ($summary['rows'] ?? 0)) }}</b></div>
|
||||
<div class="item"><span>审批单数</span><b>{{ number_format((int) ($summary['approvals'] ?? 0)) }}</b></div>
|
||||
<div class="item"><span>金额合计</span><b>{{ $money($summary['amount_total'] ?? null) }}</b></div>
|
||||
<div class="item"><span>银行付款合计</span><b>{{ $money($summary['bank_amount_total'] ?? null) }}</b></div>
|
||||
</div>
|
||||
|
||||
<p class="process-details-note">
|
||||
当前展示的是当前账号权限范围内可读取的钉钉审批流程明细;审批中的金额和行项目仍可能随流程变化。
|
||||
企业级全量数据待领导开通 OA 权限后切换。
|
||||
</p>
|
||||
|
||||
<div class="process-details-table-wrap">
|
||||
<table class="process-details-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>序号</th>
|
||||
<th>审批编号</th>
|
||||
<th>发起人</th>
|
||||
<th>状态</th>
|
||||
<th>单据类型</th>
|
||||
<th>用途/摘要</th>
|
||||
<th class="center">单据内行号</th>
|
||||
<th>科目编码</th>
|
||||
<th>科目名称</th>
|
||||
<th class="num">金额(元)</th>
|
||||
<th>银行科目编码</th>
|
||||
<th>银行科目名称</th>
|
||||
<th class="num">银行付款金额</th>
|
||||
<th>付款方式</th>
|
||||
<th>打款时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse ($processRows as $row)
|
||||
<tr>
|
||||
<td class="num">{{ ($processRows->currentPage() - 1) * $processRows->perPage() + $loop->iteration }}</td>
|
||||
<td>{{ $row->business_id }}</td>
|
||||
<td>{{ $text($row->originator_name) }}</td>
|
||||
<td class="center">
|
||||
<span class="process-details-status {{ $statusClass((string) $row->status) }}">{{ $text($row->status) }}</span>
|
||||
</td>
|
||||
<td>{{ $text($row->document_type) }}</td>
|
||||
<td class="wide" title="{{ $row->purpose }}">{{ $text($row->purpose) }}</td>
|
||||
<td class="center">{{ $row->line_no }}</td>
|
||||
<td>{{ $text($row->account_code) }}</td>
|
||||
<td class="wide" title="{{ $row->account_name }}">{{ $text($row->account_name) }}</td>
|
||||
<td class="num">{{ $money($row->amount) }}</td>
|
||||
<td>{{ $text($row->bank_account_code) }}</td>
|
||||
<td class="wide" title="{{ $row->bank_account_name }}">{{ $text($row->bank_account_name) }}</td>
|
||||
<td class="num">{{ $money($row->bank_amount) }}</td>
|
||||
<td>{{ $text($row->payment_method) }}</td>
|
||||
<td>{{ $text($row->paid_at) }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="15" class="process-details-empty">
|
||||
当前筛选条件没有流程明细。可以调整月份、单据类型、状态或关键词后重试。
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="process-details-footer">
|
||||
<span>
|
||||
第 {{ $processRows->currentPage() }} / {{ max($processRows->lastPage(), 1) }} 页,共 {{ number_format($processRows->total()) }} 行
|
||||
</span>
|
||||
<div>{{ $processRows->links() }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -47,423 +47,22 @@
|
||||
}
|
||||
@endphp
|
||||
|
||||
<x-layouts.admin>
|
||||
<x-slot name="title">
|
||||
流程明细
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
<style>
|
||||
.process-details-page {
|
||||
color: var(--vip-content-ink, #171717);
|
||||
font-size: .8125rem;
|
||||
}
|
||||
@php
|
||||
$processDetailsRouteAction = (string) request()->route()?->getActionName();
|
||||
$processDetailsEmbedded = ! str_contains($processDetailsRouteAction, 'ProcessDetails@show');
|
||||
@endphp
|
||||
|
||||
.process-details-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: .4rem .9rem;
|
||||
margin-bottom: .85rem;
|
||||
color: var(--vip-content-muted, #595959);
|
||||
font-size: .75rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
@if ($processDetailsEmbedded)
|
||||
@include('business.pages.financial-operations.process-details-content')
|
||||
@else
|
||||
<x-layouts.admin>
|
||||
<x-slot name="title">
|
||||
流程明细
|
||||
</x-slot>
|
||||
|
||||
.process-details-meta strong {
|
||||
color: var(--vip-content-ink, #171717);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.process-details-toolbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-end;
|
||||
gap: .75rem;
|
||||
padding: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-radius: .5rem;
|
||||
background: var(--vip-surface, #fff);
|
||||
}
|
||||
|
||||
.process-details-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .35rem;
|
||||
min-width: 10.5rem;
|
||||
}
|
||||
|
||||
.process-details-field.is-wide {
|
||||
min-width: 13.5rem;
|
||||
}
|
||||
|
||||
.process-details-field label {
|
||||
color: var(--vip-content-muted, #595959);
|
||||
font-size: .75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.process-details-field input,
|
||||
.process-details-field select {
|
||||
height: 2.25rem;
|
||||
padding: 0 .65rem;
|
||||
border: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-radius: .5rem;
|
||||
background: #fff;
|
||||
color: var(--vip-content-ink, #171717);
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.process-details-field input:focus,
|
||||
.process-details-field select:focus {
|
||||
border-color: var(--vip-content-accent-dark, #856632);
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px rgba(133, 102, 50, .2);
|
||||
}
|
||||
|
||||
.process-details-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: .5rem;
|
||||
}
|
||||
|
||||
.process-details-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: .35rem;
|
||||
height: 2.25rem;
|
||||
padding: 0 .85rem;
|
||||
border: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-radius: .5rem;
|
||||
background: #fff;
|
||||
color: var(--vip-content-ink, #171717);
|
||||
font: inherit;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.process-details-button:hover {
|
||||
border-color: var(--vip-content-accent, #B9954F);
|
||||
color: var(--vip-content-accent-dark, #856632);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.process-details-button.is-primary {
|
||||
border-color: var(--vip-content-accent-dark, #856632);
|
||||
background: var(--vip-content-accent-dark, #856632);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.process-details-button.is-primary:hover {
|
||||
background: #6A5129;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.process-details-alert {
|
||||
padding: .75rem 1rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid var(--vip-danger, #B80000);
|
||||
border-radius: .5rem;
|
||||
background: #fff5f5;
|
||||
color: var(--vip-danger, #B80000);
|
||||
}
|
||||
|
||||
.process-details-summary {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem 2rem;
|
||||
padding: .8rem 1rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-radius: .5rem;
|
||||
background: var(--vip-content-accent-soft, #F7F0DE);
|
||||
}
|
||||
|
||||
.process-details-summary .item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .15rem;
|
||||
}
|
||||
|
||||
.process-details-summary .item span {
|
||||
color: var(--vip-content-muted, #595959);
|
||||
font-size: .7rem;
|
||||
}
|
||||
|
||||
.process-details-summary .item b {
|
||||
font-size: .95rem;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.process-details-note {
|
||||
margin-bottom: .75rem;
|
||||
color: var(--vip-content-muted, #595959);
|
||||
font-size: .75rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.process-details-table-wrap {
|
||||
overflow: auto;
|
||||
max-height: min(68vh, 46rem);
|
||||
border: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-radius: .5rem;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.process-details-table {
|
||||
width: 100%;
|
||||
min-width: 112rem;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
font-size: .78rem;
|
||||
}
|
||||
|
||||
.process-details-table th,
|
||||
.process-details-table td {
|
||||
padding: .55rem .65rem;
|
||||
border-right: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-bottom: 1px solid var(--vip-border, #D8D2C7);
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.process-details-table th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
background: var(--vip-content-accent-soft, #F7F0DE);
|
||||
color: var(--vip-content-ink, #171717);
|
||||
font-size: .75rem;
|
||||
font-weight: 700;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.process-details-table tr:hover td {
|
||||
background: #fcfaf4;
|
||||
}
|
||||
|
||||
.process-details-table .num {
|
||||
text-align: right;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.process-details-table .center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.process-details-table .wide {
|
||||
max-width: 18rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.process-details-table .wide:hover {
|
||||
overflow: visible;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.process-details-status {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: .15rem .5rem;
|
||||
border-radius: 999px;
|
||||
font-size: .7rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.process-details-status.is-success {
|
||||
background: rgba(83, 121, 62, .12);
|
||||
color: var(--vip-success, #53793E);
|
||||
}
|
||||
|
||||
.process-details-status.is-warning {
|
||||
background: rgba(147, 95, 7, .12);
|
||||
color: var(--vip-warning, #935F07);
|
||||
}
|
||||
|
||||
.process-details-status.is-danger {
|
||||
background: rgba(184, 0, 0, .09);
|
||||
color: var(--vip-danger, #B80000);
|
||||
}
|
||||
|
||||
.process-details-status.is-neutral {
|
||||
background: #f1f1f1;
|
||||
color: var(--vip-content-muted, #595959);
|
||||
}
|
||||
|
||||
.process-details-empty {
|
||||
padding: 4rem 1rem;
|
||||
text-align: center;
|
||||
color: var(--vip-content-muted, #595959);
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.process-details-footer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: .75rem;
|
||||
padding: .8rem 1rem;
|
||||
color: var(--vip-content-muted, #595959);
|
||||
font-size: .75rem;
|
||||
}
|
||||
|
||||
.process-details-footer .pagination {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.process-details-toolbar {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.process-details-field,
|
||||
.process-details-field.is-wide {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.process-details-actions {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="process-details-page">
|
||||
<div class="process-details-meta">
|
||||
<span>数据范围:<strong>{{ $scopeLabel }}</strong></span>
|
||||
<span>镜像状态:<strong>{{ $mirrorStatus ?? 'unknown' }}</strong></span>
|
||||
@if (! empty($mirrorSyncedAt))
|
||||
<span>最近同步:<strong>{{ $mirrorSyncedAt }}</strong></span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if ($error)
|
||||
<div class="process-details-alert" role="alert">{{ $error }}</div>
|
||||
@endif
|
||||
|
||||
<form method="GET" action="{{ $pageUrl }}" class="process-details-toolbar" aria-label="流程明细筛选">
|
||||
<div class="process-details-field">
|
||||
<label for="process-details-month">月份</label>
|
||||
<input id="process-details-month" type="month" name="month" value="{{ $filters['month'] ?? '' }}">
|
||||
</div>
|
||||
<div class="process-details-field">
|
||||
<label for="process-details-type">单据类型</label>
|
||||
<select id="process-details-type" name="document_type">
|
||||
<option value="">全部类型</option>
|
||||
@foreach ($documentTypes as $option)
|
||||
<option value="{{ $option }}" @selected(($filters['document_type'] ?? '') === $option)>{{ $option }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="process-details-field">
|
||||
<label for="process-details-status">状态</label>
|
||||
<select id="process-details-status" name="status">
|
||||
<option value="">全部状态</option>
|
||||
@foreach ($statuses as $option)
|
||||
<option value="{{ $option }}" @selected(($filters['status'] ?? '') === $option)>{{ $option }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="process-details-field is-wide">
|
||||
<label for="process-details-business-id">审批编号</label>
|
||||
<input id="process-details-business-id" type="search" name="business_id" value="{{ $filters['business_id'] ?? '' }}" placeholder="支持包含查询">
|
||||
</div>
|
||||
<div class="process-details-field">
|
||||
<label for="process-details-originator">发起人</label>
|
||||
<input id="process-details-originator" type="search" name="originator_name" value="{{ $filters['originator_name'] ?? '' }}" placeholder="支持包含查询">
|
||||
</div>
|
||||
<div class="process-details-field is-wide">
|
||||
<label for="process-details-keyword">用途/摘要</label>
|
||||
<input id="process-details-keyword" type="search" name="keyword" value="{{ $filters['keyword'] ?? '' }}" placeholder="支持包含查询">
|
||||
</div>
|
||||
<div class="process-details-actions">
|
||||
<button class="process-details-button is-primary" type="submit">
|
||||
<span class="material-icons-outlined" aria-hidden="true">search</span>查询
|
||||
</button>
|
||||
<a class="process-details-button" href="{{ $pageUrl }}">
|
||||
<span class="material-icons-outlined" aria-hidden="true">refresh</span>重置
|
||||
</a>
|
||||
<a class="process-details-button" href="{{ $exportUrl }}" title="导出当前筛选结果(CSV,包含全部匹配行)">
|
||||
<span class="material-icons-outlined" aria-hidden="true">download</span>导出
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="process-details-summary">
|
||||
<div class="item"><span>明细行数</span><b>{{ number_format((int) ($summary['rows'] ?? 0)) }}</b></div>
|
||||
<div class="item"><span>审批单数</span><b>{{ number_format((int) ($summary['approvals'] ?? 0)) }}</b></div>
|
||||
<div class="item"><span>金额合计</span><b>{{ $money($summary['amount_total'] ?? null) }}</b></div>
|
||||
<div class="item"><span>银行付款合计</span><b>{{ $money($summary['bank_amount_total'] ?? null) }}</b></div>
|
||||
</div>
|
||||
|
||||
<p class="process-details-note">
|
||||
当前展示的是当前账号权限范围内可读取的钉钉审批流程明细;审批中的金额和行项目仍可能随流程变化。
|
||||
企业级全量数据待领导开通 OA 权限后切换。
|
||||
</p>
|
||||
|
||||
<div class="process-details-table-wrap">
|
||||
<table class="process-details-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>序号</th>
|
||||
<th>审批编号</th>
|
||||
<th>发起人</th>
|
||||
<th>状态</th>
|
||||
<th>单据类型</th>
|
||||
<th>用途/摘要</th>
|
||||
<th class="center">单据内行号</th>
|
||||
<th>科目编码</th>
|
||||
<th>科目名称</th>
|
||||
<th class="num">金额(元)</th>
|
||||
<th>银行科目编码</th>
|
||||
<th>银行科目名称</th>
|
||||
<th class="num">银行付款金额</th>
|
||||
<th>付款方式</th>
|
||||
<th>打款时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse ($processRows as $row)
|
||||
<tr>
|
||||
<td class="num">{{ ($processRows->currentPage() - 1) * $processRows->perPage() + $loop->iteration }}</td>
|
||||
<td>{{ $row->business_id }}</td>
|
||||
<td>{{ $text($row->originator_name) }}</td>
|
||||
<td class="center">
|
||||
<span class="process-details-status {{ $statusClass((string) $row->status) }}">{{ $text($row->status) }}</span>
|
||||
</td>
|
||||
<td>{{ $text($row->document_type) }}</td>
|
||||
<td class="wide" title="{{ $row->purpose }}">{{ $text($row->purpose) }}</td>
|
||||
<td class="center">{{ $row->line_no }}</td>
|
||||
<td>{{ $text($row->account_code) }}</td>
|
||||
<td class="wide" title="{{ $row->account_name }}">{{ $text($row->account_name) }}</td>
|
||||
<td class="num">{{ $money($row->amount) }}</td>
|
||||
<td>{{ $text($row->bank_account_code) }}</td>
|
||||
<td class="wide" title="{{ $row->bank_account_name }}">{{ $text($row->bank_account_name) }}</td>
|
||||
<td class="num">{{ $money($row->bank_amount) }}</td>
|
||||
<td>{{ $text($row->payment_method) }}</td>
|
||||
<td>{{ $text($row->paid_at) }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="15" class="process-details-empty">
|
||||
当前筛选条件没有流程明细。可以调整月份、单据类型、状态或关键词后重试。
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="process-details-footer">
|
||||
<span>
|
||||
第 {{ $processRows->currentPage() }} / {{ max($processRows->lastPage(), 1) }} 页,共 {{ number_format($processRows->total()) }} 行
|
||||
</span>
|
||||
<div>{{ $processRows->links() }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-layouts.admin>
|
||||
<x-slot name="content">
|
||||
@include('business.pages.financial-operations.process-details-content')
|
||||
</x-slot>
|
||||
</x-layouts.admin>
|
||||
@endif
|
||||
|
||||
@ -10,6 +10,25 @@ use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ProcessDetailsPageDataTest extends TestCase
|
||||
{
|
||||
public function test_embedded_process_page_uses_content_only_without_nested_admin_layout(): void
|
||||
{
|
||||
$root = dirname(__DIR__, 3);
|
||||
$page = (string) file_get_contents(
|
||||
$root . '/resources/views/business/pages/financial-operations/process-details.blade.php',
|
||||
);
|
||||
$content = (string) file_get_contents(
|
||||
$root . '/resources/views/business/pages/financial-operations/process-details-content.blade.php',
|
||||
);
|
||||
|
||||
$this->assertStringContainsString('$processDetailsEmbedded', $page);
|
||||
$this->assertStringContainsString(
|
||||
"@include('business.pages.financial-operations.process-details-content')",
|
||||
$page,
|
||||
);
|
||||
$this->assertStringNotContainsString('<x-layouts.admin>', $content);
|
||||
$this->assertStringContainsString('class="process-details-page"', $content);
|
||||
}
|
||||
|
||||
public function test_page_data_contains_real_paginator_filters_and_summary(): void
|
||||
{
|
||||
$row = (object) [
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user