forked from integrated_whb/integrated_whb_vue
init
parent
7166ee57d8
commit
41a4ee6edd
|
@ -868,6 +868,22 @@ export default [
|
|||
path: "",
|
||||
component: "online_learn_exam/courseware/video/index",
|
||||
},
|
||||
{
|
||||
path: "/online_learn_exam/courseware/video/add",
|
||||
meta: {
|
||||
title: "添加",
|
||||
activeMenu: "/online_learn_exam/courseware/video",
|
||||
},
|
||||
component: "online_learn_exam/courseware/video/add",
|
||||
},
|
||||
{
|
||||
path: "/online_learn_exam/courseware/video/edit",
|
||||
meta: {
|
||||
title: "修改",
|
||||
activeMenu: "/online_learn_exam/courseware/video",
|
||||
},
|
||||
component: "online_learn_exam/courseware/video/add",
|
||||
},
|
||||
{
|
||||
path: "/online_learn_exam/courseware/video/exercises",
|
||||
meta: {
|
||||
|
@ -887,6 +903,22 @@ export default [
|
|||
path: "",
|
||||
component: "online_learn_exam/courseware/data/index",
|
||||
},
|
||||
{
|
||||
path: "/online_learn_exam/courseware/data/add",
|
||||
meta: {
|
||||
title: "新增",
|
||||
activeMenu: "/online_learn_exam/courseware/data",
|
||||
},
|
||||
component: "online_learn_exam/courseware/data/add",
|
||||
},
|
||||
{
|
||||
path: "/online_learn_exam/courseware/data/edit",
|
||||
meta: {
|
||||
title: "修改",
|
||||
activeMenu: "/online_learn_exam/courseware/data",
|
||||
},
|
||||
component: "online_learn_exam/courseware/data/add",
|
||||
},
|
||||
{
|
||||
path: "/online_learn_exam/courseware/data/exercises",
|
||||
meta: {
|
||||
|
@ -916,6 +948,14 @@ export default [
|
|||
},
|
||||
component: "online_learn_exam/curriculum/view",
|
||||
},
|
||||
{
|
||||
path: "/online_learn_exam/curriculum/add",
|
||||
meta: {
|
||||
title: "新增",
|
||||
activeMenu: "/online_learn_exam/curriculum",
|
||||
},
|
||||
component: "online_learn_exam/curriculum/add",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
@ -0,0 +1,225 @@
|
|||
<template>
|
||||
<layout-card>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
:model="data.form"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="课件名称" prop="COURSEWARENAME">
|
||||
<el-input v-model="data.form.COURSEWARENAME" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训板块" prop="trainingSection">
|
||||
<layout-training-section-cascader
|
||||
v-model="data.form.trainingSection"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训行业类型" prop="TRAINTYPE">
|
||||
<layout-learning-train-type
|
||||
v-model="data.form.TRAINTYPE"
|
||||
type="industry"
|
||||
disabled
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="岗位培训类型" prop="POSTTYPE">
|
||||
<layout-learning-train-type
|
||||
v-model="data.form.POSTTYPE"
|
||||
type="post"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="课件学时(分钟)" prop="CLASSHOUR">
|
||||
<el-input-number v-model="data.form.CLASSHOUR" :min="1" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="讲师名称" prop="SPEAKER">
|
||||
<el-input v-model="data.form.SPEAKER" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="课件文件" prop="file">
|
||||
<layout-upload
|
||||
v-model:file-list="data.form.file"
|
||||
accept=".pdf"
|
||||
:size="500"
|
||||
@preview="fnPreviewPdf"
|
||||
>
|
||||
<template #tip> 只能上传pdf文件 </template>
|
||||
</layout-upload>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="课件截图" prop="screenshotFile">
|
||||
<layout-upload
|
||||
v-model:file-list="data.form.screenshotFile"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
list-type="picture-card"
|
||||
>
|
||||
<template #tip> 建议上传尺寸224*160 </template>
|
||||
</layout-upload>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="课件描述" prop="COURSEWAREINTRODUCE">
|
||||
<el-input
|
||||
v-model="data.form.COURSEWAREINTRODUCE"
|
||||
type="textarea"
|
||||
:autosize="{
|
||||
minRows: 3,
|
||||
}"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="大纲类型" prop="ONTLINETYPE">
|
||||
<el-select v-model="data.form.ONTLINETYPE">
|
||||
<el-option
|
||||
v-for="item in outlineTypeList"
|
||||
:key="item.DICTIONARIES_ID"
|
||||
:label="item.NAME"
|
||||
:value="item.DICTIONARIES_ID"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="tc mt-10">
|
||||
<el-button type="primary" @click="fnSubmit">提交</el-button>
|
||||
</div>
|
||||
<layout-pdf
|
||||
:src="data.pdfDialog.src"
|
||||
v-model:visible="data.pdfDialog.visible"
|
||||
/>
|
||||
</layout-card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from "vue";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import { ElMessage } from "element-plus";
|
||||
import useFormValidate from "@/assets/js/useFormValidate.js";
|
||||
import LayoutTrainingSectionCascader from "@/components/training_section_cascader/index.vue";
|
||||
import LayoutLearningTrainType from "@/components/learning_train_type/index.vue";
|
||||
import LayoutUpload from "@/components/upload/index.vue";
|
||||
import { layoutFnGetOutlineType } from "@/assets/js/data_dictionary.js";
|
||||
import LayoutPdf from "@/components/pdf/index.vue";
|
||||
import {
|
||||
getDataCoursewareView,
|
||||
setDataCoursewareAdd,
|
||||
setDataCoursewareEdit,
|
||||
} from "@/request/online_learn_exam.js";
|
||||
import { getFileName } from "@/assets/js/utils.js";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useUserStore } from "@/pinia/user.js";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
const { DATACOURSEWARE_ID } = route.query;
|
||||
const VITE_FILE_URL = import.meta.env.VITE_FILE_URL;
|
||||
const rules = {
|
||||
COURSEWARENAME: [
|
||||
{ required: true, message: "请输入课件名称", trigger: "blur" },
|
||||
],
|
||||
CLASSHOUR: [{ required: true, message: "请输入课件学时", trigger: "blur" }],
|
||||
SPEAKER: [{ required: true, message: "请输入讲师名称", trigger: "blur" }],
|
||||
file: [{ required: true, message: "请上传课件文件", trigger: "change" }],
|
||||
screenshotFile: [
|
||||
{ required: true, message: "请上传课件截图", trigger: "change" },
|
||||
],
|
||||
COURSEWAREINTRODUCE: [
|
||||
{ required: true, message: "请输入课件描述", trigger: "blur" },
|
||||
],
|
||||
ONTLINETYPE: [
|
||||
{ required: true, message: "请选择大纲类型", trigger: "change" },
|
||||
],
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const data = reactive({
|
||||
form: {
|
||||
COURSEWARENAME: "",
|
||||
trainingSection: [],
|
||||
TRAINTYPE: "",
|
||||
POSTTYPE: "",
|
||||
CLASSHOUR: 1,
|
||||
SPEAKER: "",
|
||||
file: [],
|
||||
screenshotFile: [],
|
||||
COURSEWAREINTRODUCE: "",
|
||||
ONTLINETYPE: "",
|
||||
},
|
||||
pdfDialog: {
|
||||
src: "",
|
||||
visible: false,
|
||||
},
|
||||
});
|
||||
const fnGetData = async () => {
|
||||
if (!DATACOURSEWARE_ID)
|
||||
data.form.TRAINTYPE = userStore.getUserInfo.CORP_TRAINTYPE;
|
||||
else {
|
||||
const resData = await getDataCoursewareView({ DATACOURSEWARE_ID });
|
||||
data.form = resData.pd;
|
||||
data.form.screenshotFile = [
|
||||
{
|
||||
url: VITE_FILE_URL + resData.pd.COURSEWARECAPTURE,
|
||||
name: getFileName(resData.pd.COURSEWARECAPTURE),
|
||||
},
|
||||
];
|
||||
data.form.file = [
|
||||
{
|
||||
url: VITE_FILE_URL + resData.pd.COURSEWAREFILES,
|
||||
name: getFileName(resData.pd.COURSEWAREFILES),
|
||||
},
|
||||
];
|
||||
data.form.trainingSection = resData.coursewareAllList.map((item) =>
|
||||
item.DICTIONARIES_IDS.split(",")
|
||||
);
|
||||
}
|
||||
};
|
||||
fnGetData();
|
||||
const outlineTypeList = await layoutFnGetOutlineType();
|
||||
const fnPreviewPdf = async (event) => {
|
||||
data.pdfDialog.visible = true;
|
||||
data.pdfDialog.src = event.url;
|
||||
};
|
||||
const fnSubmit = debounce(
|
||||
1000,
|
||||
async () => {
|
||||
await useFormValidate(formRef);
|
||||
const formData = new FormData();
|
||||
Object.keys(data.form).forEach((key) => {
|
||||
formData.append(key, data.form[key]);
|
||||
});
|
||||
if (data.form.trainingSection.length > 0) {
|
||||
formData.delete("trainingSection");
|
||||
formData.append("trainingSection", data.form.trainingSection.join(";"));
|
||||
}
|
||||
formData.delete("file");
|
||||
formData.delete("screenshotFile");
|
||||
if (data.form.file[0].raw) formData.append("cfile", data.form.file[0].raw);
|
||||
if (data.form.screenshotFile[0].raw)
|
||||
formData.append("ccfile", data.form.screenshotFile[0].raw);
|
||||
formData.append("captureIsType", !!data.form.screenshotFile[0].raw);
|
||||
formData.append("fileIsType", !!data.form.file[0].raw);
|
||||
!DATACOURSEWARE_ID
|
||||
? await setDataCoursewareAdd(formData)
|
||||
: await setDataCoursewareEdit(formData);
|
||||
ElMessage.success("提交成功");
|
||||
router.back();
|
||||
},
|
||||
{ atBegin: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
|
@ -1,179 +0,0 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
:title="type === 'add' ? '新增' : '修改'"
|
||||
:before-close="fnClose"
|
||||
>
|
||||
<el-form ref="formRef" :rules="rules" :model="form" label-width="120px">
|
||||
<el-form-item label="课件名称" prop="COURSEWARENAME">
|
||||
<el-input v-model="form.COURSEWARENAME" />
|
||||
</el-form-item>
|
||||
<el-form-item label="培训板块" prop="trainingSection">
|
||||
<layout-training-section-cascader v-model="form.trainingSection" />
|
||||
</el-form-item>
|
||||
<el-form-item label="培训行业类型" prop="TRAINTYPE">
|
||||
<layout-learning-train-type
|
||||
v-model="form.TRAINTYPE"
|
||||
type="industry"
|
||||
disabled
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位培训类型" prop="POSTTYPE">
|
||||
<layout-learning-train-type v-model="form.POSTTYPE" type="post" />
|
||||
</el-form-item>
|
||||
<el-form-item label="课件学时(分钟)" prop="CLASSHOUR">
|
||||
<el-input-number v-model="form.CLASSHOUR" :min="1" />
|
||||
</el-form-item>
|
||||
<el-form-item label="讲师名称" prop="SPEAKER">
|
||||
<el-input v-model="form.SPEAKER" />
|
||||
</el-form-item>
|
||||
<el-form-item label="课件文件" prop="file">
|
||||
<layout-upload
|
||||
v-model:file-list="form.file"
|
||||
accept=".pdf"
|
||||
:size="500"
|
||||
@preview="fnPreviewPdf"
|
||||
>
|
||||
<template #tip> 只能上传pdf文件 </template>
|
||||
</layout-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="课件截图" prop="screenshotFile">
|
||||
<layout-upload
|
||||
v-model:file-list="form.screenshotFile"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
list-type="picture-card"
|
||||
>
|
||||
<template #tip> 建议上传尺寸224*160 </template>
|
||||
</layout-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="课件描述" prop="COURSEWAREINTRODUCE">
|
||||
<el-input
|
||||
v-model="form.COURSEWAREINTRODUCE"
|
||||
type="textarea"
|
||||
:autosize="{
|
||||
minRows: 3,
|
||||
}"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="大纲类型" prop="ONTLINETYPE">
|
||||
<el-select v-model="form.ONTLINETYPE">
|
||||
<el-option
|
||||
v-for="item in outlineTypeList"
|
||||
:key="item.DICTIONARIES_ID"
|
||||
:label="item.NAME"
|
||||
:value="item.DICTIONARIES_ID"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="fnClose">关闭</el-button>
|
||||
<el-button type="primary" @click="fnSubmit">提交</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<layout-pdf
|
||||
:src="data.pdfDialog.src"
|
||||
v-model:visible="data.pdfDialog.visible"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useVModels } from "@vueuse/core";
|
||||
import { reactive, ref } from "vue";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import { ElMessage } from "element-plus";
|
||||
import useFormValidate from "@/assets/js/useFormValidate.js";
|
||||
import LayoutTrainingSectionCascader from "@/components/training_section_cascader/index.vue";
|
||||
import LayoutLearningTrainType from "@/components/learning_train_type/index.vue";
|
||||
import LayoutUpload from "@/components/upload/index.vue";
|
||||
import { layoutFnGetOutlineType } from "@/assets/js/data_dictionary.js";
|
||||
import LayoutPdf from "@/components/pdf/index.vue";
|
||||
import {
|
||||
setDataCoursewareAdd,
|
||||
setDataCoursewareEdit,
|
||||
} from "@/request/online_learn_exam.js";
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "",
|
||||
},
|
||||
form: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(["update:visible", "update:form", "get-data"]);
|
||||
const { visible, form } = useVModels(props, emits);
|
||||
const rules = {
|
||||
COURSEWARENAME: [
|
||||
{ required: true, message: "请输入课件名称", trigger: "blur" },
|
||||
],
|
||||
CLASSHOUR: [{ required: true, message: "请输入课件学时", trigger: "blur" }],
|
||||
SPEAKER: [{ required: true, message: "请输入讲师名称", trigger: "blur" }],
|
||||
file: [{ required: true, message: "请上传课件文件", trigger: "change" }],
|
||||
screenshotFile: [
|
||||
{ required: true, message: "请上传课件截图", trigger: "change" },
|
||||
],
|
||||
COURSEWAREINTRODUCE: [
|
||||
{ required: true, message: "请输入课件描述", trigger: "blur" },
|
||||
],
|
||||
ONTLINETYPE: [
|
||||
{ required: true, message: "请选择大纲类型", trigger: "change" },
|
||||
],
|
||||
};
|
||||
const data = reactive({
|
||||
pdfDialog: {
|
||||
src: "",
|
||||
visible: false,
|
||||
},
|
||||
});
|
||||
const formRef = ref(null);
|
||||
const outlineTypeList = await layoutFnGetOutlineType();
|
||||
const fnPreviewPdf = async (event) => {
|
||||
data.pdfDialog.visible = true;
|
||||
data.pdfDialog.src = event.url;
|
||||
};
|
||||
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]);
|
||||
});
|
||||
if (form.value.trainingSection.length > 0) {
|
||||
formData.delete("trainingSection");
|
||||
formData.append("trainingSection", form.value.trainingSection.join(";"));
|
||||
}
|
||||
formData.delete("file");
|
||||
formData.delete("screenshotFile");
|
||||
if (form.value.file[0].raw)
|
||||
formData.append("cfile", form.value.file[0].raw);
|
||||
if (form.value.screenshotFile[0].raw)
|
||||
formData.append("ccfile", form.value.screenshotFile[0].raw);
|
||||
formData.append("captureIsType", !!form.value.screenshotFile[0].raw);
|
||||
formData.append("fileIsType", !!form.value.file[0].raw);
|
||||
props.type === "add"
|
||||
? await setDataCoursewareAdd(formData)
|
||||
: await setDataCoursewareEdit(formData);
|
||||
ElMessage.success("提交成功");
|
||||
fnClose();
|
||||
emits("get-data");
|
||||
},
|
||||
{ atBegin: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
|
@ -140,7 +140,14 @@
|
|||
row.STAGECOUNT === 0 &&
|
||||
row.ISPLATFORM === '0'
|
||||
"
|
||||
@click="fnAddOrEdit(row.DATACOURSEWARE_ID, 'edit')"
|
||||
@click="
|
||||
router.push({
|
||||
path: '/online_learn_exam/courseware/data/edit',
|
||||
query: {
|
||||
DATACOURSEWARE_ID: row.DATACOURSEWARE_ID,
|
||||
},
|
||||
})
|
||||
"
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
|
@ -180,7 +187,11 @@
|
|||
<el-button
|
||||
v-if="buttonJurisdiction.add"
|
||||
type="primary"
|
||||
@click="fnAddOrEdit('', 'add')"
|
||||
@click="
|
||||
router.push({
|
||||
path: '/online_learn_exam/courseware/data/add',
|
||||
})
|
||||
"
|
||||
>
|
||||
新增
|
||||
</el-button>
|
||||
|
@ -191,44 +202,29 @@
|
|||
:src="data.pdfDialog.src"
|
||||
v-model:visible="data.pdfDialog.visible"
|
||||
/>
|
||||
<add
|
||||
v-model:visible="data.addOrEditDialog.visible"
|
||||
v-model:form="data.addOrEditDialog.form"
|
||||
:type="data.addOrEditDialog.type"
|
||||
@get-data="fnResetPagination"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import LayoutLearningTrainType from "@/components/learning_train_type/index.vue";
|
||||
import {
|
||||
getDataCoursewareList,
|
||||
getDataCoursewareView,
|
||||
setDataCoursewareDelete,
|
||||
setDataCoursewareState,
|
||||
} from "@/request/online_learn_exam.js";
|
||||
import useListData from "@/assets/js/useListData.js";
|
||||
import { nextTick, reactive } from "vue";
|
||||
import {
|
||||
getFileName,
|
||||
serialNumber,
|
||||
translationStatus,
|
||||
} from "@/assets/js/utils.js";
|
||||
import { reactive } from "vue";
|
||||
import { serialNumber, translationStatus } from "@/assets/js/utils.js";
|
||||
import useButtonJurisdiction from "@/assets/js/useButtonJurisdiction.js";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { useRouter } from "vue-router";
|
||||
import LayoutPdf from "@/components/pdf/index.vue";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import { useUserStore } from "@/pinia/user.js";
|
||||
import Add from "./components/add.vue";
|
||||
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
const stateList = [
|
||||
{ ID: 0, NAME: "启用" },
|
||||
{ ID: 1, NAME: "禁用" },
|
||||
];
|
||||
const VITE_FILE_URL = import.meta.env.VITE_FILE_URL;
|
||||
const { list, pagination, searchForm, fnGetData, fnResetPagination } =
|
||||
useListData(getDataCoursewareList);
|
||||
const buttonJurisdiction = await useButtonJurisdiction("courseware");
|
||||
|
@ -237,22 +233,6 @@ const data = reactive({
|
|||
src: "",
|
||||
visible: false,
|
||||
},
|
||||
addOrEditDialog: {
|
||||
visible: false,
|
||||
type: "",
|
||||
form: {
|
||||
COURSEWARENAME: "",
|
||||
trainingSection: [],
|
||||
TRAINTYPE: "",
|
||||
POSTTYPE: "",
|
||||
CLASSHOUR: 1,
|
||||
SPEAKER: "",
|
||||
file: [],
|
||||
screenshotFile: [],
|
||||
COURSEWAREINTRODUCE: "",
|
||||
ONTLINETYPE: "",
|
||||
},
|
||||
},
|
||||
});
|
||||
const fnPreviewPdf = (FILEPATH) => {
|
||||
data.pdfDialog.visible = true;
|
||||
|
@ -284,32 +264,6 @@ const fnDelete = debounce(
|
|||
},
|
||||
{ atBegin: true }
|
||||
);
|
||||
const fnAddOrEdit = async (DATACOURSEWARE_ID, type) => {
|
||||
data.addOrEditDialog.visible = true;
|
||||
await nextTick();
|
||||
data.addOrEditDialog.type = type;
|
||||
if (type === "add")
|
||||
data.addOrEditDialog.form.TRAINTYPE = userStore.getUserInfo.CORP_TRAINTYPE;
|
||||
else {
|
||||
const resData = await getDataCoursewareView({ DATACOURSEWARE_ID });
|
||||
data.addOrEditDialog.form = resData.pd;
|
||||
data.addOrEditDialog.form.screenshotFile = [
|
||||
{
|
||||
url: VITE_FILE_URL + resData.pd.COURSEWARECAPTURE,
|
||||
name: getFileName(resData.pd.COURSEWARECAPTURE),
|
||||
},
|
||||
];
|
||||
data.addOrEditDialog.form.file = [
|
||||
{
|
||||
url: VITE_FILE_URL + resData.pd.COURSEWAREFILES,
|
||||
name: getFileName(resData.pd.COURSEWAREFILES),
|
||||
},
|
||||
];
|
||||
data.addOrEditDialog.form.trainingSection = resData.coursewareAllList.map(
|
||||
(item) => item.DICTIONARIES_IDS.split(",")
|
||||
);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
|
@ -0,0 +1,253 @@
|
|||
<template>
|
||||
<layout-card>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
:model="data.form"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="课件名称" prop="COURSEWARENAME">
|
||||
<el-input v-model="data.form.COURSEWARENAME" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训板块" prop="trainingSection">
|
||||
<layout-training-section-cascader
|
||||
v-model="data.form.trainingSection"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训行业类型" prop="TRAINTYPE">
|
||||
<layout-learning-train-type
|
||||
v-model="data.form.TRAINTYPE"
|
||||
type="industry"
|
||||
disabled
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="岗位培训类型" prop="POSTTYPE">
|
||||
<layout-learning-train-type
|
||||
v-model="data.form.POSTTYPE"
|
||||
type="post"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="讲师名称" prop="SPEAKER">
|
||||
<el-input v-model="data.form.SPEAKER" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="课件文件" prop="file">
|
||||
<layout-upload
|
||||
v-model:file-list="data.form.file"
|
||||
accept=".mp4"
|
||||
:size="500"
|
||||
@preview="fnPreviewVideo"
|
||||
>
|
||||
<template #tip>
|
||||
只能上传mp4文件,最大上传500M
|
||||
<el-progress
|
||||
:percentage="progressBar"
|
||||
v-if="progressBarVisible"
|
||||
/>
|
||||
</template>
|
||||
</layout-upload>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item
|
||||
label="课件截图"
|
||||
prop="screenshotFile"
|
||||
v-if="data.form.screenshotFile.length > 0"
|
||||
>
|
||||
<layout-upload
|
||||
v-model:file-list="data.form.screenshotFile"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
list-type="picture-card"
|
||||
disabled
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="课件描述" prop="COURSEWAREINTRODUCE">
|
||||
<el-input
|
||||
v-model="data.form.COURSEWAREINTRODUCE"
|
||||
type="textarea"
|
||||
:autosize="{
|
||||
minRows: 3,
|
||||
}"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="大纲类型" prop="ONTLINETYPE">
|
||||
<el-select v-model="data.form.ONTLINETYPE">
|
||||
<el-option
|
||||
v-for="item in outlineTypeList"
|
||||
:key="item.DICTIONARIES_ID"
|
||||
:label="item.NAME"
|
||||
:value="item.DICTIONARIES_ID"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="tc mt-10">
|
||||
<el-button type="primary" @click="fnSubmit">提交</el-button>
|
||||
</div>
|
||||
<layout-video
|
||||
:src="data.videoDialog.src"
|
||||
:vid="data.videoDialog.vid"
|
||||
:play-auth="data.videoDialog.playAuth"
|
||||
v-model:visible="data.videoDialog.visible"
|
||||
/>
|
||||
</layout-card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from "vue";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import { ElMessage } from "element-plus";
|
||||
import useFormValidate from "@/assets/js/useFormValidate.js";
|
||||
import LayoutTrainingSectionCascader from "@/components/training_section_cascader/index.vue";
|
||||
import LayoutLearningTrainType from "@/components/learning_train_type/index.vue";
|
||||
import LayoutUpload from "@/components/upload/index.vue";
|
||||
import { layoutFnGetOutlineType } from "@/assets/js/data_dictionary.js";
|
||||
import useAliYunUpload from "@/assets/js/useAliYunUpload.js";
|
||||
import {
|
||||
getVideoCoursewareView,
|
||||
setVideoCoursewareAdd,
|
||||
setVideoCoursewareEdit,
|
||||
} from "@/request/online_learn_exam.js";
|
||||
import LayoutVideo from "@/components/video/index.vue";
|
||||
import useAliYunVideoPreview from "@/assets/js/useAliYunVideoPreview.js";
|
||||
import { getFileName } from "@/assets/js/utils.js";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useUserStore } from "@/pinia/user.js";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
const { VIDEOCOURSEWARE_ID } = route.query;
|
||||
let uploader;
|
||||
const rules = {
|
||||
COURSEWARENAME: [
|
||||
{ required: true, message: "请输入课件名称", trigger: "blur" },
|
||||
],
|
||||
SPEAKER: [{ required: true, message: "请输入讲师名称", trigger: "blur" }],
|
||||
file: [{ required: true, message: "请上传课件文件", trigger: "change" }],
|
||||
COURSEWAREINTRODUCE: [
|
||||
{ required: true, message: "请输入课件描述", trigger: "blur" },
|
||||
],
|
||||
ONTLINETYPE: [
|
||||
{ required: true, message: "请选择大纲类型", trigger: "change" },
|
||||
],
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const progressBarVisible = ref(false);
|
||||
const progressBar = ref(0);
|
||||
const data = reactive({
|
||||
form: {
|
||||
COURSEWARENAME: "",
|
||||
trainingSection: [],
|
||||
TRAINTYPE: "",
|
||||
POSTTYPE: "",
|
||||
SPEAKER: "",
|
||||
file: [],
|
||||
screenshotFile: [],
|
||||
COURSEWAREINTRODUCE: "",
|
||||
ONTLINETYPE: "",
|
||||
},
|
||||
videoDialog: {
|
||||
src: "",
|
||||
vid: "",
|
||||
playAuth: "",
|
||||
visible: false,
|
||||
},
|
||||
});
|
||||
const fnGetData = async () => {
|
||||
if (!VIDEOCOURSEWARE_ID)
|
||||
data.form.TRAINTYPE = userStore.getUserInfo.CORP_TRAINTYPE;
|
||||
else {
|
||||
const resData = await getVideoCoursewareView({ VIDEOCOURSEWARE_ID });
|
||||
data.form = resData.pd;
|
||||
data.form.screenshotFile = [
|
||||
{
|
||||
url: resData.pd.VIDEOCAPTURE,
|
||||
name: getFileName(resData.pd.VIDEOCAPTURE),
|
||||
},
|
||||
];
|
||||
data.form.file = [
|
||||
{
|
||||
url: resData.pd.VIDEOFILES,
|
||||
name: getFileName(resData.pd.VIDEOFILES),
|
||||
},
|
||||
];
|
||||
data.form.trainingSection = resData.coursewareAllList.map((item) =>
|
||||
item.DICTIONARIES_IDS.split(",")
|
||||
);
|
||||
}
|
||||
};
|
||||
fnGetData();
|
||||
const outlineTypeList = await layoutFnGetOutlineType();
|
||||
const fnPreviewVideo = async () => {
|
||||
const { src, vid, playAuth, visible } = await useAliYunVideoPreview(
|
||||
data.form
|
||||
);
|
||||
data.videoDialog.src = src;
|
||||
data.videoDialog.vid = vid;
|
||||
data.videoDialog.playAuth = playAuth;
|
||||
data.videoDialog.visible = visible;
|
||||
};
|
||||
const fnSubmit = debounce(
|
||||
1000,
|
||||
async () => {
|
||||
await useFormValidate(formRef);
|
||||
if (data.form.file[0].raw) {
|
||||
uploader = useAliYunUpload({
|
||||
onUploadSucceed: (uploadInfo) => {
|
||||
fnSubmitForm(uploadInfo.videoId);
|
||||
},
|
||||
onUploadstarted: () => {
|
||||
progressBarVisible.value = true;
|
||||
},
|
||||
onUploadFailed: () => {
|
||||
progressBarVisible.value = false;
|
||||
},
|
||||
onUploadProgress: (uploadInfo, totalSize, progress) => {
|
||||
progressBar.value = Math.ceil(progress * 100);
|
||||
},
|
||||
});
|
||||
fnSubmitVideo();
|
||||
} else {
|
||||
await fnSubmitForm();
|
||||
}
|
||||
},
|
||||
{ atBegin: true }
|
||||
);
|
||||
const fnSubmitVideo = () => {
|
||||
uploader.addFile(data.form.file[0].raw, null, null, null, '{"Vod":{}}');
|
||||
uploader.startUpload();
|
||||
};
|
||||
const fnSubmitForm = async (videoId = "") => {
|
||||
const params = {
|
||||
...data.form,
|
||||
videoId,
|
||||
isEditVideo: !!data.form.file[0].raw,
|
||||
trainingSection: data.form.trainingSection.join(";"),
|
||||
};
|
||||
!VIDEOCOURSEWARE_ID
|
||||
? await setVideoCoursewareAdd(params)
|
||||
: await setVideoCoursewareEdit(params);
|
||||
ElMessage.success("提交成功");
|
||||
router.back();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
|
@ -1,209 +0,0 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
:title="type === 'add' ? '新增' : '修改'"
|
||||
:before-close="fnClose"
|
||||
>
|
||||
<el-form ref="formRef" :rules="rules" :model="form" label-width="120px">
|
||||
<el-form-item label="课件名称" prop="COURSEWARENAME">
|
||||
<el-input v-model="form.COURSEWARENAME" />
|
||||
</el-form-item>
|
||||
<el-form-item label="培训板块" prop="trainingSection">
|
||||
<layout-training-section-cascader v-model="form.trainingSection" />
|
||||
</el-form-item>
|
||||
<el-form-item label="培训行业类型" prop="TRAINTYPE">
|
||||
<layout-learning-train-type
|
||||
v-model="form.TRAINTYPE"
|
||||
type="industry"
|
||||
disabled
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位培训类型" prop="POSTTYPE">
|
||||
<layout-learning-train-type v-model="form.POSTTYPE" type="post" />
|
||||
</el-form-item>
|
||||
<el-form-item label="讲师名称" prop="SPEAKER">
|
||||
<el-input v-model="form.SPEAKER" />
|
||||
</el-form-item>
|
||||
<el-form-item label="课件文件" prop="file">
|
||||
<layout-upload
|
||||
v-model:file-list="form.file"
|
||||
accept=".mp4"
|
||||
:size="500"
|
||||
@preview="fnPreviewVideo"
|
||||
>
|
||||
<template #tip>
|
||||
只能上传mp4文件,最大上传500M
|
||||
<el-progress :percentage="progressBar" v-if="progressBarVisible" />
|
||||
</template>
|
||||
</layout-upload>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="课件截图"
|
||||
prop="screenshotFile"
|
||||
v-if="form.screenshotFile.length > 0"
|
||||
>
|
||||
<layout-upload
|
||||
v-model:file-list="form.screenshotFile"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
list-type="picture-card"
|
||||
disabled
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="课件描述" prop="COURSEWAREINTRODUCE">
|
||||
<el-input
|
||||
v-model="form.COURSEWAREINTRODUCE"
|
||||
type="textarea"
|
||||
:autosize="{
|
||||
minRows: 3,
|
||||
}"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="大纲类型" prop="ONTLINETYPE">
|
||||
<el-select v-model="form.ONTLINETYPE">
|
||||
<el-option
|
||||
v-for="item in outlineTypeList"
|
||||
:key="item.DICTIONARIES_ID"
|
||||
:label="item.NAME"
|
||||
:value="item.DICTIONARIES_ID"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="fnClose">关闭</el-button>
|
||||
<el-button type="primary" @click="fnSubmit">提交</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<layout-video
|
||||
:src="data.videoDialog.src"
|
||||
:vid="data.videoDialog.vid"
|
||||
:play-auth="data.videoDialog.playAuth"
|
||||
v-model:visible="data.videoDialog.visible"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useVModels } from "@vueuse/core";
|
||||
import { reactive, ref } from "vue";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import { ElMessage } from "element-plus";
|
||||
import useFormValidate from "@/assets/js/useFormValidate.js";
|
||||
import LayoutTrainingSectionCascader from "@/components/training_section_cascader/index.vue";
|
||||
import LayoutLearningTrainType from "@/components/learning_train_type/index.vue";
|
||||
import LayoutUpload from "@/components/upload/index.vue";
|
||||
import { layoutFnGetOutlineType } from "@/assets/js/data_dictionary.js";
|
||||
import useAliYunUpload from "@/assets/js/useAliYunUpload.js";
|
||||
import {
|
||||
setVideoCoursewareAdd,
|
||||
setVideoCoursewareEdit,
|
||||
} from "@/request/online_learn_exam.js";
|
||||
import LayoutVideo from "@/components/video/index.vue";
|
||||
import useAliYunVideoPreview from "@/assets/js/useAliYunVideoPreview.js";
|
||||
|
||||
let uploader;
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "",
|
||||
},
|
||||
form: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(["update:visible", "update:form", "get-data"]);
|
||||
const { visible, form } = useVModels(props, emits);
|
||||
const rules = {
|
||||
COURSEWARENAME: [
|
||||
{ required: true, message: "请输入课件名称", trigger: "blur" },
|
||||
],
|
||||
SPEAKER: [{ required: true, message: "请输入讲师名称", trigger: "blur" }],
|
||||
file: [{ required: true, message: "请上传课件文件", trigger: "change" }],
|
||||
COURSEWAREINTRODUCE: [
|
||||
{ required: true, message: "请输入课件描述", trigger: "blur" },
|
||||
],
|
||||
ONTLINETYPE: [
|
||||
{ required: true, message: "请选择大纲类型", trigger: "change" },
|
||||
],
|
||||
};
|
||||
const data = reactive({
|
||||
videoDialog: {
|
||||
src: "",
|
||||
vid: "",
|
||||
playAuth: "",
|
||||
visible: false,
|
||||
},
|
||||
});
|
||||
const formRef = ref(null);
|
||||
const progressBarVisible = ref(false);
|
||||
const progressBar = ref(0);
|
||||
const outlineTypeList = await layoutFnGetOutlineType();
|
||||
const fnPreviewVideo = async () => {
|
||||
const { src, vid, playAuth, visible } = await useAliYunVideoPreview(
|
||||
form.value
|
||||
);
|
||||
data.videoDialog.src = src;
|
||||
data.videoDialog.vid = vid;
|
||||
data.videoDialog.playAuth = playAuth;
|
||||
data.videoDialog.visible = visible;
|
||||
};
|
||||
const fnClose = () => {
|
||||
formRef.value.resetFields();
|
||||
visible.value = false;
|
||||
};
|
||||
const fnSubmit = debounce(
|
||||
1000,
|
||||
async () => {
|
||||
await useFormValidate(formRef);
|
||||
if (form.value.file[0].raw) {
|
||||
uploader = useAliYunUpload({
|
||||
onUploadSucceed: (uploadInfo) => {
|
||||
fnSubmitForm(uploadInfo.videoId);
|
||||
},
|
||||
onUploadstarted: () => {
|
||||
progressBarVisible.value = true;
|
||||
},
|
||||
onUploadFailed: () => {
|
||||
progressBarVisible.value = false;
|
||||
},
|
||||
onUploadProgress: (uploadInfo, totalSize, progress) => {
|
||||
progressBar.value = Math.ceil(progress * 100);
|
||||
},
|
||||
});
|
||||
fnSubmitVideo();
|
||||
} else {
|
||||
await fnSubmitForm();
|
||||
}
|
||||
},
|
||||
{ atBegin: true }
|
||||
);
|
||||
const fnSubmitVideo = () => {
|
||||
uploader.addFile(form.value.file[0].raw, null, null, null, '{"Vod":{}}');
|
||||
uploader.startUpload();
|
||||
};
|
||||
const fnSubmitForm = async (videoId = "") => {
|
||||
const params = {
|
||||
...form.value,
|
||||
videoId,
|
||||
isEditVideo: !!form.value.file[0].raw,
|
||||
trainingSection: form.value.trainingSection.join(";"),
|
||||
};
|
||||
props.type === "add"
|
||||
? await setVideoCoursewareAdd(params)
|
||||
: await setVideoCoursewareEdit(params);
|
||||
progressBar.value = 0;
|
||||
progressBarVisible.value = false;
|
||||
ElMessage.success("提交成功");
|
||||
fnClose();
|
||||
emits("get-data");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
|
@ -142,7 +142,12 @@
|
|||
row.STAGECOUNT === 0 &&
|
||||
row.ISPLATFORM === 0
|
||||
"
|
||||
@click="fnAddOrEdit(row.VIDEOCOURSEWARE_ID, 'edit')"
|
||||
@click="
|
||||
router.push({
|
||||
path: '/online_learn_exam/courseware/video/edit',
|
||||
query: { VIDEOCOURSEWARE_ID: row.VIDEOCOURSEWARE_ID },
|
||||
})
|
||||
"
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
|
@ -182,7 +187,9 @@
|
|||
<el-button
|
||||
v-if="buttonJurisdiction.add"
|
||||
type="primary"
|
||||
@click="fnAddOrEdit('', 'add')"
|
||||
@click="
|
||||
router.push({ path: '/online_learn_exam/courseware/video/add' })
|
||||
"
|
||||
>
|
||||
新增
|
||||
</el-button>
|
||||
|
@ -195,12 +202,6 @@
|
|||
:play-auth="data.videoDialog.playAuth"
|
||||
v-model:visible="data.videoDialog.visible"
|
||||
/>
|
||||
<add
|
||||
v-model:visible="data.addOrEditDialog.visible"
|
||||
v-model:form="data.addOrEditDialog.form"
|
||||
:type="data.addOrEditDialog.type"
|
||||
@get-data="fnResetPagination"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
@ -209,26 +210,18 @@ import {
|
|||
getVideoCoursewareList,
|
||||
setVideoCoursewareState,
|
||||
setVideoCoursewareDelete,
|
||||
getVideoCoursewareView,
|
||||
} from "@/request/online_learn_exam.js";
|
||||
import useListData from "@/assets/js/useListData.js";
|
||||
import { nextTick, reactive } from "vue";
|
||||
import {
|
||||
getFileName,
|
||||
serialNumber,
|
||||
translationStatus,
|
||||
} from "@/assets/js/utils.js";
|
||||
import { reactive } from "vue";
|
||||
import { serialNumber, translationStatus } from "@/assets/js/utils.js";
|
||||
import LayoutVideo from "@/components/video/index.vue";
|
||||
import useButtonJurisdiction from "@/assets/js/useButtonJurisdiction.js";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { useRouter } from "vue-router";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import Add from "./components/add.vue";
|
||||
import { useUserStore } from "@/pinia/user.js";
|
||||
import useAliYunVideoPreview from "@/assets/js/useAliYunVideoPreview.js";
|
||||
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
const stateList = [
|
||||
{ ID: 0, NAME: "启用" },
|
||||
{ ID: 1, NAME: "禁用" },
|
||||
|
@ -243,21 +236,6 @@ const data = reactive({
|
|||
playAuth: "",
|
||||
visible: false,
|
||||
},
|
||||
addOrEditDialog: {
|
||||
visible: false,
|
||||
type: "",
|
||||
form: {
|
||||
COURSEWARENAME: "",
|
||||
trainingSection: [],
|
||||
TRAINTYPE: "",
|
||||
POSTTYPE: "",
|
||||
SPEAKER: "",
|
||||
file: [],
|
||||
screenshotFile: [],
|
||||
COURSEWAREINTRODUCE: "",
|
||||
ONTLINETYPE: "",
|
||||
},
|
||||
},
|
||||
});
|
||||
const fnPreviewVideo = async (row) => {
|
||||
const { src, vid, playAuth, visible } = await useAliYunVideoPreview(row);
|
||||
|
@ -292,32 +270,6 @@ const fnDelete = debounce(
|
|||
},
|
||||
{ atBegin: true }
|
||||
);
|
||||
const fnAddOrEdit = async (VIDEOCOURSEWARE_ID, type) => {
|
||||
data.addOrEditDialog.visible = true;
|
||||
await nextTick();
|
||||
data.addOrEditDialog.type = type;
|
||||
if (type === "add")
|
||||
data.addOrEditDialog.form.TRAINTYPE = userStore.getUserInfo.CORP_TRAINTYPE;
|
||||
else {
|
||||
const resData = await getVideoCoursewareView({ VIDEOCOURSEWARE_ID });
|
||||
data.addOrEditDialog.form = resData.pd;
|
||||
data.addOrEditDialog.form.screenshotFile = [
|
||||
{
|
||||
url: resData.pd.VIDEOCAPTURE,
|
||||
name: getFileName(resData.pd.VIDEOCAPTURE),
|
||||
},
|
||||
];
|
||||
data.addOrEditDialog.form.file = [
|
||||
{
|
||||
url: resData.pd.VIDEOFILES,
|
||||
name: getFileName(resData.pd.VIDEOFILES),
|
||||
},
|
||||
];
|
||||
data.addOrEditDialog.form.trainingSection = resData.coursewareAllList.map(
|
||||
(item) => item.DICTIONARIES_IDS.split(",")
|
||||
);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
Loading…
Reference in New Issue