|
|
@@ -139,15 +139,15 @@
|
|
|
<div class="value font-medium">{{ detail.postLevelName || detail.postLevel || '-' }}</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="form-row">
|
|
|
+ <!-- <div class="form-row">
|
|
|
<div class="label"><span class="required">*</span>测评时长</div>
|
|
|
<div class="value flex items-center gap-4">
|
|
|
<div class="gray-box !w-32 text-center font-medium">{{ detail.assessmentTime || '0' }}</div>
|
|
|
<span class="text-[#4e5969]">分钟</span>
|
|
|
</div>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
|
|
|
- <div class="form-row items-start">
|
|
|
+ <!-- <div class="form-row items-start">
|
|
|
<div class="label pt-1"><span class="required">*</span>及格线</div>
|
|
|
<div class="value flex flex-col gap-5">
|
|
|
<div class="flex items-center" v-if="detail.gradeA !== undefined && detail.gradeA !== null">
|
|
|
@@ -166,7 +166,7 @@
|
|
|
<span class="text-[#4e5969]">分</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
@@ -175,6 +175,68 @@
|
|
|
<div class="section-title">审核信息</div>
|
|
|
|
|
|
<div class="form-content">
|
|
|
+ <!-- 选择测评区域(放在定金上方) -->
|
|
|
+ <div class="evaluation-section">
|
|
|
+ <div class="form-row">
|
|
|
+ <div class="label"><span class="required">*</span>选择测评</div>
|
|
|
+ <div class="value flex items-center gap-4">
|
|
|
+ <el-select
|
|
|
+ v-model="auditForm.evaluationId"
|
|
|
+ placeholder="请选择测评"
|
|
|
+ :loading="evalLoading"
|
|
|
+ style="width: 320px"
|
|
|
+ :disabled="detail.auditResult !== 0"
|
|
|
+ @change="handleEvalChange"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in evalOptions"
|
|
|
+ :key="item.id"
|
|
|
+ :label="item.evaluationName"
|
|
|
+ :value="item.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 能力配置回显区域 -->
|
|
|
+ <div v-if="selectedAbilityConfigs.length > 0" class="ability-config-list">
|
|
|
+ <div v-for="(ability, index) in selectedAbilityConfigs" :key="index" class="ability-config-card">
|
|
|
+ <el-row :gutter="20" align="middle">
|
|
|
+ <el-col :span="6">
|
|
|
+ <div class="config-field">
|
|
|
+ <label>*能力名称</label>
|
|
|
+ <el-input v-model="ability.abilityName" disabled />
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="7">
|
|
|
+ <div class="config-field">
|
|
|
+ <label>*关联试卷</label>
|
|
|
+ <el-input v-model="ability.thirdExamName" disabled />
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="3">
|
|
|
+ <div class="config-field">
|
|
|
+ <label>时长(分)</label>
|
|
|
+ <el-input-number v-model="ability.thirdExamTime" :min="1" controls-position="right" style="width: 100%" :disabled="detail.auditResult !== 0" />
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="4">
|
|
|
+ <div class="config-field">
|
|
|
+ <label>总分</label>
|
|
|
+ <el-input-number v-model="ability.thirdExamTotalScore" :min="0" controls-position="right" style="width: 100%" :disabled="detail.auditResult !== 0" />
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="4">
|
|
|
+ <div class="config-field">
|
|
|
+ <label>及格分</label>
|
|
|
+ <el-input-number v-model="ability.thirdExamPassMark" :min="0" :max="ability.thirdExamTotalScore || 100" controls-position="right" style="width: 100%" :disabled="detail.auditResult !== 0" />
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<!-- 已审核状态 -->
|
|
|
<div v-if="detail.auditResult !== 0" class="flex flex-col gap-6 text-[14px]">
|
|
|
<div class="flex items-center">
|
|
|
@@ -221,7 +283,7 @@
|
|
|
v-model="auditForm.remark"
|
|
|
type="textarea"
|
|
|
:rows="4"
|
|
|
- placeholder="说明说明说明说明说明说明..."
|
|
|
+ placeholder="请输入审核备注说明..."
|
|
|
/>
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
@@ -238,14 +300,17 @@
|
|
|
<div class="mt-12 pl-[120px] pb-10">
|
|
|
<el-button @click="handleBack" class="px-8 !bg-[#f2f3f5] !border-none !text-[#4e5969] hover:!bg-[#e5e6eb]">返回</el-button>
|
|
|
</div>
|
|
|
+
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { ref, onMounted } from 'vue';
|
|
|
+import { ref, reactive, onMounted } from 'vue';
|
|
|
import { useRouter, useRoute } from 'vue-router';
|
|
|
+import { Refresh } from '@element-plus/icons-vue';
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
import { getAudit, auditPass, auditReject } from '@/api/system/audit';
|
|
|
+import { listEvaluation, getEvaluation } from '@/api/main/evaluation';
|
|
|
import { AuditVO } from '@/api/system/audit/types';
|
|
|
|
|
|
const router = useRouter();
|
|
|
@@ -256,9 +321,87 @@ const detail = ref<AuditVO>({} as AuditVO);
|
|
|
const auditForm = ref({
|
|
|
deposit: 0,
|
|
|
finalPayment: 0,
|
|
|
- remark: ''
|
|
|
+ remark: '',
|
|
|
+ evaluationId: undefined as number | undefined
|
|
|
});
|
|
|
|
|
|
+// 测评下拉选项
|
|
|
+const evalLoading = ref(false);
|
|
|
+const evalOptions = ref<any[]>([]);
|
|
|
+
|
|
|
+// 测评选择相关
|
|
|
+const selectedEvaluation = ref<any>({});
|
|
|
+const selectedAbilityConfigs = ref<any[]>([]);
|
|
|
+
|
|
|
+
|
|
|
+/** 获取测评列表(直接加载所有或前200条) */
|
|
|
+const getEvalList = async () => {
|
|
|
+ evalLoading.value = true;
|
|
|
+ try {
|
|
|
+ const res: any = await listEvaluation({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 200
|
|
|
+ });
|
|
|
+ evalOptions.value = res.rows || [];
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取测评列表失败', error);
|
|
|
+ } finally {
|
|
|
+ evalLoading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/** 选择测评变更处理 */
|
|
|
+const handleEvalChange = async (val: number) => {
|
|
|
+ if (!val) {
|
|
|
+ selectedEvaluation.value = {};
|
|
|
+ selectedAbilityConfigs.value = [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ const res: any = await getEvaluation(val);
|
|
|
+ const data = res.data;
|
|
|
+ selectedEvaluation.value = data;
|
|
|
+ selectedAbilityConfigs.value = (data.abilityConfigs || []).map((item: any) => ({
|
|
|
+ id: item.id,
|
|
|
+ abilityName: item.abilityName || '',
|
|
|
+ thirdExamInfoId: item.thirdExamInfoId || '',
|
|
|
+ thirdExamName: item.thirdExamName || '',
|
|
|
+ thirdExamTime: item.thirdExamTime || 60,
|
|
|
+ thirdExamTotalScore: item.thirdExamTotalScore || 100,
|
|
|
+ thirdExamPassMark: item.thirdExamPassMark || 60,
|
|
|
+ thirdExamLink: item.thirdExamLink || ''
|
|
|
+ }));
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('获取测评详情失败');
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/** 选择测评 */
|
|
|
+const selectEvaluation = async (evalRow: any) => {
|
|
|
+ try {
|
|
|
+ // 获取测评详情以拿到完整的能力配置
|
|
|
+ const res: any = await getEvaluation(evalRow.id);
|
|
|
+ const data = res.data;
|
|
|
+
|
|
|
+ selectedEvaluation.value = data;
|
|
|
+ selectedAbilityConfigs.value = (data.abilityConfigs || []).map((item: any) => ({
|
|
|
+ id: item.id,
|
|
|
+ abilityName: item.abilityName || '',
|
|
|
+ thirdExamInfoId: item.thirdExamInfoId || '',
|
|
|
+ thirdExamName: item.thirdExamName || '',
|
|
|
+ thirdExamTime: item.thirdExamTime || 60,
|
|
|
+ thirdExamTotalScore: item.thirdExamTotalScore || 100,
|
|
|
+ thirdExamPassMark: item.thirdExamPassMark || 60,
|
|
|
+ thirdExamLink: item.thirdExamLink || ''
|
|
|
+ }));
|
|
|
+
|
|
|
+ evalDialog.value.visible = false;
|
|
|
+ ElMessage.success('已选择测试:' + data.evaluationName);
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('获取测评详情失败');
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
const getDetail = async () => {
|
|
|
loading.value = true;
|
|
|
try {
|
|
|
@@ -267,6 +410,33 @@ const getDetail = async () => {
|
|
|
detail.value = res.data;
|
|
|
if (detail.value.deposit) auditForm.value.deposit = Number(detail.value.deposit);
|
|
|
if (detail.value.finalPayment) auditForm.value.finalPayment = Number(detail.value.finalPayment);
|
|
|
+
|
|
|
+ if (detail.value.evaluationId) {
|
|
|
+ auditForm.value.evaluationId = detail.value.evaluationId;
|
|
|
+ // 预加载当前选中的项到选项里,防止下拉框显示ID
|
|
|
+ evalOptions.value = [{ id: detail.value.evaluationId, evaluationName: detail.value.evaluationName }];
|
|
|
+
|
|
|
+ try {
|
|
|
+ const evalRes: any = await getEvaluation(detail.value.evaluationId);
|
|
|
+ const evalData = evalRes.data;
|
|
|
+ selectedEvaluation.value = evalData;
|
|
|
+ selectedAbilityConfigs.value = (evalData.abilityConfigs || []).map((item: any) => ({
|
|
|
+ id: item.id,
|
|
|
+ abilityName: item.abilityName || '',
|
|
|
+ thirdExamInfoId: item.thirdExamInfoId || '',
|
|
|
+ thirdExamName: item.thirdExamName || '',
|
|
|
+ thirdExamTime: item.thirdExamTime || 60,
|
|
|
+ thirdExamTotalScore: item.thirdExamTotalScore || 100,
|
|
|
+ thirdExamPassMark: item.thirdExamPassMark || 60,
|
|
|
+ thirdExamLink: item.thirdExamLink || ''
|
|
|
+ }));
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载测评详情失败:', error);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 未审核状态加载初始选项
|
|
|
+ getEvalList();
|
|
|
+ }
|
|
|
} catch (error) {
|
|
|
ElMessage.error('获取详情失败');
|
|
|
} finally {
|
|
|
@@ -275,10 +445,20 @@ const getDetail = async () => {
|
|
|
};
|
|
|
|
|
|
const handleAuditPass = async () => {
|
|
|
+ if (!auditForm.value.evaluationId) {
|
|
|
+ ElMessage.warning('请先选择测试');
|
|
|
+ return;
|
|
|
+ }
|
|
|
try {
|
|
|
await ElMessageBox.confirm('确定要审核通过吗?', '提示', { type: 'warning' });
|
|
|
submitLoading.value = true;
|
|
|
- await auditPass(route.query.id as string, auditForm.value.remark);
|
|
|
+ await auditPass(
|
|
|
+ route.query.id as string,
|
|
|
+ auditForm.value.remark,
|
|
|
+ auditForm.value.evaluationId,
|
|
|
+ auditForm.value.deposit,
|
|
|
+ auditForm.value.finalPayment
|
|
|
+ );
|
|
|
ElMessage.success('审核通过成功');
|
|
|
await getDetail();
|
|
|
} catch (error: any) {
|
|
|
@@ -394,4 +574,43 @@ onMounted(() => {
|
|
|
:deep(.custom-radio-group .el-radio.is-disabled + span.el-radio__label) {
|
|
|
color: #1d2129;
|
|
|
}
|
|
|
+
|
|
|
+/* 测评选择区域 */
|
|
|
+.evaluation-section {
|
|
|
+ padding-bottom: 20px;
|
|
|
+ border-bottom: 1px solid #f0f0f0;
|
|
|
+ margin-bottom: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.ability-config-list {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.ability-config-card {
|
|
|
+ background-color: #f7f8fa;
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 16px 20px;
|
|
|
+
|
|
|
+ .config-field {
|
|
|
+ label {
|
|
|
+ display: block;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #4e5969;
|
|
|
+ margin-bottom: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-input-number) {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-input__wrapper) {
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 2px;
|
|
|
+ box-shadow: none;
|
|
|
+ border: 1px solid #e5e6eb;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|