<script lang="ts" setup>
|
import type { ActionItem, BasicColumn } from '@jnpf/ui/vxeTable';
|
|
import type { RecordListMode, TmsRecordListItem } from './types';
|
|
import { computed, watch } from 'vue';
|
import { useRoute, useRouter } from 'vue-router';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { BasicVxeTable, TableAction, useVxeTable } from '@jnpf/ui/vxeTable';
|
|
import { Modal } from 'ant-design-vue';
|
|
import { archiveTmsRecords, deleteTmsRecords, getTmsRecordList } from '#/api/x/tms/record';
|
|
import { LIST_MODE_LABEL, RECORD_LIST_PATH } from './constants';
|
|
defineOptions({ name: 'TmsRecord' });
|
|
const route = useRoute();
|
const router = useRouter();
|
const { createMessage } = useMessage();
|
|
function modeFromPath(path: string): RecordListMode {
|
if (path.includes('/archived')) return 'archived';
|
if (path.includes('/ready')) return 'ready';
|
return 'main';
|
}
|
|
const listMode = computed(() => modeFromPath(route.path));
|
const listModeTitle = computed(() => LIST_MODE_LABEL[listMode.value]);
|
const isMainView = computed(() => listMode.value === 'main');
|
const isReadyView = computed(() => listMode.value === 'ready');
|
const isArchivedView = computed(() => listMode.value === 'archived');
|
|
const columns: BasicColumn[] = [
|
{ title: '编号', dataIndex: 'recordNo', width: 140 },
|
{ title: '培训分类', dataIndex: 'category', width: 120 },
|
{
|
title: '培训主题',
|
dataIndex: 'subject',
|
minWidth: 280,
|
slots: { default: 'subject' },
|
},
|
{ title: '培训师', dataIndex: 'trainerName', width: 100 },
|
{ title: '培训类型', dataIndex: 'trainType', width: 110 },
|
{ title: '培训开始时间', dataIndex: 'startTime', width: 160 },
|
{ title: '考核方式', dataIndex: 'evalMode', width: 110 },
|
];
|
|
const [registerTable, { reload, getSelectRows }] = useVxeTable({
|
api: fetchList,
|
columns,
|
immediate: true,
|
rowKey: 'id',
|
rowSelection: { type: 'checkbox' },
|
useSearchForm: true,
|
formConfig: {
|
baseColProps: { span: 6 },
|
compact: true,
|
showAdvancedButton: true,
|
autoAdvancedLine: 1,
|
schemas: [
|
{
|
field: 'keyword',
|
label: '关键词',
|
component: 'Input',
|
componentProps: { placeholder: '编号/主题/培训师', submitOnPressEnter: true },
|
},
|
{
|
field: 'recordNo',
|
label: '编号',
|
component: 'Input',
|
componentProps: { placeholder: '请输入编号', submitOnPressEnter: true },
|
},
|
{
|
field: 'category',
|
label: '培训分类',
|
component: 'Input',
|
componentProps: { placeholder: '请输入培训分类', submitOnPressEnter: true },
|
},
|
{
|
field: 'trainerName',
|
label: '培训师',
|
component: 'Input',
|
componentProps: { placeholder: '请输入培训师', submitOnPressEnter: true },
|
},
|
],
|
},
|
actionColumn: {
|
width: 100,
|
title: '操作',
|
dataIndex: 'action',
|
fixed: 'right',
|
},
|
});
|
|
watch(
|
() => listMode.value,
|
() => reload(),
|
);
|
|
async function fetchList(params: Record<string, any>) {
|
return {
|
data: await getTmsRecordList({
|
...params,
|
listMode: listMode.value,
|
}),
|
};
|
}
|
|
function getSelectedRows(): TmsRecordListItem[] {
|
return (getSelectRows?.() || []) as TmsRecordListItem[];
|
}
|
|
function requireOneRow(): TmsRecordListItem | null {
|
const rows = getSelectedRows();
|
if (!rows.length) {
|
createMessage.warning('请先勾选一条记录');
|
return null;
|
}
|
if (rows.length > 1) {
|
createMessage.warning('请只勾选一条记录');
|
return null;
|
}
|
return rows[0];
|
}
|
|
function requireRows(): TmsRecordListItem[] | null {
|
const rows = getSelectedRows();
|
if (!rows.length) {
|
createMessage.warning('请先勾选记录');
|
return null;
|
}
|
return rows;
|
}
|
|
function goList(mode: RecordListMode) {
|
router.push(RECORD_LIST_PATH[mode]);
|
}
|
|
function handleQrcode() {
|
const row = requireOneRow();
|
if (!row) return;
|
createMessage.success(`已生成「${row.recordNo}」签到二维码(接口联调后生效)`);
|
}
|
|
function handleAdd() {
|
createMessage.info('新增培训记录(联调任务发布后由系统自动生成,手工新增待后端接口)');
|
}
|
|
function handleEdit() {
|
const row = requireOneRow();
|
if (!row) return;
|
router.push(`/tms/record/edit/${row.id}`);
|
}
|
|
function handleView(record?: TmsRecordListItem) {
|
const row = record || requireOneRow();
|
if (!row) return;
|
router.push({
|
path: `/tms/record/detail/${row.id}`,
|
query: { from: listMode.value },
|
});
|
}
|
|
function handleSign() {
|
const row = requireOneRow();
|
if (!row) return;
|
router.push(`/tms/record/sign/${row.id}`);
|
}
|
|
function handleDelete() {
|
const rows = requireRows();
|
if (!rows) return;
|
Modal.confirm({
|
title: '确认删除',
|
content: `确定删除选中的 ${rows.length} 条培训记录吗?`,
|
onOk: async () => {
|
try {
|
await deleteTmsRecords(rows.map((x) => x.id));
|
createMessage.success('删除成功');
|
reload();
|
} catch (e: any) {
|
createMessage.error(e?.message || '删除失败');
|
}
|
},
|
});
|
}
|
|
function handleArchive() {
|
const rows = requireRows();
|
if (!rows) return;
|
Modal.confirm({
|
title: '确认归档',
|
content: `确定将选中的 ${rows.length} 条记录归档吗?`,
|
onOk: async () => {
|
try {
|
const count = await archiveTmsRecords(rows.map((x) => x.id));
|
createMessage.success(`已归档 ${count} 条`);
|
reload();
|
} catch (e: any) {
|
createMessage.error(e?.message || '归档失败');
|
}
|
},
|
});
|
}
|
|
function getTableActions(record: TmsRecordListItem): ActionItem[] {
|
const actions: ActionItem[] = [{ label: '查看', onClick: handleView.bind(null, record) }];
|
if (isMainView.value) {
|
actions.push({
|
label: '签到',
|
onClick: () => router.push(`/tms/record/sign/${record.id}`),
|
});
|
}
|
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>
|
<!-- 1. 培训记录 -->
|
<a-space v-if="isMainView" wrap>
|
<a-button pre-icon="icon-ym icon-ym-generator-qrcode" @click="handleQrcode">生成二维码</a-button>
|
<a-button pre-icon="icon-ym icon-ym-btn-edit" @click="handleEdit">修改</a-button>
|
<a-button pre-icon="icon-ym icon-ym-btn-preview" @click="handleView()">查看</a-button>
|
<a-button pre-icon="icon-ym icon-ym-extend-form" @click="handleSign">签到</a-button>
|
<a-button pre-icon="icon-ym icon-ym-file-text" @click="goList('ready')">可归档列表</a-button>
|
<a-button pre-icon="icon-ym icon-ym-extend-folder" @click="goList('archived')">已归档列表</a-button>
|
<span class="text-gray-400 text-sm">当前:{{ listModeTitle }}</span>
|
</a-space>
|
|
<!-- 2. 可归档列表 -->
|
<a-space v-else-if="isReadyView" wrap>
|
<a-button type="primary" pre-icon="icon-ym icon-ym-btn-add" @click="handleAdd">新增</a-button>
|
<a-button pre-icon="icon-ym icon-ym-btn-edit" @click="handleEdit">修改</a-button>
|
<a-button danger pre-icon="icon-ym icon-ym-btn-clearn" @click="handleDelete">删除</a-button>
|
<a-button pre-icon="icon-ym icon-ym-extend-folder" @click="handleArchive">归档</a-button>
|
<a-button @click="goList('main')">返回</a-button>
|
<a-button pre-icon="icon-ym icon-ym-file-text" @click="goList('archived')">已归档列表</a-button>
|
<span class="text-gray-400 text-sm">当前:{{ listModeTitle }}</span>
|
</a-space>
|
|
<!-- 3. 已归档列表 -->
|
<a-space v-else wrap>
|
<a-button @click="handleView()">查看</a-button>
|
<a-button @click="handleEdit">修改</a-button>
|
<a-button @click="goList('main')">返回</a-button>
|
<a-button type="primary" @click="goList('ready')">可归档列表</a-button>
|
<span class="text-gray-400 text-sm">当前:{{ listModeTitle }}</span>
|
</a-space>
|
</template>
|
<template #subject="{ record }">
|
<div class="subject-cell">{{ record.subject }}</div>
|
</template>
|
<template #action="{ record }">
|
<TableAction :actions="getTableActions(record)" />
|
</template>
|
</BasicVxeTable>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<style scoped>
|
.subject-cell {
|
white-space: pre-wrap;
|
line-height: 1.45;
|
word-break: break-word;
|
}
|
</style>
|