Files
fad_oa/ruoyi-ui/src/views/hrm/requests/travelDetail.vue

379 lines
6.6 KiB
Vue

<template>
<BizDetailContainer :bizId="currentBizId" bizType="travel" :preview="preview">
<template slot-scope="{ detail }">
<div>
<!-- 出差时间与行程 -->
<div class="block-title">出差时间与行程</div>
<el-card class="inner-card" shadow="never">
<el-descriptions :column="2" border size="small">
<el-descriptions-item label="开始时间">
<span class="date-time">{{ formatDate(detail.startTime) }}</span>
</el-descriptions-item>
<el-descriptions-item label="结束时间">
<span class="date-time">{{ formatDate(detail.endTime) }}</span>
</el-descriptions-item>
<el-descriptions-item label="出差类型">{{ detail.travelType || '-' }}</el-descriptions-item>
<el-descriptions-item label="目的地">
<span class="destination-text">{{ detail.destination || '-' }}</span>
</el-descriptions-item>
<el-descriptions-item label="出差事由" :span="2">
<div class="reason-content">{{ detail.reason || '未填写' }}</div>
</el-descriptions-item>
</el-descriptions>
</el-card>
<div class="block-title">交通/住宿/行程附件</div>
<el-card class="inner-card" shadow="never">
<file-preview v-model="detail.accessoryApplyIds" />
</el-card>
<!-- 流程状态 -->
<div class="block-title">回执附件</div>
<el-card class="inner-card" shadow="never">
<file-preview v-model="detail.accessoryReceiptIds" />
</el-card>
</div>
</template>
</BizDetailContainer>
</template>
<script>
import FilePreview from "@/components/FilePreview/index.vue";
import BizDetailContainer from '@/views/hrm/components/BizDetailContainer/index.vue';
export default {
name: 'TravelDetail',
props: {
bizId: { type: [String, Number], default: '' },
embedded: { type: Boolean, default: false },
preview: { type: Boolean, default: false }
},
components: {
BizDetailContainer,
FilePreview
},
name: 'HrmTravelDetail',
computed: {
currentBizId () {
return this.bizId || this.$route?.params?.bizId || this.$route?.query?.bizId || this.$route?.params?.id
},
},
methods: {
formatDate (val) {
if (!val) return '-'
const d = new Date(val)
const p = n => (n < 10 ? `0${n}` : n)
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`
},
}
}
</script>
<style lang="scss" scoped>
.request-page {
padding: 16px 20px 32px;
background: #f8f9fb;
}
.form-card {
max-width: 980px;
margin: 0 auto;
border: 1px solid #d7d9df;
border-radius: 12px;
background: #ffffff;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
font-weight: 700;
color: #2b2f36;
}
.actions {
display: flex;
gap: 8px;
}
.block-title {
margin: 12px 0 8px;
padding-left: 10px;
font-weight: 700;
color: #2f3440;
border-left: 3px solid #9aa3b2;
}
.hint-text {
margin: 6px 0 10px;
font-size: 12px;
color: #8a8f99;
}
.form-summary {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
padding: 12px 12px;
margin-bottom: 12px;
border: 1px solid #e6e8ed;
border-radius: 10px;
background: linear-gradient(180deg, #ffffff 0%, #fbfcfe 100%);
}
.summary-title {
font-size: 16px;
font-weight: 800;
color: #2b2f36;
}
.summary-sub {
margin-top: 4px;
font-size: 12px;
color: #8a8f99;
}
.summary-right {
display: flex;
gap: 16px;
}
.summary-item .k {
font-size: 12px;
color: #8a8f99;
}
.summary-item .v {
margin-top: 2px;
font-weight: 700;
color: #2b2f36;
}
.inner-card {
border: 1px solid #e6e8ed;
}
.approver-info {
display: flex;
gap: 24px;
padding: 12px 0;
}
.approver-item {
display: flex;
flex-direction: column;
gap: 6px;
}
.approver-label {
font-size: 12px;
color: #8a8f99;
}
.approver-value {
font-weight: 600;
color: #2b2f36;
}
.empty {
color: #a0a3ad;
font-size: 13px;
padding: 10px 4px;
}
.timeline-row .t-main {
font-weight: 600;
color: #2b2f36;
}
.timeline-row .t-remark {
margin-top: 4px;
color: #606266;
font-size: 13px;
}
.btn-row {
display: flex;
gap: 10px;
}
.attachment-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.attachment-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 12px;
border: 1px solid #e6e8ed;
border-radius: 8px;
background: #fafbfc;
}
.file-info {
display: flex;
align-items: center;
gap: 10px;
flex: 1;
}
.file-icon {
font-size: 24px;
color: #9aa3b2;
}
.file-details {
flex: 1;
}
.file-name {
font-weight: 600;
color: #2b2f36;
margin-bottom: 4px;
}
.file-meta {
font-size: 12px;
color: #8a8f99;
display: flex;
gap: 12px;
}
.date-time {
font-weight: 600;
color: #2b2f36;
}
.destination-text {
font-weight: 600;
color: #2b2f36;
font-size: 14px;
}
.cost-text {
font-weight: 700;
color: #e6a23c;
font-size: 16px;
}
.reason-content {
padding: 8px 12px;
background: #f8f9fa;
border-radius: 6px;
color: #2b2f36;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-word;
}
.info-section {
padding: 12px;
border: 1px solid #e6e8ed;
border-radius: 8px;
background: #fafbfc;
}
.info-label {
font-size: 13px;
font-weight: 600;
color: #606266;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 6px;
}
.info-label i {
color: #9aa3b2;
}
.info-content {
min-height: 40px;
}
.info-text {
color: #2b2f36;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-word;
}
.info-placeholder {
color: #c0c4cc;
font-size: 12px;
font-style: italic;
}
.remark-section {
margin-top: 16px;
padding-top: 16px;
border-top: 1px solid #e6e8ed;
}
.remark-label {
font-size: 13px;
font-weight: 600;
color: #606266;
margin-bottom: 8px;
}
.remark-content {
padding: 12px;
background: #f8f9fa;
border-radius: 6px;
color: #2b2f36;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-word;
}
.file-time {
margin-left: 8px;
}
.file-actions {
display: flex;
gap: 8px;
}
.flow-status {
display: flex;
flex-direction: column;
gap: 12px;
}
.status-item {
display: flex;
align-items: center;
gap: 12px;
padding: 8px 12px;
border: 1px solid #e6e8ed;
border-radius: 6px;
background: #fafbfc;
}
.status-label {
font-size: 13px;
font-weight: 600;
color: #606266;
min-width: 80px;
}
.status-value {
flex: 1;
color: #2b2f36;
font-weight: 500;
}
@media (max-width: 1200px) {
.summary-right {
display: none;
}
}
</style>