“修复培训审批v0923”
This commit is contained in:
1 parent
0876b60056
commit
06731fd6e0
4 files changed
+233
-178
No files matched your search
+10
@@ -127,4 +127,14 @@ public class RsTrainingRecord extends BaseEntity {
|
||||
private String courseName;
|
||||
private Integer duration;
|
||||
private String location;
|
||||
|
||||
// 关联字段 - 从申请表关联查询(不存储在记录表中)
|
||||
@TableField(exist = false)
|
||||
private String organizerUnit; // 主办单位
|
||||
|
||||
@TableField(exist = false)
|
||||
private String trainingType; // 培训类型
|
||||
|
||||
@TableField(exist = false)
|
||||
private String companions; // 同行人员
|
||||
}
|
||||
+8
-1
@@ -37,6 +37,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="duration" column="duration"/>
|
||||
<result property="location" column="location"/>
|
||||
<result property="deptId" column="dept_id"/>
|
||||
|
||||
<!-- 从申请表关联查询的字段 -->
|
||||
<result property="organizerUnit" column="organizer_unit"/>
|
||||
<result property="trainingType" column="training_type"/>
|
||||
<result property="companions" column="companions"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectRsTrainingRecordVo">
|
||||
@@ -44,8 +49,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
r.completion_status, r.completion_time, r.score, r.certificate_path, r.certificate_number, r.attachment_ids,
|
||||
r.feedback, r.tenant_id, r.create_dept, r.create_by, r.create_time, r.update_by, r.update_time,
|
||||
r.department, r.position, r.reason, r.status, r.apply_time, r.current_approver, r.start_time, r.end_time,
|
||||
r.course_name, r.duration, r.location, r.dept_id
|
||||
r.course_name, r.duration, r.location, r.dept_id,
|
||||
a.course_name as organizer_unit, a.training_type, a.companions
|
||||
from rs_training_record r
|
||||
left join rs_training_application a on r.application_id = a.application_id and a.deleted = '0'
|
||||
</sql>
|
||||
|
||||
<select id="selectRsTrainingRecordList" parameterType="RsTrainingRecord" resultMap="RsTrainingRecordResult">
|
||||
|
||||
@@ -163,6 +163,12 @@ export interface RecordVO {
|
||||
createBy: string;
|
||||
updateBy: string;
|
||||
remark: string;
|
||||
// 关联字段 - 从申请表获取
|
||||
organizerUnit?: string; // 主办单位
|
||||
trainingType?: string; // 培训类型
|
||||
companions?: string; // 同行人员
|
||||
startTime?: string; // 开始时间
|
||||
endTime?: string; // 结束时间
|
||||
}
|
||||
|
||||
// 培训记录表单类型
|
||||
|
||||
+209
-177
@@ -213,20 +213,44 @@
|
||||
@row-dblclick="handleViewRecord"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="课程名称" align="center" prop="courseName" min-width="150" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="培训地点" align="center" prop="location" min-width="110" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="部门" align="center" prop="department" min-width="110" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="完成状态" align="center" prop="completionStatus" width="100">
|
||||
<!-- 主办单位:从申请表course_name字段关联获取 -->
|
||||
<el-table-column label="主办单位" align="center" prop="organizerUnit" min-width="150" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.completionStatus === '0' ? 'warning' : scope.row.completionStatus === '1' ? 'success' : 'info'">
|
||||
{{ scope.row.completionStatus === '0' ? '未完成' : scope.row.completionStatus === '1' ? '已完成' : '未知' }}
|
||||
</el-tag>
|
||||
<span>{{ scope.row.organizerUnit || '暂无' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="学时" align="center" prop="duration" width="80" />
|
||||
<el-table-column label="完成时间" align="center" prop="completionTime" width="160">
|
||||
<!-- 培训类型:从申请表training_type字段关联获取 -->
|
||||
<el-table-column label="培训类型" align="center" prop="trainingType" min-width="110" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.completionTime) || '未完成' }}</span>
|
||||
<span>{{ scope.row.trainingType || '暂无' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 开始时间:从记录表start_time字段获取 -->
|
||||
<el-table-column label="开始时间" align="center" prop="startTime" width="160">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.startTime) || '暂无' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 结束时间:从记录表end_time字段获取 -->
|
||||
<el-table-column label="结束时间" align="center" prop="endTime" width="160">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.endTime) || '暂无' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 同行人员:从申请表companions字段关联获取,格式化为教师姓名 -->
|
||||
<el-table-column label="同行人员" align="center" prop="companions" min-width="120" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.companions && scope.row.companions !== '[]'">
|
||||
{{ formatCompanions(scope.row.companions) }}
|
||||
</span>
|
||||
<span v-else>无</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="完成状态" align="center" prop="completionStatus" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getCompletionStatusType(scope.row.completionStatus)">
|
||||
{{ getCompletionStatusLabel(scope.row.completionStatus) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
@@ -742,7 +766,6 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="完成状态" prop="completionStatus">
|
||||
<el-radio-group v-model="recordForm.completionStatus">
|
||||
<el-radio label="0">进行中</el-radio>
|
||||
<el-radio label="1">已完成</el-radio>
|
||||
<el-radio label="2">未完成</el-radio>
|
||||
</el-radio-group>
|
||||
@@ -860,79 +883,58 @@
|
||||
</el-dialog>
|
||||
|
||||
<!-- 培训记录详情对话框 -->
|
||||
<el-dialog title="培训记录详情" v-model="recordDetailDialogVisible" width="700px" append-to-body>
|
||||
<el-dialog title="培训记录详情" v-model="recordDetailDialogVisible" width="800px" append-to-body>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="课程名称">{{ recordDetail.courseName }}</el-descriptions-item>
|
||||
<!-- 学员基本信息 -->
|
||||
<el-descriptions-item label="学员姓名">{{ recordDetail.userName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在部门(系部)">{{ recordDetail.department || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="现职称">{{ recordDetail.currentTitle || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="现岗位">{{ recordDetail.currentPosition || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="参加工作时间">{{ parseTime(recordDetail.workStartTime) || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系电话">{{ recordDetail.phone || '暂无' }}</el-descriptions-item>
|
||||
|
||||
<!-- 培训情况信息 -->
|
||||
<el-descriptions-item label="主办单位">{{ recordDetail.organizerUnit || recordDetail.courseName || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培训地点">{{ recordDetail.location || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开始时间">{{ parseTime(recordDetail.startTime) || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="结束时间">{{ parseTime(recordDetail.endTime) || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培训类型">{{ recordDetail.trainingType || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培训费用">{{ recordDetail.trainingFee ? `${recordDetail.trainingFee}元` : '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请时间">{{ parseTime(recordDetail.applyTime) || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="完成状态">
|
||||
<el-tag :type="recordDetail.completionStatus === '0' ? 'warning' : recordDetail.completionStatus === '1' ? 'success' : 'info'">
|
||||
{{ recordDetail.completionStatus === '0' ? '进行中' : recordDetail.completionStatus === '1' ? '已完成' : '未完成' }}
|
||||
<el-tag :type="getCompletionStatusType(recordDetail.completionStatus)">
|
||||
{{ getCompletionStatusLabel(recordDetail.completionStatus) }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="学时">{{ recordDetail.duration || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="完成时间">{{ parseTime(recordDetail.completionTime) || '未完成' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="证书" :span="2">
|
||||
<div v-if="getCertificatePath(recordDetail)" class="certificate-preview">
|
||||
<!-- 证书预览区域 -->
|
||||
<div class="certificate-container">
|
||||
<!-- 统一显示为图片预览,支持OSS ID和传统路径 -->
|
||||
<div class="image-preview">
|
||||
<el-image
|
||||
v-if="certificatePreviewUrl"
|
||||
:src="certificatePreviewUrl"
|
||||
:preview-src-list="[certificatePreviewUrl]"
|
||||
fit="contain"
|
||||
style="width: 300px; height: 200px; border: 1px solid #dcdfe6; border-radius: 4px"
|
||||
preview-teleported
|
||||
>
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
<el-icon><Picture /></el-icon>
|
||||
<div>加载失败</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<div
|
||||
v-else
|
||||
class="loading-preview"
|
||||
style="
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
"
|
||||
>
|
||||
<el-icon class="is-loading"><Loading /></el-icon>
|
||||
<span style="margin-left: 8px">加载中...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 操作按钮 -->
|
||||
<div class="certificate-actions" style="margin-top: 10px">
|
||||
<el-button type="primary" size="small" @click="viewCertificateDetail(recordDetail)">
|
||||
<el-icon><View /></el-icon>
|
||||
查看原图
|
||||
</el-button>
|
||||
<el-button type="success" size="small" @click="downloadCertificateFile(recordDetail)">
|
||||
<el-icon><Download /></el-icon>
|
||||
下载证书
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="no-certificate">
|
||||
<el-empty description="暂无证书" :image-size="60" />
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="证书编号">{{ recordDetail.certificateNumber || '无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ parseTime(recordDetail.createTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培训反馈" :span="2">
|
||||
<div class="detail-text">{{ recordDetail.feedback || '暂无反馈' }}</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="同行人" :span="2">{{ getCompanionNames(recordDetail.companions) || '无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培训目的" :span="2">{{ recordDetail.trainingPurpose || recordDetail.reason || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注" :span="2">{{ recordDetail.remark || '暂无备注' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<!-- 申请附件显示区域 -->
|
||||
<div v-if="recordDetailAttachmentList.length > 0" class="attachment-section" style="margin-top: 20px;">
|
||||
<div class="section-title" style="margin-bottom: 15px; padding: 10px; border-left: 4px solid #409eff; background-color: #f5f7fa;">
|
||||
<el-icon style="margin-right: 8px;"><Paperclip /></el-icon>
|
||||
<strong>申请附件</strong>
|
||||
</div>
|
||||
<el-table :data="recordDetailAttachmentList" border size="small">
|
||||
<el-table-column label="序号" type="index" width="60" align="center" />
|
||||
<el-table-column label="文件名称" prop="name" align="left" show-overflow-tooltip />
|
||||
<el-table-column label="上传时间" prop="uploadTime" width="180" align="center">
|
||||
<template #default="scope">
|
||||
{{ parseTime(scope.row.uploadTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link icon="Download" @click="handleDownloadApplicationAttachment(scope.row)" size="small">
|
||||
下载
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="recordDetailDialogVisible = false">关 闭</el-button>
|
||||
@@ -1270,8 +1272,7 @@ const recordRules = reactive({
|
||||
|
||||
// 培训记录详情
|
||||
const recordDetailDialogVisible = ref(false);
|
||||
const certificatePreviewUrl = ref('');
|
||||
const recordDetail = reactive<RecordVO>({
|
||||
const recordDetail = reactive<any>({
|
||||
recordId: undefined,
|
||||
courseId: undefined,
|
||||
courseName: '',
|
||||
@@ -1285,7 +1286,22 @@ const recordDetail = reactive<RecordVO>({
|
||||
updateTime: '',
|
||||
createBy: '',
|
||||
updateBy: '',
|
||||
remark: ''
|
||||
remark: '',
|
||||
// 从培训申请获取的详细信息
|
||||
department: '',
|
||||
currentTitle: '',
|
||||
currentPosition: '',
|
||||
workStartTime: '',
|
||||
phone: '',
|
||||
organizerUnit: '',
|
||||
trainingType: '',
|
||||
trainingFee: '',
|
||||
companions: '',
|
||||
trainingPurpose: '',
|
||||
location: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
applyTime: ''
|
||||
});
|
||||
|
||||
// 培训记录多选框选中数据
|
||||
@@ -1323,6 +1339,7 @@ const applicationDialogLoading = ref(false);
|
||||
const applicationFormRef = ref<any>(null);
|
||||
const applicationAttachmentFileList = ref<any[]>([]); // 申请培训附件文件列表
|
||||
const applicationDetailAttachmentList = ref<any[]>([]); // 申请详情附件文件列表
|
||||
const recordDetailAttachmentList = ref<any[]>([]); // 培训记录详情附件文件列表
|
||||
const applicationForm = reactive<{
|
||||
applicationId?: number | string;
|
||||
// 情况基本信息
|
||||
@@ -1620,6 +1637,24 @@ function getApplicationList() {
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取完成状态的标签类型 */
|
||||
const getCompletionStatusType = (status: string) => {
|
||||
// 培训记录的完成状态逻辑
|
||||
if (status === '1') return 'success'; // 已完成 - 绿色
|
||||
if (status === '2') return 'danger'; // 未完成 - 红色
|
||||
// 对于空状态或其他状态,由于培训记录都是基于已通过审批的申请生成的,默认显示为已通过
|
||||
return 'success'; // 已通过 - 绿色
|
||||
};
|
||||
|
||||
/** 获取完成状态的标签文本 */
|
||||
const getCompletionStatusLabel = (status: string) => {
|
||||
// 培训记录的完成状态逻辑
|
||||
if (status === '1') return '已完成';
|
||||
if (status === '2') return '未完成';
|
||||
// 对于空状态或其他状态,由于培训记录都是基于已通过审批的申请生成的,默认显示为已通过
|
||||
return '已通过';
|
||||
};
|
||||
|
||||
/** 获取教师列表 */
|
||||
function getTeacherList() {
|
||||
listClassTeacherCounselorRel({})
|
||||
@@ -1712,6 +1747,8 @@ async function handleApplicationDetailAttachmentData(attachmentIds: string | nul
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** 新增培训申请 */
|
||||
async function handleAddApplication() {
|
||||
resetApplicationForm();
|
||||
@@ -2029,6 +2066,11 @@ function getCompanionNames(companions: (string | number)[] | string | null | und
|
||||
}).join('、');
|
||||
}
|
||||
|
||||
/** 格式化同行人员显示(表格列使用) */
|
||||
function formatCompanions(companions: string | undefined): string {
|
||||
return getCompanionNames(companions);
|
||||
}
|
||||
|
||||
/** 查看申请详情 */
|
||||
async function handleViewApplicant(row: any) {
|
||||
// 如果行数据中没有完整的课程名称,尝试从课程列表获取
|
||||
@@ -2372,8 +2414,16 @@ function handleRecordSelectionChange(selection: RecordVO[]) {
|
||||
function handleTrainingSubTabClick() {
|
||||
if (trainingSubTab.value === 'application') {
|
||||
getApplicationList();
|
||||
// 确保教师列表已加载(用于同行人显示)
|
||||
if (teacherList.value.length === 0) {
|
||||
loadTeacherListForDisplay();
|
||||
}
|
||||
} else if (trainingSubTab.value === 'record') {
|
||||
getRecordList();
|
||||
// 确保教师列表已加载(用于同行人显示)
|
||||
if (teacherList.value.length === 0) {
|
||||
loadTeacherListForDisplay();
|
||||
}
|
||||
} else {
|
||||
getTrainingList();
|
||||
}
|
||||
@@ -2430,6 +2480,11 @@ function getRecordList() {
|
||||
recordList.value = response.rows;
|
||||
recordTotal.value = response.total;
|
||||
recordLoading.value = false;
|
||||
|
||||
// 确保教师列表已加载(用于同行人显示)
|
||||
if (teacherList.value.length === 0) {
|
||||
loadTeacherListForDisplay();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
recordLoading.value = false;
|
||||
@@ -2453,7 +2508,7 @@ function resetRecordForm() {
|
||||
recordForm.recordId = undefined;
|
||||
recordForm.courseId = '';
|
||||
recordForm.userId = '';
|
||||
recordForm.completionStatus = '0';
|
||||
recordForm.completionStatus = '1';
|
||||
recordForm.score = '';
|
||||
recordForm.completionTime = '';
|
||||
recordForm.certificatePath = '';
|
||||
@@ -2670,31 +2725,78 @@ async function handleUpdateRecord(row: RecordVO) {
|
||||
|
||||
/** 查看培训记录详情 */
|
||||
async function handleViewRecord(row: RecordVO) {
|
||||
// 如果行数据中没有完整的课程名称,尝试从课程选项获取
|
||||
if (!row.courseName && row.courseId) {
|
||||
const course = courseOptions.value.find((c) => c.courseId === row.courseId);
|
||||
if (course) {
|
||||
row.courseName = course.title;
|
||||
try {
|
||||
// 确保教师列表已加载(用于显示同行人姓名)
|
||||
if (teacherList.value.length === 0) {
|
||||
await loadTeacherListForDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
// 复制记录详情
|
||||
Object.assign(recordDetail, row);
|
||||
// 首先复制记录的基本信息
|
||||
Object.assign(recordDetail, row);
|
||||
|
||||
// 异步获取证书预览URL
|
||||
const certificatePath = getCertificatePath(row);
|
||||
if (certificatePath) {
|
||||
try {
|
||||
certificatePreviewUrl.value = await getSecureCertificatePreviewUrl(certificatePath);
|
||||
} catch (error) {
|
||||
console.error('获取证书预览URL失败:', error);
|
||||
certificatePreviewUrl.value = '';
|
||||
// 如果行数据中没有完整的课程名称,尝试从课程选项获取
|
||||
if (!row.courseName && row.courseId) {
|
||||
const course = courseOptions.value.find((c) => c.courseId === row.courseId);
|
||||
if (course) {
|
||||
recordDetail.courseName = course.title;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
certificatePreviewUrl.value = '';
|
||||
}
|
||||
|
||||
recordDetailDialogVisible.value = true;
|
||||
// 如果有申请ID,获取完整的申请详情来补充缺失的字段
|
||||
if (row.applicationId) {
|
||||
try {
|
||||
const applicationResponse = await getTrainingApplication(row.applicationId);
|
||||
const applicationData = applicationResponse.data;
|
||||
|
||||
// 合并申请数据中的详细信息到记录详情
|
||||
Object.assign(recordDetail, {
|
||||
// 保留记录的核心信息
|
||||
recordId: row.recordId,
|
||||
completionStatus: row.completionStatus,
|
||||
completionTime: row.completionTime,
|
||||
certificatePath: row.certificatePath,
|
||||
certificateNumber: row.certificateNumber,
|
||||
feedback: row.feedback,
|
||||
|
||||
// 从申请数据中获取详细信息
|
||||
department: applicationData.department || row.department,
|
||||
currentTitle: applicationData.currentTitle,
|
||||
currentPosition: applicationData.currentPosition,
|
||||
workStartTime: applicationData.workStartTime,
|
||||
phone: applicationData.phone,
|
||||
organizerUnit: applicationData.organizerUnit,
|
||||
trainingType: applicationData.trainingType,
|
||||
trainingFee: applicationData.trainingFee,
|
||||
companions: applicationData.companions,
|
||||
trainingPurpose: applicationData.trainingPurpose || applicationData.reason,
|
||||
location: applicationData.location || row.location,
|
||||
startTime: applicationData.startTime,
|
||||
endTime: applicationData.endTime,
|
||||
applyTime: applicationData.applyTime,
|
||||
|
||||
// 其他基本信息
|
||||
courseName: applicationData.courseName || recordDetail.courseName,
|
||||
userName: applicationData.userName || row.userName,
|
||||
duration: applicationData.duration || row.duration,
|
||||
remark: row.remark
|
||||
});
|
||||
|
||||
// 加载申请附件数据
|
||||
if (applicationData.attachmentIds) {
|
||||
await handleApplicationDetailAttachmentData(applicationData.attachmentIds);
|
||||
recordDetailAttachmentList.value = [...applicationDetailAttachmentList.value];
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('获取申请详情失败,使用记录基本信息:', error);
|
||||
// 如果获取申请详情失败,继续使用记录的基本信息
|
||||
}
|
||||
}
|
||||
|
||||
recordDetailDialogVisible.value = true;
|
||||
} catch (error) {
|
||||
console.error('查看培训记录详情失败:', error);
|
||||
proxy?.$modal.msgError('获取培训记录详情失败,请重试');
|
||||
}
|
||||
}
|
||||
|
||||
/** 删除培训记录 */
|
||||
@@ -3234,82 +3336,6 @@ function getCertificateFileName(filePath: string): string {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/** 查看证书详情 */
|
||||
async function viewCertificateDetail(row: any) {
|
||||
const certificatePath = getCertificatePath(row);
|
||||
if (!certificatePath) {
|
||||
proxy?.$modal.msgWarning('该培训记录暂无证书');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const previewUrl = await getSecureCertificatePreviewUrl(certificatePath);
|
||||
if (previewUrl) {
|
||||
window.open(previewUrl, '_blank');
|
||||
} else {
|
||||
proxy?.$modal.msgError('无法获取证书预览链接');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取证书预览链接失败:', error);
|
||||
proxy?.$modal.msgError('获取证书预览链接失败');
|
||||
}
|
||||
}
|
||||
|
||||
/** 下载证书文件 */
|
||||
async function downloadCertificateFile(row: any) {
|
||||
const certificatePath = getCertificatePath(row);
|
||||
if (!certificatePath) {
|
||||
proxy?.$modal.msgWarning('该培训记录暂无证书');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 如果是OSS ID,使用专门的下载方法
|
||||
if (/^\d+$/.test(certificatePath.trim())) {
|
||||
// 使用request下载,带认证信息
|
||||
const loading = ElLoading.service({
|
||||
text: '正在下载证书...',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await request({
|
||||
url: `/resource/oss/download/${certificatePath.trim()}`,
|
||||
method: 'get',
|
||||
responseType: 'blob',
|
||||
timeout: 300000
|
||||
});
|
||||
|
||||
if (response) {
|
||||
const blob = response instanceof Blob ? response : response.data;
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = getCertificateFileName(certificatePath) || `certificate_${certificatePath}.pdf`;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
}
|
||||
} finally {
|
||||
loading?.close();
|
||||
}
|
||||
} else {
|
||||
// 普通文件路径的处理
|
||||
const downloadUrl = getCertificatePreviewUrl(certificatePath);
|
||||
const link = document.createElement('a');
|
||||
link.href = downloadUrl;
|
||||
link.download = getCertificateFileName(certificatePath);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('下载证书失败:', error);
|
||||
proxy?.$modal.msgError('下载证书失败');
|
||||
}
|
||||
}
|
||||
|
||||
/** 下载证书 */
|
||||
function downloadCertificate(row: RecordVO) {
|
||||
if (!row.certificatePath) {
|
||||
@@ -3635,6 +3661,10 @@ onActivated(() => {
|
||||
|
||||
// 同时加载课程选项,确保下拉选项可用
|
||||
loadCourseOptions();
|
||||
// 确保教师列表已加载(用于同行人显示)
|
||||
if (teacherList.value.length === 0) {
|
||||
loadTeacherListForDisplay();
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
@@ -3646,6 +3676,8 @@ onMounted(() => {
|
||||
getRecordList();
|
||||
loadCourseOptions();
|
||||
getDepartmentList();
|
||||
// 加载教师列表(用于同行人显示)
|
||||
loadTeacherListForDisplay();
|
||||
});
|
||||
|
||||
// ===== 申请培训附件上传相关方法 =====
|
||||
|
||||
Reference in new issue
Block a user