Quellcode durchsuchen

feat(report): add evaluation edit dialog

Developer vor 1 Monat
Ursprung
Commit
a85fcef436

+ 109 - 23
pages/report.vue

@@ -5,9 +5,9 @@
 			<div class="t_pre" :class="{'active':tidx===2,'inactive':tidx!==2}" @tap="changeTab(2)">个人报告</div>
 			<div class="t_pre" :class="{'active':tidx===1,'inactive':tidx!==1}" @tap="changeTab(1)">团队报告</div>
 		</div> -->
-		<template v-if="list.length">
-			<div class="list">
-				<div class="l_item" v-for="(item,index) in list" :key="index">
+		<template v-if="list.length">
+			<div class="list">
+				<div class="l_item" v-for="(item,index) in list" :key="index">
 					<div class="li_title">{{item.reportName||''}}</div>
 					<div class="li_pre">报告时间:<span>{{item.createDate||''}}</span></div>
 					<div class="li_pre" v-if="item.type==1">作答人数:<span>{{item.finishNum||0}}/{{item.answerNum||0}}</span></div>
@@ -19,24 +19,45 @@
 						</div>
 						<div class="lj_r">进度<span>{{item.finishNum||0}}/{{item.answerNum||0}}</span></div>
 					</div>
-					<div class="li_view" @tap="viewReport(item)">查看</div>
-				</div>
-			</div>
+					<div class="li_actions">
+						<div class="li_edit" v-if="canEditEvaluation(item)" @tap="openEvaluation(item)">评估修改</div>
+						<div class="li_view" @tap="viewReport(item)">查看</div>
+					</div>
+				</div>
+			</div>
 		</template>
 		<template v-else>
-			<page-empty :height="'calc(100vh - 200px)'"></page-empty>
-		</template>
-	</view>
+			<page-empty :height="'calc(100vh - 200px)'"></page-empty>
+		</template>
+		<view class="edit_mask" v-if="editVisible" @tap.stop="closeEvaluation">
+			<view class="edit_dialog" @tap.stop>
+				<view class="edit_title">修改评估内容</view>
+				<view class="edit_label">总体评估结果</view>
+				<textarea class="edit_textarea" maxlength="20000" v-model="editForm.overallAssessment" placeholder="请输入总体评估结果"></textarea>
+				<view class="edit_label">团队发展建议</view>
+				<textarea class="edit_textarea" maxlength="20000" v-model="editForm.developmentAdvice" placeholder="请输入团队发展建议"></textarea>
+				<view class="edit_actions">
+					<view class="edit_cancel" @tap="closeEvaluation">取消</view>
+					<view class="edit_submit" :class="{disabled: editSubmitting}" @tap="submitEvaluation">{{editSubmitting?'提交中':'保存提交'}}</view>
+				</view>
+			</view>
+		</view>
+	</view>
 </template>
 
 <script>
-	import pageEmpty from '@/components/pageEmpty/index.vue'
+	import pageEmpty from '@/components/pageEmpty/index.vue'
+	import { canEditEvaluation, EVALUATION_PROCESSING_PROMPT, normalizeEvaluationForm } from '@/utils/reportEvaluationEdit.js'
 	export default {
 		components:{ pageEmpty },
 		data(){
-			return {
-				tidx:1,
-				list:[]
+			return {
+				tidx:1,
+				list:[],
+				editVisible:false,
+				editSubmitting:false,
+				editReportId:'',
+				editForm:{overallAssessment:'',developmentAdvice:''}
 			}
 		},
 		onLoad() {
@@ -47,13 +68,45 @@
 				this.tidx = idx;
 				this.getReportList();
 			},
-			getReportList(){
+			getReportList(){
 				this.$api.get('/core/report/member/personalReportList').then(res=>{
 					if(res.data.code!==0) return this.$showToast(res.data.msg)
 					this.list = res.data.data;
-				})
-			},
-			viewReport(item){
+				})
+			},
+			canEditEvaluation(item){
+				return canEditEvaluation(item);
+			},
+			openEvaluation(item){
+				if(!this.canEditEvaluation(item)) return;
+				this.editReportId = item.reportId;
+				this.editSubmitting = false;
+				this.editVisible = true;
+				this.$api.get('/core/report/evaluation/'+item.reportId).then(res=>{
+					if(res.data.code!==0){ this.closeEvaluation(); return this.$showToast(res.data.msg); }
+					const data = res.data.data || {};
+					if(data.processing){ this.closeEvaluation(); return this.$showToast('评估分析正在重新生成中,请稍候'); }
+					this.editForm = normalizeEvaluationForm(data);
+				})
+			},
+			closeEvaluation(){
+				if(this.editSubmitting) return;
+				this.editVisible = false;
+				this.editReportId = '';
+			},
+			submitEvaluation(){
+				if(this.editSubmitting) return;
+				if(!this.editForm.overallAssessment.trim()) return this.$showToast('请输入总体评估结果');
+				if(!this.editForm.developmentAdvice.trim()) return this.$showToast('请输入团队发展建议');
+				this.editSubmitting = true;
+				this.$api.post('/core/report/evaluation/'+this.editReportId, this.editForm).then(res=>{
+					if(res.data.code!==0) return this.$showToast(res.data.msg);
+					this.editVisible = false;
+					this.getReportList();
+					uni.showModal({title:'温馨提示', content:EVALUATION_PROCESSING_PROMPT, showCancel:false, confirmText:'确定', confirmColor:'#007A69'});
+				}).finally(()=>{ this.editSubmitting = false; });
+			},
+			viewReport(item){
 				if(!item.fileUrl) return this.$showToast('报告pdf为空,请联系教练。')
 				uni.navigateTo({
 					url:`/pages/reportDetail?pdfUrl=${item.fileUrl}&reportId=${item.reportId}&fileName=${item.programName}-${item.reportName}`
@@ -177,7 +230,7 @@
 						}
 					}
 				}
-				.li_view{
+				.li_view{
 					width: 88rpx;
 					height: 54rpx;
 					background: #833478;
@@ -191,8 +244,41 @@
 					position: absolute;
 					top: 40rpx;
 					right: 24rpx;
-				}
-			}
-		}
-	}
-</style>
+				}
+				.li_actions{
+					position:absolute;
+					top:40rpx;
+					right:24rpx;
+					display:flex;
+					gap:12rpx;
+					.li_edit,.li_view{
+						position:static;
+						width:112rpx;
+					}
+					.li_edit{height:54rpx;background:#33A7A7;border-radius:24rpx;font-family:PingFang-SC, PingFang-SC;font-weight:bold;font-size:24rpx;color:#FFFFFF;line-height:54rpx;text-align:center;}
+				}
+			}
+		}
+	}
+	.edit_mask{
+		position:fixed;
+		z-index:20;
+		left:0;right:0;top:0;bottom:0;
+		background:rgba(0,0,0,.45);
+		display:flex;
+		align-items:center;
+		justify-content:center;
+		.edit_dialog{
+			width:650rpx;
+			background:#fff;
+			border-radius:16rpx;
+			padding:34rpx 28rpx 26rpx;
+			.edit_title{text-align:center;font-size:34rpx;font-weight:bold;color:#252525;margin-bottom:28rpx;}
+			.edit_label{font-size:28rpx;font-weight:bold;color:#333;margin:18rpx 0 12rpx;}
+			.edit_textarea{width:100%;height:180rpx;box-sizing:border-box;background:#f7f7f7;border-radius:8rpx;padding:18rpx;font-size:26rpx;color:#333;}
+			.edit_actions{display:flex;justify-content:flex-end;gap:20rpx;margin-top:28rpx;}
+			.edit_cancel,.edit_submit{padding:18rpx 28rpx;border-radius:10rpx;font-size:28rpx;}
+			.edit_cancel{color:#666;background:#f2f2f2;}.edit_submit{color:#fff;background:#833478;}.edit_submit.disabled{opacity:.5;}
+		}
+	}
+</style>

+ 62 - 3
pagesHome/components/report/generateList.vue

@@ -25,12 +25,14 @@
 					</view>
 					<view class="gbox-item-bottom adfacjb">
 						<view class="gbox-item-bottom-rightbox adfac" v-if="item.type==1">
+							<view class="gbox-item-bottom-right" @click="openEvaluation(item)" v-if="canEditEvaluation(item)">评估修改</view>
 							<view class="gbox-item-bottom-right report-button-disabled" @click="showReportUnavailable('background')" v-if="item.state==1">背景报告</view>
 							<view class="gbox-item-bottom-right report-button-disabled" @click="showReportUnavailable('professional')" v-if="item.state==1">教练报告</view>
 							<view class="gbox-item-bottom-right" @click="reviewArtifact(item, 'public')" v-if="item.state==1">团队报告</view>
 							<view class="gbox-item-bottom-right" @click="reSendReport(item)" v-if="item.state==-1">重新生成</view>
 						</view>
 						<view class="gbox-item-bottom-rightbox adfac" v-else-if="item.type==2">
+							<view class="gbox-item-bottom-right" @click="openEvaluation(item)" v-if="canEditEvaluation(item)">评估修改</view>
 							<view class="gbox-item-bottom-right" @click="reviewArtifact(item, 'background')" v-if="item.state==1">背景报告</view>
 							<view class="gbox-item-bottom-right" @click="reviewArtifact(item, 'professional')" v-if="item.state==1">教练报告</view>
 							<view class="gbox-item-bottom-right" @click="reviewArtifact(item, 'public')" v-if="item.state==1">团队报告</view>
@@ -56,6 +58,19 @@
 				<view class="kr-btn" @click="reportReminderShow=false">确定</view>
 			</view>
 		</view>
+		<view class="evaluation-mask adffcacjc" v-if="evaluationVisible">
+			<view class="evaluation-box">
+				<view class="kr-title">修改评估内容</view>
+				<view class="evaluation-label">总体评估结果</view>
+				<textarea class="evaluation-textarea" maxlength="20000" v-model="evaluationForm.overallAssessment" placeholder="请输入总体评估结果"></textarea>
+				<view class="evaluation-label">团队发展建议</view>
+				<textarea class="evaluation-textarea" maxlength="20000" v-model="evaluationForm.developmentAdvice" placeholder="请输入团队发展建议"></textarea>
+				<view class="evaluation-actions">
+					<view class="evaluation-cancel" @click="closeEvaluation">取消</view>
+					<view class="evaluation-submit" :class="{disabled:evaluationSubmitting}" @click="submitEvaluation">{{evaluationSubmitting?'提交中':'保存提交'}}</view>
+				</view>
+			</view>
+		</view>
 		<cus-select-team-user 
 			ref="selectTeamUser" 
 			:show="teamUserShow"
@@ -71,6 +86,7 @@
 <script>
 	import { getPlatformInfo } from '@/utils/platform.js'; 
 	import { reportArtifactUrl } from '@/utils/reportArtifactLinks.js'
+	import { canEditEvaluation, EVALUATION_PROCESSING_PROMPT, normalizeEvaluationForm } from '@/utils/reportEvaluationEdit.js'
 	import CusSelectTeamUser from '@/components/CusSelectTeamUser/index.vue'
 	export default {
 		props:{
@@ -104,7 +120,11 @@
 				selectItem:null,
 				testShow:false,
 				reportReminderShow:false,
-				reportReminderMsg:''
+				reportReminderMsg:'',
+				evaluationVisible:false,
+				evaluationSubmitting:false,
+				evaluationReportId:'',
+				evaluationForm:{overallAssessment:'',developmentAdvice:''}
 			}
 		},
 		methods:{
@@ -175,6 +195,38 @@
 					: '教练报告需要配合团队版评估数据生成';
 				this.reportReminderShow = true;
 			},
+			canEditEvaluation(item){
+				return canEditEvaluation(item);
+			},
+			openEvaluation(item){
+				if(!this.canEditEvaluation(item)) return;
+				this.evaluationReportId = item.reportId;
+				this.evaluationSubmitting = false;
+				this.evaluationVisible = true;
+				this.$api.get('/core/report/evaluation/'+item.reportId).then(({data:res})=>{
+					if(res.code!==0){ this.closeEvaluation(); return this.$showToast(res.msg); }
+					if(res.data && res.data.processing){ this.closeEvaluation(); return this.$showToast('评估分析正在重新生成中,请稍候'); }
+					this.evaluationForm = normalizeEvaluationForm(res.data || {});
+				})
+			},
+			closeEvaluation(){
+				if(this.evaluationSubmitting) return;
+				this.evaluationVisible = false;
+				this.evaluationReportId = '';
+			},
+			submitEvaluation(){
+				if(this.evaluationSubmitting) return;
+				if(!this.evaluationForm.overallAssessment.trim()) return this.$showToast('请输入总体评估结果');
+				if(!this.evaluationForm.developmentAdvice.trim()) return this.$showToast('请输入团队发展建议');
+				this.evaluationSubmitting = true;
+				this.$api.post('/core/report/evaluation/'+this.evaluationReportId, this.evaluationForm).then(({data:res})=>{
+					if(res.code!==0) return this.$showToast(res.msg);
+					this.evaluationVisible = false;
+					this.$emit('reSendReport');
+					this.reportReminderMsg = EVALUATION_PROCESSING_PROMPT;
+					this.reportReminderShow = true;
+				}).finally(()=>{ this.evaluationSubmitting = false; });
+			},
 			sendConfirm(){
 				if(this.teamUserList.filter(t=>t.select).length===0) return this.$showToast('请选择要发送的用户')
 				if(this.sendType===1&&(!uni.getStorageSync('userInfo')||!JSON.parse(uni.getStorageSync('userInfo')).email)) return this.$showModal('发送前请先在我的-设置-用户信息中绑定邮箱')
@@ -427,7 +479,7 @@
 			}
 		}
 	
-		.kind-reminder{
+	.kind-reminder{
 			position: fixed;
 			left: 0;
 			right: 0;
@@ -485,5 +537,12 @@
 				}
 			}
 		}
-	}
+	}
+	.evaluation-mask{position:fixed;left:0;right:0;top:0;bottom:0;z-index:30;background:rgba(0,0,0,.45);}
+	.evaluation-box{width:650rpx;background:#fff;border-radius:16rpx;padding:34rpx 28rpx 26rpx;box-sizing:border-box;}
+	.evaluation-label{font-size:28rpx;font-weight:bold;color:#333;margin:18rpx 0 12rpx;}
+	.evaluation-textarea{width:100%;height:180rpx;box-sizing:border-box;background:#f7f7f7;border-radius:8rpx;padding:18rpx;font-size:26rpx;color:#333;}
+	.evaluation-actions{display:flex;justify-content:flex-end;gap:20rpx;margin-top:28rpx;}
+	.evaluation-cancel,.evaluation-submit{padding:18rpx 28rpx;border-radius:10rpx;font-size:28rpx;}
+	.evaluation-cancel{color:#666;background:#f2f2f2;}.evaluation-submit{color:#fff;background:#833478;}.evaluation-submit.disabled{opacity:.5;}
 </style>

+ 11 - 0
tests/reportEvaluationEdit.test.js

@@ -0,0 +1,11 @@
+const assert = require('node:assert/strict')
+const { canEditEvaluation, EVALUATION_PROCESSING_PROMPT, normalizeEvaluationForm } = require('../utils/reportEvaluationEdit')
+
+assert.equal(canEditEvaluation({ reportType: '1', state: 1, status: 'SUCCEEDED' }), true)
+assert.equal(canEditEvaluation({ reportType: '1', state: 0, status: 'RUNNING' }), false)
+assert.equal(canEditEvaluation({ reportType: '2', state: 1, status: 'SUCCEEDED' }), false)
+assert.deepEqual(normalizeEvaluationForm({ overallAssessment: '评估', developmentAdvice: '建议' }), {
+	overallAssessment: '评估', developmentAdvice: '建议'
+})
+assert.match(EVALUATION_PROCESSING_PROMPT, /等待1小时左右/)
+console.log('reportEvaluationEdit tests passed')

+ 15 - 0
utils/reportEvaluationEdit.js

@@ -0,0 +1,15 @@
+const EVALUATION_PROCESSING_PROMPT = '评估分析正在进行中,你需要等待1小时左右,我们会在报告生成完成后提示你,你可以去“我的PERILL报告”查阅报告结果。'
+
+function canEditEvaluation(item = {}) {
+	return String(item.reportType || '') === '1' && String(item.state) === '1'
+		&& ['RUNNING', 'PENDING'].indexOf(String(item.status || '')) === -1
+}
+
+function normalizeEvaluationForm(data = {}) {
+	return {
+		overallAssessment: data.overallAssessment || '',
+		developmentAdvice: data.developmentAdvice || ''
+	}
+}
+
+module.exports = { EVALUATION_PROCESSING_PROMPT, canEditEvaluation, normalizeEvaluationForm }