我有两个vue组件,第一个是主页面:
<template>
<div class="page-root">
<div class="fixed-navbar">
<CustomNavBar title="现场处罚" @click-left="onClickLeft"/>
</div>
<!-- 步骤组件:提交后隐藏 -->
<div class="fixed-steps" v-if="!formData.showResult">
<van-steps :active="active"
inactive-icon="arrow"
active-icon="success"
active-color="#169BD5"
@click-step="clickStep"
>
<van-step>基础信息</van-step>
<van-step>信息7</van-step>
<van-step>信息8</van-step>
<van-step>信息9</van-step>
</van-steps>
</div>
<div
class="list-content-bg"
:class="{ 'result-mode': formData.showResult }"
>
<!-- 内容区域 -->
<div class="step-content">
<keep-alive>
<basicInfo
v-if="active === 0 && !formData.showResult"
v-model="formData"
class="step-panel"
/>
</keep-alive>
<keep-alive>
<driverInfo
v-if="active === 1 && !formData.showResult"
v-model="formData"
class="step-panel"
/>
</keep-alive>
<keep-alive>
<vehicleInfo
v-if="active === 2 && !formData.showResult"
ref="vehicleInfo"
v-model="formData"
@sync-data="handleSyncData"
class="step-panel"
@selectJtfs="changetJtfs"
/>
</keep-alive>
<keep-alive>
<wfxwInfo
v-if="active === 3 && !formData.showResult"
ref="wfxwInfo"
v-model="formData"
class="step-panel"
@checkSwjg="checkSwjgFunc"
/>
</keep-alive>
<keep-alive>
<violationResult
v-if="formData.showResult"
v-model="formData"
@exit="onClickLeft"
@punish-other="handlePunishOther"
@punish-another="handlePunishAnother"
@back-basic="backBasic"
/>
</keep-alive>
</div>
</div>
<!-- 底部按钮:提交后隐藏 -->
<div class="bottom-btns" v-if="!formData.showResult">
<van-button
color="#F59A23"
class="rect-btn prev-btn"
@click="prevStep"
>{{ active <= 0 ? '退 出' : '上一步' }}</van-button>
<van-button
color="#169BD5"
class="rect-btn"
@click="nextStep"
>{{ active === maxStep ? '提 交' : '下一步' }}</van-button>
</div>
<div v-if="formData.loadingPrintParam" class="overlay">
<div class="loading-spinner">
<div class="spinner"></div>
<p>{{formData.activateLoadingName}}</p>
</div>
</div>
</div>
</template>
<script>
import {Toast, Step, Steps} from 'vant'
import CustomNavBar from '../../../components/ui/CustomNavBar'
import basicInfo from './basicInfo.vue'
import driverInfo from './driverInfo.vue'
import vehicleInfo from './vehicleInfo.vue'
import wfxwInfo from './wfxwInfo.vue'
import violationResult from './violationResult.vue'
import cllx from '../../../components/constant/cllx'
export default {
components: {
'van-step': Step,
'van-steps': Steps,
CustomNavBar,
basicInfo,
driverInfo,
vehicleInfo,
wfxwInfo,
violationResult
},
data () {
return {
active: 0,
maxStep: 3, // 步骤索引从0开始,4个步骤最大为3
minStep: 0,
yhdh: '',
jcmj: '',
yhglbm: '',
sourcePage: '',
formData: {
showResult: false, // 是否显示结果页面
writeStatus: '0', // 文书录入状态,0-录入失败 1-录入成功
writeErrMsg: '', // 文书录入失败返回的异常信息
wslb: '1',
wsbh: '',
zqmjxm: '',
drzqmjxm: '',
glbm: '',
zjhm: '',
xm: '',
dh: '',
jyjzjl: '',
ljjf: '',
fzjg: '',
jszzt: '',
jszztmc: '',
dabh: '', // 档案编号
yxqz: '',
driverImgstr: null,
jyjzArr: [],
wfdlmc: '',
wfxlmc: '',
wfms: '',
wfnr: '',
wfjf: '',
fkbj: '',
jgbj: '',
dxbj: '',
qzcslx: '',
dmfl: '',
zkbj: '',
maxfkje: '',
minfkje: '',
wsbhLoading: false, // 新增loading状态
jtfsOptions: [],
loadingPrintParam: false,
activateLoadingName: '正在获取提交信息...',
jumpSourcePage: '',
alarmQueryData: '',
alarmQueryResendData: ''
},
cllxList: cllx.cllxList,
syxzList: cllx.syxzList,
resend_msg: '',
warning_info: null
}
},
activated () {
this.initData()
window.acceptHpzlData = this.acceptHpzlData
window.acceptHphmData = this.acceptHphmData
window.acceptNetResult = this.acceptNetResult
window.previewConfirm = this.previewConfirm
this.sourcePage = this.$route.query.sourcePage
window.onClickLeft = this.onClickLeft
this.activatedData()
},
methods: {
initData () {
this.$HttpService.callBaseNetParam.call(this)
this.formData.zqmj = this.yhdh
this.formData.zqmjxm = this.jcmj
this.formData.glbm = this.yhglbm
console.log('当前用户管理部门: ' + this.formData.glbm)
},
activatedData () {
if (this.$route.query.personList !== undefined) {
let dataArray = this.$route.query.personList
if (dataArray.length === 0) {
return
}
let tmpArray = JSON.parse(dataArray)
this.formData.drzqmj = tmpArray[0].jybh
this.formData.drzqmjxm = tmpArray[0].xm
}
if (this.$route.query.xzqh !== undefined && this.$route.query.dldm !== undefined) {
this.formData.xzqh = this.$route.query.xzqh
this.formData.wfdd = this.$route.query.dldm
this.formData.lddm = this.$route.query.lddm
this.formData.gls = this.$route.query.gls === undefined ? '' : this.$route.query.gls
this.formData.zblx = this.$route.query.zblx === undefined ? '' : this.$route.query.zblx
this.formData.dllc = this.$route.query.dllc === undefined ? '' : this.$route.query.dllc
this.formData.ddms = this.$route.query.dlms
this.formData.wfdz = this.$route.query.dlqc
this.formData.dllx = this.$route.query.dllx
}
if (this.$route.query.wfsj !== undefined) {
this.formData.wfsj = this.$route.query.wfsj
}
if (this.$route.query.sourcePage === 'SignaturePad') {
console.log('SignaturePad返回')
if (this.formData.signatureImage == null || this.formData.signatureImage === '' || this.formData.signatureImage === undefined) {
this.formData.resign = false
}
}
if (this.$route.query.sourcePage === 'alarmQueryEdit') {
this.formData.jumpSourcePage = 'alarmQueryEdit'
if (this.$route.query.warning_info !== undefined && this.$route.query.warning_info !== '' && this.$route.query.warning_info !== null) {
console.log('warringInfo: ' + this.$route.query.warning_info)
this.formData.alarmQueryData = this.$route.query.warning_info
this.formData.alarmQueryResendData = this.$route.query.resend_msg
this.warning_info = this.$route.query.warning_info
if (this.warning_info.hpzl !== '' && this.warning_info.hpzl !== null && this.warning_info.hpzl !== undefined) {
this.formData.hpzl = this.warning_info.hpzl
}
if (this.warning_info.wfsj !== '' && this.warning_info.wfsj !== null && this.warning_info.wfsj !== undefined) {
this.formData.wfsj = this.warning_info.wfsj
}
if (this.warning_info.wfxw !== '' && this.warning_info.wfxw !== null && this.warning_info.wfxw !== undefined) {
this.formData.wfxw = this.warning_info.wfxw
}
if (this.warning_info.wfdd !== '' && this.warning_info.wfdd !== null && this.warning_info.wfdd !== undefined) {
this.formData.wfdz = this.warning_info.wfdd
}
if (this.warning_info.hphm !== '' && this.warning_info.hphm !== null && this.warning_info.hphm !== undefined) {
this.formData.hphm = this.warning_info.hphm
}
}
if (this.$route.query.wslb === null || this.$route.query.wslb === undefined || this.$route.query.wslb === '') {
Toast('请选择类别')
} else {
this.formData.wslb = this.$route.query.wslb.toString()
}
}
},
acceptNetResult: function (json, url) {
json = this.$CommonUtils.handleJson(json)
},
// 安卓、鸿蒙预览弹窗调用确定方法提交文书信息
previewConfirm () {
console.log('预览后提交文书')
this.submitForm()
},
handleSyncData (data) {
this.formData = data
}
}
}
</script>
<style scoped>
.page-root {
background-color: #F5F5F5;
height: 100vh;
width: 100vw;
overflow: hidden;
position: relative;
/* 让页面根节点撑满视口,防止body滚动条 */
}
.fixed-navbar {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 100;
}
.fixed-steps {
position: fixed;
top: 46px;
left: 0;
width: 100%;
background: #F5F5F5;
z-index: 99;
padding: 2px;
box-sizing: border-box;
}
/deep/ .van-step--horizontal .van-step__title {
font-size: 14px;
font-weight: 500;
}
.steps-divider {
height: 1px;
background-color: #f0f0f0;
margin-top: 16px;
}
.list-content-bg {
background: #F5F5F5;
/* 计算内容区高度,避免被fixed元素遮挡,且内容区可滚动 */
position: absolute;
left: 0;
right: 0;
top: 108px; /* 46px(navbar) + 62px(steps) */
bottom: 56px; /* bottom-btns高度 */
overflow-y: auto;
min-height: 0;
padding: 0 0 0 0;
box-sizing: border-box;
transition: top 0.2s, bottom 0.2s;
}
.list-content-bg.result-mode {
top: 46px !important; /* 只保留navbar高度 */
bottom: 0 !important; /* 占满底部,去除底部按钮高度 */
}
.step-content {
min-height: 100%;
/* 可根据需要添加padding */
}
.bottom-btns {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
background: #fff;
display: flex;
gap: 0;
padding: 0;
box-sizing: border-box;
z-index: 101;
height: 56px;
/* 移除内边距,按钮贴边 */
}
.rect-btn {
border-radius: 0;
flex: 1 1 0;
font-size: 16px;
min-width: 0;
margin: 0;
border-right: 1px solid #f0f0f0;
height: 56px;
line-height: 56px;
}
.rect-btn:last-child {
border-right: none;
}
.prev-btn.deep-orange-btn:disabled {
background: #f8c9a0;
color: #c8c9cc;
border: 1px solid #f8c9a0;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 999;
}
.loading-spinner {
background-color: white;
padding: 20px;
border-radius: 8px;
text-align: center;
}
.spinner {
border: 4px solid rgba(0, 0, 0, 0.1);
border-left-color: #000;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 0 auto 10px;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
</style>
第二个是子页面:
<template>
<div class="basic-info-step">
<div class="form-content">
<van-cell-group style="margin-top:1px;">
<van-field
readonly
required
clickable
label="类别"
:value="wslbText"
right-icon="arrow"
class="font-bold"
@click="showWslbPicker = true"
/>
<van-popup v-model="showWslbPicker" position="bottom">
<van-picker
title="选择类别"
show-toolbar
:columns="wslbOption"
@cancel="showWslbPicker = false"
@confirm="onWslbConfirm"
/>
</van-popup>
<van-field
v-model="localFormData.wsbh"
center
label="编号"
required
placeholder=""
@input="handlWsbhInput"
@change="handleChange"
>
<template #button>
<van-button
color="#169BD5"
size="small"
type="info"
:loading="localFormData.wsbhLoading"
:disabled="localFormData.wsbhLoading"
@click="getWsbh"
>{{ localFormData.wsbhLoading ? '获取中...' : '获取' }}</van-button>
</template>
</van-field>
</van-cell-group>
</div>
</div>
</template>
<script>
import {Toast} from 'vant'
export default {
name: 'basicInfo',
props: {
value: {
type: Object,
default: () => ({})
}
},
data () {
const now = new Date()
return {
localFormData: {
wslb: '1',
wsbh: '',
zqmj: '',
zqmjxm: '',
drzqmj: '',
drzqmjxm: '',
wfsj: '',
wfdz: '',
glbm: '',
xzqh: '',
wfdd: '',
lddm: '',
gls: '',
zblx: '',
dllc: '',
dllx: '',
ddms: '',
dlfjxx: '',
wsbhLoading: false,
resign: false,
signatureImage: null,
jumpSourcePage: ''
},
drzqmjArr: [],
showWslbPicker: false,
updateTimer: null,
showWfsjPicker: false,
tempWfsj: now, // 默认时间选择器为当前时间
minDate: new Date(now.getFullYear() - 2, 0, 1, 0, 0, 0),
maxDate: new Date(now.getFullYear() + 1, 11, 31, 23, 59, 59),
isFirstEnter: true, // 标记是否首次进入组件
showSignaturePad: false
}
},
computed: {
wslbText () {
const opt = this.wslbOption && this.wslbOption.find(o => o.value === this.localFormData.wslb)
return opt ? opt.text : '请选择'
}
},
watch: {
value: {
handler (newVal) {
// 避免循环更新,只在值真正改变时更新
if (JSON.stringify(this.localFormData) !== JSON.stringify(newVal)) {
this.localFormData = { ...newVal }
}
},
immediate: true,
deep: true
},
'localFormData.glbm': {
handler (newVal) {
// 当 glbm 有值,且是首次进入(
console.log('首次进入获取管理部门: ' + newVal)
if (newVal && this.isFirstEnter) {
this.getWsbh()
this.isFirstEnter = false
}
},
immediate: true // 初始化时立即检查
}
},
methods: {
getWsbh () {
console.log('当前文书获取状态,wsbhLoading: ' + this.localFormData.wsbhLoading)
if (this.localFormData.wsbhLoading) return
this.localFormData.wsbhLoading = true
console.log('开始获取文书编号')
let param = {
'jdslb': this.localFormData.wslb,
'glbm': this.localFormData.glbm,
'fhwsbht': '1'
}
this.$HttpService.post.call(this, '文书编号获取接口', 'appAlarmHandle.do?method=appAutoWsbhQuery', 'appAlarmHandle.do', param, 'sync')
},
onWslbConfirm (val) {
this.localFormData.wslb = val.value
this.showWslbPicker = false
this.getWsbh()
this.debounceEmit()
},
handlWsbhInput (value) {
this.localFormData.wsbh = value
// 移除所有非数字字符
const numericValue = value.replace(/\D/g, '')
// 仅当值有变化时才
if (numericValue !== this.localFormData.wsbh) {
this.localFormData.wsbh = numericValue
}
},
// 处理值变化的最终状态
handleChange (value) {
const strValue = String(value || '')
// 2. 过滤非数字字符
this.localFormData.wsbh = strValue.replace(/\D/g, '')
this.$emit('input', { wsbh: this.localFormData.wsbh })
},
debounceEmit () {
// 清除之前的定时器,确保只保留最后一次输入后的触发
if (this.updateTimer) {
clearTimeout(this.updateTimer)
}
// 设置新的定时器,延迟300ms后将 localFormData 通过 input 事件同步给父组件
this.updateTimer = setTimeout(() => {
this.$emit('input', { ...this.localFormData })
}, 300)
}
},
beforeDestroy () {
// 组件销毁前清除定时器
if (this.updateTimer) {
clearTimeout(this.updateTimer)
}
}
}
</script>
<style scoped>
.basic-info-step {
padding: 2px;
margin-bottom: 24px;
}
.form-content {
margin-bottom: 20px;
}
/* 包裹容器:flex布局,垂直居中对齐(保证图片和按钮高度一致) */
.button-with-image {
display: flex;
align-items: center; /* 垂直居中,确保图片和按钮高度对齐 */
gap: 2px; /* 图片和按钮之间的间距 */
}
/* 图片容器:限制高度与按钮一致,宽度自适应 */
.signature-preview {
height: 100%; /* 继承父容器高度(即按钮高度) */
display: flex;
align-items: center; /* 图片在容器内垂直居中 */
}
/* 图片样式:高度与按钮一致,宽度自适应(保持比例) */
.signature-preview img {
max-height: 45px; /* Vant small按钮默认高度约28px,与按钮高度匹配 */
//width: 100%; /* 宽度自适应,避免变形 */
max-width: 250px;
object-fit: contain; /* 保持图片比例,完整显示 */
}
.font-bold {
font-weight: bold !important;
}
/deep/ .van-field__label {
font-weight: normal;
}
</style>
当我启动项目后,在网页端打开,子页面发送网络请求,主页面通过window.acceptNetResult = this.acceptNetResult 接收请求时网页端 提示Uncaught (in promise) TypeError :_this2.acceptNetResult is not a function 是哪里的错误,但是部署到安卓端就没有这个错误,请检查代码,解答问题
最新发布