commit
This commit is contained in:
@@ -119,3 +119,103 @@ const modal = {
|
||||
}
|
||||
}
|
||||
Vue.prototype.$modal = modal
|
||||
|
||||
// H5 弹框共享一个 popstate 监听器;仅主动注册的页面会写入历史记录。
|
||||
const mobilePopupHistory = (() => {
|
||||
const marker = '__mobilePopupId'
|
||||
const entries = []
|
||||
let sequence = 0
|
||||
let owners = 0
|
||||
let pending = null
|
||||
const session = Date.now().toString(36)
|
||||
|
||||
// 先移除栈项再同步界面,避免 v-model 的 watcher 再次触发历史回退。
|
||||
const removeFrom = (index) => {
|
||||
const removed = entries.splice(index)
|
||||
removed.reverse().forEach(entry => entry.close())
|
||||
}
|
||||
const onPopState = (event) => {
|
||||
const id = event.state && event.state[marker]
|
||||
const index = entries.findIndex(entry => entry.id === id)
|
||||
removeFrom(index + 1)
|
||||
if (pending) {
|
||||
const resolve = pending.resolve
|
||||
pending = null
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
const backFrom = (index) => {
|
||||
if (index < 0) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
const count = entries.length - index
|
||||
let resolveBack
|
||||
const promise = new Promise(resolve => { resolveBack = resolve })
|
||||
pending = {promise: promise, resolve: resolveBack}
|
||||
removeFrom(index)
|
||||
window.history.go(-count)
|
||||
return promise
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* 注册当前页面,无参数。返回 sync/close/clear/dispose 方法。
|
||||
* sync(key, visible, close):key 为页面内唯一弹框名,visible 为显示状态,
|
||||
* close 为无参关闭回调。close(key) 和 clear() 返回历史回退完成的 Promise,
|
||||
* 页面跳转必须等待 clear() 完成;dispose() 用于销毁时注销回调和监听器。
|
||||
*/
|
||||
register() {
|
||||
const owner = {}
|
||||
let disposed = false
|
||||
if (owners++ === 0) {
|
||||
window.addEventListener('popstate', onPopState)
|
||||
}
|
||||
const handle = {
|
||||
sync(key, visible, close) {
|
||||
if (disposed) {
|
||||
return
|
||||
}
|
||||
if (pending) {
|
||||
pending.promise.then(() => handle.sync(key, visible, close))
|
||||
return
|
||||
}
|
||||
const index = entries.findIndex(entry => entry.owner === owner && entry.key === key)
|
||||
if (!visible) {
|
||||
handle.close(key)
|
||||
} else if (index < 0) {
|
||||
const id = session + '-' + (++sequence)
|
||||
const state = Object.assign({}, window.history.state)
|
||||
state[marker] = id
|
||||
window.history.pushState(state, '', window.location.href)
|
||||
entries.push({id: id, key: key, owner: owner, close: close})
|
||||
}
|
||||
},
|
||||
close(key) {
|
||||
if (pending) {
|
||||
return pending.promise.then(() => handle.close(key))
|
||||
}
|
||||
// 关闭下层弹框时一并关闭其上层,保持浏览器历史与可见层级一致。
|
||||
return backFrom(entries.findIndex(entry => entry.owner === owner && entry.key === key))
|
||||
},
|
||||
clear() {
|
||||
if (pending) {
|
||||
return pending.promise.then(() => handle.clear())
|
||||
}
|
||||
return backFrom(entries.findIndex(entry => entry.owner === owner))
|
||||
},
|
||||
dispose() {
|
||||
if (disposed) {
|
||||
return
|
||||
}
|
||||
disposed = true
|
||||
handle.clear().then(() => {
|
||||
if (--owners === 0) {
|
||||
window.removeEventListener('popstate', onPopState)
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
return handle
|
||||
},
|
||||
}
|
||||
})()
|
||||
|
||||
@@ -113,6 +113,30 @@ layout("/mobile/platform.html"){
|
||||
/*margin-top: 30px;*/
|
||||
}
|
||||
|
||||
/* 标题不参与滚动,说明正文独占弹框剩余高度。 */
|
||||
.checkup-desc-popup {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.checkup-desc-popup > .van-nav-bar {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.checkup-desc-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
overscroll-behavior-y: contain;
|
||||
}
|
||||
|
||||
.checkup-desc-content img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
|
||||
.van-dropdown-menu__bar {
|
||||
display: flex;
|
||||
@@ -183,7 +207,7 @@ layout("/mobile/platform.html"){
|
||||
</div>
|
||||
<div class="van-card-body">
|
||||
<template v-if="!optionTypeList || optionTypeList.length == 0">
|
||||
<van-field @click="campusVisible = true" readonly is-link label="院区" name="campus"
|
||||
<van-field @click="openCampus" readonly is-link label="院区" name="campus"
|
||||
placeholder="请选择体检院区" v-model="formData.campusName"
|
||||
:rules="[{ required: true }]"></van-field>
|
||||
</template>
|
||||
@@ -260,21 +284,21 @@ layout("/mobile/platform.html"){
|
||||
<van-picker
|
||||
title="院区" show-toolbar
|
||||
:columns="campusList" value-key="campusName"
|
||||
@confirm="(value, index) => {formData.campusName = value.campusName; formData.campus = value.id; campusVisible = false}"
|
||||
@cancel="campusVisible = false">
|
||||
@confirm="confirmCampus"
|
||||
@cancel="closeCampus">
|
||||
</van-picker>
|
||||
</van-popup>
|
||||
|
||||
<!--查看说明-->
|
||||
<van-popup position="right" v-model="descVisible" :style="{ height: '100%',width: '100%'}">
|
||||
<van-sticky :offset-top="0">
|
||||
<van-nav-bar @click-left="descVisible=false" left-arrow
|
||||
<van-popup class="checkup-desc-popup" position="right" v-model="descVisible" :style="{ height: '100%',width: '100%'}">
|
||||
<van-nav-bar @click-left="closeDescription" left-arrow
|
||||
title="详情"></van-nav-bar>
|
||||
</van-sticky>
|
||||
<div v-html="desc" class="pre_text" @click="descClick($event)"></div>
|
||||
<div ref="descContent" class="checkup-desc-content">
|
||||
<div v-html="desc" class="pre_text" @click="descClick($event)"></div>
|
||||
</div>
|
||||
</van-popup>
|
||||
|
||||
<van-dialog v-model="confirmShow" title="提示" show-cancel-button :before-close="onBeforeClose">
|
||||
<van-dialog v-model="confirmShow" title="提示" show-cancel-button :close-on-popstate="false" :before-close="onBeforeClose">
|
||||
<div class="van-dialog__message van-dialog__message--has-title">您确定要选择{{chooseOptionName}}吗?</div>
|
||||
<van-radio-group v-model="formData.marry">
|
||||
<van-cell-group>
|
||||
@@ -322,10 +346,59 @@ layout("/mobile/platform.html"){
|
||||
noticeText: '',
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
descVisible(value) {
|
||||
this.syncPopupHistory('descVisible', value)
|
||||
},
|
||||
campusVisible(value) {
|
||||
this.syncPopupHistory('campusVisible', value)
|
||||
},
|
||||
confirmShow(value) {
|
||||
this.syncPopupHistory('confirmShow', value)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// visible 为弹框显示状态;关闭回调仅同步状态,历史回退由全局管理器负责。
|
||||
syncPopupHistory(key, visible) {
|
||||
this.popupHistory.sync(key, visible, () => {
|
||||
this.$set(this, key, false)
|
||||
})
|
||||
},
|
||||
closeDescription() {
|
||||
this.popupHistory.close('descVisible')
|
||||
},
|
||||
openCampus() {
|
||||
this.$set(this, 'campusVisible', true)
|
||||
},
|
||||
closeCampus() {
|
||||
this.popupHistory.close('campusVisible')
|
||||
},
|
||||
// value 为院区选项,包含 campusName(显示名称)和 id(提交值)。
|
||||
confirmCampus(value) {
|
||||
this.$set(this.formData, 'campusName', value.campusName)
|
||||
this.$set(this.formData, 'campus', value.id)
|
||||
this.closeCampus()
|
||||
},
|
||||
// 条件校验提示也占一层历史;系统返回只关闭提示,不离开选择页面。
|
||||
showConditionMessage(title, message) {
|
||||
this.popupHistory.sync('conditionMessage', true, () => vant.Dialog.close())
|
||||
vant.Dialog.alert({
|
||||
title: title,
|
||||
message: message,
|
||||
confirmButtonColor: '#1867b0',
|
||||
closeOnPopstate: false,
|
||||
}).then(() => this.popupHistory.close('conditionMessage'))
|
||||
.catch(() => this.popupHistory.close('conditionMessage'))
|
||||
},
|
||||
descClick(e) {
|
||||
if (e.target.tagName === 'IMG') {
|
||||
vant.ImagePreview([e.target.src])
|
||||
// 图片预览叠加在详情之上,返回时先关闭预览,再关闭详情。
|
||||
const preview = vant.ImagePreview({
|
||||
images: [e.target.src],
|
||||
closeOnPopstate: false,
|
||||
onClose: () => this.popupHistory.close('descriptionImage'),
|
||||
})
|
||||
this.popupHistory.sync('descriptionImage', true, () => preview.close())
|
||||
}
|
||||
},
|
||||
async doChangeHealthProjectSubject(item) {
|
||||
@@ -333,11 +406,7 @@ layout("/mobile/platform.html"){
|
||||
cndId: item.conditionStructureId,
|
||||
})
|
||||
if (res.code !== 0) {
|
||||
vant.Dialog.alert({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
confirmButtonColor: '#1867b0'
|
||||
})
|
||||
this.showConditionMessage('提示', res.msg)
|
||||
this.formData.subjectId = ''
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
@@ -355,6 +424,11 @@ layout("/mobile/platform.html"){
|
||||
if (o.description) {
|
||||
this.desc = o.description
|
||||
this.descVisible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.descContent) {
|
||||
this.$refs.descContent.scrollTop = 0
|
||||
}
|
||||
})
|
||||
} else {
|
||||
vant.Toast('暂无详细说明')
|
||||
}
|
||||
@@ -404,7 +478,9 @@ layout("/mobile/platform.html"){
|
||||
toast.clear()
|
||||
}, 500)
|
||||
if (resp.code === 0) {
|
||||
location.href = '/mobile/healthCheckup/mine'
|
||||
this.popupHistory.clear().then(() => {
|
||||
location.href = '/mobile/healthCheckup/mine'
|
||||
})
|
||||
}
|
||||
}, 1000)
|
||||
},
|
||||
@@ -418,11 +494,7 @@ layout("/mobile/platform.html"){
|
||||
cndId: p.conditionStructureId,
|
||||
})
|
||||
if (res.code !== 0) {
|
||||
vant.Dialog.alert({
|
||||
title: '温馨提醒',
|
||||
message: res.msg,
|
||||
confirmButtonColor: '#1867b0'
|
||||
})
|
||||
this.showConditionMessage('温馨提醒', res.msg)
|
||||
return
|
||||
}
|
||||
this.chooseOptionName = p.optionName
|
||||
@@ -484,6 +556,7 @@ layout("/mobile/platform.html"){
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
this.popupHistory = mobilePopupHistory.register()
|
||||
this.id = GetQueryString('projectId')
|
||||
this.selectId = GetQueryString('selectId')
|
||||
await this.getCampus()
|
||||
@@ -492,6 +565,9 @@ layout("/mobile/platform.html"){
|
||||
await this.getSelectInfo()
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.popupHistory.dispose()
|
||||
},
|
||||
})
|
||||
window.onload = () => {
|
||||
window.addEventListener('pageshow', e => {
|
||||
|
||||
Reference in New Issue
Block a user