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/personTask/index.vue |  200 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 200 insertions(+), 0 deletions(-)

diff --git a/apps/jnpf-web-apps-main/src/views/x/tms/personTask/index.vue b/apps/jnpf-web-apps-main/src/views/x/tms/personTask/index.vue
new file mode 100644
index 0000000..9931798
--- /dev/null
+++ b/apps/jnpf-web-apps-main/src/views/x/tms/personTask/index.vue
@@ -0,0 +1,200 @@
+<script lang="ts" setup>
+import type { ActionItem, BasicColumn } from '@jnpf/ui/vxeTable';
+
+import type { PersonTaskItem } from './types';
+
+import { onMounted } from 'vue';
+import { useRouter } from 'vue-router';
+
+import { useMessage } from '@jnpf/hooks';
+import { BasicVxeTable, TableAction, useVxeTable } from '@jnpf/ui/vxeTable';
+
+import { getMyPersonTaskList } from '#/api/x/tms/personTask';
+import { TMS_DIC_FIELD_NAMES } from '#/views/x/tms/shared/dic';
+import { TMS_BTN } from '#/views/x/tms/shared/ui';
+
+import {
+  PERSON_STATUS_OPTIONS,
+  labelOfEvalMode,
+  labelOfPersonStatus,
+  labelOfTrainMode,
+  loadPersonTaskDics,
+} from './constants';
+
+import '#/views/x/tms/shared/page.css';
+
+defineOptions({ name: 'TmsPersonTask' });
+
+const router = useRouter();
+const { createMessage } = useMessage();
+
+const columns: BasicColumn[] = [
+  { title: '鍩硅缂栧彿', dataIndex: 'taskNo', width: 140 },
+  { title: '鍩硅涓婚', dataIndex: 'subject', minWidth: 200 },
+  {
+    title: '鍩硅鏂瑰紡',
+    dataIndex: 'trainMode',
+    width: 110,
+    customRender: ({ record }) => labelOfTrainMode((record as PersonTaskItem).trainMode),
+  },
+  { title: '寮�濮嬫椂闂�', dataIndex: 'startTime', width: 170 },
+  { title: '缁撴潫鏃堕棿', dataIndex: 'endTime', width: 170 },
+  {
+    title: '鐘舵��',
+    dataIndex: 'bizStatus',
+    width: 100,
+    customRender: ({ record }) => labelOfPersonStatus((record as PersonTaskItem).bizStatus),
+  },
+  { title: '瀛︿範杩涘害', dataIndex: 'learnStatus', width: 100 },
+  {
+    title: '鏄惁鍙��',
+    dataIndex: 'canExam',
+    width: 100,
+    customRender: ({ record }) => {
+      const row = record as PersonTaskItem;
+      if (row.canExam) return '鏄�';
+      return row.examTip ? '鍚�' : '鍚�';
+    },
+  },
+  {
+    title: '鑰冩牳鏂瑰紡',
+    dataIndex: 'evalMode',
+    width: 110,
+    customRender: ({ record }) => labelOfEvalMode((record as PersonTaskItem).evalMode),
+  },
+];
+
+const [registerTable, { reload, getForm }] = useVxeTable({
+  api: fetchList,
+  columns,
+  immediate: false,
+  rowKey: 'id',
+  useSearchForm: true,
+  formConfig: {
+    baseColProps: { span: 6 },
+    compact: true,
+    showAdvancedButton: true,
+    alwaysShowLines: 1,
+    autoAdvancedLine: 1,
+    schemas: [
+      {
+        field: 'keyword',
+        label: '鍏抽敭璇�',
+        component: 'Input',
+        componentProps: { placeholder: '缂栧彿/涓婚', submitOnPressEnter: true },
+      },
+      {
+        field: 'bizStatus',
+        label: '鐘舵��',
+        component: 'Select',
+        componentProps: {
+          allowClear: true,
+          placeholder: '璇烽�夋嫨',
+          options: PERSON_STATUS_OPTIONS.value,
+          fieldNames: TMS_DIC_FIELD_NAMES,
+        },
+      },
+    ],
+  },
+  actionColumn: {
+    width: 160,
+    title: '鎿嶄綔',
+    dataIndex: 'action',
+    fixed: 'right',
+  },
+});
+
+onMounted(async () => {
+  await loadPersonTaskDics();
+  getForm()?.updateSchema?.({
+    field: 'bizStatus',
+    componentProps: {
+      allowClear: true,
+      placeholder: '璇烽�夋嫨',
+      options: PERSON_STATUS_OPTIONS.value,
+      fieldNames: TMS_DIC_FIELD_NAMES,
+    },
+  });
+  reload();
+});
+
+async function fetchList(params: Record<string, any>) {
+  const page = await getMyPersonTaskList(params);
+  return {
+    data: {
+      list: Array.isArray(page?.list) ? page.list : [],
+      pagination: page?.pagination || { total: 0 },
+    },
+  };
+}
+
+function isClosedStatus(status?: string) {
+  return status === 'cancelled' || status === 'expired';
+}
+
+function canEnterLearn(record: PersonTaskItem) {
+  return !isClosedStatus(record.bizStatus);
+}
+
+function handleView(record: PersonTaskItem) {
+  router.push(`/tms/personTask/detail/${record.id}`);
+}
+
+function handleLearn(record: PersonTaskItem) {
+  if (!canEnterLearn(record)) {
+    createMessage.warning(
+      record.bizStatus === 'cancelled' ? '浠诲姟宸插彇娑堬紝鏃犳硶瀛︿範' : '浠诲姟宸茶繃鏈燂紝鏃犳硶瀛︿範',
+    );
+    return;
+  }
+  router.push(`/tms/personTask/learn/${record.id}`);
+}
+
+function handleExamHint(record: PersonTaskItem) {
+  if (record.canExam) {
+    router.push(`/tms/personTask/learn/${record.id}`);
+    return;
+  }
+  createMessage.info(record.examTip || record.signTip || '褰撳墠鏆備笉鍙�冭瘯');
+}
+
+function getTableActions(record: PersonTaskItem): ActionItem[] {
+  const actions: ActionItem[] = [{ label: TMS_BTN.detail, onClick: handleView.bind(null, record) }];
+  if (canEnterLearn(record)) {
+    actions.push({ label: TMS_BTN.learn, onClick: handleLearn.bind(null, record) });
+  }
+  if (record.canExam) {
+    actions.push({
+      label: record.passFlag === '0' ? TMS_BTN.retake : TMS_BTN.exam,
+      onClick: handleExamHint.bind(null, record),
+    });
+  } else if (canEnterLearn(record) && record.examTip) {
+    actions.push({
+      label: TMS_BTN.exam,
+      disabled: true,
+      tooltip: record.examTip,
+    });
+  }
+  return actions;
+}
+</script>
+
+<template>
+  <div class="jnpf-content-wrapper">
+    <div class="jnpf-content-wrapper-center">
+      <div class="jnpf-content-wrapper-content">
+        <BasicVxeTable @register="registerTable">
+          <template #tableTitle>
+            <div>
+              <div class="tms-page-header__title">涓汉鍩硅浠诲姟</div>
+              <div class="tms-page-header__sub">瀛︿範鏁欐潗骞跺畬鎴愯�冩牳锛涘彲鑰冩椂鎿嶄綔鍒楃洿鎺ヨ繘鍏ヨ�冭瘯銆�</div>
+            </div>
+          </template>
+          <template #action="{ record }">
+            <TableAction :actions="getTableActions(record)" />
+          </template>
+        </BasicVxeTable>
+      </div>
+    </div>
+  </div>
+</template>

--
Gitblit v1.8.0