From 8534025c45b4736975730678b9ccf23570a75f95 Mon Sep 17 00:00:00 2001
From: liuyu <yu.liu@cqgbkj.com>
Date: 星期二, 22 九月 2026 09:25:48 +0800
Subject: [PATCH] feat(tms): 新增试卷、培训任务、个人任务页面
---
apps/jnpf-web-apps-main/src/views/x/tms/task/Detail.vue | 192 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 192 insertions(+), 0 deletions(-)
diff --git a/apps/jnpf-web-apps-main/src/views/x/tms/task/Detail.vue b/apps/jnpf-web-apps-main/src/views/x/tms/task/Detail.vue
new file mode 100644
index 0000000..3336f36
--- /dev/null
+++ b/apps/jnpf-web-apps-main/src/views/x/tms/task/Detail.vue
@@ -0,0 +1,192 @@
+<script lang="ts" setup>
+import type { TaskEntity } from './types';
+
+import { onMounted, ref } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+
+import { useMessage } from '@jnpf/hooks';
+import {
+ Descriptions as ADescriptions,
+ DescriptionsItem as ADescriptionsItem,
+} from 'ant-design-vue';
+
+import { getUserInfoList } from '#/api/permission/user';
+import { getTaskInfo } from '#/api/x/tms/task';
+import { TMS_BTN } from '#/views/x/tms/shared/ui';
+
+import {
+ labelOfCategory,
+ labelOfEvalMode,
+ labelOfPersonStatus,
+ labelOfPublishStatus,
+ labelOfSourceType,
+ labelOfTaskKind,
+ labelOfTrainMode,
+ loadTaskDics,
+ publishStatusColor,
+} from './constants';
+
+import '#/views/x/tms/shared/page.css';
+
+defineOptions({ name: 'TmsTaskDetail' });
+
+const route = useRoute();
+const router = useRouter();
+const { createMessage } = useMessage();
+
+const loading = ref(false);
+const detail = ref<TaskEntity | null>(null);
+
+onMounted(async () => {
+ await loadTaskDics();
+ await loadData();
+});
+
+async function loadData() {
+ const id = String(route.params.id || '');
+ if (!id) {
+ router.replace('/tms/task');
+ return;
+ }
+ loading.value = true;
+ try {
+ const info = await getTaskInfo(id);
+ await fillUserNames(info);
+ detail.value = info;
+ } catch (e: any) {
+ createMessage.error(e?.message || '鍔犺浇澶辫触');
+ router.replace('/tms/task');
+ } finally {
+ loading.value = false;
+ }
+}
+
+async function fillUserNames(info: TaskEntity) {
+ const ids = [
+ info.teacherId,
+ ...(info.personTasks || []).map((item) => item.userId),
+ ].filter((id): id is string => !!id);
+ const uniqueIds = [...new Set(ids)];
+ if (!uniqueIds.length) return;
+ const res = await getUserInfoList(uniqueIds);
+ const list = res?.data?.list || [];
+ const nameOf = new Map<string, string>();
+ for (const user of list) {
+ const name = user.realName || String(user.fullName || '').split('/')[0] || user.account;
+ if (user.id && name) nameOf.set(user.id, name);
+ }
+ info.teacherName = nameOf.get(info.teacherId || '') || info.teacherId;
+ for (const item of info.personTasks || []) {
+ item.userName = nameOf.get(item.userId || '') || item.userId;
+ }
+}
+
+function goBack() {
+ router.push('/tms/task');
+}
+
+function goEdit() {
+ if (!detail.value?.id || detail.value.publishStatus !== 'draft') return;
+ router.push(`/tms/task/edit/${detail.value.id}`);
+}
+</script>
+
+<template>
+ <div class="jnpf-content-wrapper tms-task-detail-page" v-loading="loading">
+ <div class="jnpf-content-wrapper-center">
+ <div class="jnpf-content-wrapper-content tms-task-detail-wrap" v-if="detail">
+ <a-card title="鍩硅浠诲姟璇︽儏" :bordered="false">
+ <template #extra>
+ <a-space>
+ <a-button @click="goBack">{{ TMS_BTN.back }}</a-button>
+ <a-button
+ type="primary"
+ :disabled="detail.publishStatus !== 'draft'"
+ @click="goEdit"
+ >
+ {{ TMS_BTN.edit }}
+ </a-button>
+ </a-space>
+ </template>
+
+ <ADescriptions :column="2" bordered size="small">
+ <ADescriptionsItem label="鍩硅缂栧彿">{{ detail.taskNo || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="鐘舵��">
+ <a-tag :color="publishStatusColor(detail.publishStatus)">
+ {{ labelOfPublishStatus(detail.publishStatus) }}
+ </a-tag>
+ </ADescriptionsItem>
+ <ADescriptionsItem label="鍩硅涓婚" :span="2">{{ detail.subject }}</ADescriptionsItem>
+ <ADescriptionsItem label="鍩硅鍒嗙被">{{ labelOfCategory(detail.category) }}</ADescriptionsItem>
+ <ADescriptionsItem label="鏉ユ簮绫诲瀷">{{ labelOfSourceType(detail.sourceType) }}</ADescriptionsItem>
+ <ADescriptionsItem label="鍩硅鏂瑰紡">{{ labelOfTrainMode(detail.trainMode) }}</ADescriptionsItem>
+ <ADescriptionsItem label="鑰冩牳鏂瑰紡">{{ labelOfEvalMode(detail.evalMode) }}</ADescriptionsItem>
+ <ADescriptionsItem label="浠诲姟绫诲瀷">{{ labelOfTaskKind(detail.taskKind) }}</ADescriptionsItem>
+ <ADescriptionsItem label="涓婃浠诲姟缂栧彿">{{ detail.prevTaskNo || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="寮�濮嬫椂闂�">{{ detail.startTime || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="缁撴潫鏃堕棿">{{ detail.endTime || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="鍏抽棴鏃堕棿">{{ detail.closeTime || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="鍙戝竷鏃堕棿">{{ detail.publishTime || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="鍦扮偣">{{ detail.placeName || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="鏁欐潗缂栧彿">{{ detail.materialNo || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="闄勪欢" :span="2">
+ {{ detail.files?.map((item) => item.fileName).filter(Boolean).join('銆�') || '-' }}
+ </ADescriptionsItem>
+ <ADescriptionsItem label="璇曞嵎">{{ detail.paperName || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="琛ヨ�冩鏁�">{{ detail.retakeLimit ?? 1 }}</ADescriptionsItem>
+ <ADescriptionsItem label="鍚堟牸鍒�">{{ detail.passScore ?? '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="鑰冭瘯寮�濮�">{{ detail.examStart || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="鑰冭瘯缁撴潫">{{ detail.examEnd || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="鍩硅甯�">{{ detail.teacherName || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="鍩硅瀵硅薄鏁�">
+ {{ detail.personCount ?? detail.traineeIds?.length ?? '-' }}
+ </ADescriptionsItem>
+ <ADescriptionsItem label="鍩硅瑕佺偣" :span="2">{{ detail.keyPoints || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="澶囨敞" :span="2">{{ detail.remark || '-' }}</ADescriptionsItem>
+ <ADescriptionsItem label="鍒涘缓鏃堕棿">{{ detail.creatorTime || '-' }}</ADescriptionsItem>
+ </ADescriptions>
+
+ <a-divider>涓汉浠诲姟</a-divider>
+ <a-table
+ size="small"
+ :pagination="false"
+ row-key="id"
+ :data-source="detail.personTasks || []"
+ :columns="[
+ { title: '鐢ㄦ埛鍚嶇О', dataIndex: 'userName', width: 160 },
+ { title: '鐘舵��', dataIndex: 'bizStatus', width: 100 },
+ { title: '绛惧埌鏃堕棿', dataIndex: 'signTime', width: 170 },
+ { title: '鎴愮哗', dataIndex: 'examScore', width: 90 },
+ { title: '鍚堟牸', dataIndex: 'passFlag', width: 90 },
+ ]"
+ >
+ <template #bodyCell="{ column, record }">
+ <template v-if="column.dataIndex === 'bizStatus'">
+ {{ labelOfPersonStatus(record.bizStatus) }}
+ </template>
+ <template v-else-if="column.dataIndex === 'passFlag'">
+ {{ record.passFlag === '1' ? '鍚堟牸' : record.passFlag === '0' ? '涓嶅悎鏍�' : '-' }}
+ </template>
+ </template>
+ </a-table>
+ </a-card>
+ </div>
+ </div>
+ </div>
+</template>
+
+<style scoped>
+.tms-task-detail-page {
+ height: 100%;
+ min-height: 0;
+}
+
+.tms-task-detail-wrap {
+ height: 100%;
+ min-height: 0;
+ overflow-x: hidden;
+ overflow-y: auto !important;
+ background: #fff;
+ box-sizing: border-box;
+}
+</style>
--
Gitblit v1.8.0