档案管理和效果评估

dev
zhangyanli 2024-03-20 10:02:16 +08:00
parent 8156e84bff
commit 1ffbba0de9
19 changed files with 1505 additions and 247 deletions

View File

@ -1,4 +1,4 @@
import { post } from "@/request/axios.js";
import { post, upload } from "@/request/axios.js";
export const getStudentsList = (params) =>
post("/archives/getStudentsList", params); // 一人一档用户列表
@ -24,6 +24,8 @@ export const getLearningRecord = (params) =>
export const getDict = (params) => post("/dictionaries/getLevels", params); // 获取人员类型
export const downloadFilesdetailword = (params) =>
post("/archives/filesdetailword", params); // 一人一档:档案详情导出
export const downloadAward = (params) =>
post("/archives/batchDownloadWord", params); // 一人一档:补充档案导出
export const getClassPapers = (params) =>
post("/archives/getClassPapers", params); // 一期一档:班级试卷列表
@ -70,12 +72,19 @@ export const downloadSign = (params) => post("/archives/sign", params); // 一
export const downloadAllwordzip = (params) =>
post("/archivesallcorpword/allwordzip", params); // 一企一档:档案目录
export const getArchivesfilesList = (params) =>
post("/archivesfiles/list", params); // 一企一档列表
export const getArchivesPostmanList = (params) =>
post("/archivespostman/list", params); // 一企一档:年度三岗人员管理台账列表
export const downloadPersonmanage = (params) =>
post("/archivespostman/personmanage", params); // 一企一档:三岗人员管理台账导出
export const getPostmanView = (params) =>
post("/archivespostman/goEdit", params); // 一企一档:三岗人员管理台账查看
export const setPostmanDelete = (params) =>
post("/archivespostman/delete", params); // 一企一档:三岗人员管理台账删除
export const setPostmanAdd = (params) => upload("/archivespostman/add", params); // 一企一档:三岗人员管理台账添加
export const setPostmanEdit = (params) =>
upload("/archivespostman/edit", params); // 一企一档:三岗人员管理台账修改
export const setPostmanImport = (params) =>
upload("/archivespostman/readExcel", params); // 一企一档:三岗人员管理台账导入
export const getArchivesTeacherList = (params) =>
post("/archivesteacher/list", params); // 一企一档:年度本单位师资管理台账
export const getArchivesPlanList = (params) =>
@ -84,6 +93,18 @@ export const getArchivesManagerList = (params) =>
post("/archivesedumanager/list", params); // 一企一档:年度安全培训教育管理台账
export const getArchivesCapitalList = (params) =>
post("/archivescapital/list", params); // 一企一档:年度培训资金提取和使用情况管理台账
export const setCapitalDelete = (params) =>
post("/archivescapital/delete", params); // 一企一档:年度培训资金提取和使用情况管理台账删除
export const getCapitalView = (params) =>
post("/archivescapital/goEdit", params); // 一企一档:年度培训资金提取和使用情况管理台账查看
export const setCapitalAdd = (params) => post("/archivescapital/add", params); // 一企一档:年度培训资金提取和使用情况管理台账添加
export const setCapitalEdit = (params) => post("/archivescapital/edit", params); // 一企一档:年度培训资金提取和使用情况管理台账修改
export const setArchivesFilesUpload = (params) =>
upload("/archivesfiles/add", params); // 一企一档上传pdf文件
export const getArchivesFilesList = (params) =>
post("/archivesfiles/listAll", params); // 一企一档:获取附件
export const setArchivesFilesDelete = (params) =>
post("/archivesfiles/delete", params); // 一企一档:删除附件
export const downloadFundmanageword = (params) =>
post("/archivescapital/fundmanageword", params); // 一企一档:年度培训资金提取和使用情况管理台账导出
export const downloadTrainingplanword = (params) =>
@ -96,3 +117,12 @@ export const downloadTeacherword = (params) =>
export const getPdffileList = (params) => post("/archivespdffile/list", params); // 档案下载重新下载
export const redownLoad = (params) =>
post("/archivespdffile/redownload", params); // 档案下载重新下载
export const getClassStrengthenDetailsList = (params) =>
post("/class/strengthenlist", params); // 效果评估:班级列表
export const getStudentStrengthenDetailsList = (params) =>
post("/class/strengthenstudentlist", params); // 效果评估:学员列表
export const getClassEvaluation = (params) =>
post("/class/getEvaluation", params); // 获取班级效果评估表信息
export const getStudentEvaluation = (params) =>
post("/student/getEvaluation", params); // 获取个人效果评估表信息
export const downloadClassEvaluation = (params) => post("class/hs", params); // 导出班级效果评估表信息

View File

@ -34,6 +34,7 @@
v-if="data.component"
v-model:type="data.type"
:title="data.title"
:corp-name="data.corp_name"
:year="data.YEAR"
/>
</el-card>
@ -53,6 +54,7 @@ import Eduplan from "./components/eduplan";
import Edumanager from "./components/edumanager";
import Capital from "./components/capital";
import { downloadAllwordzip } from "@/request/training_archive_management.js";
import { getEnterpriseInfo } from "@/request/enterprise_management.js";
const data = reactive({
list: [
@ -81,8 +83,14 @@ const data = reactive({
YEAR: dayjs().format("YYYY"),
component: "",
type: "",
corp_name: "",
title: "",
});
const fnGetData = async () => {
const resData = await getEnterpriseInfo();
data.corp_name = resData.pd.CORP_NAME;
};
fnGetData();
const fnExport = debounce(
1000,
async () => {

View File

@ -6,13 +6,22 @@
@close="fnClose"
>
<div class="tr">
<el-button type="primary" @click="list.push({})"></el-button>
<el-button type="danger" @click="fnDelete"></el-button>
<el-button type="primary" @click="fnExport"></el-button>
</div>
<div class="tc">
<h3>{{ year }}年度培训资金提取和使用情况管理台账</h3>
</div>
<p class="mb">单位名称:{{ name }}</p>
<layout-table :data="data.list" :show-pagination="false">
<p class="mb">单位名称:{{ corpName }}</p>
<layout-table
:data="list"
:show-pagination="false"
:stripe="false"
:highlight-current-row="true"
@row-click="fnRowClick"
@row-dblclick="fnRowDblclick"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="DATE" label="日期" />
<el-table-column label="费用项目">
@ -32,6 +41,43 @@
</el-table-column>
<el-table-column prop="BALANCE" label="余额" />
</layout-table>
<table class="print_use dn">
<thead>
<tr>
<td rowspan="2">序号</td>
<td rowspan="2">日期</td>
<td colspan="9">费用项目</td>
<td rowspan="2">余额</td>
</tr>
<tr>
<td>提取金额</td>
<td>培训教材教具费</td>
<td>师资费</td>
<td>试卷印制费</td>
<td>外出培训费</td>
<td>教学设备课桌椅等购置维护费</td>
<td>培训活动费</td>
<td>委托培训费</td>
<td>其他与培训有关的直接支出</td>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in list" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ item.DATE }}</td>
<td>{{ item.AMOUNT }}</td>
<td>{{ item.MATERIAL_COST }}</td>
<td>{{ item.TEACHER_COST }}</td>
<td>{{ item.PAPER_COST }}</td>
<td>{{ item.OUTSIDE_COST }}</td>
<td>{{ item.EQUIPMENT_COST }}</td>
<td>{{ item.TRAIN_COST }}</td>
<td>{{ item.ENTRUST_COST }}</td>
<td>{{ item.OTHER_COST }}</td>
<td>{{ item.BALANCE }}</td>
</tr>
</tbody>
</table>
<div class="flex mt">
<div>制表人:</div>
<div>编制日期:</div>
@ -45,17 +91,28 @@
<el-button @click="fnClose"></el-button>
</template>
</el-dialog>
<capital-add
v-model:visible="data.addOrEditDialog.visible"
v-model:form="data.addOrEditDialog.form"
:type="data.addOrEditDialog.type"
:year="year"
@get-data="fnGetData"
/>
</template>
<script setup>
import LayoutTable from "@/components/table/index";
import { reactive, watchEffect } from "vue";
import { ElMessageBox } from "element-plus";
import { nextTick, reactive, watchEffect } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { debounce } from "throttle-debounce";
import {
getArchivesCapitalList,
downloadFundmanageword,
setCapitalDelete,
getCapitalView,
} from "@/request/training_archive_management.js";
import useListData from "@/assets/js/useListData.js";
import capitalAdd from "./capital_add.vue";
const props = defineProps({
type: {
@ -66,31 +123,44 @@ const props = defineProps({
type: String,
required: true,
},
CORPINFO_ID: {
type: String,
required: true,
},
name: {
type: String,
required: true,
},
year: {
type: String,
required: true,
},
corpName: {
type: String,
required: true,
},
});
const data = reactive({
list: [],
ARCHIVESCAPITAL_ID: "",
addOrEditDialog: {
visible: false,
type: "",
form: {
DATE: "",
AMOUNT: "",
MATERIAL_COST: "",
TEACHER_COST: "",
PAPER_COST: "",
OUTSIDE_COST: "",
EQUIPMENT_COST: "",
TRAIN_COST: "",
ENTRUST_COST: "",
OTHER_COST: "",
BALANCE: "",
},
},
});
const emits = defineEmits(["update:type"]);
const fnGetData = async () => {
const resData = await getArchivesCapitalList({
const { list, fnGetData } = useListData(getArchivesCapitalList, {
otherParams: {
TYPE: props.type,
CORPINFO_ID: props.CORPINFO_ID,
YEAR: props.year,
});
data.list = resData.varList;
};
},
usePagination: false,
immediate: false,
});
watchEffect(() => {
if (props.type === 105) fnGetData();
});
@ -100,8 +170,7 @@ const fnExport = debounce(
await ElMessageBox.confirm("确定要导出吗?", { type: "warning" });
await downloadFundmanageword({
YEAR: props.year,
CORPINFO_ID: props.CORPINFO_ID,
NAME: props.name,
NAME: props.corpName,
});
await ElMessageBox.confirm(
"导出后请前往档案下载中下载该档案!",
@ -111,6 +180,35 @@ const fnExport = debounce(
},
{ atBegin: true }
);
const fnRowClick = (row) => {
data.ARCHIVESCAPITAL_ID = row.ARCHIVESCAPITAL_ID;
};
const fnRowDblclick = async (row) => {
data.addOrEditDialog.visible = true;
await nextTick();
if (row.ARCHIVESCAPITAL_ID) {
const resData = await getCapitalView({
ARCHIVESCAPITAL_ID: row.ARCHIVESCAPITAL_ID,
});
data.addOrEditDialog.form = resData.pd;
data.addOrEditDialog.type = "edit";
} else data.addOrEditDialog.type = "add";
};
const fnDelete = debounce(
1000,
async () => {
if (data.ARCHIVESCAPITAL_ID) {
await ElMessageBox.confirm("确定要删除吗?", { type: "warning" });
await setCapitalDelete({
ARCHIVESCAPITAL_ID: data.ARCHIVESCAPITAL_ID,
});
ElMessage.success("删除成功");
}
data.ARCHIVESCAPITAL_ID = "";
fnGetData();
},
{ atBegin: true }
);
const fnClose = () => {
emits("update:type", 0);
};

View File

@ -0,0 +1,153 @@
<template>
<el-dialog
v-model="visible"
:append-to-body="true"
:title="type === 'edit' ? '修改' : '新增'"
:on-close="fnClose"
>
<el-form ref="formRef" :model="form" :rules="rules" label-width="220px">
<el-form-item label="日期" prop="DATE">
<el-date-picker
v-model="form.DATE"
type="date"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="提取金额 " prop="AMOUNT">
<el-input v-model="form.AMOUNT" />
</el-form-item>
<el-form-item label="项目类型 " prop="ITEM_TYPE">
<el-input v-model="form.ITEM_TYPE" />
</el-form-item>
<el-form-item label="培训教材教具费" prop="MATERIAL_COST">
<el-input v-model="form.MATERIAL_COST" />
</el-form-item>
<el-form-item label="师资费 " prop="TEACHER_COST">
<el-input v-model="form.TEACHER_COST" />
</el-form-item>
<el-form-item label="试卷印制费 " prop="PAPER_COST">
<el-input v-model="form.PAPER_COST" />
</el-form-item>
<el-form-item label="外出培训费 " prop="OUTSIDE_COST">
<el-input v-model="form.OUTSIDE_COST" />
</el-form-item>
<el-form-item label="教学设备、课桌椅等购置维护费 " prop="EQUIPMENT_COST">
<el-input v-model="form.EQUIPMENT_COST" />
</el-form-item>
<el-form-item label="培训活动费 " prop="TRAIN_COST">
<el-input v-model="form.TRAIN_COST" />
</el-form-item>
<el-form-item label="委托培训费 " prop="ENTRUST_COST">
<el-input v-model="form.ENTRUST_COST" />
</el-form-item>
<el-form-item label="其他与培训有关的直接支出" prop="OTHER_COST">
<el-input v-model="form.OTHER_COST" />
</el-form-item>
<el-form-item label="余额" prop="BALANCE">
<el-input v-model="form.BALANCE" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="fnClose"></el-button>
<el-button type="primary" @click="fnSubmit"></el-button>
</template>
</el-dialog>
</template>
<script setup>
import { useVModels } from "@vueuse/core";
import { ref } from "vue";
import { debounce } from "throttle-debounce";
import useFormValidate from "@/assets/js/useFormValidate.js";
import {
setCapitalAdd,
setCapitalEdit,
} from "@/request/training_archive_management.js";
import { ElMessage } from "element-plus";
const props = defineProps({
visible: {
type: Boolean,
required: true,
default: false,
},
form: {
type: Object,
required: true,
default: () => ({}),
},
type: {
type: String,
required: true,
default: "",
},
year: {
type: String,
required: true,
default: "",
},
});
const emits = defineEmits(["update:visible", "update:form", "get-data"]);
const { visible, form } = useVModels(props, emits);
const rules = {
DATE: [{ required: true, message: "请选择日期", trigger: "blur" }],
AMOUNT: [{ required: true, message: "提取金额不能为空", trigger: "blur" }],
ITEM_TYPE: [{ required: true, message: "项目类型不能为空", trigger: "blur" }],
MATERIAL_COST: [
{ required: true, message: "培训教材教具费不能为空", trigger: "blur" },
],
TEACHER_COST: [
{ required: true, message: "师资费不能为空", trigger: "blur" },
],
PAPER_COST: [
{ required: true, message: "试卷印制费不能为空", trigger: "blur" },
],
OUTSIDE_COST: [
{ required: true, message: "外出培训费不能为空", trigger: "blur" },
],
EQUIPMENT_COST: [
{
required: true,
message: "教学设备、课桌椅等购置维护费不能为空",
trigger: "blur",
},
],
TRAIN_COST: [
{ required: true, message: "培训活动费不能为空", trigger: "blur" },
],
ENTRUST_COST: [
{ required: true, message: "委托培训费不能为空", trigger: "blur" },
],
OTHER_COST: [
{
required: true,
message: "其他与培训有关的直接支出不能为空",
trigger: "blur",
},
],
BALANCE: [{ required: true, message: "余额不能为空", trigger: "blur" }],
};
const formRef = ref(null);
const fnClose = () => {
formRef.value.resetFields();
visible.value = false;
};
const fnSubmit = debounce(
1000,
async () => {
await useFormValidate(formRef);
props.type === "add"
? await setCapitalAdd({ ...props.form, YEAR: props.year })
: await setCapitalEdit({ ...props.form });
ElMessage.success("操作成功");
fnClose();
emits("get-data");
},
{
atBegin: true,
}
);
</script>
<style scoped lang="scss"></style>

View File

@ -11,8 +11,8 @@
<div class="tc">
<h3>{{ year }}年度安全培训教育管理台账</h3>
</div>
<p class="mb">单位名称:{{ name }}</p>
<layout-table :data="data.list" :show-pagination="false">
<p class="mb">单位名称:{{ corpName }}</p>
<layout-table :data="list" :show-pagination="false">
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="TRAINING_DATE" label="培训时间" />
<el-table-column prop="TRAINING_OBJECT" label="培训对象" />
@ -27,9 +27,7 @@
<el-table-column prop="TRAINING_CONTENT" label="培训内容" />
<el-table-column prop="PERSON_NUMBER" label="参加人数" />
<el-table-column prop="CLASS_HOURS" label="培训学时" />
<el-table-column prop="TRAINING_PLACE" label="培训地点">
<span>{{ name }}</span>
</el-table-column>
<el-table-column prop="CORP_NAME" label="培训地点" />
<el-table-column prop="TRAINING_TEACHERS" label="培训教师" />
<el-table-column prop="ASSESSMENT_METHOD" label="考核方式">
<span>线上考核</span>
@ -60,13 +58,14 @@
<script setup>
import LayoutTable from "@/components/table/index";
import { reactive, watchEffect } from "vue";
import { watchEffect } from "vue";
import { ElMessageBox } from "element-plus";
import { debounce } from "throttle-debounce";
import {
getArchivesManagerList,
downloadEdumanageword,
} from "@/request/training_archive_management.js";
import useListData from "@/assets/js/useListData.js";
const props = defineProps({
type: {
@ -77,11 +76,7 @@ const props = defineProps({
type: String,
required: true,
},
CORPINFO_ID: {
type: String,
required: true,
},
name: {
corpName: {
type: String,
required: true,
},
@ -90,19 +85,15 @@ const props = defineProps({
required: true,
},
});
const data = reactive({
list: [],
});
const emits = defineEmits(["update:type"]);
const fnGetData = async () => {
const resData = await getArchivesManagerList({
const { list, fnGetData } = useListData(getArchivesManagerList, {
otherParams: {
TYPE: props.type,
CORPINFO_ID: props.CORPINFO_ID,
YEAR: props.year,
});
data.list = resData.varList;
};
},
usePagination: false,
immediate: false,
});
watchEffect(() => {
if (props.type === 104) fnGetData();
});
@ -112,8 +103,7 @@ const fnExport = debounce(
await ElMessageBox.confirm("确定要导出吗?", { type: "warning" });
await downloadEdumanageword({
YEAR: props.year,
CORPINFO_ID: props.CORPINFO_ID,
NAME: props.name,
NAME: props.corpName,
});
await ElMessageBox.confirm(
"导出后请前往档案下载中下载该档案!",

View File

@ -7,15 +7,13 @@
>
<div class="tr">
<el-button type="primary" @click="fnExport"></el-button>
<el-button type="primary" @click="data.dialogForFile = true"
>上传文件</el-button
>
<el-button type="primary" @click="fnImport"></el-button>
</div>
<div class="tc">
<h3>{{ year }}年度安全培训教育计划</h3>
</div>
<p class="mb">单位名称:{{ name }}</p>
<layout-table :data="data.list" :show-pagination="false">
<p class="mb">单位名称:{{ corpName }}</p>
<layout-table :data="list" :show-pagination="false">
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="START_TIME" label="开始时间" />
<el-table-column prop="END_TIME" label="结束时间" />
@ -28,9 +26,7 @@
<span>线上考核</span>
</el-table-column>
<el-table-column prop="CLASSHOUR" label="学时" />
<el-table-column prop="PLACE" label="地点">
<span>{{ name }}</span>
</el-table-column>
<el-table-column prop="CORP_NAME" label="地点" />
<el-table-column prop="TRAINING_TEACHERS" label="培训教师" />
<el-table-column prop="FUND_GUARANTEE" label="经费保障">
<span>安全生产投入</span>
@ -43,28 +39,9 @@
<div>档案管理人员:</div>
<div>更新日期:</div>
</div>
<template #footer>
<el-button @click="fnClose"></el-button>
</template>
<el-dialog
v-model:visible="data.dialogForFile"
:title="'安全培训教育计划'"
top="50px"
width="1200px"
append-to-body
>
<file
v-if="data.dialogForFile"
:id="CORPINFO_ID"
:year="year"
:type="103"
/>
<template #footer>
<el-button @click="data.dialogForFile = false">关闭</el-button>
</template>
</el-dialog>
<template #footer> <el-button @click="fnClose"></el-button> </template>
<pdf
v-if="data.dialogForFile"
v-model:visible="data.dialogForFile.visible"
:title="'安全培训教育计划'"
:type="103"
:year="year"
@ -82,6 +59,7 @@ import {
downloadTrainingplanword,
} from "@/request/training_archive_management.js";
import Pdf from "./pdf.vue";
import useListData from "@/assets/js/useListData.js";
const props = defineProps({
type: {
@ -92,11 +70,7 @@ const props = defineProps({
type: String,
required: true,
},
id: {
type: String,
required: true,
},
name: {
corpName: {
type: String,
required: true,
},
@ -106,19 +80,16 @@ const props = defineProps({
},
});
const data = reactive({
list: [],
dialogForFile: false,
dialogForFile: {
visible: false,
},
});
const emits = defineEmits(["update:type"]);
const fnGetData = async () => {
const resData = await getArchivesPlanList({
TYPE: props.type,
CORPINFO_ID: props.CORPINFO_ID,
ENTERPRISE_ID: props.ENTERPRISE_ID,
YEAR: props.year,
});
data.list = resData.varList;
};
const { list, fnGetData } = useListData(getArchivesPlanList, {
otherParams: { TYPE: props.type, YEAR: props.year },
usePagination: false,
immediate: false,
});
watchEffect(() => {
if (props.type === 103) fnGetData();
});
@ -128,8 +99,6 @@ const fnExport = debounce(
await ElMessageBox.confirm("确定要导出吗?", { type: "warning" });
await downloadTrainingplanword({
YEAR: props.year,
CORPINFO_ID: props.CORPINFO_ID,
ENTERPRISE_ID: props.ENTERPRISE_ID,
NAME: props.name,
});
await ElMessageBox.confirm(
@ -140,6 +109,9 @@ const fnExport = debounce(
},
{ atBegin: true }
);
const fnImport = () => {
data.dialogForFile.visible = !data.dialogForFile.visible;
};
const fnClose = () => {
emits("update:type", 0);
};

View File

@ -1,17 +1,30 @@
<template>
<el-dialog
v-model="visible"
:title="title"
:model-value="
type === 1 || type === 2 || type === 3 || type === 4 || type === 103
type === 1 || type === 2 || type === 3 || type === 4 || visible
"
width="1100px"
@close="fnClose"
>
<div>
<layout-upload
:file-list="[]"
auto-upload
:http-request="fnUpload"
accept=".pdf"
:show-file-list="false"
:limit="999"
>
<template #tip>只能上传pdf文件</template>
</layout-upload>
</div>
<div class="content-flex">
<div class="content-left">
<el-scrollbar style="height: 600px">
<layout-table
:data="data.list"
:data="list"
:show-header="false"
:show-pagination="false"
:border="false"
@ -20,16 +33,26 @@
@row-click="fnRowClick"
>
<el-table-column prop="FILE_NAME" />
<el-table-column label="操作">
<template #default="{ row }">
<el-button type="primary" text link @click.stop="fnDelete(row)">
<el-icon color="red" class="mr-10">
<delete />
</el-icon>
删除
</el-button>
</template>
</el-table-column>
</layout-table>
</el-scrollbar>
</div>
<div class="content-right">
<div v-if="!data.pdfSrc" class="content-tip">
<div v-if="!pdfSrc" class="content-tip">
<div class="box">
<div class="icon">
<icon-file-pdf-one
theme="filled"
size="60"
size="50"
fill="#fff"
:stroke-width="3"
/>
@ -40,16 +63,7 @@
</div>
</div>
</div>
<el-scrollbar style="height: 600px">
<div v-if="data.pdfSrc">
<vue-pdf
v-for="page in data.numOfPages"
:key="page"
:src="data.pdfSrc"
:page="page"
/>
</div>
</el-scrollbar>
<layout-pdf v-if="pdfSrc" :src="pdfSrc" model="normal" />
</div>
</div>
<template #footer>
@ -59,13 +73,26 @@
</template>
<script setup>
import LayoutTable from "@/components/table/index";
import { nextTick, reactive, watchEffect } from "vue";
import { VuePdf, createLoadingTask } from "vue3-pdfjs/esm";
import { getArchivesfilesList } from "@/request/training_archive_management.js";
import {
getArchivesFilesList,
setArchivesFilesDelete,
setArchivesFilesUpload,
} from "@/request/training_archive_management.js";
import LayoutUpload from "@/components/upload/index.vue";
import LayoutPdf from "@/components/pdf/index.vue";
import { ref, watchEffect } from "vue";
import { Delete } from "@element-plus/icons-vue";
import useListData from "@/assets/js/useListData.js";
import { debounce } from "throttle-debounce";
import { ElMessage, ElMessageBox } from "element-plus";
import { useVModels } from "@vueuse/core";
const FILE_URL = import.meta.env.VITE_FILE_URL;
const props = defineProps({
visible: {
type: Boolean,
required: false,
default: false,
},
type: {
type: Number,
required: true,
@ -74,7 +101,7 @@ const props = defineProps({
type: String,
required: true,
},
CORPINFO_ID: {
corpName: {
type: String,
required: true,
},
@ -83,21 +110,14 @@ const props = defineProps({
required: true,
},
});
const data = reactive({
list: [],
pdfSrc: "",
numOfPages: 0,
const emits = defineEmits(["update:visible", "update:type"]);
const { visible } = useVModels(props, emits);
const pdfSrc = ref("");
const { list, fnGetData } = useListData(getArchivesFilesList, {
otherParams: { TYPE: props.type, YEAR: props.year },
usePagination: false,
immediate: false,
});
const emits = defineEmits(["update:type"]);
const fnGetData = async () => {
const resData = await getArchivesfilesList({
TYPE: props.type,
YEAR: props.year,
CORPINFO_ID: props.CORPINFO_ID,
MODULE: "corp",
});
data.list = resData.varList;
};
watchEffect(() => {
if (
props.type === 1 ||
@ -106,21 +126,38 @@ watchEffect(() => {
props.type === 4 ||
props.type === 103
)
fnGetData();
fnGetData({ TYPE: props.type, YEAR: props.year });
});
const fnUpload = async (item) => {
const formData = new FormData();
formData.append("FFILE", item.file);
formData.append("TYPE", props.type);
formData.append("YEAR", props.year);
await setArchivesFilesUpload(formData);
fnGetData({ TYPE: props.type, YEAR: props.year });
};
const fnDelete = debounce(
1000,
async ({ ARCHIVESFILES_ID, FILE_PATH }) => {
await ElMessageBox.confirm("确定要删除吗?", {
type: "warning",
});
await setArchivesFilesDelete({
ARCHIVESFILES_ID,
FILE_PATH,
});
ElMessage.success("删除成功");
fnGetData({ TYPE: props.type, YEAR: props.year });
},
{ atBegin: true }
);
const fnRowClick = async (row) => {
data.pdfSrc = "";
await nextTick();
data.pdfSrc = FILE_URL + row.FILE_PATH;
const loadingTask = createLoadingTask(FILE_URL + row.FILE_PATH);
loadingTask.promise.then((pdf) => {
data.numOfPages = pdf.numPages;
});
pdfSrc.value = row.FILE_PATH;
};
const fnClose = () => {
data.pdfSrc = "";
data.numOfPages = 0;
pdfSrc.value = "";
emits("update:type", 0);
visible.value = false;
};
</script>

View File

@ -6,13 +6,23 @@
@close="fnClose"
>
<div class="tr">
<el-button type="primary" @click="list.push({})"></el-button>
<el-button type="danger" @click="fnDelete"></el-button>
<el-button type="primary" @click="fnImport"></el-button>
<el-button type="primary" @click="fnExport"></el-button>
</div>
<div class="tc">
<h3>{{ year }}年度三岗人员管理台账</h3>
</div>
<p class="mb">单位名称:{{ name }}</p>
<layout-table :data="data.list" :show-pagination="false">
<p class="mb">单位名称:{{ corpName }}</p>
<layout-table
:data="list"
:show-pagination="false"
:stripe="false"
:highlight-current-row="true"
@row-click="fnRowClick"
@row-dblclick="fnRowDblclick"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="NAME" label="姓名" />
<el-table-column prop="POST" label="岗位/操作项目" />
@ -30,12 +40,31 @@
<el-table-column prop="CARD_ID" label="证书号" />
<el-table-column prop="EFFECTIVE_DATE" label="证书有效期限" />
<el-table-column prop="RETRAINING" label="复训日期" />
<el-table-column prop="RETRAINING" label="操作" align="center">
<template #default="{ row }">
<el-button type="primary" @click="handleEdit(row)"></el-button>
</template>
</el-table-column>
</layout-table>
<table class="print_use dn">
<thead>
<tr>
<td>序号</td>
<td>姓名</td>
<td>岗位/操作项目</td>
<td>电话</td>
<td>证书号</td>
<td>证书有效期限</td>
<td>复训日期</td>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in list" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ item.NAME }}</td>
<td>{{ item.POST }}</td>
<td>{{ item.PHONE }}</td>
<td>{{ item.CARD_ID }}</td>
<td>{{ item.EFFECTIVE_DATE }}</td>
<td>{{ item.RETRAINING }}</td>
</tr>
</tbody>
</table>
<div class="flex mt">
<div>档案管理人员:</div>
<div>更新日期:</div>
@ -43,18 +72,36 @@
<template #footer>
<el-button @click="fnClose"></el-button>
</template>
<postman-add
v-model:visible="data.addOrEditDialog.visible"
v-model:form="data.addOrEditDialog.form"
:type="data.addOrEditDialog.type"
:year="year"
@get-data="fnGetData"
/>
<layout-import-file
v-model:visible="data.importDialogVisible"
template-url="/TrafficFile/template/post.xls"
@submit="fnSubmitImport"
/>
</el-dialog>
</template>
<script setup>
import LayoutTable from "@/components/table/index";
import { reactive, watchEffect } from "vue";
import { ElMessageBox } from "element-plus";
import { nextTick, reactive, watchEffect } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { debounce } from "throttle-debounce";
import {
getArchivesPostmanList,
downloadPersonmanage,
getPostmanView,
setPostmanDelete,
setPostmanImport,
} from "@/request/training_archive_management.js";
import PostmanAdd from "./postman_add.vue";
import LayoutImportFile from "@/components/import_file/index.vue";
import useListData from "@/assets/js/useListData.js";
const FILE_URL = import.meta.env.VITE_FILE_URL;
const props = defineProps({
@ -66,31 +113,37 @@ const props = defineProps({
type: String,
required: true,
},
CORPINFO_ID: {
type: String,
required: true,
},
year: {
type: String,
required: true,
},
name: {
corpName: {
type: String,
required: true,
},
});
const data = reactive({
list: [],
importDialogVisible: false,
ARCHIVES_POSTMAN_ID: "",
addOrEditDialog: {
visible: false,
type: "",
form: {
NAME: "",
POST: "",
PHONE: "",
CARD_ID: "",
EFFECTIVE_DATE: "",
RETRAINING: "",
},
},
});
const emits = defineEmits(["update:type"]);
const fnGetData = async () => {
const resData = await getArchivesPostmanList({
TYPE: props.type,
CORPINFO_ID: props.CORPINFO_ID,
YEAR: props.year,
});
data.list = resData.varList;
};
const { list, fnGetData } = useListData(getArchivesPostmanList, {
otherParams: { TYPE: props.type, YEAR: props.year },
usePagination: false,
immediate: false,
});
watchEffect(() => {
if (props.type === 101) fnGetData();
});
@ -100,8 +153,7 @@ const fnExport = debounce(
await ElMessageBox.confirm("确定要导出吗?", { type: "warning" });
await downloadPersonmanage({
YEAR: props.year,
CORPINFO_ID: props.CORPINFO_ID,
NAME: props.name,
NAME: props.corpName,
});
await ElMessageBox.confirm(
"导出后请前往档案下载中下载该档案!",
@ -111,6 +163,42 @@ const fnExport = debounce(
},
{ atBegin: true }
);
const fnRowClick = (row) => {
data.ARCHIVES_POSTMAN_ID = row.ARCHIVES_POSTMAN_ID;
};
const fnRowDblclick = async (row) => {
data.addOrEditDialog.visible = true;
await nextTick();
if (row.ARCHIVES_POSTMAN_ID) {
const resData = await getPostmanView({
ARCHIVES_POSTMAN_ID: row.ARCHIVES_POSTMAN_ID,
});
data.addOrEditDialog.form = resData.pd;
data.addOrEditDialog.type = "edit";
} else data.addOrEditDialog.type = "add";
};
const fnDelete = debounce(
1000,
async () => {
if (data.ARCHIVES_POSTMAN_ID) {
await ElMessageBox.confirm("确定要删除吗?", { type: "warning" });
await setPostmanDelete({
ARCHIVES_POSTMAN_ID: data.ARCHIVES_POSTMAN_ID,
});
ElMessage.success("删除成功");
}
data.ARCHIVES_POSTMAN_ID = "";
fnGetData();
},
{ atBegin: true }
);
const fnImport = () => {
data.importDialogVisible = !data.importDialogVisible;
};
const fnSubmitImport = async (formData) => {
const resData = await setPostmanImport(formData);
ElMessage.success(resData.msg);
};
const fnClose = () => {
emits("update:type", 0);
};

View File

@ -0,0 +1,141 @@
<template>
<el-dialog
v-model="visible"
:append-to-body="true"
:title="type === 'edit' ? '修改' : '新增'"
:on-close="fnClose"
>
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="姓名" prop="NAME">
<el-input v-model="form.NAME" />
</el-form-item>
<el-form-item label="岗位/操作项目" prop="POST">
<el-input v-model="form.POST" />
</el-form-item>
<el-form-item label="手机号" prop="PHONE">
<el-input v-model="form.PHONE" />
</el-form-item>
<el-form-item label="照片" prop="hideUpload">
<layout-upload
v-model:file-list="form.hideUpload"
accept=".jpg,.jpeg,.png"
list-type="picture-card"
:limit="1"
delete-to-server
/>
</el-form-item>
<el-form-item label="证书号" prop="CARD_ID">
<el-input v-model="form.CARD_ID" />
</el-form-item>
<el-form-item label="证书有效期限" prop="EFFECTIVE_DATE">
<el-date-picker
v-model="form.EFFECTIVE_DATE"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
type="date"
/>
</el-form-item>
<el-form-item label="复训日期" prop="RETRAINING">
<el-date-picker
v-model="form.RETRAINING"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
type="date"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="fnClose"></el-button>
<el-button type="primary" @click="fnSubmit"></el-button>
</template>
</el-dialog>
</template>
<script setup>
import { useVModels } from "@vueuse/core";
import { ref } from "vue";
import { debounce } from "throttle-debounce";
import useFormValidate from "@/assets/js/useFormValidate.js";
import {
setPostmanAdd,
setPostmanEdit,
} from "@/request/training_archive_management.js";
import { ElMessage } from "element-plus";
import LayoutUpload from "@/components/upload/index.vue";
const props = defineProps({
visible: {
type: Boolean,
required: true,
default: false,
},
form: {
type: Object,
required: true,
default: () => ({}),
},
type: {
type: String,
required: true,
default: "",
},
year: {
type: String,
required: true,
default: "",
},
});
const emits = defineEmits(["update:visible", "update:form", "get-data"]);
const { visible, form } = useVModels(props, emits);
const rules = {
NAME: [{ required: true, message: "姓名不能为空", trigger: "blur" }],
POST: [{ required: true, message: "岗位/操作项目不能为空", trigger: "blur" }],
PHONE: [
{ required: true, message: "手机号不能为空", trigger: "blur" },
{
pattern:
/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
message: "请输入正确的手机号",
trigger: "blur",
},
],
hideUpload: [{ required: true, message: "照片不能为空", trigger: "blur" }],
CARD_ID: [{ required: true, message: "证书号不能为空", trigger: "blur" }],
EFFECTIVE_DATE: [
{ required: true, message: "请选择证书有效期限", trigger: "change" },
],
RETRAINING: [
{ required: true, message: "请选择复训日期", trigger: "change" },
],
};
const formRef = ref(null);
const fnClose = () => {
formRef.value.resetFields();
visible.value = false;
};
const fnSubmit = debounce(
1000,
async () => {
await useFormValidate(formRef);
const formData = new FormData();
Object.keys(props.form).forEach((key) => {
formData.append(key, props.form[key]);
});
if (props.form.hideUpload[0].raw) {
formData.append("FFILE", props.form.hideUpload[0].raw);
}
formData.append("YEAR", props.year);
props.type === "add"
? await setPostmanAdd(formData)
: await setPostmanEdit(formData);
ElMessage.success("操作成功");
fnClose();
emits("get-data");
},
{
atBegin: true,
}
);
</script>
<style scoped lang="scss"></style>

View File

@ -11,8 +11,8 @@
<div class="tc">
<h3>{{ year }}年度本单位师资管理台账</h3>
</div>
<p class="mb">单位名称:{{ name }}</p>
<layout-table :data="data.list" :show-pagination="false">
<p class="mb">单位名称:{{ corpName }}</p>
<layout-table :data="list" :show-pagination="false">
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="NAME" label="姓名" />
<el-table-column prop="WORKYEAR" label="从事本专业工作年限" />
@ -37,13 +37,14 @@
<script setup>
import LayoutTable from "@/components/table/index";
import { reactive, watchEffect } from "vue";
import { watchEffect } from "vue";
import { ElMessageBox } from "element-plus";
import { debounce } from "throttle-debounce";
import {
getArchivesTeacherList,
downloadTeacherword,
} from "@/request/training_archive_management.js";
import useListData from "@/assets/js/useListData.js";
const props = defineProps({
type: {
@ -54,11 +55,7 @@ const props = defineProps({
type: String,
required: true,
},
CORPINFO_ID: {
type: String,
required: true,
},
name: {
corpName: {
type: String,
required: true,
},
@ -67,18 +64,12 @@ const props = defineProps({
required: true,
},
});
const data = reactive({
list: [],
});
const emits = defineEmits(["update:type"]);
const fnGetData = async () => {
const resData = await getArchivesTeacherList({
TYPE: props.type,
CORPINFO_ID: props.CORPINFO_ID,
YEAR: props.year,
});
data.list = resData.varList;
};
const { list, fnGetData } = useListData(getArchivesTeacherList, {
otherParams: { TYPE: props.type, YEAR: props.year },
usePagination: false,
immediate: false,
});
watchEffect(() => {
if (props.type === 102) fnGetData();
});
@ -88,8 +79,7 @@ const fnExport = debounce(
await ElMessageBox.confirm("确定要导出吗?", { type: "warning" });
await downloadTeacherword({
YEAR: props.year,
CORPINFO_ID: props.CORPINFO_ID,
NAME: props.name,
NAME: props.corpName,
});
await ElMessageBox.confirm(
"导出后请前往档案下载中下载该档案!",

View File

@ -11,7 +11,7 @@
<div id="printContent">
<h2 class="tc">学员考核成绩统计表</h2>
<div class="flex mt mb">
<span>平台名称:{{ data.info.CORPINFO_NAME }}</span>
<span>平台名称:{{ corpName }}</span>
<span
>报表日期:{{ dayjs(data.clazz.END_TIME).format("YYYY-MM-DD") }}</span
>
@ -21,7 +21,7 @@
<td colspan="2">公司名称</td>
</tr>
<tr>
<td colspan="2">{{ data.clazz.CORP_INFO }}</td>
<td colspan="2">{{ corpName }}</td>
</tr>
<tr>
<td>培训时间</td>
@ -173,6 +173,10 @@ const props = defineProps({
type: String,
required: true,
},
corpName: {
type: String,
required: true,
},
});
const data = reactive({
info: {},

View File

@ -9,9 +9,9 @@
<el-button type="primary" @click="fnExport"></el-button>
</div>
<div class="tc">
<h3>{{ CORP_NAME }}培训计划</h3>
<h3>{{ corpName }}培训计划</h3>
</div>
<p class="mb">单位名称:{{ CORP_INFO }}</p>
<p class="mb">单位名称:{{ corpName }}</p>
<layout-table :data="data.list" :show-pagination="false">
<el-table-column type="index" label="序号" width="50" />
<el-table-column label="培训人员类型"> 从业人员 </el-table-column>
@ -33,7 +33,7 @@
<el-table-column prop="TRAINING_TEACHERS" label="授课教师" />
</layout-table>
<div class="flex mt">
<div>编制单位:{{ CORP_NAME }}</div>
<div>编制单位:{{ corpName }}</div>
<div>编制日期:</div>
</div>
<template #footer>

View File

@ -6,15 +6,15 @@
</div>
<layout-table
ref="tableRef"
v-model:pagination="data.pagination"
v-model:pagination="pagination"
row-key="CURRICULUM_ID"
:data="data.varlist"
:data="list"
@get-data="fnGetData"
>
<el-table-column reserve-selection type="selection" width="55" />
<el-table-column label="序号" width="60">
<template #default="{ $index }">
{{ serialNumber(data.pagination, $index) }}
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column prop="CURRICULUMNAME" label="教材名称" />
@ -50,17 +50,12 @@ import {
getClassCurriculumList,
downloadTeachingMaterialAll,
} from "@/request/training_archive_management.js";
import useListData from "@/assets/js/useListData.js";
const route = useRoute();
const { CLASS_ID } = route.query;
const tableRef = ref(null);
const data = reactive({
varlist: [],
pagination: {
currentPage: 1,
pageSize: 10,
total: 0,
},
type: 0,
CURRICULUM_ID: "",
});
@ -68,16 +63,9 @@ const fnView = (row) => {
data.type = 106;
data.CURRICULUM_ID = row.CURRICULUM_ID;
};
const fnGetData = async () => {
const resData = await getClassCurriculumList({
currentPage: data.pagination.currentPage,
pageSize: data.pagination.pageSize,
CLASS_ID,
});
data.varlist = resData.varList;
data.pagination.total = resData.page.totalResult;
};
fnGetData();
const { list, pagination, fnGetData } = useListData(getClassCurriculumList, {
otherParams: { CLASS_ID },
});
const fnExport = debounce(
1000,
async () => {

View File

@ -2,14 +2,14 @@
<div>
<el-card>
<el-form
:model="data.searchForm"
:model="searchForm"
label-width="80px"
@submit.prevent="fnResetPagination"
>
<el-row>
<el-col :span="6">
<el-form-item label="试卷名称" prop="KEYWORDS">
<el-input v-model="data.searchForm.KEYWORDS" />
<el-input v-model="searchForm.KEYWORDS" />
</el-form-item>
</el-col>
<el-col :span="6">
@ -18,10 +18,7 @@
<el-button native-type="reset" @click="fnResetPagination">
重置
</el-button>
<el-button
v-if="data.varlist.length > 0"
type="primary"
@click="fnExport"
<el-button v-if="list.length > 0" type="primary" @click="fnExport"
>导出</el-button
>
</el-form-item>
@ -30,15 +27,15 @@
</el-form>
<layout-table
ref="tableRef"
v-model:pagination="data.pagination"
v-model:pagination="pagination"
row-key="STAGEEXAMPAPERINPUT_ID"
:data="data.varlist"
:data="list"
@get-data="fnGetData"
>
<el-table-column reserve-selection type="selection" width="55" />
<el-table-column label="序号" width="60">
<template #default="{ $index }">
{{ serialNumber(data.pagination, $index) }}
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column prop="EXAMNAME" label="试卷名称" />
@ -78,18 +75,12 @@ import {
getClassPaperList,
downloadArchivePapers,
} from "@/request/training_archive_management.js";
import useListData from "@/assets/js/useListData.js";
const route = useRoute();
const { CLASS_ID, CLASS_NAME } = route.query;
const tableRef = ref(null);
const data = reactive({
varlist: [],
pagination: {
currentPage: 1,
pageSize: 10,
total: 0,
},
searchForm: {},
type: 0,
STAGEEXAMPAPERINPUT_ID: "",
});
@ -97,26 +88,8 @@ const fnView = (STAGEEXAMPAPERINPUT_ID) => {
data.type = 103;
data.STAGEEXAMPAPERINPUT_ID = STAGEEXAMPAPERINPUT_ID;
};
const fnGetData = async () => {
const resData = await getClassPaperList({
currentPage: data.pagination.currentPage,
pageSize: data.pagination.pageSize,
CLASS_ID,
...data.searchForm,
});
data.varlist = resData.varList;
data.pagination.total = resData.page.totalResult;
};
fnGetData();
const fnResetPagination = () => {
data.pagination = {
currentPage: 1,
pageSize: 10,
total: 0,
};
tableRef.value.clearSelection();
fnGetData();
};
const { list, pagination, searchForm, fnGetData, fnResetPagination } =
useListData(getClassPaperList, { otherParams: { CLASS_ID } });
const fnExport = debounce(
1000,
async () => {

View File

@ -15,7 +15,7 @@
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-col :span="4">
<el-form-item label-width="10px">
<el-button type="primary" native-type="submit">搜索</el-button>
<el-button native-type="reset" @click="fnResetPagination">
@ -23,6 +23,14 @@
</el-button>
</el-form-item>
</el-col>
<el-form-item label-width="10px">
<el-button type="primary" @click="fnBatchDownload">
下载补充档案
</el-button>
</el-form-item>
<el-form-item label-width="10px">
<el-button type="primary"> 班级档案 </el-button>
</el-form-item>
</el-row>
</el-form>
</el-card>
@ -83,12 +91,42 @@ import { serialNumber } from "@/assets/js/utils.js";
import useListData from "@/assets/js/useListData.js";
import { ref } from "vue";
import { getStudentsList } from "@/request/training_archive_management.js";
import {
downloadAward,
getStudentsList,
} from "@/request/training_archive_management.js";
import router from "@/router/index.js";
import { ElMessage, ElMessageBox } from "element-plus";
import { debounce } from "throttle-debounce";
const tableRef = ref(null);
const { list, pagination, searchForm, fnGetData, fnResetPagination } =
useListData(getStudentsList);
</script>
const fnBatchDownload = debounce(
1000,
async () => {
const selectionData = tableRef.value.getSelectionRows();
if (selectionData.length === 0) {
ElMessage.warning("请选中要下载的学员补充档案...");
return;
}
const ids = selectionData
.map((item) => {
return item.USER_ID;
})
.join(",");
await downloadAward({
ids,
});
await ElMessageBox.confirm(
"导出后请前往档案下载中下载该档案!",
"温馨提示",
{ type: "info" }
);
tableRef.value.clearSelection();
},
{ atBegin: true }
);
</script>
<style scoped></style>

View File

@ -0,0 +1,211 @@
<template>
<el-dialog v-model="visible" width="1100px" title="效果评估表">
<div class="tr mb">
<el-button type="primary" @click="fnExport"></el-button>
</div>
<div id="printContent">
<h1 style="text-align: center; margin-left: 60px">
安全生产教育培训动态评估报告
</h1>
<p class="p1" style="width: 100%; text-align: center">
企业名称:
{{ data.evaluationDialogForm.CORP_NAME }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
评估日期:
{{ data.evaluationDialogForm.END_TIME }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</p>
<h3>评估概述</h3>
<p class="p1">
本报告旨在对{{ data.evaluationDialogForm.CORP_NAME }}公司
的安全生产培训进行动态评估安全生产培训的目标是提高员工的安全意识和技能促进工作场所的安全管理和事故预防本报告将对培训的实施情况培训效果参与度员工考试通过率知识盲点以及可能的改进措施进行评估和分析
</p>
<h3>评估内容</h3>
<p class="p1">
贵公司于{{ data.evaluationDialogForm.START_TIME }}时间 -
{{ data.evaluationDialogForm.END_TIME }}时间进行了{{
data.evaluationDialogForm.CLASS_NAME
}}培训培训内容如下{{ data.evaluationDialogForm.coursewareName }}
</p>
<h3>考试结果</h3>
<p class="p1">
<b
>本次考试共{{
data.evaluationDialogForm.EXMA_COUNT
}}人参加合格人数{{
data.evaluationDialogForm.PASS_COUNT
}}未合格人数{{
data.evaluationDialogForm.NO_PASS_COUNT
}}通过率{{
data.evaluationDialogForm.passRate
}}%具体情况如下</b
>
</p>
<div id="chart" ref="chart" style="width: 900px; height: 320px" />
<p class="p1"><b>评估结果和分析</b></p>
<p class="p1">
基于评估结果和培训过程中的观察我们对员工的知识盲点进行分析指出可能存在的理解不足或需要加强的知识领域主要知识盲点体现为
</p>
<p class="p1">{{ data.evaluationDialogForm.error }}</p>
<table class="table">
<tr>
<td>标签名称</td>
<td>错误率</td>
</tr>
<tr
v-for="(value, key) in data.evaluationDialogForm.ratioMap"
:key="key"
>
<td>{{ key }}</td>
<td>{{ value }}%</td>
</tr>
</table>
<p class="p1">知识盲点对应课件为</p>
<p class="p1">{{ data.evaluationDialogForm.errorVideoName }}</p>
<p class="p1"><b>评估建议</b></p>
<p class="p1">
存在的知识盲点需要进一步加强和补充我们建议您将重点放在弥补这些盲点上通过进一步学习参与讨论或与安全专家交流弥补知识盲区
</p>
<h3>强化培训记录</h3>
<p class="p1"><b>强化培训考试记录</b></p>
<table class="table">
<tr>
<td colspan="3">班级名称</td>
<td colspan="3">培训时间</td>
</tr>
<tr>
<td colspan="3">{{ data.evaluationDialogForm.CLASS_NAME }}</td>
<td colspan="3">
{{
dayjs(data.evaluationDialogForm.START_TIME).format(
"YYYY年MM月DD日"
)
}}
-
{{
dayjs(data.evaluationDialogForm.END_TIME).format("YYYY年MM月DD日")
}}
</td>
</tr>
<tr>
<td colspan="3">培训人数</td>
<td colspan="3">合格人数</td>
</tr>
<tr>
<td colspan="3">{{ data.evaluationDialogForm.STR_EXMA_COUNT }}</td>
<td colspan="3">{{ data.evaluationDialogForm.STR_PASS_COUNT }}</td>
</tr>
<tr>
<td colspan="6">合格学员名单</td>
</tr>
<tr>
<td style="width: 10%">序号</td>
<td style="width: 15%">姓名</td>
<td style="width: 25%">身份证号</td>
<td style="width: 20%">手机号</td>
<td style="width: 10%">性别</td>
<td style="width: 25%">效果评估成绩</td>
</tr>
<tr
v-for="(value, key) in data.evaluationDialogForm.PASS_List"
:key="key"
>
<td style="width: 10%">{{ key + 1 }}</td>
<td style="width: 15%">{{ value.NAME }}</td>
<td style="width: 25%">{{ value.USER_ID_CARD }}</td>
<td style="width: 20%">{{ value.PHONE }}</td>
<td style="width: 10%">{{ value.SEX }}</td>
<td style="width: 25%">{{ value.STRENGTHENEXAMSCORE }}</td>
</tr>
<tr>
<td colspan="6">未合格学员名单</td>
</tr>
<tr>
<td style="width: 10%">序号</td>
<td style="width: 15%">姓名</td>
<td style="width: 25%">身份证号</td>
<td style="width: 20%">手机号</td>
<td style="width: 10%">性别</td>
<td style="width: 25%">效果评估成绩</td>
</tr>
<tr
v-for="(value, key) in data.evaluationDialogForm.NO_PASS_List"
:key="key"
>
<td style="width: 10%">{{ key + 1 }}</td>
<td style="width: 15%">{{ value.NAME }}</td>
<td style="width: 25%">{{ value.USER_ID_CARD }}</td>
<td style="width: 20%">{{ value.PHONE }}</td>
<td style="width: 10%">{{ value.SEX }}</td>
<td style="width: 25%">{{ value.STRENGTHENEXAMSCORE }}</td>
</tr>
</table>
</div>
<template #footer>
<el-button @click="visible = false">关闭</el-button>
</template>
</el-dialog>
</template>
<script setup>
import { reactive, watchEffect } from "vue";
import { ElMessageBox } from "element-plus";
import { getClassEvaluation } from "@/request/training_archive_management.js";
import { useVModel } from "@vueuse/core";
import dayjs from "dayjs";
const props = defineProps({
classId: {
type: String,
required: true,
},
visible: {
type: Boolean,
default: false,
},
});
const visible = useVModel(props, "visible");
const data = reactive({
evaluationDialogForm: {},
count1: "",
count2: "",
count3: "",
});
const fnGetData = async () => {
const resData = await getClassEvaluation({
CLASS_ID: props.classId,
});
data.evaluationDialogForm = resData.pageData;
data.count1 = data.pageData.count1;
data.count2 = data.pageData.count2;
data.count3 = data.pageData.count3;
};
const fnExport = async () => {
await ElMessageBox.confirm("确定要导出吗?", { type: "warning" });
window.location.href =
import.meta.env[import.meta.env.DEV ? "VITE_PROXY" : "VITE_BASE_URL"] +
"class/hs?CLASS_ID=" +
props.classId;
};
watchEffect(() => {
if (visible.value) fnGetData();
});
</script>
<style scoped lang="scss">
.flex {
display: flex;
align-items: center;
justify-content: space-between;
}
table {
width: 100%;
border-collapse: collapse;
td {
border: 1px solid var(--el-border-color);
padding: 8px;
font-size: 14px;
text-align: center;
}
}
</style>

View File

@ -0,0 +1,283 @@
<template>
<el-dialog v-model="visible" width="1100px" title="效果评估表">
<div class="tr mb">
<el-button type="primary" @click="fnExport"></el-button>
</div>
<div id="printContent">
<h1 style="text-align: center; margin-left: 60px">
安全生产教育培训动态评估报告
</h1>
<p class="p1" style="width: 100%; text-align: center">
姓名: {{ data.evaluationDialogForm.NAME }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
身份证号:
{{
data.evaluationDialogForm.USER_ID_CARD
}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 评估日期:
{{ data.evaluationDialogForm.OPERATTIME }}
</p>
<h3>评估概述</h3>
<p class="p1">
本报告旨在评估您在最近接受的安全培训中的个人效果并提供课程考试结果以及指出可能存在的知识盲点安全培训的目标是提高您在工作环境中的安全意识和行为以减少事故和伤害的发生本报告将对您的培训参与度知识掌握程度课程考试成绩以及可能存在的知识盲点进行评估
</p>
<h3>学员基本情况</h3>
<table
align="center"
border="1"
cellspacing="0"
width="100%"
class="table"
>
<tr>
<td style="width: 70px">姓名</td>
<td style="width: 60px">{{ data.evaluationDialogForm.NAME }}</td>
<td style="width: 55px">性别</td>
<td style="width: 80px">{{ data.evaluationDialogForm.SEX }}</td>
<td style="width: 60px">身份证号</td>
<td style="width: 150px">
{{ data.evaluationDialogForm.USER_ID_CARD }}
</td>
<td style="width: 60px">学历</td>
<td style="width: 200px">
{{ data.evaluationDialogForm.DEGREE_OF_EDUCATION }}
</td>
<td style="width: 60px">专业</td>
<td>{{ data.evaluationDialogForm.MAJOR }}</td>
</tr>
<tr>
<td>职务/职称</td>
<td>{{ data.evaluationDialogForm.DUTIES }}</td>
<td>部门</td>
<td>{{ data.evaluationDialogForm.DEPARTMENT_NAME }}</td>
<td>工种</td>
<td>{{ data.evaluationDialogForm.POST_NAME }}</td>
<td>行业类别</td>
<td>{{ data.evaluationDialogForm.INDUSTRY_ALL_NAME }}</td>
<td>联系电话</td>
<td>{{ data.evaluationDialogForm.PHONE }}</td>
</tr>
<tr>
<td>人员类型</td>
<td colspan="9">{{ data.evaluationDialogForm.PERSONNEL_TYPE }}</td>
</tr>
</table>
<h3>评估内容</h3>
<p class="p1">
您在 {{ data.evaluationDialogForm.START_TIME }} -
{{ data.evaluationDialogForm.END_TIME }} 进行了
{{ data.evaluationDialogForm.CLASS_NAME }} 培训内容如下
{{ data.evaluationDialogForm.coursewareName }}
</p>
<p class="p1">
您参加了培训后的课程考试并取得了以下成绩{{
data.evaluationDialogForm.STAGEEXAMSCORE
}}
</p>
<h3>评估结果</h3>
<p class="p1">根据我们的评估您的个人培训效果如下</p>
<p class="p1">
<b
>您在培训期间表现出积极的参与度完成了所有的培训课程和活动</b
>
</p>
<p class="p1">
<b
><span v-if="data.evaluationDialogForm.correct !== ''"
>您对 {{ data.evaluationDialogForm.correct }} 知识掌握得很好</span
>在评估过程中我们发现您可能存在以下知识盲点{{
data.evaluationDialogForm.error
}}</b
>
</p>
<p class="p1">知识盲点对应课件为</p>
<p class="p1">{{ data.evaluationDialogForm.errorVideoName }}</p>
<p class="p1"><b>评估建议</b></p>
<p class="p1">
存在的知识盲点需要进一步加强和补充我们建议您将重点放在弥补这些盲点上通过进一步学习参与讨论或与安全专家交流弥补知识盲区
</p>
<h3>强化培训记录</h3>
<p class="p1"><b>强化培训考试记录</b></p>
<div
v-if="data.evaluationDialogForm.STRENGTHEN_EXAMNAME !== '0'"
class="page-break"
>
<div class="levelup no-print">
<h1>考卷详情</h1>
</div>
<div class="paper-details chapter_box">
<div class="chapter_right_img" />
<h1 style="text-align: center">
{{ data.evaluationDialogForm.STRENGTHEN_EXAMNAME }}
</h1>
<div style="text-align: center">
(满分:{{ data.evaluationDialogForm.STRENGTHEN_EXAMSCORE }})
</div>
<div class="subflex">
<span>班级名称:{{ data.evaluationDialogForm.CLASS_NAME }}</span>
<span>姓名:{{ data.evaluationDialogForm.NAME }}</span>
</div>
<div class="subflex">
<span
>考试时间:{{
data.evaluationDialogForm.STRENGTHEN_OPERATTIME
}}</span
>
<span
>分数:{{ data.evaluationDialogForm.STRENGTHENEXAMSCORE }}</span
>
</div>
<div class="study-papg">
<dl
v-for="(row, key) in data.evaluationDialogForm
.strengthenexamrecord"
:key="key"
>
<dt>
<span v-if="row.QUESTIONTYPE === '1'" class="mark mark-green"
>(单选题)
</span>
<span v-if="row.QUESTIONTYPE === '2'" class="mark mark-blue"
>(多选题)</span
>
<span v-if="row.QUESTIONTYPE === '3'" class="mark mark-orange"
>(判断题)</span
>
<span v-if="row.QUESTIONTYPE === '4'" class="mark mark-purple"
>(填空题)</span
>
{{ key + 1 }}.{{ row.QUESTIONDRY }}
<span class="ml-10">(题目分值{{ row.SCORE }})</span>
</dt>
<el-radio-group
v-if="row.QUESTIONTYPE === '1'"
v-model="row.ANSWER"
:disabled="true"
>
<dd>
<el-radio label="A">A.{{ row.OPTIONA }}</el-radio>
</dd>
<dd>
<el-radio label="B">B.{{ row.OPTIONB }}</el-radio>
</dd>
<dd>
<el-radio label="C">C.{{ row.OPTIONC }}</el-radio>
</dd>
<dd>
<el-radio label="D">D.{{ row.OPTIOND }}</el-radio>
</dd>
</el-radio-group>
<el-checkbox-group
v-if="row.QUESTIONTYPE === '2'"
v-model="row.checkList"
:disabled="true"
>
<dd>
<el-checkbox label="A">A.{{ row.OPTIONA }}</el-checkbox>
</dd>
<dd>
<el-checkbox label="B">B.{{ row.OPTIONB }}</el-checkbox>
</dd>
<dd>
<el-checkbox label="C">C.{{ row.OPTIONC }}</el-checkbox>
</dd>
<dd>
<el-checkbox label="D">D.{{ row.OPTIOND }}</el-checkbox>
</dd>
</el-checkbox-group>
<el-radio-group
v-if="row.QUESTIONTYPE === '3'"
v-model="row.ANSWER"
:disabled="true"
>
<dd>
<el-radio label="A">A.{{ row.OPTIONA }}</el-radio>
</dd>
<dd>
<el-radio label="B">B.{{ row.OPTIONB }}</el-radio>
</dd>
</el-radio-group>
<div class="flex-layout space-between">
<div>
<div v-if="row.QUESTIONTYPE === '4'" class="mb-10">
学员答案{{ row.ANSWER }}
</div>
<div class="mb-10">参考答案{{ row.ANSWERRIGHT }}</div>
<div>答案解析{{ row.DESCR }}</div>
</div>
</div>
</dl>
</div>
</div>
</div>
</div>
<template #footer>
<el-button @click="visible = false">关闭</el-button>
</template>
</el-dialog>
</template>
<script setup>
import { reactive, watchEffect } from "vue";
import { ElMessageBox } from "element-plus";
import { getStudentEvaluation } from "@/request/training_archive_management.js";
import { useVModel } from "@vueuse/core";
const props = defineProps({
studentId: {
type: String,
required: true,
},
visible: {
type: Boolean,
default: false,
},
});
const visible = useVModel(props, "visible");
const data = reactive({
evaluationDialogForm: {},
count1: "",
count2: "",
count3: "",
});
const fnGetData = async () => {
const resData = await getStudentEvaluation({
STUDENT_ID: props.studentId,
});
data.evaluationDialogForm = resData.pageData;
data.count1 = data.pageData.count1;
data.count2 = data.pageData.count2;
data.count3 = data.pageData.count3;
};
const fnExport = async () => {
await ElMessageBox.confirm("确定要导出吗?", { type: "warning" });
window.location.href =
import.meta.env[import.meta.env.DEV ? "VITE_PROXY" : "VITE_BASE_URL"] +
"student/hs?STUDENT_ID=" +
props.studentId;
};
watchEffect(() => {
if (visible.value) fnGetData();
});
</script>
<style scoped lang="scss">
.flex {
display: flex;
align-items: center;
justify-content: space-between;
}
table {
width: 100%;
border-collapse: collapse;
td {
border: 1px solid var(--el-border-color);
padding: 8px;
font-size: 14px;
text-align: center;
}
}
</style>

View File

@ -0,0 +1,126 @@
<template>
<div>
<el-card>
<el-form
:model="searchForm"
label-width="100px"
@submit.prevent="fnResetPagination"
>
<el-row>
<el-col :span="6">
<el-form-item label="班级名称" prop="NAME">
<el-input
v-model="searchForm.NAME"
placeholder="请输入班级名称"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="年份" prop="YEAR">
<el-date-picker
v-model="searchForm.YEAR"
value-format="YYYY"
type="year"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label-width="10px">
<el-button type="primary" native-type="submit">搜索</el-button>
<el-button native-type="reset" @click="fnResetPagination">
重置
</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<layout-card>
<layout-table
ref="tableRef"
v-model:pagination="pagination"
:data="list"
@get-data="fnGetData"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column label="序号" width="60">
<template #default="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column prop="NAME" label="班级名称" width="200" />
<el-table-column prop="CODE" label="班级编码" width="200" />
<el-table-column prop="TRAINTYPENAME" label="培训类型" width="200" />
<el-table-column prop="POSTTYPENAME" label="岗位类型" width="200" />
<el-table-column
prop="PASSSTUDENTCOUNT"
label="效果评估通过人数"
width="200"
/>
<el-table-column
prop="ALLSTUDENTCOUNT"
label="效果评估总人数"
width="200"
/>
<el-table-column label="操作">
<template #default="{ row }">
<el-button
type="primary"
text
link
@click="
router.push({
path: '/effect_appraisal/enterprise_effect/index/studentStrengthenDetailsList',
query: {
CLASS_ID: row.CLASS_ID,
},
})
"
>
学员详情
</el-button>
<el-button
type="primary"
text
link
@click="goClassStrengthenInfo(row.CLASS_ID)"
>
班级效果评估表
</el-button>
</template>
</el-table-column>
</layout-table>
</layout-card>
<class-strengthen
v-model:visible="data.evaluationDialog.visible"
:class-id="data.evaluationDialog.CLASS_ID"
/>
</div>
</template>
<script setup>
import { serialNumber } from "@/assets/js/utils.js";
import useListData from "@/assets/js/useListData.js";
import { reactive, ref } from "vue";
import { getClassStrengthenDetailsList } from "@/request/training_archive_management.js";
import router from "@/router/index.js";
import ClassStrengthen from "./components/classStrengthen.vue";
const data = reactive({
evaluationDialog: {
visible: false,
CLASS_ID: "",
},
});
const tableRef = ref(null);
const { list, pagination, searchForm, fnGetData, fnResetPagination } =
useListData(getClassStrengthenDetailsList);
const goClassStrengthenInfo = (class_id) => {
data.evaluationDialog.visible = true;
data.evaluationDialog.CLASS_ID = class_id;
};
</script>
<style scoped></style>

View File

@ -0,0 +1,128 @@
<template>
<div>
<el-card>
<el-form
:model="searchForm"
label-width="100px"
@submit.prevent="fnResetPagination"
>
<el-row>
<el-col :span="6">
<el-form-item label="姓名" prop="STUDENTNAME">
<el-input v-model="searchForm.NAME" placeholder="请输入姓名" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="年份" prop="YEAR">
<el-date-picker
v-model="searchForm.YEAR"
value-format="YYYY"
type="year"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label-width="10px">
<el-button type="primary" native-type="submit">搜索</el-button>
<el-button native-type="reset" @click="fnResetPagination">
重置
</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<layout-card>
<layout-table
ref="tableRef"
v-model:pagination="pagination"
:data="list"
@get-data="fnGetData"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column label="序号" width="60">
<template #default="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column prop="STUDENTNAME" label="姓名" width="200" />
<el-table-column prop="USERIDCARD" label="身份证号" width="200" />
<el-table-column prop="PHONE" label="手机号" width="200" />
<el-table-column
prop="STRENGTHENEXAMSTATE"
label="效果评估状态"
width="200"
>
<template #default="{ row }">
<span>
{{ row.STRENGTHENEXAMSTATE === "3" ? "通过" : "未通过" }}
</span>
</template>
</el-table-column>
<el-table-column
prop="STRENGTHENEXAMSCORE"
label="效果评估最高分"
width="200"
>
<template #default="{ row }">
<span>
{{
row.STRENGTHENEXAMSCORE
? row.STRENGTHENEXAMSCORE
: "未进行评估考试"
}}
</span>
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<el-button
type="primary"
text
link
@click="goStudentStrengthenInfo(row.STUDENT_ID)"
>
查看个人效果评估
</el-button>
</template>
</el-table-column>
</layout-table>
</layout-card>
<student-strengthen
v-model:visible="data.evaluationDialog.visible"
:student-id="data.evaluationDialog.STUDENT_ID"
/>
</div>
</template>
<script setup>
import { serialNumber } from "@/assets/js/utils.js";
import useListData from "@/assets/js/useListData.js";
import { reactive, ref } from "vue";
import { getStudentStrengthenDetailsList } from "@/request/training_archive_management.js";
import { useRoute } from "vue-router";
import StudentStrengthen from "./components/studentStrengthen.vue";
const route = useRoute();
const { CLASS_ID } = route.query;
const tableRef = ref(null);
const data = reactive({
evaluationDialog: {
visible: false,
STUDENT_ID: "",
},
});
const { list, pagination, searchForm, fnGetData, fnResetPagination } =
useListData(getStudentStrengthenDetailsList, {
otherParams: { CLASS_ID },
});
const goStudentStrengthenInfo = (student_id) => {
data.evaluationDialog.visible = true;
data.evaluationDialog.STUDENT_ID = student_id;
};
</script>
<style scoped></style>