Merge remote-tracking branch 'origin/dev' into dev

pull/1/head
dearlin 2024-01-29 17:35:26 +08:00
commit 3e489b86f3
38 changed files with 2750 additions and 118 deletions

View File

@ -255,7 +255,7 @@
box-shadow: 0 0 0 1px var(--el-border-color) inset !important;
}
.el-select__tags .el-tag--info {
.el-select .el-tag.el-tag--info {
background-color: #214082 !important;
--el-tag-text-color: var(--el-text-color-regular) !important;
}

View File

@ -2146,4 +2146,64 @@ export default [
},
],
},
{
path: "/security_investment",
redirect: "/security_investment/plan",
meta: { title: "安全投入", model: MODEL["5"] },
component: "children",
children: [
{
path: "/security_investment/plan",
meta: { title: "安全投入计划", isSubMenu: false },
component: "security_investment/plan/index",
},
{
path: "/security_investment/plan_review",
meta: { title: "安全投入计划审核", isSubMenu: false },
component: "security_investment/plan_review/index",
},
{
path: "/security_investment/extraction_and_use",
meta: { title: "安全生产费用提取和使用管理", isSubMenu: false },
component: "security_investment/extraction_and_use/index",
},
],
},
{
path: "/learning_garden",
redirect: "/learning_garden/learning_garden",
meta: { title: "学习园地", model: MODEL["5"] },
component: "children",
children: [
{
path: "/learning_garden/learning_garden",
meta: { title: "学习园地", isSubMenu: false },
component: "children",
children: [
{
path: "",
component: "learning_garden/learning_garden/index",
},
{
path: "/learning_garden/learning_garden/task_list",
meta: {
title: "任务列表",
activeMenu: "/learning_garden/learning_garden",
},
component: "learning_garden/learning_garden/task_list",
},
],
},
{
path: "/learning_garden/enterprise_video",
meta: { title: "企业视频", isSubMenu: false },
component: "learning_garden/enterprise_video/index",
},
{
path: "/learning_garden/regulatory_library",
meta: { title: "法规库", isSubMenu: false },
component: "learning_garden/regulatory_library/index",
},
],
},
];

View File

@ -258,6 +258,20 @@ export const layoutFnGetEquipmentType = async () => {
});
return ref(resData.list);
};
// 学习园地类型
export const layoutFnGetLearningGardenType = async () => {
const resData = await getLevels({
DICTIONARIES_ID: "5aa989ad8fd54bef862c1b096a3b07d8",
});
return ref(resData.list);
};
// 学习园地学习类型
export const layoutFnGetLearningGardenLearningType = async () => {
const resData = await getLevels({
DICTIONARIES_ID: "c4f00e7ed9334789ba2fb4795f54bae2",
});
return ref(resData.list);
};
// 部门树
export const layoutFnGetDepartmentTree = async (params) => {
const resData = await getDepartmentTree(params);

View File

@ -74,6 +74,10 @@ export default function useListData(api, options = {}) {
list.value = resData[key];
if (usePagination) pagination.value.total = resData.page.totalResult;
options.callbackFn && options.callbackFn(list.value, resData);
!usePagination &&
clearSelection &&
tableRef.value &&
tableRef.value.clearSelection();
};
immediate && fnGetData().then();
const fnResetPagination = async (otherParams) => {

View File

@ -40,10 +40,14 @@ const props = defineProps({
required: true,
default: "",
validator: (value) => {
if (["industry", "post", "plate"].includes(value)) {
// industry:
// post:
// plate:
const typeList = ["industry", "post", "plate"];
if (typeList.includes(value)) {
return true;
} else {
throw new Error("type必须是industry、post、plate之一");
throw new Error(`type必须是${typeList.join("、")}之一`);
}
},
},

View File

@ -0,0 +1,110 @@
<template>
<div style="display: inline-block">
<el-button
link
type="primary"
v-if="interceptTheSuffix(filePath, '.txt')"
@click="fnPreviewTxt(filePath)"
>
[预览]
</el-button>
<el-button
text
link
type="primary"
v-if="interceptTheSuffix(filePath, '.pdf')"
@click="fnPreviewPdf(filePath)"
>
[预览]
</el-button>
<el-button
link
type="primary"
v-if="interceptTheSuffix(filePath, '.mp4')"
@click="fnPreviewVideo(filePath)"
>
[预览]
</el-button>
<a
v-if="
interceptTheSuffix(filePath, '.doc') ||
interceptTheSuffix(filePath, '.xls') ||
interceptTheSuffix(filePath, '.ppt') ||
interceptTheSuffix(filePath, '.docx') ||
interceptTheSuffix(filePath, '.xlsx') ||
interceptTheSuffix(filePath, '.pptx')
"
:href="
'http://view.officeapps.live.com/op/view.aspx?src=' +
VITE_FILE_URL +
filePath
"
target="_blank"
>
[预览]
</a>
<layout-pdf
:src="data.pdfDialog.src"
v-model:visible="data.pdfDialog.visible"
append-to-body
/>
<layout-txt
:src="data.txtDialog.src"
v-model:visible="data.txtDialog.visible"
append-to-body
/>
<layout-video
:src="data.videoDialog.src"
v-model:visible="data.videoDialog.visible"
append-to-body
/>
</div>
</template>
<script setup>
import { interceptTheSuffix } from "@/assets/js/utils.js";
import { reactive } from "vue";
import LayoutVideo from "@/components/video/index.vue";
import LayoutTxt from "@/components/txt/index.vue";
import LayoutPdf from "@/components/pdf/index.vue";
defineOptions({
name: "LayoutMultipleAttachmentPreviews",
});
defineProps({
filePath: {
type: String,
required: true,
default: "",
},
});
const VITE_FILE_URL = import.meta.env.VITE_FILE_URL;
const data = reactive({
pdfDialog: {
visible: false,
src: "",
},
videoDialog: {
visible: false,
src: "",
},
txtDialog: {
visible: false,
src: "",
},
});
const fnPreviewTxt = async (FILEPATH) => {
data.txtDialog.visible = true;
data.txtDialog.src = FILEPATH;
};
const fnPreviewPdf = (FILEPATH) => {
data.pdfDialog.visible = true;
data.pdfDialog.src = FILEPATH;
};
const fnPreviewVideo = (FILEPATH) => {
data.videoDialog.visible = true;
data.videoDialog.src = FILEPATH;
};
</script>
<style scoped lang="scss"></style>

View File

@ -3,6 +3,7 @@
title="文档"
:model-value="visible && model === 'dialog'"
@update:model-value="visible = false"
:append-to-body="appendToBody"
>
<div v-if="visible" style="height: 690px; overflow-y: auto">
<vue-pdf
@ -49,14 +50,19 @@ const props = defineProps({
model: {
type: String,
validator: (value) => {
if (["dialog", "normal"].includes(value)) {
const typeList = ["dialog", "normal"];
if (typeList.includes(value)) {
return true;
} else {
throw new Error("model必须是dialog或normal");
throw new Error(`model必须是${typeList.join("、")}之一`);
}
},
default: "dialog",
},
appendToBody: {
type: Boolean,
default: false,
},
});
const emits = defineEmits(["update:visible"]);
const visible = useVModel(props, "visible", emits);

View File

@ -35,10 +35,11 @@ const props = defineProps({
type: String,
default: "vertical",
validator: (value) => {
if (["vertical", "horizontal"].includes(value)) {
const typeList = ["vertical", "horizontal"];
if (typeList.includes(value)) {
return true;
} else {
throw new Error('direction必须是"vertical"或"horizontal"');
throw new Error(`direction必须是${typeList.join("、")}之一`);
}
},
},

View File

@ -0,0 +1,94 @@
<template>
<el-tree-select
ref="treeSelectRef"
v-model="modelValue"
:data="tree"
:props="{
value: type !== 'label' ? 'DICTIONARIES_ID' : 'BUS_LABEL_FACTORY_ID',
children: type !== 'label' ? 'nodes' : 'children',
label: 'NAME',
isLeaf: 'isLeaf',
}"
:node-key="type !== 'label' ? 'DICTIONARIES_ID' : 'BUS_LABEL_FACTORY_ID'"
:render-after-expand="false"
accordion
check-strictly
:lazy="type !== 'label'"
:load="fnLoad"
:clearable="true"
show-checkbox
multiple
collapse-tags
/>
</template>
<script setup>
import { ref } from "vue";
import { useVModel } from "@vueuse/core";
import { layoutFnGetLevelsAndChildrenNumber } from "@/assets/js/data_dictionary.js";
import { getThreeInstitutionalLibrariesLabel } from "@/request/three_institutional_libraries.js";
defineOptions({
name: "LayoutThreeInstitutionalLibraries",
});
const props = defineProps({
modelValue: {
type: String,
required: true,
default: "",
},
type: {
type: String,
required: true,
default: "",
validator: (value) => {
// regulations:
// type:
// industry:
// label:
const typeList = ["regulations", "type", "industry", "label"];
if (typeList.includes(value)) {
return true;
} else {
throw new Error(`type必须是${typeList.join("、")}之一`);
}
},
},
});
const emits = defineEmits(["update:modelValue", "update:checkList"]);
const modelValue = useVModel(props, "modelValue", emits);
const treeSelectRef = ref(null);
const fnLoad = async (node, resolve) => {
if (props.type === "label") return;
const resData = await layoutFnGetLevelsAndChildrenNumber(
node.data.DICTIONARIES_ID || id
);
resolve(
resData.value.map((item) => {
return {
DICTIONARIES_ID: item.DICTIONARIES_ID,
BIANMA: item.BIANMA,
NAME: item.NAME,
isLeaf: item.zcount === 0,
};
})
);
};
const getCheckedNodes = () => {
return treeSelectRef.value.getCheckedNodes();
};
defineExpose({
getCheckedNodes,
});
let tree = [];
let id = "";
if (props.type === "regulations") id = "84254cb5b2ae40eb9f451509b2d370ae";
if (props.type === "type") id = "5a7c94b2b9514285b433759edd848b4a";
if (props.type === "industry") id = "f2598ba72e864eadabf0ca4b664d26b9";
if (props.type === "label") {
const resData = await getThreeInstitutionalLibrariesLabel();
tree = resData.tree;
}
</script>
<style scoped></style>

View File

@ -1,5 +1,5 @@
<template>
<el-dialog title="文本文档" v-model="visible">
<el-dialog title="文本文档" v-model="visible" :append-to-body="appendToBody">
<el-input autosize :model-value="value" readonly type="textarea" />
</el-dialog>
</template>
@ -23,6 +23,10 @@ const props = defineProps({
required: true,
default: "",
},
appendToBody: {
type: Boolean,
default: false,
},
});
const value = ref("");
const emits = defineEmits(["update:visible"]);

View File

@ -1,5 +1,5 @@
<template>
<el-dialog title="视频" v-model="visible">
<el-dialog title="视频" v-model="visible" :append-to-body="appendToBody">
<ali-player
:source="fnSrc(src)"
:vid="vid"
@ -37,6 +37,10 @@ const props = defineProps({
required: true,
default: false,
},
appendToBody: {
type: Boolean,
default: false,
},
});
const emits = defineEmits(["update:visible"]);
const visible = useVModel(props, "visible", emits);

View File

@ -1,5 +1,6 @@
import { post, upload } from "@/request/axios.js";
export const getEnterpriseList = (params) => post("/corpinfo/list", params); // 获取企业列表
export const getEnterpriseInfo = (params) => post("/corpinfo/goEdit", params); // 获取企业信息
export const setEnterpriseInfo = (params) => upload("/corpinfo/edit", params); // 修改企业信息
export const getIndustryQualificationsList = (params) =>

View File

@ -0,0 +1,28 @@
import { post, upload } from "@/request/axios.js";
export const getLearningGardenList = (params) =>
post("/studysection/list", params); // 学习园地列表
export const setLearningGardenDelete = (params) =>
post("/studysection/delete", params); // 学习园地删除
export const setLearningGardenAdd = (params) =>
upload("/studysection/add", params); // 学习园地新增
export const getLearningGardenTaskList = (params) =>
post("/tempstudy/list", params); // 学习园地任务列表
export const setLearningGardenTaskDelete = (params) =>
post("/tempstudy/delete", params); // 学习园地任务删除
export const setLearningGardenTaskBatchDelete = (params) =>
post("/tempstudy/deleteAll", params); // 学习园地任务批量删除
export const setLearningGardenTaskDisableOrEnable = (params) =>
post("/tempstudy/edit", params); // 学习园地任务禁用或启用
export const setLearningGardenTaskLearningSituationList = (params) =>
post("/tempstudy/studentList", params); // 学习园地任务学习情况列表
export const setLearningGardenTaskLearningSituationAdd = (params) =>
post("/tempstudy/add", params); // 学习园地任务学习情况新增
export const getEnterpriseVideoList = (params) => post("/video/list", params); // 企业视频列表
export const setEnterpriseVideoDelete = (params) =>
post("/video/delete", params); // 企业视频删除
export const setEnterpriseVideoRelease = (params) =>
post("/video/editZhiding", params); // 企业视频发布
export const setEnterpriseVideoAdd = (params) => upload("/video/add", params); // 企业视频新增
export const getRegulatoryLibraryList = (params) =>
post("/mfolderStipulate/list", params); // 法规库列表

View File

@ -0,0 +1,21 @@
import { post } from "@/request/axios.js";
export const getPlanList = (params) =>
post("/safetyinvestmentplan/list", params); // 安全投入计划列表
export const getPlanView = (params) =>
post("/safetyinvestmentplan/goEdit", params); // 安全投入计划查看
export const setPlanDelete = (params) =>
post("/safetyinvestmentplan/delete", params); // 安全投入计划删除
export const setPlanBatchDelete = (params) =>
post("/safetyinvestmentplan/deleteAll", params); // 安全投入计划批量删除
export const setPlanAdd = (params) => post("/safetyinvestmentplan/add", params); // 安全投入计划新增
export const setPlanEdit = (params) =>
post("/safetyinvestmentplan/edit", params); // 安全投入计划编辑
export const setPlanReview = (params) =>
post("/safetyinvestmentplan/editStatus", params); // 安全投入计划审核
export const getExtractionAndUseList = (params) =>
post("/safetyinvestmentuse/listAll", params); // 安全生产费用提取和使用管理列表
export const setExtractionAndUseBatchDelete = (params) =>
post("/safetyinvestmentuse/deleteAll", params); // 安全生产费用提取和使用管理批量删除
export const setExtractionAndUseAdd = (params) =>
post("/safetyinvestmentuse/add", params); // 安全生产费用提取和使用管理新增

View File

@ -0,0 +1,6 @@
import { post } from "@/request/axios.js";
export const getThreeInstitutionalLibrariesList = (params) =>
post("/textLibrary/list", params); // 三项制度库列表
export const getThreeInstitutionalLibrariesLabel = (params) =>
post("/labelFactory/tree", params); // 三项制度库标签

View File

@ -94,7 +94,10 @@ const props = defineProps({
const emits = defineEmits(["update:visible", "submit"]);
const visible = useVModel(props, "visible", emits);
const { list, searchForm, pagination, fnGetData, fnResetPagination, tableRef } =
useListData(getInventoryManagementOtherRiskList, { immediate: false });
useListData(getInventoryManagementOtherRiskList, {
immediate: false,
clearSelection: false,
});
const riskClassificationList = await layoutFnGetRiskClassification();
const stop = watch(
() => props.visible,

View File

@ -0,0 +1,83 @@
<template>
<el-dialog v-model="visible" title="新增" :on-close="fnClose">
<el-form ref="formRef" :rules="rules" :model="form" label-width="110px">
<el-form-item label="视频名称" prop="NAME">
<el-input v-model="form.NAME" />
</el-form-item>
<el-form-item label="内容" prop="DESCR">
<el-input
v-model="form.DESCR"
type="textarea"
:autosize="{ minRows: 3 }"
/>
</el-form-item>
<el-form-item label="附件路径" prop="file">
<layout-upload v-model:file-list="form.file" accept=".mp4">
<template #tip>最大支持100M视频</template>
</layout-upload>
</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 { useVModel } from "@vueuse/core";
import { ref } from "vue";
import { debounce } from "throttle-debounce";
import useFormValidate from "@/assets/js/useFormValidate.js";
import { ElMessage } from "element-plus";
import LayoutUpload from "@/components/upload/index.vue";
import { setEnterpriseVideoAdd } from "@/request/learning_garden.js";
const props = defineProps({
visible: {
type: Boolean,
required: true,
default: false,
},
});
const emits = defineEmits(["update:visible", "get-data"]);
const visible = useVModel(props, "visible", emits);
const rules = ref({
NAME: [{ required: true, message: "视频名称不能为空", trigger: "blur" }],
DESCR: [{ required: true, message: "内容不能为空", trigger: "blur" }],
file: [{ required: true, message: "请上传附件", trigger: "change" }],
});
const formRef = ref(null);
const form = ref({
NAME: "",
DESCR: "",
file: [],
CORPINFO_TYPE: "1",
});
const fnClose = () => {
formRef.value.resetFields();
visible.value = false;
};
const fnSubmit = debounce(
1000,
async () => {
await useFormValidate(formRef);
const formData = new FormData();
Object.keys(form.value).forEach((key) => {
formData.append(key, form.value[key]);
});
formData.delete("file");
if (form.value.file[0].raw) {
formData.append("file", form.value.file[0].raw);
formData.append("fileName", form.value.file[0].name);
}
await setEnterpriseVideoAdd(formData);
ElMessage.success("提交成功");
fnClose();
emits("get-data");
},
{ atBegin: true }
);
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,126 @@
<template>
<div>
<el-card>
<el-form
:model="searchForm"
label-width="90px"
@submit.prevent="fnResetPagination"
>
<el-row>
<el-col :span="6">
<el-form-item label="视频名称" prop="KEYWORDS">
<el-input
v-model="searchForm.KEYWORDS"
placeholder="请输入关键字"
/>
</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
:data="list"
v-model:pagination="pagination"
@get-data="fnGetData"
>
<el-table-column label="序号" width="70">
<template v-slot="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column prop="NAME" label="视频名称" />
<el-table-column prop="CREATOR" label="添加人" />
<el-table-column prop="CREATTIME" label="添加时间" />
<el-table-column label="是否置顶">
<template v-slot="{ row }">
<span v-if="row.TYPE === '0'"></span>
<span v-if="row.TYPE === '1'"></span>
</template>
</el-table-column>
<el-table-column label="操作" width="150">
<template v-slot="{ row }">
<el-button
v-if="row.TYPE === '0' && buttonJurisdiction.add"
type="primary"
text
link
@click="fnRelease(row.VIDEO_ID)"
>
发布
</el-button>
<el-button
v-if="buttonJurisdiction.del"
type="primary"
text
link
@click="fnDelete(row.VIDEO_ID)"
>
删除
</el-button>
</template>
</el-table-column>
<template #button>
<el-button
v-if="buttonJurisdiction.add"
type="primary"
@click="addDialogVisible = true"
>
新增
</el-button>
</template>
</layout-table>
</layout-card>
<add v-model:visible="addDialogVisible" @get-data="fnResetPagination" />
</div>
</template>
<script setup>
import { serialNumber } from "@/assets/js/utils.js";
import useListData from "@/assets/js/useListData.js";
import { debounce } from "throttle-debounce";
import { ElMessage, ElMessageBox } from "element-plus";
import useButtonJurisdiction from "@/assets/js/useButtonJurisdiction.js";
import {
getEnterpriseVideoList,
setEnterpriseVideoDelete,
setEnterpriseVideoRelease,
} from "@/request/learning_garden.js";
import { ref } from "vue";
import Add from "./components/add.vue";
const addDialogVisible = ref(false);
const { list, pagination, searchForm, fnGetData, fnResetPagination } =
useListData(getEnterpriseVideoList);
const buttonJurisdiction = await useButtonJurisdiction("video");
const fnDelete = debounce(
1000,
async (VIDEO_ID) => {
await ElMessageBox.confirm("确定要删除吗?", { type: "warning" });
await setEnterpriseVideoDelete({ VIDEO_ID });
ElMessage.success("删除成功");
fnResetPagination();
},
{ atBegin: true }
);
const fnRelease = debounce(
1000,
async (VIDEO_ID) => {
await ElMessageBox.confirm("确定要发布吗?", { type: "warning" });
await setEnterpriseVideoRelease({ VIDEO_ID });
ElMessage.success("发布成功");
fnResetPagination();
},
{ atBegin: true }
);
</script>
<style scoped></style>

View File

@ -0,0 +1,94 @@
<template>
<el-dialog v-model="visible" title="新增" :on-close="fnClose">
<el-form ref="formRef" :rules="rules" :model="form" label-width="110px">
<el-form-item label="类型" prop="TYPE">
<el-select v-model="form.TYPE">
<el-option
v-for="item in learningGardenTypeList"
:key="item.DICTIONARIES_ID"
:label="item.NAME"
:value="item.DICTIONARIES_ID"
/>
</el-select>
</el-form-item>
<el-form-item label="标题" prop="TITLE">
<el-input v-model="form.TITLE" />
</el-form-item>
<el-form-item label="内容" prop="CONTENT">
<el-input
v-model="form.CONTENT"
type="textarea"
:autosize="{ minRows: 3 }"
/>
</el-form-item>
<el-form-item label="附件路径" prop="file">
<layout-upload v-model:file-list="form.file" accept=".pdf" />
</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 { useVModel } from "@vueuse/core";
import { ref } from "vue";
import { debounce } from "throttle-debounce";
import useFormValidate from "@/assets/js/useFormValidate.js";
import { ElMessage } from "element-plus";
import LayoutUpload from "@/components/upload/index.vue";
import { layoutFnGetLearningGardenType } from "@/assets/js/data_dictionary.js";
import { setLearningGardenAdd } from "@/request/learning_garden.js";
const props = defineProps({
visible: {
type: Boolean,
required: true,
default: false,
},
});
const emits = defineEmits(["update:visible", "get-data"]);
const visible = useVModel(props, "visible", emits);
const rules = ref({
TYPE: [{ required: true, message: "请选择类型", trigger: "change" }],
TITLE: [{ required: true, message: "请输入标题", trigger: "blur" }],
CONTENT: [{ required: true, message: "请输入内容", trigger: "blur" }],
file: [{ required: true, message: "请上传附件", trigger: "change" }],
});
const formRef = ref(null);
const form = ref({
TYPE: "",
TITLE: "",
CONTENT: "",
file: [],
});
const learningGardenTypeList = await layoutFnGetLearningGardenType();
const fnClose = () => {
formRef.value.resetFields();
visible.value = false;
};
const fnSubmit = debounce(
1000,
async () => {
await useFormValidate(formRef);
const formData = new FormData();
Object.keys(form.value).forEach((key) => {
formData.append(key, form.value[key]);
});
formData.delete("file");
if (form.value.file[0].raw) {
formData.append("file", form.value.file[0].raw);
formData.append("fileName", form.value.file[0].name);
}
await setLearningGardenAdd(formData);
ElMessage.success("提交成功");
fnClose();
emits("get-data");
},
{ atBegin: true }
);
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,109 @@
<template>
<el-dialog v-model="visible" title="新增" :on-close="fnClose">
<el-form ref="formRef" :rules="rules" :model="form" label-width="110px">
<el-form-item label="名称" prop="NAME">
<el-input v-model="form.NAME" />
</el-form-item>
<el-form-item label="学习类型" prop="STUDY_TYPE">
<el-select v-model="form.STUDY_TYPE">
<el-option
v-for="item in learningGardenLearningTypeList"
:key="item.BIANMA"
:label="item.NAME"
:value="item.BIANMA"
/>
</el-select>
</el-form-item>
<el-form-item label="学习人员" prop="STUDY_USER_NAMES">
<div>
<div>{{ form.STUDY_USER_NAMES.join("、") }}</div>
<el-button type="primary" @click="userDialogVisible = true">
添加人员
</el-button>
</div>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="fnClose"> </el-button>
<el-button type="primary" @click="fnSubmit"> </el-button>
</template>
<user
type=""
v-model:user-list="form.STUDY_USER_IDS"
v-model:user-name="form.STUDY_USER_NAMES"
v-model:visible="userDialogVisible"
/>
</el-dialog>
</template>
<script setup>
import { useVModel } from "@vueuse/core";
import { ref } from "vue";
import { debounce } from "throttle-debounce";
import useFormValidate from "@/assets/js/useFormValidate.js";
import { ElMessage } from "element-plus";
import { layoutFnGetLearningGardenLearningType } from "@/assets/js/data_dictionary.js";
import User from "./user.vue";
import { setLearningGardenTaskLearningSituationAdd } from "@/request/learning_garden.js";
const props = defineProps({
visible: {
type: Boolean,
required: true,
default: false,
},
id: {
type: String,
required: true,
default: "",
},
});
const emits = defineEmits(["update:visible", "get-data"]);
const visible = useVModel(props, "visible", emits);
const rules = ref({
NAME: [{ required: true, message: "名称不能为空", trigger: "blur" }],
STUDY_TYPE: [
{ required: true, message: "学习类型不能为空", trigger: "blur" },
],
STUDY_USER_NAMES: [
{ required: true, message: "请选择学习人员", trigger: "change" },
],
});
const formRef = ref(null);
const form = ref({
NAME: "",
STUDY_TYPE: "",
STUDY_USER_IDS: [],
STUDY_USER_NAMES: [],
COURSEWARE_TYPE: 2,
STATUS: "1",
});
const userDialogVisible = ref(false);
const learningGardenLearningTypeList =
await layoutFnGetLearningGardenLearningType();
const fnClose = () => {
formRef.value.resetFields();
form.value.STUDY_USER_IDS = [];
visible.value = false;
};
const fnSubmit = debounce(
1000,
async () => {
await useFormValidate(formRef);
const STUDY_USER_IDS = form.value.STUDY_USER_IDS.map(
(item) => item.USER_ID
).join(",");
await setLearningGardenTaskLearningSituationAdd({
...form.value,
COURSEWARE_ID: props.id,
STUDY_USER_IDS,
});
ElMessage.success("提交成功");
fnClose();
emits("get-data");
},
{ atBegin: true }
);
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,68 @@
<template>
<el-dialog v-model="visible" title="学员详情">
<layout-table
:data="list"
v-model:pagination="pagination"
@get-data="fnGetDataTransfer"
>
<el-table-column label="序号" width="70">
<template v-slot="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column prop="USER_NAME" label="姓名" />
<el-table-column label="课件类型">
<template v-slot="{ row }">
<span v-if="row.STUDY_STATUS === '0'"></span>
<span v-if="row.STUDY_STATUS === '1'"></span>
</template>
</el-table-column>
<el-table-column prop="STUDY_TIME" label="学习时间" />
</layout-table>
<template #footer>
<el-button @click="visible = false">关闭</el-button>
</template>
</el-dialog>
</template>
<script setup>
import { useVModel } from "@vueuse/core";
import { serialNumber } from "@/assets/js/utils.js";
import { setLearningGardenTaskLearningSituationList } from "@/request/learning_garden.js";
import useListData from "@/assets/js/useListData.js";
import { watch } from "vue";
const props = defineProps({
visible: {
type: Boolean,
required: true,
default: false,
},
id: {
type: String,
required: true,
default: "",
},
});
const emits = defineEmits(["update:visible"]);
const visible = useVModel(props, "visible", emits);
setLearningGardenTaskLearningSituationList();
const { list, pagination, fnGetData, fnResetPagination } = useListData(
setLearningGardenTaskLearningSituationList,
{ immediate: false }
);
const fnGetDataTransfer = () => {
fnGetData({ TEMPSTUDY_ID: props.id });
};
const fnResetPaginationTransfer = () => {
fnResetPagination({ TEMPSTUDY_ID: props.id });
};
watch(
() => props.visible,
() => {
if (props.visible) fnResetPaginationTransfer();
}
);
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,124 @@
<template>
<el-dialog v-model="visible" title="选择人员" :on-close="fnClose">
<el-form
:model="searchForm"
label-width="80px"
@submit.prevent="fnResetPagination"
>
<el-row>
<el-col :span="9">
<el-form-item label="人员名称" prop="KEYWORDS">
<el-input v-model="searchForm.KEYWORDS" />
</el-form-item>
</el-col>
<el-col :span="9">
<el-form-item label="部门" prop="DEPARTMENT_ID">
<layout-department v-model="searchForm.DEPARTMENT_ID" />
</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>
<layout-table
ref="tableRef"
row-key="USER_ID"
:data="list"
v-model:pagination="pagination"
@get-data="fnGetData"
>
<el-table-column reserve-selection type="selection" width="55" />
<el-table-column label="序号" width="60">
<template #default="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column prop="USERNAME" label="用户名" />
<el-table-column prop="NAME" label="姓名" />
<el-table-column prop="DEPARTMENT_NAME" label="部门" />
<el-table-column
prop="POST_NAME"
label="岗位"
width="150"
show-overflow-tooltip
/>
<el-table-column prop="ROLE_NAME" label="角色" />
</layout-table>
<template #footer>
<el-button @click="fnClose"></el-button>
<el-button type="primary" @click="fnSubmit"></el-button>
</template>
</el-dialog>
</template>
<script setup>
import { serialNumber } from "@/assets/js/utils.js";
import LayoutDepartment from "@/components/department/index.vue";
import useListData from "@/assets/js/useListData.js";
import { getUserList } from "@/request/enterprise_management.js";
import { useVModels } from "@vueuse/core";
import { nextTick, watch } from "vue";
const props = defineProps({
visible: {
type: Boolean,
required: true,
default: false,
},
userList: {
type: Array,
required: true,
default: () => [],
},
userName: {
type: Array,
required: true,
default: () => [],
},
});
const emits = defineEmits([
"update:visible",
"update:userList",
"update:userName",
]);
const { visible, userList, userName } = useVModels(props, emits);
const { list, pagination, fnGetData, fnResetPagination, tableRef, searchForm } =
useListData(getUserList, {
immediate: false,
clearSelection: false,
key: "userList",
});
const fnInit = async () => {
await nextTick();
props.userList.forEach((item) => {
tableRef.value.toggleRowSelection(item);
});
list.value.length === 0 && fnResetPagination();
};
const fnClose = () => {
tableRef.value.clearSelection();
visible.value = false;
};
const fnSubmit = () => {
const selectionData = tableRef.value.getSelectionRows();
userList.value = selectionData;
userName.value = selectionData.map((item) => item.NAME);
fnClose();
};
watch(
() => props.visible,
(val) => {
if (val) {
fnInit();
}
}
);
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,123 @@
<template>
<div>
<el-card>
<el-form
:model="searchForm"
label-width="90px"
@submit.prevent="fnResetPagination"
>
<el-row>
<el-col :span="6">
<el-form-item label="标题/内容" prop="KEYWORDS">
<el-input
v-model="searchForm.KEYWORDS"
placeholder="请输入关键字"
/>
</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
:data="list"
v-model:pagination="pagination"
@get-data="fnGetData"
>
<el-table-column label="序号" width="70">
<template v-slot="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column prop="TYPENAME" label="类型" />
<el-table-column prop="TITLE" label="标题" />
<el-table-column prop="CONTENT" label="内容" />
<el-table-column label="附件路径">
<template v-slot="{ row }">
{{ row.NAME }}
<layout-multiple-attachment-previews :file-path="row.FILEPATH" />
</template>
</el-table-column>
<el-table-column label="操作" width="150">
<template v-slot="{ row }">
<el-button
v-if="buttonJurisdiction.add"
type="primary"
text
link
@click="
router.push({
path: '/learning_garden/learning_garden/task_list',
query: { STUDYSECTION_ID: row.STUDYSECTION_ID },
})
"
>
任务列表
</el-button>
<el-button
v-if="buttonJurisdiction.del"
type="primary"
text
link
@click="fnDelete(row.STUDYSECTION_ID)"
>
删除
</el-button>
</template>
</el-table-column>
<template #button>
<el-button
v-if="buttonJurisdiction.add"
type="primary"
@click="addDialogVisible = true"
>
新增
</el-button>
</template>
</layout-table>
</layout-card>
<add v-model:visible="addDialogVisible" @get-data="fnResetPagination" />
</div>
</template>
<script setup>
import { serialNumber } from "@/assets/js/utils.js";
import useListData from "@/assets/js/useListData.js";
import { debounce } from "throttle-debounce";
import { ElMessage, ElMessageBox } from "element-plus";
import useButtonJurisdiction from "@/assets/js/useButtonJurisdiction.js";
import { useRouter } from "vue-router";
import {
getLearningGardenList,
setLearningGardenDelete,
} from "@/request/learning_garden.js";
import LayoutMultipleAttachmentPreviews from "@/components/multiple_attachment_previews/index.vue";
import Add from "./components/add.vue";
import { ref } from "vue";
const router = useRouter();
const addDialogVisible = ref(false);
const { list, pagination, searchForm, fnGetData, fnResetPagination } =
useListData(getLearningGardenList);
const buttonJurisdiction = await useButtonJurisdiction("studysection");
const fnDelete = debounce(
1000,
async (STUDYSECTION_ID) => {
await ElMessageBox.confirm("确定要删除吗?", { type: "warning" });
await setLearningGardenDelete({ STUDYSECTION_ID });
ElMessage.success("删除成功");
fnResetPagination();
},
{ atBegin: true }
);
</script>
<style scoped></style>

View File

@ -0,0 +1,212 @@
<template>
<div>
<el-card>
<el-form
:model="searchForm"
label-width="50px"
@submit.prevent="fnResetPagination"
>
<el-row>
<el-col :span="6">
<el-form-item label="名称" prop="KEYWORDS">
<el-input
v-model="searchForm.KEYWORDS"
placeholder="请输入关键字"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="状态">
<el-select v-model="searchForm.STATUS">
<el-option
v-for="item in statusList"
:key="item.ID"
:value="item.ID"
:label="item.NAME"
/>
</el-select>
</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"
row-key="TEMPSTUDY_ID"
:data="list"
v-model:pagination="pagination"
@get-data="fnGetData"
>
<el-table-column reserve-selection type="selection" width="55" />
<el-table-column label="序号" width="70">
<template v-slot="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column prop="NAME" label="名称" />
<el-table-column label="课件类型">
<template v-slot="{ row }">
<span v-if="row.COURSEWARE_TYPE === '1'"></span>
<span v-if="row.COURSEWARE_TYPE === '2'"></span>
</template>
</el-table-column>
<el-table-column prop="COURSEWARE_NAME" label="课件" />
<el-table-column prop="STUDY_TYPE_NAME" label="学习类型" />
<el-table-column prop="USER_NUM" label="人数">
<template v-slot="{ row }">
<el-button
type="primary"
text
link
@click="fnLearningSituation(row.TEMPSTUDY_ID)"
>
{{ row.done_num }}/{{ row.USER_NUM }}
</el-button>
</template>
</el-table-column>
<el-table-column label="状态">
<template v-slot="{ row }">
{{ translationStatus(row.STATUS, statusList) }}
</template>
</el-table-column>
<el-table-column label="操作" width="150">
<template v-slot="{ row }">
<el-button
type="primary"
text
link
@click="
fnDisableOrEnable(row.TEMPSTUDY_ID, row.STATUS === 1 ? 0 : 1)
"
>
{{ row.STATUS === 1 ? "启用" : "禁用" }}
</el-button>
<el-button
v-if="buttonJurisdiction.del"
type="primary"
text
link
@click="fnDelete(row.TEMPSTUDY_ID)"
>
删除
</el-button>
</template>
</el-table-column>
<template #button>
<el-button
v-if="buttonJurisdiction.add"
type="primary"
@click="data.addDialogVisible = true"
>
新增
</el-button>
<el-button
v-if="buttonJurisdiction.del"
type="danger"
@click="fnBatchDelete"
>
批量删除
</el-button>
</template>
</layout-table>
</layout-card>
<learning-situation
v-model:visible="data.learningSituationDialog.visible"
:id="data.learningSituationDialog.TEMPSTUDY_ID"
/>
<add-task
v-model:visible="data.addDialogVisible"
:id="STUDYSECTION_ID"
@get-data="fnResetPagination"
/>
</div>
</template>
<script setup>
import { serialNumber, translationStatus } from "@/assets/js/utils.js";
import useListData from "@/assets/js/useListData.js";
import { debounce } from "throttle-debounce";
import { ElMessage, ElMessageBox } from "element-plus";
import useButtonJurisdiction from "@/assets/js/useButtonJurisdiction.js";
import {
getLearningGardenTaskList,
setLearningGardenTaskBatchDelete,
setLearningGardenTaskDelete,
setLearningGardenTaskDisableOrEnable,
} from "@/request/learning_garden.js";
import { reactive } from "vue";
import { useRoute } from "vue-router";
import LearningSituation from "./components/learning_situation.vue";
import AddTask from "./components/add_task.vue";
const statusList = [
{ NAME: "启用", ID: 0 },
{ NAME: "禁用", ID: 1 },
];
const route = useRoute();
const { STUDYSECTION_ID } = route.query;
const { list, pagination, searchForm, fnGetData, fnResetPagination, tableRef } =
useListData(getLearningGardenTaskList, {
otherParams: { COURSEWARE_ID: STUDYSECTION_ID },
});
const data = reactive({
learningSituationDialog: {
visible: false,
TEMPSTUDY_ID: "",
},
addDialogVisible: false,
});
const buttonJurisdiction = await useButtonJurisdiction("studysection");
const fnDelete = debounce(
1000,
async (TEMPSTUDY_ID) => {
await ElMessageBox.confirm("确定要删除吗?", { type: "warning" });
await setLearningGardenTaskDelete({ TEMPSTUDY_ID });
ElMessage.success("删除成功");
fnResetPagination();
},
{ atBegin: true }
);
const fnBatchDelete = debounce(
1000,
async () => {
const selectionData = tableRef.value.getSelectionRows();
if (selectionData.length === 0) {
ElMessage.warning("请选中要删除的项");
return;
}
await ElMessageBox.confirm("确定要删除选中的数据吗?", { type: "warning" });
const DATA_IDS = selectionData.map((item) => item.TEMPSTUDY_ID).join(",");
await setLearningGardenTaskBatchDelete({ DATA_IDS });
ElMessage.success("删除成功");
fnResetPagination();
},
{ atBegin: true }
);
const fnDisableOrEnable = debounce(
1000,
async (TEMPSTUDY_ID, STATUS) => {
const message = STATUS === 1 ? "禁用" : "启用";
await ElMessageBox.confirm(`确定要${message}吗?`, { type: "warning" });
await setLearningGardenTaskDisableOrEnable({ TEMPSTUDY_ID, STATUS });
ElMessage.success(`${message}成功`);
fnResetPagination();
},
{ atBegin: true }
);
const fnLearningSituation = (TEMPSTUDY_ID) => {
data.learningSituationDialog.TEMPSTUDY_ID = TEMPSTUDY_ID;
data.learningSituationDialog.visible = true;
};
</script>
<style scoped></style>

View File

@ -0,0 +1,125 @@
<template>
<layout-card>
<layout-table
:data="list"
v-model:pagination="pagination"
@get-data="fnGetDataTransfer"
>
<el-table-column label="序号" width="60">
<template #default="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<template v-if="levelType !== '2'">
<el-table-column label="目录名" width="220">
<template v-slot="{ row }">
<el-button
link
type="primary"
@click="
router.push({
path: '/learning_garden/regulatory_library',
query: {
MFOLDER_ID: row.MFOLDER_ID,
},
})
"
>
{{ row.NAME }}<el-icon><ArrowRight /></el-icon>
</el-button>
</template>
</el-table-column>
<el-table-column prop="CTIME" label="创建时间" />
<el-table-column label="是否共享">
<template v-slot="{ row }">
{{ row.SHARE === "no" ? "私有文件" : "公共文件" }}
</template>
</el-table-column>
<el-table-column prop="REMARKS" label="备注说明" />
</template>
<template v-if="levelType === '2'">
<el-table-column label="文件名">
<template v-slot="{ row }">
{{ row.NAME }}
<layout-multiple-attachment-previews :file-path="row.FILEPATH" />
</template>
</el-table-column>
<el-table-column prop="POSTNO" label="发文号" />
<el-table-column label="文件大小" width="100">
<template v-slot="{ row }">
{{ calculateFileSize(row.FILESIZE) }}
</template>
</el-table-column>
<el-table-column prop="CTIME" label="上传时间" width="150" />
<el-table-column prop="STARTTIME" label="颁布日期" width="150" />
<el-table-column prop="UNIT" label="颁布单位" />
<el-table-column prop="ENDTIME" label="实施日期" width="150" />
<el-table-column label="时效状态" width="100">
<template v-slot="{ row }">
{{ row.ISVALID === "0" ? "无效" : "有效" }}
</template>
</el-table-column>
<el-table-column label="操作" width="80">
<template v-slot="{ row }">
<el-button
v-show="MFOLDER_ID !== '0'"
type="primary"
text
link
@click="useDownloadFile(row.FILEPATH)"
>
下载
</el-button>
</template>
</el-table-column>
</template>
<template #button>
<el-button @click="router.back" v-if="MFOLDER_ID !== '0'">
返回
</el-button>
</template>
</layout-table>
</layout-card>
</template>
<script setup>
import { ref } from "vue";
import { serialNumber, calculateFileSize } from "@/assets/js/utils";
import { onBeforeRouteUpdate, useRoute, useRouter } from "vue-router";
import useListData from "@/assets/js/useListData.js";
import { ArrowRight } from "@element-plus/icons-vue";
import useDownloadFile from "@/assets/js/useDownloadFile.js";
import LayoutMultipleAttachmentPreviews from "@/components/multiple_attachment_previews/index.vue";
import { getRegulatoryLibraryList } from "@/request/learning_garden.js";
const router = useRouter();
const route = useRoute();
const mfolderIdDefault = "0";
const MFOLDER_ID = ref(route.query.MFOLDER_ID || mfolderIdDefault);
const levelType = ref("0");
const { list, pagination, fnGetData, fnResetPagination } = useListData(
getRegulatoryLibraryList,
{
otherParams: { MFOLDER_ID: MFOLDER_ID.value, SHARE: "yes" },
callbackFn: (list) => {
levelType.value = list?.[0]?.TYPE || "0";
},
}
);
const fnGetDataTransfer = () => {
fnGetData({
MFOLDER_ID: MFOLDER_ID.value,
});
};
const fnResetPaginationTransfer = () => {
fnResetPagination({
MFOLDER_ID: MFOLDER_ID.value,
});
};
onBeforeRouteUpdate((to) => {
MFOLDER_ID.value = to.query.MFOLDER_ID || mfolderIdDefault;
fnResetPaginationTransfer();
});
</script>
<style scoped></style>

View File

@ -178,15 +178,15 @@ const { list, pagination, searchForm, fnGetData, fnResetPagination } =
useListData(getMyTaskList, {
callbackFn: (list) => {
for (let i = 0; i < list.length; i++) {
if (dayjs(list[i].PEIXUE_START_TIME).diff(dayjs(), "day") > 0)
list[i].kaishiState = "1";
if (dayjs(list[i].PEIXUE_END_TIME).diff(dayjs(), "day") <= 0)
list[i].kaishiState = "3";
if (
dayjs(list[i].PEIXUE_START_TIME).diff(dayjs(), "day") <= 0 &&
dayjs(list[i].PEIXUE_END_TIME).diff(dayjs(), "day") >= 0
)
list[i].kaishiState = "2";
else if (dayjs(list[i].PEIXUE_END_TIME).diff(dayjs(), "day") <= 0)
list[i].kaishiState = "3";
else if (dayjs(list[i].PEIXUE_START_TIME).diff(dayjs(), "day") > 0)
list[i].kaishiState = "1";
let canExam = "0";
if (parseFloat(list[i].STAGEEXAMSCORE) >= parseFloat(list[i].PASSSCORE))
canExam = "0";

View File

@ -107,11 +107,13 @@
</span>
<span
class="text-green"
v-if="dayjs(row.PEIXUE_END_TIME).diff(dayjs(), 'day') <= 0"
v-else-if="dayjs(row.PEIXUE_END_TIME).diff(dayjs(), 'day') <= 0"
>
已结束
</span>
<span v-if="dayjs(row.PEIXUE_START_TIME).diff(dayjs(), 'day') > 0">
<span
v-else-if="dayjs(row.PEIXUE_START_TIME).diff(dayjs(), 'day') > 0"
>
未开始
</span>
</template>

View File

@ -2,7 +2,7 @@
<layout-card>
<el-tabs v-model="name" @tab-change="fnTabChange">
<el-tab-pane label="年度考核" name="year" lazy>
<list @assessment-standards="fnAssessmentStandards" type="year">
<list-view @assessment-standards="fnAssessmentStandards" type="year">
<template v-slot="{ searchForm }">
<el-col :span="4">
<el-form-item label="时间" prop="YEAR">
@ -17,10 +17,10 @@
</el-form-item>
</el-col>
</template>
</list>
</list-view>
</el-tab-pane>
<el-tab-pane label="季度考核" name="season" lazy>
<list @assessment-standards="fnAssessmentStandards" type="season">
<list-view @assessment-standards="fnAssessmentStandards" type="season">
<template v-slot="{ searchForm }">
<el-col :span="3">
<el-form-item label="年" prop="YEAR">
@ -45,10 +45,10 @@
</el-form-item>
</el-col>
</template>
</list>
</list-view>
</el-tab-pane>
<el-tab-pane label="月度考核" name="month" lazy>
<list @assessment-standards="fnAssessmentStandards" type="month">
<list-view @assessment-standards="fnAssessmentStandards" type="month">
<template v-slot="{ searchForm }">
<el-col :span="4">
<el-form-item label="时间" prop="MONTH">
@ -63,7 +63,7 @@
</el-form-item>
</el-col>
</template>
</list>
</list-view>
</el-tab-pane>
</el-tabs>
<assessment-standards v-model:visible="assessmentStandardsVisible" />
@ -72,7 +72,7 @@
<script setup>
import { ref } from "vue";
import List from "./components/list.vue";
import ListView from "./components/list.vue";
import AssessmentStandards from "./components/assessment_standards.vue";
import { useRouter, useRoute, onBeforeRouteUpdate } from "vue-router";

View File

@ -2,7 +2,7 @@
<layout-card>
<el-tabs v-model="name" @tab-change="fnTabChange">
<el-tab-pane label="年度考核" name="year" lazy>
<list @assessment-standards="fnAssessmentStandards" type="year">
<list-view @assessment-standards="fnAssessmentStandards" type="year">
<template v-slot="{ searchForm }">
<el-col :span="4">
<el-form-item label="时间" prop="YEAR">
@ -17,10 +17,10 @@
</el-form-item>
</el-col>
</template>
</list>
</list-view>
</el-tab-pane>
<el-tab-pane label="季度考核" name="season" lazy>
<list @assessment-standards="fnAssessmentStandards" type="season">
<list-view @assessment-standards="fnAssessmentStandards" type="season">
<template v-slot="{ searchForm }">
<el-col :span="3">
<el-form-item label="年" prop="YEAR">
@ -45,10 +45,10 @@
</el-form-item>
</el-col>
</template>
</list>
</list-view>
</el-tab-pane>
<el-tab-pane label="月度考核" name="month" lazy>
<list @assessment-standards="fnAssessmentStandards" type="month">
<list-view @assessment-standards="fnAssessmentStandards" type="month">
<template v-slot="{ searchForm }">
<el-col :span="4">
<el-form-item label="时间" prop="MONTH">
@ -63,7 +63,7 @@
</el-form-item>
</el-col>
</template>
</list>
</list-view>
</el-tab-pane>
</el-tabs>
<assessment-standards v-model:visible="assessmentStandardsVisible" />
@ -72,7 +72,7 @@
<script setup>
import { ref } from "vue";
import List from "./components/list.vue";
import ListView from "./components/list.vue";
import AssessmentStandards from "./components/assessment_standards.vue";
import { useRouter, useRoute, onBeforeRouteUpdate } from "vue-router";

View File

@ -0,0 +1,131 @@
<template>
<el-dialog v-model="visible" title="新增" :on-close="fnClose">
<div>
<el-form ref="formRef" :rules="rules" :model="form" label-width="80px">
<el-row :gutter="12">
<el-col :span="12">
<el-form-item label="时间" prop="USE_DATE">
<el-date-picker
v-model="form.USE_DATE"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
type="date"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="12">
<el-col :span="12">
<el-form-item label="使用类型" prop="USE_TYPE">
<el-select v-model="form.USE_TYPE">
<el-option value="1" label="预提" />
<el-option value="2" label="支出" />
</el-select>
</el-form-item>
</el-col>
<el-col v-if="form.USE_TYPE === '1'" :span="12">
<el-form-item label="金额(元)" prop="AMOUNT">
<el-input-number
v-model="form.AMOUNT"
:min="1"
precision="2"
controls-position="right"
/>
</el-form-item>
</el-col>
<template v-if="form.USE_TYPE === '2'">
<el-col :span="12">
<el-form-item label="用途摘要" prop="PURPOSESUMMARY">
<el-input v-model="form.PURPOSESUMMARY" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="费用项目" prop="TYPE">
<el-select v-model="form.TYPE">
<el-option
v-for="(item, index) in costItems"
:key="index"
:value="item"
:label="item"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="金额(元)" prop="AMOUNT">
<el-input-number
v-model="form.AMOUNT"
:min="1"
precision="2"
controls-position="right"
/>
</el-form-item>
</el-col>
</template>
</el-row>
</el-form>
</div>
<template #footer>
<el-button @click="fnClose"></el-button>
<el-button type="primary" @click="fnSubmit"> </el-button>
</template>
</el-dialog>
</template>
<script setup>
import { useVModel } from "@vueuse/core";
import { ref } from "vue";
import { debounce } from "throttle-debounce";
import useFormValidate from "@/assets/js/useFormValidate.js";
import { ElMessage } from "element-plus";
import { setExtractionAndUseAdd } from "@/request/security_investment.js";
const props = defineProps({
visible: {
type: Boolean,
required: true,
default: false,
},
costItems: {
type: Array,
required: true,
default: () => [],
},
});
const emits = defineEmits(["update:visible", "get-data"]);
const visible = useVModel(props, "visible", emits);
const rules = {
USE_DATE: [{ required: true, message: "请选择使用时间", trigger: "change" }],
USE_TYPE: [{ required: true, message: "请选择使用类型", trigger: "change" }],
AMOUNT: [{ required: true, message: "金额不能为空", trigger: "blur" }],
PURPOSESUMMARY: [
{ required: true, message: "用途摘要不能为空", trigger: "blur" },
],
TYPE: [{ required: true, message: "费用项目不能为空", trigger: "change" }],
};
const formRef = ref(null);
const form = ref({
USE_DATE: "",
USE_TYPE: "",
AMOUNT: "",
PURPOSESUMMARY: "",
TYPE: "",
});
const fnClose = () => {
formRef.value.resetFields();
visible.value = false;
};
const fnSubmit = debounce(
1000,
async () => {
await useFormValidate(formRef);
await setExtractionAndUseAdd({ ...form.value });
ElMessage.success("新增成功");
fnClose();
emits("get-data");
},
{ atBegin: true }
);
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,220 @@
<template>
<div>
<el-card>
<el-form
:model="searchForm"
label-width="90px"
@submit.prevent="fnGetData"
>
<el-row>
<el-col :span="6">
<el-form-item label="计划年份" prop="YEAR">
<el-select v-model="searchForm.YEAR">
<el-option
v-for="item in yearList"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</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="fnGetData">
重置
</el-button>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item class="end">
<el-button v-print="'#printContent'"> </el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<layout-card>
<layout-table
ref="tableRef"
row-key="SAFETYINVESTMENTUSE_ID"
:data="list"
:show-pagination="false"
show-summary
:summary-method="fnGetSummaries"
>
<el-table-column reserve-selection type="selection" width="55" />
<el-table-column label="序号" width="60" type="index" />
<el-table-column prop="USE_DATE" label="日期" />
<el-table-column label="预提额">
<template v-slot="{ row }">
<span v-if="row.USE_TYPE === '1'">{{ row.AMOUNT }}</span>
</template>
</el-table-column>
<el-table-column label="用途摘要">
<template v-slot="{ row }">
<span v-if="row.USE_TYPE === '2'">{{ row.PURPOSESUMMARY }}</span>
</template>
</el-table-column>
<el-table-column label="费用项目">
<el-table-column
v-for="(item, index) in costItems"
:key="index"
:label="item"
>
<template v-slot="{ row }">
<span v-if="row.TYPE === item">
{{ row.AMOUNT }}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column prop="TOTAL" label="余额" />
<template #button>
<el-button type="primary" @click="addDialogVisible = true">
新增
</el-button>
<el-button type="danger" @click="fnDelete"></el-button>
</template>
</layout-table>
<div id="printContent">
<table class="print_use">
<thead>
<tr>
<th rowspan="2" style="width: 55px">日期</th>
<th rowspan="2" style="width: 70px">预提额</th>
<th rowspan="2" style="width: 85px">用途摘要</th>
<th colspan="10" class="tc">费用项目</th>
<th rowspan="2" style="width: 55px">余额</th>
</tr>
<tr>
<th v-for="(item, index) in costItems" :key="index">
{{ item }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in list" :key="index">
<td>{{ item.USE_DATE }}</td>
<td>{{ item.USE_TYPE === "1" ? item.AMOUNT : "" }}</td>
<td>{{ item.USE_TYPE === "2" ? item.PURPOSESUMMARY : "" }}</td>
<td v-for="(item1, index1) in costItems" :key="index1">
{{ item.TYPE === item1 ? item.AMOUNT : "" }}
</td>
<td>{{ item.TOTAL }}</td>
</tr>
</tbody>
</table>
<div v-html="PRINT_STYLE" />
</div>
</layout-card>
<add
v-model:visible="addDialogVisible"
:cost-items="costItems"
@get-data="fnGetData"
/>
</div>
</template>
<script setup>
import useListData from "@/assets/js/useListData.js";
import {
getExtractionAndUseList,
setExtractionAndUseBatchDelete,
} from "@/request/security_investment.js";
import { debounce } from "throttle-debounce";
import { ElMessage, ElMessageBox } from "element-plus";
import { ref } from "vue";
import Add from "./components/add.vue";
import { PRINT_STYLE } from "@/assets/js/constant.js";
const yearList = (() => {
const year = new Date().getFullYear();
const arr = [];
for (let i = 2021; i <= year + 1; i++) {
arr.push(i);
}
return arr;
})();
const costItems = [
"完善、改造和维护安全防护设备设施和器具",
"安全生产宣传、教育培训、技术研究和推广",
"安全评价、标准化建设等安全技术服务",
"安全生产风险因素辨识管控和事故隐患排查治理",
"重大危险源监控、设备设施安全性能检测检验",
"劳动防护用品配备、更换和安全生产津贴、奖金发放",
"应急管理、事故救援演练以及救援队伍建设",
"安全标志及标识",
"配备劳动防护用品",
"其它与安全生产直接相关的物品或者活动",
];
const addDialogVisible = ref(false);
const { list, searchForm, fnGetData, tableRef } = useListData(
getExtractionAndUseList,
{
usePagination: false,
defaultSearchForm: {
YEAR: new Date().getFullYear(),
},
callbackFn: (list) => {
for (let i = 0; i < list.length; i++) {
if (i === 0) {
if (list[i].USE_TYPE === "1") list[i].TOTAL = list[i].AMOUNT;
else list[i].TOTAL = 0 - list[i].AMOUNT;
} else {
if (list[i].USE_TYPE === "1")
list[i].TOTAL = list[i - 1].TOTAL + list[i].AMOUNT;
else list[i].TOTAL = list[i - 1].TOTAL - list[i].AMOUNT;
}
}
},
}
);
const fnGetSummaries = ({ columns, data }) => {
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = "合计";
return;
}
if (index !== columns.length - 1) {
sums[index] = "--";
return;
}
const values = data.map((item) => Number(item[column.property]));
if (!values.every((value) => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
sums[index] = "--";
}
});
return sums;
};
const fnDelete = debounce(
1000,
async () => {
const selectionData = tableRef.value.getSelectionRows();
if (selectionData.length === 0) {
ElMessage.warning("请选中要删除的项");
return;
}
await ElMessageBox.confirm("确定要删除选中的数据吗?", { type: "warning" });
const DATA_IDS = selectionData
.map((item) => item.SAFETYINVESTMENTUSE_ID)
.join(",");
await setExtractionAndUseBatchDelete({ DATA_IDS });
ElMessage.success("删除成功");
fnGetData();
},
{ atBegin: true }
);
</script>
<style scoped></style>

View File

@ -0,0 +1,227 @@
<template>
<el-dialog
v-model="visible"
:title="type === 'add' ? '新增' : '修改'"
:on-close="fnClose"
width="1500"
>
<el-form ref="formRef" :rules="rules" :model="form" label-width="110px">
<el-row>
<el-col :span="8">
<el-form-item label="计划名称" prop="PLAN_NAME">
<el-input v-model="form.PLAN_NAME" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="计划年份" prop="PLAN_YEAR">
<el-select v-model="form.PLAN_YEAR">
<el-option
v-for="item in yearList"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="计划周期" prop="PLAN_PERIOD">
<el-select v-model="form.PLAN_PERIOD">
<el-option
v-for="item in planPeriodList"
:key="item.ID"
:value="item.ID"
:label="item.NAME"
/>
</el-select>
</el-form-item>
</el-col>
<template
v-for="(item, index) in form.infos"
:key="item.id || item.SAFETYINVESTMENTPLANINFO_ID"
>
<el-col :span="8">
<el-form-item
:label="'费用类型' + (index + 1)"
:prop="'infos.' + index + '.TYPE'"
:rules="{ required: true, message: '请选择费用类型' }"
>
<el-select v-model="item.TYPE">
<el-option
v-for="item in typeList"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
:label="'明细' + (index + 1)"
:prop="'infos.' + index + '.DESCR'"
:rules="{
required: true,
message: '请输入明细',
trigger: 'blur',
}"
>
<el-input v-model="item.DESCR" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item
:label="'金额' + (index + 1)"
:prop="'infos.' + index + '.AMOUNT'"
:rules="[
{
required: true,
message: '请输入金额',
trigger: 'blur',
},
{
type: 'number',
message: '请输入数字',
trigger: 'blur',
},
]"
>
<el-input
v-model.number="item.AMOUNT"
@input="fnCalculateTotalAmount"
>
<template v-slot:append></template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="2">
<el-form-item label-width="0" class="end">
<el-button v-show="index === 0" type="primary" @click="fnAddInfo">
添加使用明细
</el-button>
<el-button
v-show="index > 0"
type="danger"
@click="fnRemoveInfo(index)"
>
删除使用明细
</el-button>
</el-form-item>
</el-col>
</template>
<el-col :span="24">
<el-form-item label="总金额" prop="TOTAL_AMOUNT">
<el-input
v-model="form.TOTAL_AMOUNT"
placeholder="这里输入总金额..."
readonly
>
<template v-slot:append></template>
</el-input>
</el-form-item>
</el-col>
</el-row>
</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 { ElMessage } from "element-plus";
import { sumBy } from "lodash-es";
import { setPlanAdd, setPlanEdit } from "@/request/security_investment.js";
const props = defineProps({
visible: {
type: Boolean,
required: true,
default: false,
},
form: {
type: Object,
required: true,
default: () => ({}),
},
type: {
type: String,
required: true,
default: "add",
},
yearList: {
type: Array,
required: true,
default: () => [],
},
planPeriodList: {
type: Array,
required: true,
default: () => [],
},
});
const emits = defineEmits(["update:visible", "update:form", "get-data"]);
const { visible, form } = useVModels(props, emits);
const typeList = [
"完善、改造和维护安全防护设备设施",
"安全生产教育培训教育",
"安全评价、重大危险源监控、事故隐患评估和整改",
"设备设施安全性能检测检验",
"应急救援器材、装备的配备及应急救援演练",
"安全标志及标识",
"配备劳动防护用品",
"他与安全生产直接相关的物品或者活动",
];
const rules = {
PLAN_NAME: [
{ required: true, message: "计划名称不能为空", trigger: "change" },
],
PLAN_YEAR: [
{ required: true, message: "计划年份不能为空", trigger: "change" },
],
PLAN_PERIOD: [
{ required: true, message: "计划周期不能为空", trigger: "blur" },
],
TOTAL_AMOUNT: [
{ required: true, message: "总金额不能为空", trigger: "blur" },
],
};
const formRef = ref(null);
const fnAddInfo = () => {
form.value.infos.push({ TYPE: "", DESCR: "", AMOUNT: 0, id: Math.random() });
};
const fnRemoveInfo = (index) => {
form.value.infos.splice(index, 1);
fnCalculateTotalAmount();
};
const fnCalculateTotalAmount = () => {
form.value.TOTAL_AMOUNT = sumBy(form.value.infos, (item) => item.AMOUNT);
};
const fnClose = () => {
formRef.value.resetFields();
visible.value = false;
};
const fnSubmit = debounce(
1000,
async () => {
await useFormValidate(formRef);
const params = {
...form.value,
STATUS: 0,
info: JSON.stringify(form.value.infos),
};
props.type === "add" ? await setPlanAdd(params) : await setPlanEdit(params);
ElMessage.success("操作成功");
fnClose();
emits("get-data");
},
{ atBegin: true }
);
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,80 @@
<template>
<el-dialog v-model="visible" title="查看" width="1500">
<el-descriptions :column="3" border>
<el-descriptions-item label="计划名称">
{{ info.PLAN_NAME }}
</el-descriptions-item>
<el-descriptions-item label="计划年份">
{{ info.PLAN_YEAR }}
</el-descriptions-item>
<el-descriptions-item label="计划周期">
{{ info.PLAN_PERIOD }}
</el-descriptions-item>
<template v-for="(item, index) in info.infos" :key="index">
<el-descriptions-item label="费用类型">
{{ item.TYPE }}
</el-descriptions-item>
<el-descriptions-item label="明细">
{{ item.DESCR }}
</el-descriptions-item>
<el-descriptions-item label="金额">
{{ item.AMOUNT }}
</el-descriptions-item>
</template>
<el-descriptions-item label="总金额">
{{ info.TOTAL_AMOUNT }}
</el-descriptions-item>
</el-descriptions>
<template #footer>
<template v-if="type === 'review'">
<el-button type="primary" @click="fnSubmit(1)"></el-button>
<el-button type="danger" @click="fnSubmit(-1)"></el-button>
</template>
<el-button @click="fnClose"></el-button>
</template>
</el-dialog>
</template>
<script setup>
import { useVModel } from "@vueuse/core";
import { setPlanReview } from "@/request/security_investment.js";
import { debounce } from "throttle-debounce";
import { ElMessage } from "element-plus";
const props = defineProps({
visible: {
type: Boolean,
required: true,
default: false,
},
info: {
type: Object,
required: true,
default: () => ({}),
},
type: {
type: String,
default: "view",
},
});
const emits = defineEmits(["update:visible", "get-data"]);
const visible = useVModel(props, "visible", emits);
const fnClose = () => {
visible.value = false;
};
const fnSubmit = debounce(
1000,
async (STATUS) => {
await setPlanReview({
SAFETYINVESTMENTPLAN_ID: props.info.SAFETYINVESTMENTPLAN_ID,
STATUS,
});
ElMessage.success(`${STATUS === 1 ? "通过" : "打回"}成功`);
fnClose();
emits("get-data");
},
{ atBegin: true }
);
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,262 @@
<template>
<div>
<el-card>
<el-form
:model="searchForm"
label-width="90px"
@submit.prevent="fnResetPagination"
>
<el-row>
<el-col :span="5">
<el-form-item label="计划名称" prop="KEYWORDS">
<el-input v-model="searchForm.KEYWORDS" />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="计划年份" prop="PLAN_YEAR">
<el-select v-model="searchForm.PLAN_YEAR">
<el-option
v-for="item in yearList"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="计划周期" prop="PLAN_PERIOD">
<el-select v-model="searchForm.PLAN_PERIOD">
<el-option
v-for="item in planPeriodList"
:key="item.ID"
:value="item.ID"
:label="item.NAME"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="状态" prop="STATUS">
<el-select v-model="searchForm.STATUS">
<el-option
v-for="item in statusList"
:key="item.ID"
:value="item.ID"
:label="item.NAME"
/>
</el-select>
</el-form-item>
</el-col>
<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">
重置
</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<layout-card>
<layout-table
ref="tableRef"
row-key="SAFETYINVESTMENTPLAN_ID"
:data="list"
@get-data="fnGetData"
v-model:pagination="pagination"
>
<el-table-column reserve-selection type="selection" width="55" />
<el-table-column label="序号" width="60">
<template #default="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column prop="PLAN_NAME" label="计划名称" />
<el-table-column prop="PLAN_YEAR" label="计划年份" />
<el-table-column prop="PLAN_PERIOD" label="计划周期" />
<el-table-column prop="INFO_COUNT" label="涉及费用项数" />
<el-table-column prop="TOTAL_AMOUNT" label="总金额" />
<el-table-column prop="CREATOR" label="编制人" />
<el-table-column label="审核人">
<template v-slot="{ row }">
<span v-if="row.STATUS !== 0">{{ row.OPERATOR }}</span>
</template>
</el-table-column>
<el-table-column label="状态">
<template v-slot="{ row }">
{{ translationStatus(row.STATUS, statusList) }}
</template>
</el-table-column>
<el-table-column label="操作" width="150">
<template v-slot="{ row }">
<el-button
type="primary"
text
link
@click="fnView(row.SAFETYINVESTMENTPLAN_ID)"
>
查看
</el-button>
<el-button
v-if="buttonJurisdiction.del && row.STATUS < 1"
type="primary"
text
link
@click="fnDelete(row.SAFETYINVESTMENTPLAN_ID)"
>
删除
</el-button>
<el-button
v-if="buttonJurisdiction.edit && row.STATUS < 1"
type="primary"
text
link
@click="fnAddOrEdit(row.SAFETYINVESTMENTPLAN_ID, 'edit')"
>
编辑
</el-button>
</template>
</el-table-column>
<template #button>
<el-button
v-if="buttonJurisdiction.add"
type="primary"
@click="fnAddOrEdit('', 'add')"
>
新增
</el-button>
<el-button
v-if="buttonJurisdiction.del"
type="danger"
@click="fnBatchDelete"
>
批量删除
</el-button>
</template>
</layout-table>
</layout-card>
<view-info
v-model:visible="data.viewDialog.visible"
:info="data.viewDialog.info"
/>
<add
v-model:visible="data.addDialog.visible"
v-model:form="data.addDialog.form"
:type="data.addDialog.type"
:year-list="yearList"
:plan-period-list="planPeriodList"
@get-data="fnResetPagination"
/>
</div>
</template>
<script setup>
import { serialNumber, translationStatus } from "@/assets/js/utils";
import useListData from "@/assets/js/useListData.js";
import { debounce } from "throttle-debounce";
import { ElMessage, ElMessageBox } from "element-plus";
import {
getPlanList,
getPlanView,
setPlanBatchDelete,
setPlanDelete,
} from "@/request/security_investment.js";
import useButtonJurisdiction from "@/assets/js/useButtonJurisdiction.js";
import ViewInfo from "./components/view.vue";
import add from "./components/add.vue";
import { nextTick, reactive } from "vue";
const yearList = (() => {
const year = new Date().getFullYear();
const arr = [];
for (let i = 2021; i <= year + 1; i++) {
arr.push(i);
}
return arr;
})();
const planPeriodList = [
{ NAME: "季度计划1", ID: "季度计划1" },
{ NAME: "季度计划2", ID: "季度计划2" },
{ NAME: "季度计划3", ID: "季度计划3" },
{ NAME: "季度计划4", ID: "季度计划4" },
];
const statusList = [
{ NAME: "待审核", ID: 0 },
{ NAME: "已归档", ID: 1 },
{ NAME: "已打回", ID: -1 },
];
const { list, pagination, searchForm, fnGetData, fnResetPagination, tableRef } =
useListData(getPlanList);
const data = reactive({
viewDialog: {
visible: false,
info: {},
},
addDialog: {
visible: false,
type: "",
form: {
PLAN_NAME: "",
PLAN_YEAR: "",
PLAN_PERIOD: "",
TOTAL_AMOUNT: 0,
infos: [],
},
},
});
const buttonJurisdiction = await useButtonJurisdiction("safetyinvestmentplan");
const fnDelete = debounce(
1000,
async (SAFETYINVESTMENTPLAN_ID) => {
await ElMessageBox.confirm(`确定要删除吗?`, {
type: "warning",
});
await setPlanDelete({ SAFETYINVESTMENTPLAN_ID });
ElMessage.success(`删除成功`);
fnResetPagination();
},
{ atBegin: true }
);
const fnBatchDelete = debounce(
1000,
async () => {
const selectionData = tableRef.value.getSelectionRows();
if (selectionData.length === 0) {
ElMessage.warning("请选中要删除的项");
return;
}
await ElMessageBox.confirm("确定要删除选中的数据吗?", { type: "warning" });
const DATA_IDS = selectionData
.map((item) => item.SAFETYINVESTMENTPLAN_ID)
.join(",");
await setPlanBatchDelete({ DATA_IDS });
ElMessage.success("删除成功");
fnResetPagination();
},
{ atBegin: true }
);
const fnView = async (SAFETYINVESTMENTPLAN_ID) => {
const resData = await getPlanView({ SAFETYINVESTMENTPLAN_ID });
data.viewDialog.info = resData.pd;
data.viewDialog.info.infos = resData.infoList;
data.viewDialog.visible = true;
};
const fnAddOrEdit = async (SAFETYINVESTMENTPLAN_ID, type) => {
data.addDialog.visible = true;
await nextTick();
data.addDialog.type = type;
if (type === "edit") {
const resData = await getPlanView({ SAFETYINVESTMENTPLAN_ID });
data.addDialog.form = resData.pd;
data.addDialog.form.infos = resData.infoList;
} else {
data.addDialog.form.infos = [
{ TYPE: "", DESCR: "", AMOUNT: 0, id: Math.random() },
];
}
};
</script>
<style scoped></style>

View File

@ -0,0 +1,155 @@
<template>
<div>
<el-card>
<el-form
:model="searchForm"
label-width="90px"
@submit.prevent="fnResetPagination"
>
<el-row>
<el-col :span="5">
<el-form-item label="计划名称" prop="KEYWORDS">
<el-input v-model="searchForm.KEYWORDS" />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="计划年份" prop="PLAN_YEAR">
<el-select v-model="searchForm.PLAN_YEAR">
<el-option
v-for="item in yearList"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="计划周期" prop="PLAN_PERIOD">
<el-select v-model="searchForm.PLAN_PERIOD">
<el-option
v-for="item in planPeriodList"
:key="item.ID"
:value="item.ID"
:label="item.NAME"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="状态" prop="STATUS">
<el-select v-model="searchForm.STATUS">
<el-option
v-for="item in statusList"
:key="item.ID"
:value="item.ID"
:label="item.NAME"
/>
</el-select>
</el-form-item>
</el-col>
<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">
重置
</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<layout-card>
<layout-table
:data="list"
@get-data="fnGetData"
v-model:pagination="pagination"
>
<el-table-column label="序号" width="60">
<template #default="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column prop="PLAN_NAME" label="计划名称" />
<el-table-column prop="PLAN_YEAR" label="计划年份" />
<el-table-column prop="PLAN_PERIOD" label="计划周期" />
<el-table-column prop="INFO_COUNT" label="涉及费用项数" />
<el-table-column prop="TOTAL_AMOUNT" label="总金额" />
<el-table-column prop="CREATOR" label="编制人" />
<el-table-column label="审核人">
<template v-slot="{ row }">
<span v-if="row.STATUS !== 0">{{ row.OPERATOR }}</span>
</template>
</el-table-column>
<el-table-column label="状态">
<template v-slot="{ row }">
{{ translationStatus(row.STATUS, statusList) }}
</template>
</el-table-column>
<el-table-column label="操作" width="80">
<template v-slot="{ row }">
<el-button
v-if="row.STATUS === 0"
type="primary"
text
link
@click="fnReview(row.SAFETYINVESTMENTPLAN_ID)"
>
审核
</el-button>
</template>
</el-table-column>
</layout-table>
</layout-card>
<view-info
v-model:visible="data.reviewDialog.visible"
:info="data.reviewDialog.info"
type="review"
@get-data="fnResetPagination"
/>
</div>
</template>
<script setup>
import { serialNumber, translationStatus } from "@/assets/js/utils";
import useListData from "@/assets/js/useListData.js";
import { getPlanList, getPlanView } from "@/request/security_investment.js";
import ViewInfo from "../plan/components/view.vue";
import { reactive } from "vue";
const yearList = (() => {
const year = new Date().getFullYear();
const arr = [];
for (let i = 2021; i <= year + 1; i++) {
arr.push(i);
}
return arr;
})();
const planPeriodList = [
{ NAME: "季度计划1", ID: "季度计划1" },
{ NAME: "季度计划2", ID: "季度计划2" },
{ NAME: "季度计划3", ID: "季度计划3" },
{ NAME: "季度计划4", ID: "季度计划4" },
];
const statusList = [
{ NAME: "待审核", ID: 0 },
{ NAME: "已归档", ID: 1 },
{ NAME: "已打回", ID: -1 },
];
const { list, pagination, searchForm, fnGetData, fnResetPagination } =
useListData(getPlanList);
const data = reactive({
reviewDialog: {
visible: false,
info: {},
},
});
const fnReview = async (SAFETYINVESTMENTPLAN_ID) => {
const resData = await getPlanView({ SAFETYINVESTMENTPLAN_ID });
data.reviewDialog.info = resData.pd;
data.reviewDialog.info.infos = resData.infoList;
data.reviewDialog.visible = true;
};
</script>
<style scoped></style>

View File

@ -31,49 +31,7 @@
<el-table-column v-if="MFOLDER_ID !== '0'" label="文件名">
<template v-slot="{ row }">
{{ row.NAME }}
<el-button
link
type="primary"
v-if="interceptTheSuffix(row.FILEPATH, '.txt')"
@click="fnPreviewTxt(row.FILEPATH)"
>
[预览]
</el-button>
<el-button
text
link
type="primary"
v-if="interceptTheSuffix(row.FILEPATH, '.pdf')"
@click="fnPreviewPdf(row.FILEPATH)"
>
[预览]
</el-button>
<el-button
link
type="primary"
v-if="interceptTheSuffix(row.FILEPATH, '.mp4')"
@click="fnPreviewVideo(row.FILEPATH)"
>
[预览]
</el-button>
<a
v-if="
interceptTheSuffix(row.FILEPATH, '.doc') ||
interceptTheSuffix(row.FILEPATH, '.xls') ||
interceptTheSuffix(row.FILEPATH, '.ppt') ||
interceptTheSuffix(row.FILEPATH, '.docx') ||
interceptTheSuffix(row.FILEPATH, '.xlsx') ||
interceptTheSuffix(row.FILEPATH, '.pptx')
"
:href="
'http://view.officeapps.live.com/op/view.aspx?src=' +
VITE_FILE_URL +
row.FILEPATH
"
target="_blank"
>
[预览]
</a>
<layout-multiple-attachment-previews :file-path="row.FILEPATH" />
</template>
</el-table-column>
<el-table-column v-if="MFOLDER_ID === '0'" prop="num" label="文件数量" />
@ -139,18 +97,6 @@
</template>
</template>
</layout-table>
<layout-pdf
:src="data.pdfDialog.src"
v-model:visible="data.pdfDialog.visible"
/>
<layout-txt
:src="data.txtDialog.src"
v-model:visible="data.txtDialog.visible"
/>
<layout-video
:src="data.videoDialog.src"
v-model:visible="data.videoDialog.visible"
/>
<add-folder
v-model:visible="data.addFolderDialogVisible"
:mfolder-id="MFOLDER_ID"
@ -175,14 +121,7 @@ import {
setSystemDocumentsDelete,
} from "@/request/system_operation.js";
import { reactive, ref } from "vue";
import LayoutPdf from "@/components/pdf/index";
import LayoutTxt from "@/components/txt/index.vue";
import LayoutVideo from "@/components/video/index";
import {
serialNumber,
calculateFileSize,
interceptTheSuffix,
} from "@/assets/js/utils";
import { serialNumber, calculateFileSize } from "@/assets/js/utils";
import useButtonJurisdiction from "@/assets/js/useButtonJurisdiction.js";
import { onBeforeRouteUpdate, useRoute, useRouter } from "vue-router";
import useListData from "@/assets/js/useListData.js";
@ -194,8 +133,8 @@ import useDownloadFile from "@/assets/js/useDownloadFile.js";
import AddFolder from "./components/add_folder.vue";
import UploadFolder from "./components/upload_file.vue";
import BatchUploadFile from "./components/batch_upload_file.vue";
import LayoutMultipleAttachmentPreviews from "@/components/multiple_attachment_previews/index.vue";
const VITE_FILE_URL = import.meta.env.VITE_FILE_URL;
const router = useRouter();
const route = useRoute();
const userStore = useUserStore();
@ -212,18 +151,6 @@ const { list, pagination, fnGetData, fnResetPagination } = useListData(
}
);
const data = reactive({
pdfDialog: {
visible: false,
src: "",
},
videoDialog: {
visible: false,
src: "",
},
txtDialog: {
visible: false,
src: "",
},
addFolderDialogVisible: false,
uploadFileDialogVisible: false,
batchUploadFileDialogVisible: false,
@ -255,18 +182,6 @@ const fnDelete = debounce(
},
{ atBegin: true }
);
const fnPreviewTxt = async (FILEPATH) => {
data.txtDialog.visible = true;
data.txtDialog.src = FILEPATH;
};
const fnPreviewPdf = (FILEPATH) => {
data.pdfDialog.visible = true;
data.pdfDialog.src = FILEPATH;
};
const fnPreviewVideo = (FILEPATH) => {
data.videoDialog.visible = true;
data.videoDialog.src = FILEPATH;
};
</script>
<style scoped></style>

View File

@ -0,0 +1,177 @@
<template>
<div>
<el-form
:model="searchForm"
label-width="80px"
@submit.prevent="fnResetPaginationTransfer"
>
<el-row>
<el-col :span="6">
<el-form-item label="名称" prop="KEYWORDS">
<el-input
v-model="searchForm.KEYWORDS"
placeholder="请输入关键字"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="规程属性" prop="CATEGORY_LIST">
<layout-three-institutional-libraries
ref="regulationsRef"
v-model="searchForm.CATEGORY_LIST"
type="regulations"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="类型" prop="TYPES">
<layout-three-institutional-libraries
ref="typeRef"
v-model="searchForm.TYPES"
type="type"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item
label="国民经济行业类型"
prop="SPECIFICATION_TYPES"
label-width="130px"
>
<layout-three-institutional-libraries
ref="industryRef"
v-model="searchForm.SPECIFICATION_TYPES"
type="industry"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="标签" prop="LABELS">
<layout-three-institutional-libraries
ref="labelRef"
v-model="searchForm.LABELS"
type="label"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="企业" prop="CORPINFO_ID">
<el-select
v-model="searchForm.CORPINFO_ID"
:remote-method="fnRemoteMethod"
:loading="selectLoading"
filterable
remote
reserve-keyword
placeholder="请输入关键词"
>
<el-option
v-for="item in enterpriseList"
:key="item.CORPINFO_ID"
:label="item.CORP_NAME"
:value="item.CORPINFO_ID"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label-width="10px">
<el-button type="primary" native-type="submit">搜索</el-button>
<el-button native-type="reset" @click="fnResetPaginationTransfer">
重置
</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
<layout-table
:data="list"
v-model:pagination="pagination"
@get-data="fnGetDataTransfer"
>
<el-table-column label="序号" width="70">
<template v-slot="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column prop="REMARKS" label="安全生产管理制度名称" />
<el-table-column label="类型">
<template v-slot="{ row }">
{{
row.TYPES.map((item) => item.CATEGORY_NAME)
.filter(Boolean)
.join("、")
}}
</template>
</el-table-column>
<el-table-column label="标签">
<template v-slot="{ row }">
{{
row.labels
.map((item) => item.NAME)
.filter(Boolean)
.join("、")
}}
</template>
</el-table-column>
<el-table-column label="国民经济行业类型">
<template v-slot="{ row }">
<span v-if="row.SPECIFICATION_TYPES?.length > 0">
{{
row.SPECIFICATION_TYPES.map((item) => item.CATEGORY_NAME)
.filter(Boolean)
.join("、")
}}
</span>
<span v-else></span>
</template>
</el-table-column>
<el-table-column prop="UPLOAD_TIME" label="上传时间" width="150px" />
</layout-table>
</div>
</template>
<script setup>
import { serialNumber } from "@/assets/js/utils.js";
import useListData from "@/assets/js/useListData.js";
import { getThreeInstitutionalLibrariesList } from "@/request/three_institutional_libraries.js";
import LayoutThreeInstitutionalLibraries from "@/components/three_institutional_libraries/index.vue";
import { ref } from "vue";
import { getEnterpriseList } from "@/request/enterprise_management.js";
import { throttle } from "throttle-debounce";
const regulationsRef = ref(null);
const typeRef = ref(null);
const industryRef = ref(null);
const labelRef = ref(null);
const { list, pagination, searchForm, fnGetData, fnResetPagination } =
useListData(getThreeInstitutionalLibrariesList, {
otherParams: { ASSOCIATION: "2", ENTERPRISE_SIDE: "0" },
});
const fnGetCheckedNodes = () => {
return {
CATEGORY_LIST: JSON.stringify(regulationsRef.value.getCheckedNodes()),
TYPES: JSON.stringify(typeRef.value.getCheckedNodes()),
SPECIFICATION_TYPES: JSON.stringify(industryRef.value.getCheckedNodes()),
LABELS: JSON.stringify(labelRef.value.getCheckedNodes()),
};
};
const fnGetDataTransfer = () => {
fnGetData({ ...fnGetCheckedNodes() });
};
const fnResetPaginationTransfer = () => {
fnResetPagination({ ...fnGetCheckedNodes() });
};
const selectLoading = ref(false);
const enterpriseList = ref([]);
const fnRemoteMethod = throttle(500, async (query) => {
if (query) {
selectLoading.value = true;
const resData = await getEnterpriseList({ KEYWORDS: query });
enterpriseList.value = resData.varList;
selectLoading.value = false;
}
});
</script>
<style scoped></style>

View File

@ -0,0 +1,39 @@
<template>
<layout-card>
<el-tabs v-model="name" @tab-change="fnTabChange">
<el-tab-pane label="安全生产责任制" name="responsibility_system" lazy>
<list-view />
</el-tab-pane>
<el-tab-pane
label="安全生产责任制平台资源库"
name="platform_resource_library"
lazy
></el-tab-pane>
</el-tabs>
</layout-card>
</template>
<script setup>
import { ref } from "vue";
import { onBeforeRouteUpdate, useRoute, useRouter } from "vue-router";
import ListView from "./components/list.vue";
const router = useRouter();
const route = useRoute();
const defaultName = "responsibility_system";
const name = ref(route.query.name || defaultName);
onBeforeRouteUpdate((to, from, next) => {
name.value = to.query.name || defaultName;
next();
});
const fnTabChange = (name) => {
router.push({
path: "/three_institutional_libraries/safety_production_responsibility_system",
query: {
name,
},
});
};
</script>
<style scoped lang="scss"></style>