业务场景,实现向导页面,每个向导对应一个vue组件。由于向导信息和vue组件名称在表里存储所以页面上要完全动态渲染。
结构
完整代码:
<template>
<div class="body">
<div class="header">
<a-row>
<a-col :span="3">
<span>客户编号:{
{ }}</span>
</a-col>
<a-col :span="5">
<span>客户名称:{
{ }}</span>
</a-col>
<a-col :span="3">
<span></span>
</a-col>
<a-col :span="3">
<span></span>
</a-col>
<a-col :span="4">
<span></span>
</a-col>
<a-col :span="3">
<span></span>
</a-col>
<a-col :span="3">
<span></span>
</a-col>
</a-row>
</div>
<div class="sider">
<div style="height: 90%;">
<a-steps v-model="step" direction="vertical" :disabled="true">
<a-step
v-for="item in wizard"
:title="item.WKFL_STEP_NAME"
:key="item.WKFL_STEP_SEQ"
:description="item.WKFL_STEP_DESC"
:disabled="true"
/>
</a-steps>
</div>
<div style="height: 10%;">
<div>
<div style="float:left;">
<a-button style="width: 74px;" @click="lastStep" v-show="lastBtnVisible">{
{ lastText }}</a-button>
</div>
<div style="float:right;">
<a-button style="width: 74px;" @click="nextStep" type="primary">{
{ nextText }}</a-button>
</div>
</div>
</div>
</div>
<div class="content">
<keep-alive>
<component ref="child" :is="component" :param="param" :step="step"></component>
</keep-alive>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import {
qryWkflWizardList, qryRatingResultList, getDeptNoByEmpeNo } from '@/api/api'
export default {
data () {
return {
component: null,
step: 0,
wizard: [],
lastText: '<上一步',
nextText: '下一步>',
lastBtnVisible: false,
parentQuery: this.$route.query,
ratingResult: {
},
dict: {
},
param: {
custId: '',
custName: '',
modelId: '',
modelName: '',
modelVersn: '',
rptTmptId: '',
rptTmptName: '',
rptTmptVersn: '',
rptPeriod: ''
}
}
},
created () {
this.init()
},
watch: {
step: function (newValue, oldValue) {
this.component = this.wizard[newValue].WKFL_STEP_APP
if (newValue === this.wizard.length - 1) {
this.nextText = ' 完成 '
} else {
this.nextText = '下一步>'
}
if (newValue === 0) {
this.lastBtnVisible = false
} else {
this.lastBtnVisible = true
}
}
},
methods: {
async init () {
let OPT_DEPT = {
}
await getDeptNoByEmpeNo().then((res) => {
OPT_DEPT = res.OPT_DEPT
})
// 初始化字典
this.dict.RATING_TYPE = await this.$getDictByCode('RATING_TYPE')
this.dict.WKFL_STAGE = await this.$getDictByCode('WKFL_STAGE')
this.dict.RATING_WKFL_TYPE = await this.$getDictByCode('RATING_WKFL_TYPE')
const param0 = {
RATING_ID: this.parentQuery.ratingId,
ratingWkflType: this.parentQuery.ratingWkflType
}
await qryRatingResultList(param0).then((res) => {
console.log(this.dict.RATING_WKFL_TYPE, this.parentQuery.ratingWkflType)
res.ratingWkflTypeName = this.dict.RATING_WKFL_TYPE[this.parentQuery.ratingWkflType] ? this.dict.RATING_WKFL_TYPE[this.parentQuery.ratingWkflType].name : this.this.parentQuery.ratingWkflType
res.RATING_TYPE_NAME = this.dict.RATING_TYPE[res.RATING_TYPE] ? this.dict.RATING_TYPE[res.RATING_TYPE].name : res.RATING_TYPE
res.WKFL_STAGE_NAME = this.dict.WKFL_STAGE[res.WKFL_STAGE] ? this.dict.WKFL_STAGE[res.WKFL_STAGE].name : res.WKFL_STAGE
this.ratingResult = res
this.param = {
}
console.log('公共字段:', this.param)
})
// 2、查询对应向导流程数据:实现动态挂载组件,动态组件渲染,通过1定位到该用户执行到了哪个流程
const param1 = {
WKFL_STEP_TYPE: this.parentQuery.wkflStepType,
RATING_ID: this.parentQuery.ratingId,
RATING_WKFL_TYPE: this.parentQuery.ratingWkflType
}
await qryWkflWizardList(param1).then((res) => {
for (const i in res.VALUE_LIST) {
// 动态向vue挂载组件
Vue.component(res.VALUE_LIST[i].WKFL_STEP_APP, () =>
import('./components/' + res.VALUE_LIST[i].WKFL_STEP_APP)
)
}
this.wizard = res.VALUE_LIST
this.step = 0
this.component = this.wizard[this.step].WKFL_STEP_APP // 默认渲染组件
})
},
/**
父组件点击下一步触发子组件方法,可直接在子组件定义名为 parentNextStepChange() 方法,该方法返回值必须为{status:true or false},来告诉父组件是否可以进行下一步操作,切记parentNextStepChange()方法内如果涉及到请求后端,一定要改成同步请求。
如果子组件不需要控制下一步是否可以点击,则不需要定义parentNextStepChange方法;
*/
async nextStep () {
if (this.step <= this.wizard.length - 1) {
let isContinue = true
if (this.$refs.child.parentNextStepChange !== undefined) {
const val = await this.$refs.child.parentNextStepChange()
isContinue = val.status
}
if (isContinue && this.step !== this.wizard.length - 1) {
this.step = this.step + 1
}
console.log('STEP+++++++' + this.step)
}
},
lastStep () {
if (this.step > 0) {
this.step = this.step - 1
}
}
}
}
</script>
<style scoped>
.body {
padding: 16px 11px 11px 11px;
background: #efefef;
height: 100%;
}
.header {
left: 12px;
top: 16px;
width: 100%;
height: 48px;
background-color: #ffffff;
margin-bottom: 11px;
padding: 13px 19px 13px 19px;
}
.header >>> span {
font-family: MiSans-Medium;
font-size: 14px;
font-weight: 500;
color: #202020;
}
.sider {
left: 12px;
top: 75px;
width: 15%;
height: 93%;
background: #ffffff;
float: left;
margin-right: 11px;
padding-left: 25px;
padding-top: 37px;
padding-right: 25px;
}
.content {
left: 223px;
top: 75px;
width: 84%;
height: 93%;
background: #ffffff;
float: left;
padding: 10px 10px 10px 10px;
}
</style>
子组件
<template>
<a-spin :spinning="loadding">
</a-spin>
</template>
<script>
export default {
props: {
param: {
type: Object,
default: function () {
return {
}
}
}
},
data () {
return {
loadding: false,
}
},
// created () {
// this.init()
// },
mounted () {
},
activated () {
// keep-live 生命周期,每次进入即触发
this.init()
},
methods: {
async init () {
await this.refreshFinData()
await this.qryCustFinDataList()
},
/**
* 监听父组件点击下一步,校验是否可以下一步操作
* @return 必须返回 {
status: true 向导进入下一步,flase 向导停留在当前 }
*/
async parentNextStepChange () {
const stepResult = await this.checkReportCount01()
return stepResult
},
/**
* 财报数量检查,判断查询结果大于等于3
*/
async checkReportCount01 () {
const stepResult = {
status: false }
const BEGINDATE = String(Number(String(this.param.rptPeriod).substring(0, 4)) - 2) + '1231'
const checkParam = {
CUST_ID: this.param.custId,
BEGINDATE: BEGINDATE,
ENDDATE: this.param.rptPeriod
}
await queryReportCount01(checkParam).then((res) => {
if (res.RPT_CNT !== undefined) {
if (res.RPT_CNT >= 3) {
stepResult.status = true
} else {
this.$message.warning('')
}
} else {
this.$message.error('服务器异常')
}
})
return stepResult
}
}
}
</script>
<style scoped>
</style>
扩展: 如果需要在每次上下一步来回切换组件时都要触发的方法,则需要将该方法放在keep-live的生命周期内,而非created
activated () {
// keep-live 生命周期,每次进入即触发
this.init()
},