This commit is contained in:
2026-03-12 15:05:24 +08:00
parent 58c24fc7d0
commit 9ce85395fd
9 changed files with 127 additions and 82 deletions
@@ -42,70 +42,70 @@ module.exports = {
},
methods: {
jump(tab, event) {
let target = document.querySelector('.scroll-content')
let scrollItems = document.querySelectorAll('.scroll-item')
// 判断滚动条是否滚动到底部
if (target.scrollHeight <= target.scrollTop + target.clientHeight) {
this.tabIndex = tab.index.toString()
}
let totalY = scrollItems[tab.index].offsetTop - scrollItems[0].offsetTop // 锚点元素距离其offsetParent(这里是body)顶部的距离(待滚动的距离)
let distance = document.querySelector('.scroll-content').scrollTop // 滚动条距离滚动区域顶部的距离
// let distance = document.body.scrollTop || document.documentElement.scrollTop || window.pageYOffset // 滚动条距离滚动区域顶部的距离(滚动区域为窗口)
// 滚动动画实现, 使用setTimeout的递归实现平滑滚动,将距离细分为50小段,10ms滚动一次
// 计算每一小段的距离
let step = totalY / 50
if (totalY > distance) {
smoothDown(document.querySelector('.scroll-content'))
} else {
let newTotal = distance - totalY
step = newTotal / 50
smoothUp(document.querySelector('.scroll-content'))
}
const container = this.$el.querySelector('.scroll-content')
const scrollItems = this.$el.querySelectorAll('.scroll-item')
// 参数element为滚动区域
function smoothDown(element) {
if (distance < totalY) {
distance += step
element.scrollTop = distance
setTimeout(smoothDown.bind(this, element), 10)
} else {
element.scrollTop = totalY
}
}
if (!container || !scrollItems.length) return
// 参数element为滚动区域
function smoothUp(element) {
if (distance > totalY) {
distance -= step
element.scrollTop = distance
setTimeout(smoothUp.bind(this, element), 10)
} else {
element.scrollTop = totalY
}
}
const targetIndex = Number(tab.index)
const targetTop = scrollItems[targetIndex].offsetTop - scrollItems[0].offsetTop
console.log(this.tabName)
// ✅ 设置标志位,锁定 tab 不被 onScroll 覆盖
this.isJumping = true
this.tabName = this.tabs[targetIndex]?.refName
container.scrollTo({
top: targetTop,
behavior: 'smooth'
})
// ✅ 滚动动画结束后解锁(smooth 滚动大约 300~500ms)
clearTimeout(this._jumpTimer)
this._jumpTimer = setTimeout(() => {
this.isJumping = false
}, 500)
},
onScroll(e) {
if (e.target.scrollTop === 0) {
this.tabName = this.tabs[0].refName
// ✅ jump 期间不处理滚动联动
if (this.isJumping) return
const container = e.target
const { scrollTop, scrollHeight, clientHeight } = container
// 1. 滚动到底部
if (scrollTop + clientHeight >= scrollHeight - 1) {
const lastIndex = this.tabs.length - 1
if (this.tabIndex !== lastIndex) {
this.tabIndex = lastIndex
this.tabName = this.tabs[lastIndex]?.refName
}
return
}
$('#app > div.guava-main-content > span > div.el-card').each((idx, item) => {
if ($(item).is(':visible')) {
const scrollItems = $(item).find('.scroll-item')
for (let i = scrollItems.length - 1; i >= 0; i--) {
let judge = e.target.scrollTop >= scrollItems[i].offsetTop - scrollItems[0].offsetTop - 300
if (judge) {
this.tabIndex = i.toString()
this.tabName = this.tabs[this.tabIndex].refName
break
}
}
// 2. 顶部
if (scrollTop === 0) {
if (this.tabIndex !== 0) {
this.tabIndex = 0
this.tabName = this.tabs[0]?.refName
}
})
return
}
// 3. 中间区域
const scrollItems = this.$el.querySelectorAll('.scroll-item')
const threshold = 100
for (let i = scrollItems.length - 1; i >= 0; i--) {
const itemTop = scrollItems[i].offsetTop - scrollItems[0].offsetTop
if (scrollTop + threshold >= itemTop) {
if (this.tabIndex !== i) {
this.tabIndex = i
this.tabName = this.tabs[i]?.refName
}
break
}
}
},
scrollEnd() {
@@ -121,7 +121,29 @@ module.exports = {
this.tabName = 'audit'
}, 250)
})
}
},
scrollToTop() {
const tryScroll = () => {
const scrollEl = this.$el.querySelector('.scroll-content')
if (!scrollEl) return
// 检查内容是否已渲染(scrollHeight > clientHeight 说明有滚动空间)
if (scrollEl.scrollHeight <= scrollEl.clientHeight) {
// 内容还没加载完,100ms 后重试
setTimeout(tryScroll, 100)
return
}
// ✅ 内容就绪,执行滚动
scrollEl.scrollTo({top: 0, behavior: 'auto'})
this.tabIndex = 0
this.tabName = this.tabs[0]?.refName
}
this.$nextTick(() => {
setTimeout(tryScroll, 200)
})
},
},
created() {
@@ -206,4 +228,4 @@ module.exports = {
color: #fff;
}
</style>
</style>
@@ -1058,14 +1058,14 @@ module.exports = {
if (this.viewData.delegationAudit && this.viewData.delegationAudit.length > 0) {
tabs.push({name: '团长审核', refName: 'delegation-audit-info'})
}
if (proposal.enableState.some(v => v.stateCode === proposal.PREAUDIT)) {
tabs.push({name: '预审核', refName: 'pre-audit-info'})
if (this.viewData.preAudit && this.viewData.preAudit.length > 0) {
tabs.push({name: '提案委秘书、主任审核', refName: 'pre-audit-info'})
}
if (this.viewData.membersOpinions && this.viewData.membersOpinions.length > 0) {
tabs.push({name: '委员会成员意见', refName: 'members-audit-info'})
}
if (this.viewData.caseAuditId && this.viewData.caseAudit) {
tabs.push({name: '提案委员会立案', refName: 'case-audit-info'})
tabs.push({name: '提案委主任、秘书提交上会讨论结果', refName: 'case-audit-info'})
}
if (this.viewData.underTakeFirstOpinion && this.viewData.underTakeFirstOpinion.length > 0) {
tabs.push({name: '承办单位初步意见', refName: 'undertake-first-audit-info'})
@@ -1107,7 +1107,9 @@ module.exports = {
this.$refs.etp.scrollEnd()
}
} else {
this.$refs.etp.tabName = tabs[0].refName
if (this.$refs.etp) {
this.$refs.etp.scrollToTop()
}
}
this.tabs = tabs
@@ -1228,4 +1230,8 @@ module.exports = {
height: 15px;
}
</style>
.custom-desc .el-descriptions-item__label {
width: 15% !important;
}
</style>
@@ -1,5 +1,6 @@
<template>
<el-card shadow="never" style="position:relative;">
<div class="d-search-item btn-group tool-button">
<el-input placeholder="请输入内容" clearable v-model="page.searchKeyword"
@keyup.enter.native="$emit('doSearch')">
@@ -65,6 +66,7 @@
<div class="btn-group tool-button" style="margin-left: 10px">
<el-button type="primary" icon="el-icon-search" @click="$emit('search')"></el-button>
</div>
</div>
@@ -110,7 +112,7 @@ module.exports = {
default: true
},
audit: {
type: String,
type: Boolean,
default: true
},
title: {
@@ -181,4 +183,4 @@ module.exports = {
top: 0;
right: 10px;
}
</style>
</style>
@@ -39,7 +39,7 @@ layout("/layouts/platform.html"){
<proposal-search :page="pageForm" @search="doSearch"></proposal-search>
<el-card shadow="never" class="mt20">
<table-tool label="提案委员会立案审核" :app="this">
<table-tool label="提案委主任、秘书提交上会讨论结果" :app="this">
<template #func>
<el-button @click="mergeAudit"
:disabled="multipleSelection && multipleSelection.length >=2 ? false : true"
@@ -133,7 +133,7 @@ layout("/layouts/platform.html"){
</template>
<template #edit>
<proposal-info ref="audit" label="提案委员会立案审核" handle>
<proposal-info ref="audit" label="提案委主任、秘书提交上会讨论结果" handle>
<template #handle>
<el-form :model="formData" ref="auditForm" :rules="formRules" label-width="120px">
<!-- <vi-title title="审核信息"></vi-title>-->
@@ -808,4 +808,4 @@ layout("/layouts/platform.html"){
<!--#
}
#-->
#-->
@@ -310,4 +310,4 @@ layout("/layouts/platform.html"){
<!--#
}
#-->
#-->
@@ -9,7 +9,7 @@ layout("/layouts/platform.html"){
<proposal-search :page="pageForm" @search="doSearch"></proposal-search>
<el-card shadow="never" class="mt20">
<table-tool label="预审核" :app="this">
<table-tool label="提案委秘书、主任审核" :app="this">
<template #func>
<!--# if(@shiro.hasRole('jdhdbt01')){ #-->
<!-- <el-button v-if="!pageForm.isAudit" type="primary" size="small"-->
@@ -62,7 +62,7 @@ layout("/layouts/platform.html"){
</template>
<template #edit>
<proposal-info ref="audit" label="预审核" handle>
<proposal-info ref="audit" label="提案委秘书、主任审核" handle>
<template #handle>
<el-form :model="formData" ref="auditForm" :rules="formRules" label-width="120px">
<vi-title title="审核信息"></vi-title>
@@ -238,4 +238,4 @@ layout("/layouts/platform.html"){
<!--#
}
#-->
#-->