|
|
@@ -14,8 +14,8 @@
|
|
|
</div>
|
|
|
<div class="flex gap-8 relative">
|
|
|
<div class="flex flex-col items-center">
|
|
|
- <el-avatar :size="100" :src="form.avatar" />
|
|
|
- <el-tag type="success" size="small" class="mt-2">{{ form.availability || '未知状态' }}</el-tag>
|
|
|
+ <el-avatar :size="100" :src="form.avatarUrl" />
|
|
|
+ <dict-tag :options="main_arrivail_time" :value="form.availability" class="mt-2" />
|
|
|
</div>
|
|
|
<div class="flex-1">
|
|
|
<el-form v-if="isEditing" :model="form" label-width="100px" size="small">
|
|
|
@@ -30,7 +30,7 @@
|
|
|
</el-form-item>
|
|
|
<el-form-item label="用户类型">
|
|
|
<el-select v-model="form.userType" placeholder="请选择">
|
|
|
- <el-option v-for="item in main_user_type" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ <el-option v-for="item in main_student_type" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="联系电话">
|
|
|
@@ -82,11 +82,15 @@
|
|
|
<div class="col-span-1">
|
|
|
<div class="flex items-center gap-2 mb-2">
|
|
|
<span class="text-2xl font-bold">{{ form.name }}</span>
|
|
|
- <el-icon v-if="form.gender === '0'" class="text-blue-500"><Male /></el-icon>
|
|
|
- <el-icon v-else-if="form.gender === '1'" class="text-pink-500"><Female /></el-icon>
|
|
|
+ <el-icon v-if="form.gender === '0' || form.gender === 'M'" class="text-blue-500"><Male /></el-icon>
|
|
|
+ <el-icon v-else-if="form.gender === '1' || form.gender === 'F'" class="text-pink-500"><Female /></el-icon>
|
|
|
<span v-if="form.userType === '1'" class="text-orange-400">💎</span>
|
|
|
</div>
|
|
|
- <div class="text-xs text-gray-400 mb-1">身份证号</div>
|
|
|
+ <div class="text-xs text-gray-400 mb-1">用户类型</div>
|
|
|
+ <div class="text-sm">
|
|
|
+ <dict-tag :options="main_student_type" :value="form.userType" />
|
|
|
+ </div>
|
|
|
+ <div class="text-xs text-gray-400 mb-1 mt-2">身份证号</div>
|
|
|
<div class="text-sm">{{ form.idCardNumber || '-' }}</div>
|
|
|
</div>
|
|
|
<div>
|
|
|
@@ -161,7 +165,11 @@
|
|
|
<section>
|
|
|
<h3 class="font-bold text-base mb-4 border-l-4 border-blue-500 pl-2">工作经历</h3>
|
|
|
<el-table :data="form.experienceList" border>
|
|
|
- <el-table-column prop="company" label="公司" />
|
|
|
+ <el-table-column label="公司">
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.isHidden === 1 ? '***(已屏蔽)' : scope.row.company }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column prop="industry" label="行业" />
|
|
|
<el-table-column label="时间" width="200">
|
|
|
<template #default="scope">
|
|
|
@@ -178,18 +186,30 @@
|
|
|
<h3 class="font-bold text-base mb-4 border-l-4 border-blue-500 pl-2">项目经历</h3>
|
|
|
<el-table :data="form.projectList" border>
|
|
|
<el-table-column prop="projectName" label="项目名称" />
|
|
|
- <el-table-column prop="role" label="担任角色" />
|
|
|
+ <el-table-column prop="role" label="角色" />
|
|
|
<el-table-column label="时间" width="200">
|
|
|
<template #default="scope">
|
|
|
{{ scope.row.startTime }} - {{ scope.row.endTime }}
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column prop="description" label="描述" show-overflow-tooltip />
|
|
|
- <el-table-column prop="achievement" label="业绩" show-overflow-tooltip />
|
|
|
- <el-table-column prop="link" label="链接">
|
|
|
+ <el-table-column prop="description" label="项目描述" show-overflow-tooltip />
|
|
|
+ </el-table>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <!-- 简历附件列表 -->
|
|
|
+ <section v-if="form.appendixList && form.appendixList.length > 0">
|
|
|
+ <h3 class="font-bold text-base mb-4 border-l-4 border-blue-500 pl-2">简历附件</h3>
|
|
|
+ <el-table :data="form.appendixList" border>
|
|
|
+ <el-table-column prop="fileName" label="文件名" />
|
|
|
+ <el-table-column label="文件大小" width="120">
|
|
|
<template #default="scope">
|
|
|
- <el-link v-if="scope.row.link" type="primary" :href="scope.row.link" target="_blank">{{ scope.row.link }}</el-link>
|
|
|
- <span v-else>-</span>
|
|
|
+ {{ (scope.row.fileSize / 1024).toFixed(2) }} KB
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="createTime" label="上传时间" width="180" />
|
|
|
+ <el-table-column label="操作" width="100" fixed="right">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-button link type="primary" icon="Download" @click="proxy.$download.oss(scope.row.ossId)">下载</el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
@@ -199,13 +219,19 @@
|
|
|
|
|
|
<!-- 测评信息 -->
|
|
|
<el-tab-pane label="测评信息" name="assessment">
|
|
|
- <div class="p-4">
|
|
|
- <el-table :data="assessmentData" border>
|
|
|
- <el-table-column prop="name" label="名称" />
|
|
|
- <el-table-column prop="position" label="岗位" />
|
|
|
- <el-table-column prop="result" label="结果" />
|
|
|
- <el-table-column prop="time" label="测评时间" />
|
|
|
- <el-table-column label="操作" width="100" align="center">
|
|
|
+ <div class="p-4" v-loading="assessmentLoading">
|
|
|
+ <el-table :data="assessmentList" border>
|
|
|
+ <el-table-column prop="evaluationName" label="测评名称" min-width="180" />
|
|
|
+ <el-table-column label="结果" width="120" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-tag :type="scope.row.statusType === 'pass' ? 'success' : (scope.row.statusType === 'fail' ? 'danger' : 'info')">
|
|
|
+ {{ scope.row.statusText }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="createTime" label="申请时间" width="180" align="center" />
|
|
|
+ <el-table-column prop="finishedTime" label="完成时间" width="180" align="center" />
|
|
|
+ <el-table-column label="操作" width="100" align="center" fixed="right">
|
|
|
<template #default="scope">
|
|
|
<el-button link type="primary" @click="handleViewAssessment(scope.row)">查看</el-button>
|
|
|
</template>
|
|
|
@@ -216,18 +242,32 @@
|
|
|
|
|
|
<!-- 培训信息 -->
|
|
|
<el-tab-pane label="培训信息" name="training">
|
|
|
- <div class="p-4">
|
|
|
- <el-table :data="trainingData" border>
|
|
|
- <el-table-column prop="name" label="名称" />
|
|
|
- <el-table-column prop="mode" label="培训方式" />
|
|
|
- <el-table-column prop="time" label="培训时间" />
|
|
|
+ <div class="p-4" v-loading="trainingLoading">
|
|
|
+ <el-table :data="trainingList" border>
|
|
|
+ <el-table-column prop="name" label="培训名称" min-width="180" />
|
|
|
+ <el-table-column label="学习进度" width="180" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-progress :percentage="scope.row.progress || 0" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="learnedTime" label="累计学时" width="150" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.learnedTime || 0 }} 分钟
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="lastLearnTime" label="最后学习时间" width="180" align="center" />
|
|
|
+ <el-table-column prop="finishTime" label="完成时间" width="180" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.finishTime || '-' }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
</el-table>
|
|
|
</div>
|
|
|
</el-tab-pane>
|
|
|
|
|
|
<!-- 订单信息 -->
|
|
|
<el-tab-pane label="订单信息" name="order">
|
|
|
- <div class="p-4">
|
|
|
+ <div class="p-4" v-loading="orderLoading">
|
|
|
<div class="flex items-center gap-2 mb-6">
|
|
|
<div class="w-1 h-4 bg-blue-500"></div>
|
|
|
<span class="font-bold text-gray-800">订单信息</span>
|
|
|
@@ -250,35 +290,49 @@
|
|
|
<div class="w-48 text-center">操作</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="space-y-4">
|
|
|
- <div v-for="order in orderList" :key="order.orderId" class="order-item border border-gray-100">
|
|
|
+ <div class="space-y-4" v-if="orderList && orderList.length > 0">
|
|
|
+ <div v-for="order in orderList" :key="order.id" class="order-item border border-gray-100">
|
|
|
<div class="order-info-bar flex justify-between items-center bg-[#f4faff] py-2 px-4 text-[11px] text-gray-500 border-b border-gray-100">
|
|
|
<div class="flex gap-8">
|
|
|
<span>订单编号:{{ order.orderNo }}</span>
|
|
|
<span>下单时间:{{ order.createTime }}</span>
|
|
|
- <span>{{ order.payMode }}</span>
|
|
|
+ <span>{{ order.payTime ? '支付时间:' + order.payTime : '未支付' }}</span>
|
|
|
</div>
|
|
|
- <div class="text-[12px] font-bold text-gray-800">实付款(元):{{ order.amount }}元</div>
|
|
|
+ <div class="text-[12px] font-bold text-gray-800">实付款(元):{{ order.totalAmount }}元</div>
|
|
|
</div>
|
|
|
<div class="flex items-center py-4 px-4">
|
|
|
<div class="flex-1 flex items-center gap-4">
|
|
|
- <el-image :src="order.goodsImage" class="w-14 h-14 rounded object-cover border border-gray-100" />
|
|
|
+ <el-image :src="order.productImg" class="w-14 h-14 rounded object-cover border border-gray-100">
|
|
|
+ <template #error>
|
|
|
+ <div class="image-slot bg-gray-100 w-full h-full flex items-center justify-center">
|
|
|
+ <el-icon><Picture /></el-icon>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-image>
|
|
|
<div class="flex flex-col gap-1">
|
|
|
- <div class="font-bold text-blue-500 hover:text-blue-600 cursor-pointer text-[13px]">{{ order.goodsName }}</div>
|
|
|
- <div class="text-[11px] text-gray-400">单价:{{ order.price }} 数量:{{ order.count }}</div>
|
|
|
+ <div class="font-bold text-blue-500 hover:text-blue-600 cursor-pointer text-[13px]">{{ order.productName || '未知商品' }}</div>
|
|
|
+ <div class="text-[11px] text-gray-400">单价:{{ order.totalAmount }} 数量:{{ order.quantity || 1 }}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="w-48 flex items-center justify-center gap-2 border-l border-gray-50 h-14">
|
|
|
<el-avatar :size="28" :src="order.userAvatar" />
|
|
|
<div class="flex flex-col items-start leading-tight">
|
|
|
- <div class="text-[12px] font-medium text-blue-500 cursor-pointer">{{ order.userName }}</div>
|
|
|
- <div class="text-[11px] text-gray-400 mt-0.5">{{ order.userPhone || '18854789000' }}</div>
|
|
|
+ <div class="text-[12px] font-medium text-blue-500 cursor-pointer">{{ order.buyerName }}</div>
|
|
|
+ <div class="text-[11px] text-gray-400 mt-0.5">{{ order.phone || '-' }}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="w-32 text-center text-[12px] text-gray-600 border-l border-gray-50 h-14 flex items-center justify-center">小程序</div>
|
|
|
- <div class="w-32 text-center text-[12px] text-gray-600 border-l border-gray-50 h-14 flex items-center justify-center">{{ order.orderType }}</div>
|
|
|
+ <div class="w-32 text-center text-[12px] text-gray-600 border-l border-gray-50 h-14 flex items-center justify-center">{{ order.source || '小程序' }}</div>
|
|
|
+ <div class="w-32 text-center text-[12px] text-gray-600 border-l border-gray-50 h-14 flex items-center justify-center">
|
|
|
+ <span v-if="order.orderType === 1">岗位</span>
|
|
|
+ <span v-else-if="order.orderType === 2">培训</span>
|
|
|
+ <span v-else-if="order.orderType === 3">商品</span>
|
|
|
+ <span v-else>其他</span>
|
|
|
+ </div>
|
|
|
<div class="w-32 flex justify-center border-l border-gray-50 h-14 items-center">
|
|
|
- <span class="text-[#2dc26b] font-bold text-[12px]">已完成</span>
|
|
|
+ <el-tag v-if="order.orderStatus === 0" type="warning">待付款</el-tag>
|
|
|
+ <el-tag v-else-if="order.orderStatus === 1" type="success">已完成</el-tag>
|
|
|
+ <el-tag v-else-if="order.orderStatus === 2" type="info">已关闭</el-tag>
|
|
|
+ <el-tag v-else-if="order.orderStatus === 3" type="danger">售后中</el-tag>
|
|
|
</div>
|
|
|
<div class="w-48 flex items-center justify-center gap-4 border-l border-gray-50 h-14 text-[12px]">
|
|
|
<el-button link type="primary" class="!p-0 !text-[12px]" @click="handleOrderDetail(order)">订单详情</el-button>
|
|
|
@@ -287,6 +341,7 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <el-empty v-else description="暂无订单数据" />
|
|
|
</div>
|
|
|
</el-tab-pane>
|
|
|
|
|
|
@@ -341,23 +396,102 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
+
|
|
|
+ <!-- 测评详情弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="assessmentDialog.visible"
|
|
|
+ :title="'测评详情 - ' + assessmentDialog.evaluationName"
|
|
|
+ width="900px"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ >
|
|
|
+ <div v-loading="assessmentDialog.loading">
|
|
|
+ <!-- 无数据 -->
|
|
|
+ <el-empty v-if="!assessmentDialog.loading && assessmentDialog.abilityDetails.length === 0" description="暂无考试记录" />
|
|
|
+
|
|
|
+ <!-- 各能力维度详情 -->
|
|
|
+ <div v-for="(ability, index) in assessmentDialog.abilityDetails" :key="index" class="mb-6 last:mb-0">
|
|
|
+ <div class="ability-section-header">
|
|
|
+ <h3 class="font-bold text-base mb-1">{{ ability.abilityName }}</h3>
|
|
|
+ <div class="text-sm text-gray-500 space-x-4">
|
|
|
+ <span>关联考试:{{ ability.examName || '-' }}</span>
|
|
|
+ <span>总分:{{ ability.totalScore || 0 }}分</span>
|
|
|
+ <span>及格分:{{ ability.passMark || 0 }}分</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 作答记录表格 -->
|
|
|
+ <el-table :data="ability.records" border size="small" class="mt-3" v-if="ability.records && ability.records.length > 0">
|
|
|
+ <el-table-column label="作答次数" width="80" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ 第{{ scope.row.times }}次
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="examName" label="考试名称" min-width="140" show-overflow-tooltip />
|
|
|
+ <el-table-column prop="examStyleName" label="考试分类" width="120" align="center" />
|
|
|
+ <el-table-column label="考试时间范围" min-width="180">
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.examStartTime }} ~ {{ scope.row.examEndTime }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="examTime" label="时长" width="70" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.examTime }}分钟
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="开始时间" width="160" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.startTime || '-' }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="交卷时间" width="160" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.commitTime || '未交卷' }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="成绩" width="90" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <span :class="{ 'text-red-500': Number(scope.row.score) < (ability.passMark || 0), 'font-bold': true }">
|
|
|
+ {{ scope.row.score }}分
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="是否通过" width="100" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-tag v-if="scope.row.isPass === 1" type="success" size="small">及格</el-tag>
|
|
|
+ <el-tag v-else-if="scope.row.isPass === 0" type="danger" size="small">不及格</el-tag>
|
|
|
+ <el-tag v-else type="info" size="small">未知</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <div v-else class="mt-3 text-center text-gray-400 py-4 bg-gray-50 rounded">
|
|
|
+ 该维度暂无作答记录
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup name="StudentDetail" lang="ts">
|
|
|
-import { ref, reactive, onMounted, getCurrentInstance, ComponentInternalInstance } from 'vue'
|
|
|
+import { ref, reactive, onMounted, watch, getCurrentInstance, ComponentInternalInstance } from 'vue'
|
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
|
-import { ArrowLeft, Male, Female, Download } from '@element-plus/icons-vue'
|
|
|
-import { getStudent } from "@/api/main/student";
|
|
|
-import { StudentVO } from "@/api/main/student/types";
|
|
|
+import { ArrowLeft, Male, Female, Download, Picture } from '@element-plus/icons-vue'
|
|
|
+import { getStudent, updateStudent } from "@/api/main/student";
|
|
|
+import { StudentVO, StudentForm } from "@/api/main/student/types";
|
|
|
+import { listOrder } from "@/api/system/order";
|
|
|
+import { OrderVO } from "@/api/system/order/types";
|
|
|
+import { listEvaluationRecord, getEvaluationDetailResult } from "@/api/main/evaluation";
|
|
|
+import { EvaluationApplyRecordVO } from "@/api/main/evaluation/types";
|
|
|
+import { listStudentTrainingRecords } from "@/api/main/training";
|
|
|
+import { TrainingLearnRecordVO } from "@/api/main/training/types";
|
|
|
|
|
|
const route = useRoute()
|
|
|
const router = useRouter()
|
|
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
|
|
|
-const { sys_user_sex, main_user_type, main_arrivail_time, main_position_type, main_education, main_experience, main_internship_duration } = proxy?.useDict(
|
|
|
+const { sys_user_sex, main_student_type, main_arrivail_time, main_position_type, main_education, main_experience, main_internship_duration } = proxy?.useDict(
|
|
|
"sys_user_sex",
|
|
|
- "main_user_type",
|
|
|
+ "main_student_type",
|
|
|
"main_arrivail_time",
|
|
|
"main_position_type",
|
|
|
"main_education",
|
|
|
@@ -372,6 +506,12 @@ const form = ref<Partial<StudentVO>>({})
|
|
|
const originalForm = ref<Partial<StudentVO>>({})
|
|
|
const activeTab = ref('resume')
|
|
|
const orderSubTab = ref('all')
|
|
|
+const orderList = ref<OrderVO[]>([])
|
|
|
+const orderLoading = ref(false)
|
|
|
+const assessmentList = ref<EvaluationApplyRecordVO[]>([])
|
|
|
+const assessmentLoading = ref(false)
|
|
|
+const trainingList = ref<TrainingLearnRecordVO[]>([])
|
|
|
+const trainingLoading = ref(false)
|
|
|
|
|
|
const getDetail = () => {
|
|
|
// router/index.ts uses 'userId' for the param name
|
|
|
@@ -379,15 +519,90 @@ const getDetail = () => {
|
|
|
if (id) {
|
|
|
loading.value = true;
|
|
|
getStudent(id as string).then(response => {
|
|
|
- form.value = response.data;
|
|
|
- originalForm.value = JSON.parse(JSON.stringify(response.data));
|
|
|
+ const data = response.data;
|
|
|
+ // 强制转换字典字段为字符串,确保 el-select 正确回显
|
|
|
+ const dictFields = ['gender', 'userType', 'education', 'grade', 'internshipDuration', 'availability', 'jobType'];
|
|
|
+ dictFields.forEach(field => {
|
|
|
+ if (data[field] !== null && data[field] !== undefined) {
|
|
|
+ data[field] = String(data[field]);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ form.value = data;
|
|
|
+ originalForm.value = JSON.parse(JSON.stringify(data));
|
|
|
loading.value = false;
|
|
|
+ // 加载订单信息
|
|
|
+ fetchOrderList();
|
|
|
+ // 加载测评信息
|
|
|
+ fetchAssessmentList();
|
|
|
+ // 加载培训信息
|
|
|
+ fetchTrainingList();
|
|
|
}).catch(() => {
|
|
|
loading.value = false;
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+const fetchOrderList = () => {
|
|
|
+ const id = route.params && route.params.userId;
|
|
|
+ if (!id) return;
|
|
|
+
|
|
|
+ orderLoading.value = true;
|
|
|
+ const query: any = {
|
|
|
+ buyerId: id,
|
|
|
+ buyerType: 2, // 学员
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 100
|
|
|
+ };
|
|
|
+
|
|
|
+ if (orderSubTab.value !== 'all') {
|
|
|
+ const statusMap: any = {
|
|
|
+ 'pending': 0,
|
|
|
+ 'completed': 1,
|
|
|
+ 'closed': 2,
|
|
|
+ 'refunding': 3
|
|
|
+ };
|
|
|
+ query.orderStatus = statusMap[orderSubTab.value];
|
|
|
+ }
|
|
|
+
|
|
|
+ listOrder(query).then(response => {
|
|
|
+ orderList.value = response.rows || [];
|
|
|
+ orderLoading.value = false;
|
|
|
+ }).catch(() => {
|
|
|
+ orderLoading.value = false;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+const fetchAssessmentList = () => {
|
|
|
+ const id = route.params && route.params.userId;
|
|
|
+ if (!id) return;
|
|
|
+
|
|
|
+ assessmentLoading.value = true;
|
|
|
+ listEvaluationRecord(id as string).then(response => {
|
|
|
+ assessmentList.value = response.data || [];
|
|
|
+ assessmentLoading.value = false;
|
|
|
+ }).catch(() => {
|
|
|
+ assessmentLoading.value = false;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+const fetchTrainingList = () => {
|
|
|
+ const id = route.params && route.params.userId;
|
|
|
+ if (!id) return;
|
|
|
+
|
|
|
+ trainingLoading.value = true;
|
|
|
+ listStudentTrainingRecords(id as string).then(response => {
|
|
|
+ trainingList.value = response.data || [];
|
|
|
+ trainingLoading.value = false;
|
|
|
+ }).catch(() => {
|
|
|
+ trainingLoading.value = false;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+watch(orderSubTab, () => {
|
|
|
+ fetchOrderList();
|
|
|
+});
|
|
|
+
|
|
|
onMounted(() => {
|
|
|
getDetail()
|
|
|
})
|
|
|
@@ -398,63 +613,20 @@ const handleBack = () => {
|
|
|
|
|
|
/** 导出在线简历 */
|
|
|
const handleExport = () => {
|
|
|
- proxy.download('main/student/export', {
|
|
|
- id: form.value.id
|
|
|
- }, `student_resume_${form.value.name}_${new Date().getTime()}.xlsx`)
|
|
|
+ const userId = route.params && route.params.userId;
|
|
|
+ if (!userId) return;
|
|
|
+ // 调用后端 GET 接口:/main/student/exportResume/{id}
|
|
|
+ proxy.$download.resource(`/main/student/exportResume/${userId}`);
|
|
|
}
|
|
|
|
|
|
/** 下载简历附件 */
|
|
|
const handleDownload = () => {
|
|
|
- if (form.value.resumeFile) {
|
|
|
- proxy.$download.oss(form.value.resumeFile)
|
|
|
- } else {
|
|
|
- proxy.$modal.msgWarning("该学员未上传简历附件")
|
|
|
- }
|
|
|
+ const userId = route.params && route.params.userId;
|
|
|
+ if (!userId) return;
|
|
|
+ // 调用后端接口,后端会自动判断单文件或多文件打包
|
|
|
+ proxy.$download.resource(`/main/student/downloadResume/${userId}`);
|
|
|
}
|
|
|
|
|
|
-const assessmentData = ref([
|
|
|
- {
|
|
|
- id: '1',
|
|
|
- name: '审计A1测评',
|
|
|
- position: '审计A1',
|
|
|
- result: '通过',
|
|
|
- time: '2023.12.12 12:12'
|
|
|
- },
|
|
|
- {
|
|
|
- id: '2',
|
|
|
- name: '审计A2测评',
|
|
|
- position: '审计A2',
|
|
|
- result: '未通过',
|
|
|
- time: '2023.12.13 10:00'
|
|
|
- }
|
|
|
-])
|
|
|
-
|
|
|
-const trainingData = ref([
|
|
|
- {
|
|
|
- name: '审计A1培训',
|
|
|
- mode: '线下',
|
|
|
- time: '2023.12.12 12:12'
|
|
|
- }
|
|
|
-])
|
|
|
-
|
|
|
-const orderList = ref([
|
|
|
- {
|
|
|
- orderId: 1,
|
|
|
- orderNo: '2020033016180804520',
|
|
|
- createTime: '2020-03-30 16:18:08',
|
|
|
- payMode: '微信支付',
|
|
|
- amount: '4000.00',
|
|
|
- goodsImage: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
|
|
|
- goodsName: '审计师A·R2高级直通',
|
|
|
- price: '400.00',
|
|
|
- count: 1,
|
|
|
- userName: '王军',
|
|
|
- userAvatar: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
|
|
|
- orderType: '测评-定金',
|
|
|
- status: '已完成'
|
|
|
- }
|
|
|
-])
|
|
|
-
|
|
|
const jobData = ref([
|
|
|
{
|
|
|
company: 'XXXX公司',
|
|
|
@@ -486,17 +658,33 @@ const evaluationForm = reactive({
|
|
|
commentB: '在职期间表现极佳'
|
|
|
})
|
|
|
|
|
|
-const handleViewAssessment = (row) => {
|
|
|
- router.push({
|
|
|
- path: '/system/assessment/report',
|
|
|
- query: { id: row.id }
|
|
|
- })
|
|
|
+const handleViewAssessment = async (row: EvaluationApplyRecordVO) => {
|
|
|
+ const id = route.params && route.params.userId;
|
|
|
+ if (!id) return;
|
|
|
+
|
|
|
+ // 打开详情弹窗并加载数据
|
|
|
+ assessmentDialog.visible = true;
|
|
|
+ assessmentDialog.loading = true;
|
|
|
+ assessmentDialog.evaluationName = row.evaluationName;
|
|
|
+ assessmentDialog.abilityDetails = [];
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res: any = await getEvaluationDetailResult(row.evaluationId, id);
|
|
|
+ if (res.data) {
|
|
|
+ assessmentDialog.abilityDetails = res.data.abilityDetails || [];
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取测评详情失败:', error);
|
|
|
+ proxy?.$modal.msgError('获取测评详情失败');
|
|
|
+ } finally {
|
|
|
+ assessmentDialog.loading = false;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-const handleOrderDetail = (order) => {
|
|
|
+const handleOrderDetail = (order: OrderVO) => {
|
|
|
router.push({
|
|
|
path: '/system/order/detail',
|
|
|
- query: { orderId: order.orderId }
|
|
|
+ query: { id: order.id }
|
|
|
})
|
|
|
}
|
|
|
|
|
|
@@ -504,12 +692,24 @@ const handleViewEvaluation = (row) => {
|
|
|
evaluationOpen.value = true
|
|
|
}
|
|
|
|
|
|
+// 测评详情弹窗
|
|
|
+const assessmentDialog = reactive({
|
|
|
+ visible: false,
|
|
|
+ loading: false,
|
|
|
+ evaluationName: '',
|
|
|
+ abilityDetails: [] as any[]
|
|
|
+})
|
|
|
+
|
|
|
const handleSave = () => {
|
|
|
saveLoading.value = true;
|
|
|
- proxy.$modal.msgSuccess('保存成功');
|
|
|
- originalForm.value = JSON.parse(JSON.stringify(form.value));
|
|
|
- isEditing.value = false;
|
|
|
- saveLoading.value = false;
|
|
|
+ updateStudent(form.value as StudentForm).then(() => {
|
|
|
+ proxy.$modal.msgSuccess('保存成功');
|
|
|
+ originalForm.value = JSON.parse(JSON.stringify(form.value));
|
|
|
+ isEditing.value = false;
|
|
|
+ saveLoading.value = false;
|
|
|
+ }).catch(() => {
|
|
|
+ saveLoading.value = false;
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
const handleCancel = () => {
|
|
|
@@ -541,4 +741,9 @@ const handleCancel = () => {
|
|
|
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+.ability-section-header {
|
|
|
+ padding-bottom: 8px;
|
|
|
+ border-bottom: 2px solid #409eff;
|
|
|
+}
|
|
|
</style>
|