优化报销功能
This commit is contained in:
1 parent
395c7f717e
commit
4306cbd74b
19 files changed
+2059
-534
No files matched your search
@@ -47,43 +47,33 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 审批流程时间线 -->
|
||||
<!-- 审批流程 -->
|
||||
<view class="card">
|
||||
<text class="card-title">审批流程</text>
|
||||
<view v-if="!timeline.length" class="timeline-empty">暂无流程节点</view>
|
||||
<view v-else class="timeline-list">
|
||||
<view
|
||||
v-for="(task, idx) in timeline"
|
||||
:key="task.id || idx"
|
||||
class="timeline-item"
|
||||
:class="{ current: task.is_current }"
|
||||
:key="`${task.node_key || 'node'}-${idx}`"
|
||||
class="tl-item"
|
||||
:class="{ current: task.is_current, edge: task.node_type === 1 || task.node_type === 3 }"
|
||||
>
|
||||
<view class="timeline-dot">
|
||||
<view class="dot-inner" :class="dotClass(task)"></view>
|
||||
<view class="tl-rail">
|
||||
<view class="tl-avatar-wrap">
|
||||
<view class="tl-avatar" :class="avatarClass(task)">{{ avatarText(task) }}</view>
|
||||
<view class="tl-badge" :class="badgeClass(task)">{{ badgeIcon(task) }}</view>
|
||||
</view>
|
||||
<view v-if="idx !== timeline.length - 1" class="tl-line" />
|
||||
</view>
|
||||
<view class="timeline-content" v-if="idx === 0 || task.node_key !== timeline[idx - 1].node_key">
|
||||
<view class="timeline-head">
|
||||
<text class="node-name">{{ task.node_name || task.node_key }}</text>
|
||||
<u-tag
|
||||
:text="task.status_label || ''"
|
||||
:type="task.status_tag || 'info'"
|
||||
size="mini"
|
||||
/>
|
||||
</view>
|
||||
<view v-if="task.is_current" class="timeline-row">
|
||||
<text class="node-meta current">当前节点 · 等待 {{ task.approver_name || '审批人' }} 处理</text>
|
||||
</view>
|
||||
<view v-else-if="task.status === 1" class="timeline-row">
|
||||
<text class="node-meta">{{ task.approver_name || '-' }} · 通过于 {{ task.finish_time }}</text>
|
||||
<text v-if="task.comment" class="node-comment">{{ task.comment }}</text>
|
||||
</view>
|
||||
<view v-else-if="task.status === 2" class="timeline-row">
|
||||
<text class="node-meta">{{ task.approver_name || '-' }} · 驳回于 {{ task.finish_time }}</text>
|
||||
<text v-if="task.comment" class="node-comment">{{ task.comment }}</text>
|
||||
</view>
|
||||
<view v-else class="timeline-row">
|
||||
<text class="node-meta">{{ task.approver_name || '-' }} · {{ task.finish_time || task.create_time }}</text>
|
||||
<view class="tl-main">
|
||||
<view class="tl-head">
|
||||
<view class="tl-title">
|
||||
<text class="tl-name">{{ nodeTitle(task) }}</text>
|
||||
<text v-if="nodeSub(task)" class="tl-sub">{{ nodeSub(task) }}</text>
|
||||
</view>
|
||||
<text class="tl-time">{{ nodeTime(task) }}</text>
|
||||
</view>
|
||||
<view v-if="task.comment" class="tl-comment">{{ task.comment }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -203,11 +193,50 @@ async function loadDetail(id) {
|
||||
}
|
||||
}
|
||||
|
||||
function dotClass(task) {
|
||||
if (task.is_current) return 'dot-running'
|
||||
if (task.status === 1) return 'dot-pass'
|
||||
if (task.status === 2) return 'dot-reject'
|
||||
return 'dot-default'
|
||||
/** 头像文字:取姓名字首字 */
|
||||
function avatarText(task) {
|
||||
const name = String(task.approver_name || '').trim()
|
||||
return name ? name.slice(0, 1) : '系'
|
||||
}
|
||||
|
||||
/** 头像底色:审批人蓝色,结束节点灰色 */
|
||||
function avatarClass(task) {
|
||||
return task.node_type === 3 ? 'avatar-end' : ''
|
||||
}
|
||||
|
||||
/** 状态角标配色:进行中橙 / 已通过绿 / 已驳回红 / 其它灰 */
|
||||
function badgeClass(task) {
|
||||
if (task.is_current) return 'badge-running'
|
||||
if (task.status === 1) return 'badge-pass'
|
||||
if (task.status === 2) return 'badge-reject'
|
||||
return 'badge-skip'
|
||||
}
|
||||
|
||||
function badgeIcon(task) {
|
||||
if (task.is_current) return '·'
|
||||
if (task.status === 1) return '✓'
|
||||
if (task.status === 2) return '✕'
|
||||
return '—'
|
||||
}
|
||||
|
||||
/** 主标题:申请人带「(申请人)」标识,末尾固定「流程结束」 */
|
||||
function nodeTitle(task) {
|
||||
if (task.node_type === 1) return `${task.approver_name || '发起人'}(申请人)`
|
||||
if (task.node_type === 3) return '流程结束'
|
||||
return task.approver_name || task.node_name || '审批节点'
|
||||
}
|
||||
|
||||
/** 副标题:部门/角色,缺失时回退节点名 */
|
||||
function nodeSub(task) {
|
||||
if (task.node_type === 1) return '提交申请'
|
||||
if (task.node_type === 3) return task.status_label || ''
|
||||
return task.approver_sub || task.node_name || '审批'
|
||||
}
|
||||
|
||||
/** 时间只展示到分钟,保持与设计稿一致的紧凑排版 */
|
||||
function nodeTime(task) {
|
||||
const value = task.finish_time || task.create_time || ''
|
||||
return value ? String(value).slice(0, 16) : ''
|
||||
}
|
||||
|
||||
function openApprove(pass) {
|
||||
@@ -338,10 +367,25 @@ async function doWithdraw() {
|
||||
|
||||
.card-title {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding-left: 18rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: $color-text;
|
||||
margin-bottom: 18rpx;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
/* 左侧蓝色竖条标识(与设计稿一致) */
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 8rpx;
|
||||
height: 26rpx;
|
||||
border-radius: 4rpx;
|
||||
background: $color-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.info-row {
|
||||
@@ -375,112 +419,8 @@ async function doWithdraw() {
|
||||
padding: 16rpx 0 8rpx;
|
||||
}
|
||||
|
||||
.timeline-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-left: 12rpx;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
position: relative;
|
||||
padding-bottom: 18rpx;
|
||||
|
||||
&:not(:last-child)::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 18rpx;
|
||||
top: 30rpx;
|
||||
bottom: 0;
|
||||
width: 2rpx;
|
||||
background: $color-divider;
|
||||
}
|
||||
|
||||
&.current {
|
||||
.node-name { color: $color-primary; }
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-dot {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.dot-inner {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
border-radius: 50%;
|
||||
background: $color-text-muted;
|
||||
|
||||
&.dot-default { background: $color-text-muted; }
|
||||
&.dot-pass { background: #16a34a; }
|
||||
&.dot-reject { background: #f04438; }
|
||||
&.dot-running {
|
||||
background: $color-primary;
|
||||
box-shadow: 0 0 0 8rpx rgba(37, 99, 235, 0.16);
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding-top: 4rpx;
|
||||
}
|
||||
|
||||
.timeline-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4rpx;
|
||||
margin-bottom: 6rpx;
|
||||
|
||||
&:last-child { margin-bottom: 0; }
|
||||
}
|
||||
|
||||
/* 节点头部:节点名 + 状态 tag 横排,tag 不要撑满 100% */
|
||||
.timeline-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12rpx;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
.node-name {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 28rpx;
|
||||
color: $color-text;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.node-meta {
|
||||
font-size: 24rpx;
|
||||
color: $color-text-muted;
|
||||
word-break: break-all;
|
||||
|
||||
&.current {
|
||||
color: $color-primary;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.node-comment {
|
||||
font-size: 24rpx;
|
||||
color: $color-text-secondary;
|
||||
background: $color-bg-page;
|
||||
padding: 10rpx 14rpx;
|
||||
border-radius: $radius-sm;
|
||||
margin-top: 6rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
/* 审批流时间线(公共 mixin,与报销详情的审批记录同一套样式) */
|
||||
@include flow-timeline;
|
||||
|
||||
.bottom-space {
|
||||
height: 40rpx;
|
||||
|
||||
Reference in new issue
Block a user