|
|
@@ -1,139 +1,338 @@
|
|
|
-<template>
|
|
|
- <view class="default_page" :style="{'height':h+'px', 'padding-top':mt+'px'}">
|
|
|
- <cus-header title='生成报告' bgColor="transparent"></cus-header>
|
|
|
- <div class="box adffcac">
|
|
|
- <image class="box-loading" src="https://gitee.com/hw_0302/chuang-heng-wechat-images/raw/e6d5bea9491a14aafd3f955d332e62d08e521229/report_success.png" v-if="result==0"></image>
|
|
|
- <image class="box-loading" src="https://gitee.com/hw_0302/chuang-heng-wechat-images/raw/e6d5bea9491a14aafd3f955d332e62d08e521229/report_fail.png" v-else></image>
|
|
|
- <div class="box-p1">{{result==0?'报告正在生成中~':'报告生成失败'}}</div>
|
|
|
- <div class="box-p2" v-if="result==0">预计所需时间1小时左右</div>
|
|
|
- <div class="box-p3">{{result==0?'我们会在报告生成完成后提示你,你可以去我的PREILL报告查阅报告结果。':'失败原因:网络延迟'}}</div>
|
|
|
- </div>
|
|
|
- <div class="form">
|
|
|
- <div class="form-item adfacjb">
|
|
|
- <div class="form-item-left">问卷名称</div>
|
|
|
- <div class="form-item-right">{{info.title||''}}</div>
|
|
|
- </div>
|
|
|
- <div class="form-item adfacjb">
|
|
|
- <div class="form-item-left">团队名称</div>
|
|
|
- <div class="form-item-right">{{info.teamName||''}}</div>
|
|
|
- </div>
|
|
|
- <div class="form-item adfacjb">
|
|
|
- <div class="form-item-left">创建时间</div>
|
|
|
- <div class="form-item-right">{{info.startTime||info.createDate||''}}</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="btn">
|
|
|
- <div class="zt_btn" @click="handleBack" v-if="result==0">返回</div>
|
|
|
- <div class="zt_btn" @click="handleReCreate" v-else>重新生成</div>
|
|
|
- </div>
|
|
|
- </view>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script>
|
|
|
- export default {
|
|
|
- data(){
|
|
|
- return {
|
|
|
- result:'',
|
|
|
- info:null
|
|
|
- }
|
|
|
- },
|
|
|
- onLoad(options) {
|
|
|
- this.result = options.result;
|
|
|
- this.info = options.info&&JSON.parse(decodeURIComponent(options.info));
|
|
|
- },
|
|
|
- methods:{
|
|
|
- handleBack(){
|
|
|
- uni.navigateBack()
|
|
|
- },
|
|
|
- handleReCreate(){
|
|
|
- this.$api.get(`/core/team/questionnaire/genReport/${this.info.teamQuestionnaireId}`).then(({data:res})=>{
|
|
|
- if(res.code!==0) return this.$showToast(res.msg)
|
|
|
- this.$showToast('重新生成成功')
|
|
|
- setTimeout(()=>{
|
|
|
- uni.redirectTo({
|
|
|
- url:'pagesHome/questionnaire?type=create'
|
|
|
- })
|
|
|
- },1500)
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-</script>
|
|
|
-
|
|
|
-<style scoped lang="scss">
|
|
|
- .default_page{
|
|
|
- background: #F7F7F7;
|
|
|
- .box{
|
|
|
- width: 100%;
|
|
|
- background: #FFFFFF;
|
|
|
- border-radius: 36rpx 36rpx 0rpx 0rpx;
|
|
|
- padding: 54rpx 0 64rpx;
|
|
|
- &-loading{
|
|
|
- width: 340rpx;
|
|
|
- height: 340rpx;
|
|
|
- }
|
|
|
- &-p1{
|
|
|
- font-family: PingFang-SC, PingFang-SC;
|
|
|
- font-weight: bold;
|
|
|
- font-size: 32rpx;
|
|
|
- color: #002846;
|
|
|
- line-height: 40rpx;
|
|
|
- text-align: center;
|
|
|
- margin-top: 41rpx;
|
|
|
- }
|
|
|
- &-p2{
|
|
|
- font-family: PingFang-SC, PingFang-SC;
|
|
|
- font-weight: bold;
|
|
|
- font-size: 28rpx;
|
|
|
- color: #002846;
|
|
|
- line-height: 28rpx;
|
|
|
- text-align: center;
|
|
|
- margin-top: 23rpx;
|
|
|
- }
|
|
|
- &-p3{
|
|
|
- padding: 0 100rpx;
|
|
|
- font-family: PingFangSC, PingFang SC;
|
|
|
- font-weight: 400;
|
|
|
- font-size: 28rpx;
|
|
|
- color: #667E90;
|
|
|
- line-height: 42rpx;
|
|
|
- text-align: center;
|
|
|
- margin-top: 24rpx;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .form{
|
|
|
- width: 100%;
|
|
|
- margin-top: 20rpx;
|
|
|
- &-item{
|
|
|
- padding: 28rpx 24rpx;
|
|
|
- background: #FFFFFF;
|
|
|
- box-shadow: inset 0rpx -1rpx 0rpx 0rpx #EFEFEF;
|
|
|
- &-left{
|
|
|
- width: 140rpx;
|
|
|
- font-family: PingFangSC, PingFang SC;
|
|
|
- font-weight: 400;
|
|
|
- font-size: 30rpx;
|
|
|
- color: #002846;
|
|
|
- line-height: 42rpx;
|
|
|
- }
|
|
|
- &-right{
|
|
|
- width: calc(100% - 140rpx);
|
|
|
- padding-left: 20rpx;
|
|
|
- box-sizing: border-box;
|
|
|
- font-family: PingFangSC, PingFang SC;
|
|
|
- font-weight: 400;
|
|
|
- font-size: 30rpx;
|
|
|
- color: #667E90;
|
|
|
- line-height: 32rpx;
|
|
|
- text-align: right;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .btn{
|
|
|
- width: calc(100% -100rpx);
|
|
|
- margin: 120rpx 50rpx 0;
|
|
|
- }
|
|
|
- }
|
|
|
-</style>
|
|
|
+<template>
|
|
|
+ <view class="default_page" :style="{'height':h+'px', 'padding-top':mt+'px'}">
|
|
|
+ <cus-header title='生成报告' bgColor="transparent"></cus-header>
|
|
|
+ <div class="box adffcac">
|
|
|
+ <image class="box-loading" src="https://gitee.com/hw_0302/chuang-heng-wechat-images/raw/e6d5bea9491a14aafd3f955d332e62d08e521229/report_success.png" v-if="generation.imageKey==='success'"></image>
|
|
|
+ <image class="box-loading" src="https://gitee.com/hw_0302/chuang-heng-wechat-images/raw/e6d5bea9491a14aafd3f955d332e62d08e521229/report_fail.png" v-else></image>
|
|
|
+ <div class="box-p1">{{generation.title}}</div>
|
|
|
+ <div class="box-p2" v-if="generation.subtitle">{{generation.subtitle}}</div>
|
|
|
+ <div class="box-p3">{{generation.state===-1 ? '失败原因:'+generation.errorMessage : generation.description}}</div>
|
|
|
+ </div>
|
|
|
+ <div class="form">
|
|
|
+ <div class="form-item adfacjb">
|
|
|
+ <div class="form-item-left">问卷名称</div>
|
|
|
+ <div class="form-item-right">{{info.title||''}}</div>
|
|
|
+ </div>
|
|
|
+ <div class="form-item adfacjb">
|
|
|
+ <div class="form-item-left">团队名称</div>
|
|
|
+ <div class="form-item-right">{{info.teamName||''}}</div>
|
|
|
+ </div>
|
|
|
+ <div class="form-item adfacjb">
|
|
|
+ <div class="form-item-left">创建时间</div>
|
|
|
+ <div class="form-item-right">{{info.startTime||info.createDate||''}}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="btn">
|
|
|
+ <div class="zt_btn" @click="handleAction">{{generation.actionText}}</div>
|
|
|
+ </div>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ function toNumber(value) {
|
|
|
+ if (value === '' || value === null || value === undefined) return undefined
|
|
|
+ const numeric = Number(value)
|
|
|
+ return Number.isNaN(numeric) ? undefined : numeric
|
|
|
+ }
|
|
|
+
|
|
|
+ function extractReportId(payload) {
|
|
|
+ if (payload === null || payload === undefined) return undefined
|
|
|
+ if (typeof payload === 'number') return payload
|
|
|
+ if (typeof payload === 'string') return toNumber(payload)
|
|
|
+ if (typeof payload !== 'object') return undefined
|
|
|
+ const direct = toNumber(payload.reportId ?? payload.id)
|
|
|
+ if (direct !== undefined) return direct
|
|
|
+ for (const key of ['data', 'dto', 'info']) {
|
|
|
+ const nested = extractReportId(payload[key])
|
|
|
+ if (nested !== undefined) return nested
|
|
|
+ }
|
|
|
+ return undefined
|
|
|
+ }
|
|
|
+
|
|
|
+ function normalizeGenerationStatus(payload = {}) {
|
|
|
+ const source = payload && typeof payload === 'object' ? payload : {}
|
|
|
+ const state = toNumber(source.state)
|
|
|
+ return {
|
|
|
+ reportId: extractReportId(source) || '',
|
|
|
+ state: state === undefined ? 0 : state,
|
|
|
+ status: source.status || '',
|
|
|
+ errorMessage: source.errorMessage || ''
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function applyGenerationStatus(payload = {}) {
|
|
|
+ const generation = normalizeGenerationStatus(payload)
|
|
|
+ if (generation.state === -1) {
|
|
|
+ return {
|
|
|
+ ...generation,
|
|
|
+ title: '报告生成失败',
|
|
|
+ subtitle: '',
|
|
|
+ description: generation.errorMessage || '失败原因:网络延迟',
|
|
|
+ errorMessage: generation.errorMessage || '网络延迟',
|
|
|
+ polling: false,
|
|
|
+ actionText: '重新生成',
|
|
|
+ imageKey: 'fail'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (generation.state === 1) {
|
|
|
+ return {
|
|
|
+ ...generation,
|
|
|
+ title: '报告生成成功',
|
|
|
+ subtitle: '',
|
|
|
+ description: '报告已生成完成,你可以去我的PREILL报告查阅报告结果。',
|
|
|
+ errorMessage: '',
|
|
|
+ polling: false,
|
|
|
+ actionText: '返回',
|
|
|
+ imageKey: 'success'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ ...generation,
|
|
|
+ title: '报告正在生成中~',
|
|
|
+ subtitle: '预计所需时间1小时左右',
|
|
|
+ description: '我们会在报告生成完成后提示你,你可以去我的PREILL报告查阅报告结果。',
|
|
|
+ errorMessage: '',
|
|
|
+ polling: true,
|
|
|
+ actionText: '返回',
|
|
|
+ imageKey: 'success'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function shouldResumePolling(reportId, generation = {}) {
|
|
|
+ return Boolean(reportId && normalizeGenerationStatus(generation).state === 0)
|
|
|
+ }
|
|
|
+
|
|
|
+ function setStatusPageVisible(vm, visible) {
|
|
|
+ if(vm.isPageVisible === visible) return vm.statusVisibilityToken
|
|
|
+ vm.isPageVisible = visible
|
|
|
+ if(!visible){
|
|
|
+ vm.statusVisibilityToken++
|
|
|
+ vm.statusActiveRequestId = 0
|
|
|
+ vm.statusRequestInFlight = false
|
|
|
+ }
|
|
|
+ return vm.statusVisibilityToken
|
|
|
+ }
|
|
|
+
|
|
|
+ function beginStatusRequest(vm) {
|
|
|
+ if(!vm.isPageVisible || vm.statusRequestInFlight) return null
|
|
|
+ vm.statusRequestSeq++
|
|
|
+ vm.statusActiveRequestId = vm.statusRequestSeq
|
|
|
+ vm.statusRequestInFlight = true
|
|
|
+ return {
|
|
|
+ requestId: vm.statusActiveRequestId,
|
|
|
+ visibilityToken: vm.statusVisibilityToken
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function shouldApplyStatusResponse(vm, meta) {
|
|
|
+ return Boolean(
|
|
|
+ meta
|
|
|
+ && vm.isPageVisible
|
|
|
+ && vm.statusRequestInFlight
|
|
|
+ && vm.statusActiveRequestId === meta.requestId
|
|
|
+ && vm.statusVisibilityToken === meta.visibilityToken
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ function finishStatusRequest(vm, meta) {
|
|
|
+ if(!meta) return
|
|
|
+ if(vm.statusActiveRequestId === meta.requestId){
|
|
|
+ vm.statusActiveRequestId = 0
|
|
|
+ vm.statusRequestInFlight = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ export default {
|
|
|
+ data(){
|
|
|
+ return {
|
|
|
+ reportId:'',
|
|
|
+ info:{},
|
|
|
+ generation:applyGenerationStatus(),
|
|
|
+ pollTimer:null,
|
|
|
+ hasStatusErrorToastShown:false,
|
|
|
+ isPageVisible:false,
|
|
|
+ statusVisibilityToken:0,
|
|
|
+ statusRequestSeq:0,
|
|
|
+ statusActiveRequestId:0,
|
|
|
+ statusRequestInFlight:false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLoad(options) {
|
|
|
+ this.info = options.info&&JSON.parse(decodeURIComponent(options.info)) || {}
|
|
|
+ this.reportId = extractReportId({ reportId:options.reportId, dto:options, info:this.info }) || ''
|
|
|
+ if(!this.reportId){
|
|
|
+ this.stopPolling('报告编号缺失')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onShow() {
|
|
|
+ setStatusPageVisible(this, true)
|
|
|
+ if(shouldResumePolling(this.reportId, this.generation)){
|
|
|
+ this.startPolling()
|
|
|
+ this.fetchGenerationStatus(false)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onHide() {
|
|
|
+ setStatusPageVisible(this, false)
|
|
|
+ this.clearPolling()
|
|
|
+ },
|
|
|
+ onUnload() {
|
|
|
+ setStatusPageVisible(this, false)
|
|
|
+ this.clearPolling()
|
|
|
+ },
|
|
|
+ methods:{
|
|
|
+ startPolling(){
|
|
|
+ if(!this.isPageVisible || !shouldResumePolling(this.reportId, this.generation) || this.pollTimer) return
|
|
|
+ this.pollTimer = setInterval(() => {
|
|
|
+ this.fetchGenerationStatus(false)
|
|
|
+ }, 5000)
|
|
|
+ },
|
|
|
+ clearPolling(){
|
|
|
+ if(this.pollTimer){
|
|
|
+ clearInterval(this.pollTimer)
|
|
|
+ this.pollTimer = null
|
|
|
+ }
|
|
|
+ },
|
|
|
+ reconcileGeneration(status){
|
|
|
+ this.generation = applyGenerationStatus(status)
|
|
|
+ this.hasStatusErrorToastShown = false
|
|
|
+ if(this.generation.polling && this.reportId) return this.startPolling()
|
|
|
+ this.clearPolling()
|
|
|
+ },
|
|
|
+ stopPolling(errorMessage){
|
|
|
+ this.clearPolling()
|
|
|
+ this.generation = applyGenerationStatus({
|
|
|
+ reportId:this.reportId,
|
|
|
+ state:-1,
|
|
|
+ errorMessage:errorMessage || this.generation.errorMessage || '网络延迟'
|
|
|
+ })
|
|
|
+ },
|
|
|
+ fetchGenerationStatus(showErrorToast = true){
|
|
|
+ if(!this.reportId){
|
|
|
+ this.stopPolling('报告编号缺失')
|
|
|
+ return Promise.resolve()
|
|
|
+ }
|
|
|
+ const requestMeta = beginStatusRequest(this)
|
|
|
+ if(!requestMeta) return Promise.resolve()
|
|
|
+ return this.$api.get(`/core/report/generationStatus/${this.reportId}`, {}, false).then(({data:res})=>{
|
|
|
+ if(!shouldApplyStatusResponse(this, requestMeta)) return
|
|
|
+ if(res.code!==0){
|
|
|
+ if(showErrorToast && !this.hasStatusErrorToastShown){
|
|
|
+ this.$showToast(res.msg || '报告状态获取失败')
|
|
|
+ this.hasStatusErrorToastShown = true
|
|
|
+ }
|
|
|
+ this.startPolling()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.reconcileGeneration({ ...(res.data || {}), reportId:this.reportId })
|
|
|
+ }).catch(error => {
|
|
|
+ if(!shouldApplyStatusResponse(this, requestMeta)) return
|
|
|
+ const message = error && (error.message || error.msg) || '报告状态获取失败'
|
|
|
+ if(showErrorToast && !this.hasStatusErrorToastShown){
|
|
|
+ this.$showToast(message)
|
|
|
+ this.hasStatusErrorToastShown = true
|
|
|
+ }
|
|
|
+ this.startPolling()
|
|
|
+ }).finally(() => {
|
|
|
+ finishStatusRequest(this, requestMeta)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ handleAction(){
|
|
|
+ if(this.generation.state===-1){
|
|
|
+ this.handleReCreate()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uni.navigateBack()
|
|
|
+ },
|
|
|
+ handleReCreate(){
|
|
|
+ this.$api.get(`/core/team/questionnaire/genReport/${this.info.teamQuestionnaireId}`).then(({data:res})=>{
|
|
|
+ if(res.code!==0) return this.$showToast(res.msg)
|
|
|
+ const nextReportId = extractReportId(res.data)
|
|
|
+ if(!nextReportId) return this.$showToast('未获取到报告编号')
|
|
|
+ this.$showToast('重新生成成功')
|
|
|
+ uni.redirectTo({
|
|
|
+ url:'/pagesHome/reportResult?reportId='+nextReportId+'&info='+encodeURIComponent(JSON.stringify(this.info))
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+ .default_page{
|
|
|
+ background: #F7F7F7;
|
|
|
+ .box{
|
|
|
+ width: 100%;
|
|
|
+ background: #FFFFFF;
|
|
|
+ border-radius: 36rpx 36rpx 0rpx 0rpx;
|
|
|
+ padding: 54rpx 0 64rpx;
|
|
|
+ &-loading{
|
|
|
+ width: 340rpx;
|
|
|
+ height: 340rpx;
|
|
|
+ }
|
|
|
+ &-p1{
|
|
|
+ font-family: PingFang-SC, PingFang-SC;
|
|
|
+ font-weight: bold;
|
|
|
+ font-size: 32rpx;
|
|
|
+ color: #002846;
|
|
|
+ line-height: 40rpx;
|
|
|
+ text-align: center;
|
|
|
+ margin-top: 41rpx;
|
|
|
+ }
|
|
|
+ &-p2{
|
|
|
+ font-family: PingFang-SC, PingFang-SC;
|
|
|
+ font-weight: bold;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #002846;
|
|
|
+ line-height: 28rpx;
|
|
|
+ text-align: center;
|
|
|
+ margin-top: 23rpx;
|
|
|
+ }
|
|
|
+ &-p3{
|
|
|
+ padding: 0 100rpx;
|
|
|
+ font-family: PingFangSC, PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #667E90;
|
|
|
+ line-height: 42rpx;
|
|
|
+ text-align: center;
|
|
|
+ margin-top: 24rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .form{
|
|
|
+ width: 100%;
|
|
|
+ margin-top: 20rpx;
|
|
|
+ &-item{
|
|
|
+ padding: 28rpx 24rpx;
|
|
|
+ background: #FFFFFF;
|
|
|
+ box-shadow: inset 0rpx -1rpx 0rpx 0rpx #EFEFEF;
|
|
|
+ &-left{
|
|
|
+ width: 140rpx;
|
|
|
+ font-family: PingFangSC, PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: 30rpx;
|
|
|
+ color: #002846;
|
|
|
+ line-height: 42rpx;
|
|
|
+ }
|
|
|
+ &-right{
|
|
|
+ width: calc(100% - 140rpx);
|
|
|
+ padding-left: 20rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+ font-family: PingFangSC, PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: 30rpx;
|
|
|
+ color: #667E90;
|
|
|
+ line-height: 32rpx;
|
|
|
+ text-align: right;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn{
|
|
|
+ width: calc(100% -100rpx);
|
|
|
+ margin: 120rpx 50rpx 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|