|
|
|
@ -14,92 +14,108 @@ |
|
|
|
</div> --> |
|
|
|
|
|
|
|
<van-pull-refresh v-model="refreshing" @refresh="onRefresh"> |
|
|
|
<van-list |
|
|
|
v-model:loading="loading" |
|
|
|
:finished="finished" |
|
|
|
finished-text="没有更多了" |
|
|
|
@load="onLoad" |
|
|
|
> |
|
|
|
<van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad"> |
|
|
|
<div class="reserve-list"> |
|
|
|
<section |
|
|
|
v-for="item in reserveList" |
|
|
|
:key="item.id" |
|
|
|
class="reserve-card" |
|
|
|
:class="{ 'approved-card': item.opStatus === 1, 'rejected-card': item.opStatus === 2, 'pending-card': item.opStatus === 3 }" |
|
|
|
> |
|
|
|
<div class="card-header"> |
|
|
|
<section v-for="item in reserveList" :key="item.id" class="reserve-card" |
|
|
|
:class="{ 'approved-card': item.opStatus === 1, 'rejected-card': item.opStatus === 2, 'pending-card': item.opStatus === 3 }"> |
|
|
|
<!-- <div class="card-header"> |
|
|
|
<div class="card-label">系统匹配</div> |
|
|
|
</div> |
|
|
|
</div> --> |
|
|
|
|
|
|
|
<!-- 本单位信息 --> |
|
|
|
<div class="unit-block"> |
|
|
|
<div class="unit-block-header"> |
|
|
|
<!-- <div class="unit-block-header"> |
|
|
|
<span class="unit-block-tag">本单位计划</span> |
|
|
|
</div> --> |
|
|
|
<div class="unit-block-content"> |
|
|
|
<div class="unit-block-title">{{ item.enterpriseName || '-' }}</div> |
|
|
|
<div class="unit-block-tip" :class="'status-text' + getStatusClass(item.opStatus)"> |
|
|
|
{{ getStatusText(item.opStatus) }} |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="unit-block-title">{{ item.enterpriseName || '-' }}</div> |
|
|
|
<div class="unit-block-subtitle">{{ formatDateShort(item.planDate) }} {{ getPlanTimeText(item.planTime) }}</div> |
|
|
|
|
|
|
|
<div class="unit-block-subtitle">{{ formatDateShort(item.planDate) }} {{ |
|
|
|
getPlanTimeText(item.planTime) }}</div> |
|
|
|
<div class="unit-block-divider"></div> |
|
|
|
<div class="info-row"> |
|
|
|
<!-- <div class="info-row"> |
|
|
|
<div class="label">预约状态:</div> |
|
|
|
<div class="value"> |
|
|
|
<span :class="'status-text ' + getStatusClass(item.opStatus)">{{ getStatusText(item.opStatus) }}</span> |
|
|
|
<span :class="'status-text ' + getStatusClass(item.opStatus)">{{ |
|
|
|
getStatusText(item.opStatus) }}</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> --> |
|
|
|
<div class="info-row"> |
|
|
|
<div class="label">执法单位:</div> |
|
|
|
<div class="value">{{ item.bureauDeptName || '-' }}</div> |
|
|
|
</div> |
|
|
|
<div class="info-row"> |
|
|
|
<div class="label">执法人员:</div> |
|
|
|
<div class="value pre-line">{{ formatUserInfo(item.enforceUserNames, item.enforceUserTels) }}</div> |
|
|
|
<div class="value pre-line">{{ formatUserInfo(item.enforceUserNames, |
|
|
|
item.enforceUserTels) }}</div> |
|
|
|
</div> |
|
|
|
<div class="info-row"> |
|
|
|
<div class="label">执法事项:</div> |
|
|
|
<div class="value">{{ item.enforceContent || '-' }}</div> |
|
|
|
</div> |
|
|
|
<div class="info-row"> |
|
|
|
<!-- <div class="info-row"> |
|
|
|
<div class="label">匹配时间:</div> |
|
|
|
<div class="value">{{ formatDate(item.reserveTime) }}</div> |
|
|
|
</div> |
|
|
|
</div> --> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- 关联计划(默认展开) --> |
|
|
|
<div v-if="groupMembersMap[item.id] && groupMembersMap[item.id].length > 0" class="unit-block unit-block-target"> |
|
|
|
<div class="unit-block-header"> |
|
|
|
<span class="unit-block-tag unit-block-tag-target">关联单位 ({{ groupMembersMap[item.id].length }})</span> |
|
|
|
</div> |
|
|
|
<div v-for="(member, idx) in groupMembersMap[item.id]" :key="member.id" class="member-section"> |
|
|
|
<div class="unit-block-title">{{ member.bureauDeptName || '-' }}</div> |
|
|
|
<div v-if="groupMembersMap[item.id] && groupMembersMap[item.id].length > 0" |
|
|
|
class="unit-block unit-block-target"> |
|
|
|
<!-- <div class="unit-block-header"> |
|
|
|
<span class="unit-block-tag unit-block-tag-target">关联单位 ({{ |
|
|
|
groupMembersMap[item.id].length }})</span> |
|
|
|
</div> --> |
|
|
|
<div v-for="(member, idx) in groupMembersMap[item.id]" :key="member.id" |
|
|
|
class="member-section"> |
|
|
|
<div class="unit-block-content"> |
|
|
|
<div class="unit-block-title">{{ member.bureauDeptName || '-' }}</div> |
|
|
|
<div class="unit-block-tip" |
|
|
|
:class="'status-text' + getStatusClass(member.opStatus)"> |
|
|
|
{{ getStatusText(member.opStatus) }} |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<!-- <div class="unit-block-title">{{ member.bureauDeptName || '-' }}</div> --> |
|
|
|
<div class="unit-block-text">联合单位</div> |
|
|
|
<div class="unit-block-divider"></div> |
|
|
|
<div class="info-row"> |
|
|
|
<div class="label">计划时间:</div> |
|
|
|
<div class="value">{{ formatDateShort(member.planDate) }} {{ getPlanTimeText(member.planTime) }}</div> |
|
|
|
<div class="value">{{ formatDateShort(member.planDate) }} {{ |
|
|
|
getPlanTimeText(member.planTime) }}</div> |
|
|
|
</div> |
|
|
|
<div class="info-row"> |
|
|
|
<!-- <div class="info-row"> |
|
|
|
<div class="label">预约状态:</div> |
|
|
|
<div class="value"> |
|
|
|
<span :class="'status-text ' + getStatusClass(member.opStatus)">{{ getStatusText(member.opStatus) }}</span> |
|
|
|
<span :class="'status-text ' + getStatusClass(member.opStatus)">{{ |
|
|
|
getStatusText(member.opStatus) }}</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> --> |
|
|
|
<div class="info-row"> |
|
|
|
<div class="label">执法人员:</div> |
|
|
|
<div class="value pre-line">{{ formatUserInfo(member.enforceUserNames, member.enforceUserTels) }}</div> |
|
|
|
<div class="value pre-line">{{ formatUserInfo(member.enforceUserNames, |
|
|
|
member.enforceUserTels) }}</div> |
|
|
|
</div> |
|
|
|
<div class="info-row"> |
|
|
|
<div class="label">执法事项:</div> |
|
|
|
<div class="value">{{ member.enforceContent || '-' }}</div> |
|
|
|
</div> |
|
|
|
<div v-if="idx < groupMembersMap[item.id].length - 1" class="member-divider"></div> |
|
|
|
<!-- <div v-if="idx < groupMembersMap[item.id].length - 1" class="member-divider"></div> --> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div v-else-if="item.planGroupId && groupLoadingSet.has(item.id)" class="unit-block unit-block-target"> |
|
|
|
<div v-else-if="item.planGroupId && groupLoadingSet.has(item.id)" |
|
|
|
class="unit-block unit-block-target"> |
|
|
|
<div class="group-loading">加载关联计划中...</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- 待确认状态直接显示操作按钮 --> |
|
|
|
<div v-if="item.opStatus === 3" class="card-actions"> |
|
|
|
<div class="actions-left"> |
|
|
|
<div v-if="item.opMessage" class="action-item message-action" @click.stop="onShowMessage(item)"> |
|
|
|
<div v-if="item.opMessage" class="action-item message-action" |
|
|
|
@click.stop="onShowMessage(item)"> |
|
|
|
<van-icon name="chat-o" /> |
|
|
|
<span>查看备注</span> |
|
|
|
</div> |
|
|
|
@ -126,24 +142,14 @@ |
|
|
|
<!-- 时间选择弹窗(opOrder==0 时弹出) --> |
|
|
|
<van-action-sheet v-model:show="showTimePicker" title="请选择执行计划的时间"> |
|
|
|
<div class="time-picker-content"> |
|
|
|
<div |
|
|
|
v-for="(opt, idx) in timeOptions" |
|
|
|
:key="idx" |
|
|
|
class="time-option" |
|
|
|
:class="{ 'time-option-selected': selectedTimeIdx === idx }" |
|
|
|
@click="selectedTimeIdx = idx" |
|
|
|
> |
|
|
|
<div v-for="(opt, idx) in timeOptions" :key="idx" class="time-option" |
|
|
|
:class="{ 'time-option-selected': selectedTimeIdx === idx }" @click="selectedTimeIdx = idx"> |
|
|
|
<div class="time-option-unit">{{ opt.bureauDeptName }}</div> |
|
|
|
<div class="time-option-date">{{ opt.dateLabel }}</div> |
|
|
|
</div> |
|
|
|
<div v-if="timeOptions.length === 0" class="time-option-empty">没有可选的时间</div> |
|
|
|
<van-button |
|
|
|
type="primary" |
|
|
|
block |
|
|
|
:disabled="selectedTimeIdx === null" |
|
|
|
class="time-confirm-btn" |
|
|
|
@click="onConfirmTimeSelection" |
|
|
|
>确认选择</van-button> |
|
|
|
<van-button type="primary" block :disabled="selectedTimeIdx === null" class="time-confirm-btn" |
|
|
|
@click="onConfirmTimeSelection">确认选择</van-button> |
|
|
|
</div> |
|
|
|
</van-action-sheet> |
|
|
|
</div> |
|
|
|
@ -353,7 +359,7 @@ const onApprove = (item) => { |
|
|
|
cancelButtonText: '取消', |
|
|
|
}).then(() => { |
|
|
|
doApprove(item.id, null); |
|
|
|
}).catch(() => {}); |
|
|
|
}).catch(() => { }); |
|
|
|
} |
|
|
|
}, () => { |
|
|
|
showDialog({ title: '提示', message: '网络异常,请稍后重试' }); |
|
|
|
@ -421,7 +427,7 @@ const onReject = (item) => { |
|
|
|
showDialog({ title: '提示', message: res.msg || '操作失败' }); |
|
|
|
} |
|
|
|
}); |
|
|
|
}).catch(() => {}); |
|
|
|
}).catch(() => { }); |
|
|
|
}; |
|
|
|
</script> |
|
|
|
|
|
|
|
@ -462,14 +468,15 @@ const onReject = (item) => { |
|
|
|
} |
|
|
|
|
|
|
|
.reserve-card { |
|
|
|
background: #fff; |
|
|
|
border-radius: 14px; |
|
|
|
background: linear-gradient(220deg, #175cc4 1%, #3b8dda 20%, #0b3fb4 100%); |
|
|
|
border-radius: 8px; |
|
|
|
padding: 0; |
|
|
|
box-shadow: 0 4px 16px rgba(44, 116, 190, 0.12), 0 1px 4px rgba(0, 0, 0, 0.06); |
|
|
|
border: 2.5px solid #1a5fb4; |
|
|
|
// border: 2.5px solid #1a5fb4; |
|
|
|
overflow: hidden; |
|
|
|
padding-bottom: 4px; |
|
|
|
|
|
|
|
> .card-header { |
|
|
|
>.card-header { |
|
|
|
padding: 12px 16px; |
|
|
|
background: linear-gradient(135deg, #0d4fad 0%, #1565c8 50%, #1e7fe0 100%); |
|
|
|
|
|
|
|
@ -483,16 +490,21 @@ const onReject = (item) => { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
> .reserve-time-row { |
|
|
|
>.reserve-time-row { |
|
|
|
margin: 0 16px; |
|
|
|
padding: 10px 0; |
|
|
|
} |
|
|
|
|
|
|
|
> .card-actions { |
|
|
|
margin: 0 16px; |
|
|
|
padding-bottom: 14px; |
|
|
|
padding-top: 12px; |
|
|
|
border-top: 1px solid #999; |
|
|
|
>.card-actions { |
|
|
|
margin: 4px; |
|
|
|
padding: 12px; |
|
|
|
border-top: 1px solid rgba(0, 0, 0, 0.06); |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
align-items: center; |
|
|
|
background-color: #ffffff; |
|
|
|
border-radius: 4px; |
|
|
|
margin-bottom: 0px; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -528,18 +540,41 @@ const onReject = (item) => { |
|
|
|
font-size: 14px; |
|
|
|
font-weight: 500; |
|
|
|
|
|
|
|
&.blue { color: #1f75c9; } |
|
|
|
&.green { color: #07c160; } |
|
|
|
&.red { color: #ee0a24; } |
|
|
|
&.gray { color: #999; } |
|
|
|
&.blue { |
|
|
|
color: #1f75c9; |
|
|
|
} |
|
|
|
|
|
|
|
&.green { |
|
|
|
color: #07c160; |
|
|
|
} |
|
|
|
|
|
|
|
&.red { |
|
|
|
color: #ee0a24; |
|
|
|
} |
|
|
|
|
|
|
|
&.gray { |
|
|
|
color: #999; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.status-text { |
|
|
|
font-weight: 500; |
|
|
|
&.blue { color: #1f75c9; } |
|
|
|
&.green { color: #07c160; } |
|
|
|
&.red { color: #ee0a24; } |
|
|
|
&.gray { color: #999; } |
|
|
|
|
|
|
|
&.blue { |
|
|
|
color: #1f75c9; |
|
|
|
} |
|
|
|
|
|
|
|
&.green { |
|
|
|
color: #07c160; |
|
|
|
} |
|
|
|
|
|
|
|
&.red { |
|
|
|
color: #ee0a24; |
|
|
|
} |
|
|
|
|
|
|
|
&.gray { |
|
|
|
color: #999; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.info-row { |
|
|
|
@ -553,24 +588,55 @@ const onReject = (item) => { |
|
|
|
.label { |
|
|
|
width: 72px; |
|
|
|
flex-shrink: 0; |
|
|
|
color: #333; |
|
|
|
color: #FFFFFF; |
|
|
|
font-weight: 500; |
|
|
|
font-size: 14px; |
|
|
|
} |
|
|
|
|
|
|
|
.value { |
|
|
|
flex: 1; |
|
|
|
color: #8a8a8a; |
|
|
|
color: rgba(255, 255, 255, 0.6); |
|
|
|
|
|
|
|
&.pre-line { |
|
|
|
color: #666; |
|
|
|
white-space: pre-line; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.unit-block { |
|
|
|
background: linear-gradient(135deg, #0d4fad 0%, #1565c8 50%, #1e7fe0 100%); |
|
|
|
padding: 14px 16px; |
|
|
|
margin-bottom: 0; |
|
|
|
border-bottom: 1px solid rgba(255,255,255,0.12); |
|
|
|
// border-bottom: 1px solid rgba(255, 255, 255, 0.12); |
|
|
|
padding-bottom: 0px; |
|
|
|
|
|
|
|
.unit-block-content { |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
|
|
|
|
.unit-block-tip { |
|
|
|
width: 52px; |
|
|
|
height: 24px; |
|
|
|
border-radius: 4px; |
|
|
|
font-size: 12px; |
|
|
|
text-align: center; |
|
|
|
line-height: 24px; |
|
|
|
} |
|
|
|
|
|
|
|
.status-textblue { |
|
|
|
background: rgba(241, 116, 24, 0.1); |
|
|
|
color: #F17418; |
|
|
|
} |
|
|
|
|
|
|
|
.status-textgreen { |
|
|
|
background: rgba(19, 103, 254, 0.1); |
|
|
|
color: #1367FE; |
|
|
|
} |
|
|
|
|
|
|
|
.pending-tip { |
|
|
|
background: rgba(241, 116, 24, 0.1); |
|
|
|
color: #F17418; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.unit-block-tag { |
|
|
|
background: rgba(255, 255, 255, 0.18); |
|
|
|
@ -579,10 +645,12 @@ const onReject = (item) => { |
|
|
|
|
|
|
|
.unit-block-title { |
|
|
|
color: #fff; |
|
|
|
font-size: 14px; |
|
|
|
} |
|
|
|
|
|
|
|
.unit-block-subtitle { |
|
|
|
color: rgba(255, 255, 255, 0.7); |
|
|
|
color: rgba(255, 255, 255, 0.6); |
|
|
|
font-size: 14px; |
|
|
|
} |
|
|
|
|
|
|
|
.unit-block-divider { |
|
|
|
@ -590,11 +658,11 @@ const onReject = (item) => { |
|
|
|
} |
|
|
|
|
|
|
|
.label { |
|
|
|
color: rgba(255, 255, 255, 0.85); |
|
|
|
color: rgb(255, 255, 255); |
|
|
|
} |
|
|
|
|
|
|
|
.value { |
|
|
|
color: rgba(255, 255, 255, 0.75); |
|
|
|
color: rgba(255, 255, 255, 0.6); |
|
|
|
} |
|
|
|
|
|
|
|
.status-text { |
|
|
|
@ -603,10 +671,12 @@ const onReject = (item) => { |
|
|
|
} |
|
|
|
|
|
|
|
.unit-block-target { |
|
|
|
padding: 14px 16px; |
|
|
|
border-bottom: none; |
|
|
|
background: #fff; |
|
|
|
padding: 4px; |
|
|
|
|
|
|
|
// border-bottom: none; |
|
|
|
// background: #fff; |
|
|
|
// margin: 0px 4px 0px 4px; |
|
|
|
// border-radius: 4px; |
|
|
|
.unit-block-tag { |
|
|
|
background: #fff7e6; |
|
|
|
color: #fa8c16; |
|
|
|
@ -621,15 +691,17 @@ const onReject = (item) => { |
|
|
|
} |
|
|
|
|
|
|
|
.unit-block-divider { |
|
|
|
border-bottom-color: #eef2f7; |
|
|
|
// border-bottom-color: #eef2f7; |
|
|
|
} |
|
|
|
|
|
|
|
.label { |
|
|
|
color: #333; |
|
|
|
color: #1D1F24; |
|
|
|
font-size: 14px; |
|
|
|
} |
|
|
|
|
|
|
|
.value { |
|
|
|
color: #8a8a8a; |
|
|
|
color: #666666; |
|
|
|
font-size: 14px; |
|
|
|
} |
|
|
|
|
|
|
|
.status-text { |
|
|
|
@ -676,14 +748,26 @@ const onReject = (item) => { |
|
|
|
} |
|
|
|
|
|
|
|
.member-section { |
|
|
|
padding-bottom: 10px; |
|
|
|
// padding-bottom: 10px; |
|
|
|
// margin-bottom: 10px; |
|
|
|
// border-bottom: 1px dashed #999; |
|
|
|
padding: 14px 16px; |
|
|
|
border-bottom: none; |
|
|
|
background: #fff; |
|
|
|
border-radius: 4px; |
|
|
|
margin-bottom: 10px; |
|
|
|
border-bottom: 1px dashed #999; |
|
|
|
|
|
|
|
&:last-child { |
|
|
|
padding-bottom: 0; |
|
|
|
// padding-bottom: 0; |
|
|
|
margin-bottom: 0; |
|
|
|
border-bottom: none; |
|
|
|
// border-bottom: none; |
|
|
|
} |
|
|
|
|
|
|
|
.unit-block-text { |
|
|
|
font-size: 14px; |
|
|
|
color: #666666; |
|
|
|
padding-bottom: 10px; |
|
|
|
border-bottom: 1px solid #F6F6F6; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -714,6 +798,9 @@ const onReject = (item) => { |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
align-items: center; |
|
|
|
background-color: #ffffff; |
|
|
|
border-radius: 4px; |
|
|
|
margin-bottom: 0px; |
|
|
|
} |
|
|
|
|
|
|
|
.actions-left { |
|
|
|
|