讲师认证
@@ -7,7 +7,7 @@ import Cookies from 'vue-cookies'
|
||||
axios.defaults.withCredentials = true;
|
||||
const http = axios.create({
|
||||
timeout: 1000 * 15,
|
||||
headers: { "Content-Type": "application/json", },
|
||||
headers: { "Content-Type":"application/json", },
|
||||
});
|
||||
|
||||
http.interceptors.request.use(
|
||||
|
||||
115
src/api/examineApi.js
Normal file
@@ -0,0 +1,115 @@
|
||||
import { data } from "jquery";
|
||||
import http from "./configPublic";
|
||||
//认证审批项目列表
|
||||
export const getexamineList = (data) => {
|
||||
return http({
|
||||
url: "/activityApi/examine/list",
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
|
||||
}
|
||||
export const getexamine = (data) => {
|
||||
return http({
|
||||
url: "/activityApi/teacher/list",
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
|
||||
}
|
||||
//创建认证
|
||||
export const CreateAuthentication = (data)=>{
|
||||
return http({
|
||||
url:'/activityApi/examine/launchOrUpdate',
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//删除认证
|
||||
export const delExamine = (data)=>{
|
||||
return http({
|
||||
url:'/activityApi/examine/deleteExamine',
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//讲师列表
|
||||
export const getTeacherList = (data)=>{
|
||||
return http({
|
||||
url:'/activityApi/teacher/list',
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//删除教师
|
||||
export const deleTeTeacher = (data)=>{
|
||||
return http({
|
||||
url:'/activityApi//teacher/deleTeTeacher',
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//发起评审列表
|
||||
export const getReview = (data) =>{
|
||||
return http({
|
||||
url:'/activityApi/review/list',
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//删除评审
|
||||
export const delreview=(data) =>{
|
||||
return http({
|
||||
url:'/activityApi/review/delete',
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//查看评审
|
||||
export const reviewdetail =(data)=>{
|
||||
return http({
|
||||
url:'/activityApi/review/detail',
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//发起评审
|
||||
export const reviewSave = (data) =>{
|
||||
return http({
|
||||
url:'/activityApi/review/save',
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//添加教师
|
||||
export const addTeacher= (data)=>{
|
||||
return http({
|
||||
url:'/activityApi/review/selectTeacher',
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//结束评审并通知结果
|
||||
export const endreview = (data) =>{
|
||||
return http({
|
||||
url:'/activityApi/review/endReview',
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//编辑评审
|
||||
export const editreview = (data) =>{
|
||||
return http({
|
||||
url:'/activityApi/review/edit',
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//添加导师
|
||||
export const addTutor = (data) =>{
|
||||
return http({
|
||||
url:'/activityApi/teacher/saveTeacher',
|
||||
method: "post",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
BIN
src/assets/2.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/33.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
src/assets/39.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
src/assets/44.png
Normal file
|
After Width: | Height: | Size: 145 KiB |
BIN
src/assets/46.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
src/assets/47.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
src/assets/49.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
src/assets/50.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
src/assets/8.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
@@ -495,6 +495,18 @@
|
||||
}
|
||||
];
|
||||
}
|
||||
if (
|
||||
n.indexOf("/InstructorCertification") !== -1 ||
|
||||
n.indexOf("/InstructorCertification") !== -1
|
||||
) {
|
||||
state.list = [
|
||||
{
|
||||
name: "感恩教师",
|
||||
}, {
|
||||
name:'讲师认证'
|
||||
}
|
||||
];
|
||||
}
|
||||
if (
|
||||
n.indexOf("/tooldown") !== -1 ||
|
||||
n.indexOf("/ToolDown") !== -1
|
||||
|
||||
@@ -339,7 +339,7 @@
|
||||
</a-menu-item>
|
||||
</a-sub-menu>
|
||||
<!-- 教师专区 -->
|
||||
<a-sub-menu key="sub22" @titleClick="titleClick" v-if="checkMenu('gratefulnotice,gratefulcarousel,teacherempowerment,teachertopic,tooldown,teacheropinion')">
|
||||
<a-sub-menu key="sub22" @titleClick="titleClick" v-if="checkMenu('gratefulnotice,gratefulcarousel,teacherempowerment,teachertopic,tooldown,teacheropinion,InstructorCertification')">
|
||||
<template #icon>
|
||||
<div class="imgBox">
|
||||
<img
|
||||
@@ -376,6 +376,17 @@
|
||||
></span>
|
||||
<router-link to="/teacherempowerment">教师赋能</router-link>
|
||||
</a-menu-item>
|
||||
|
||||
<a-menu-item key="sub22-7" >
|
||||
<span
|
||||
:class="{
|
||||
circleActive: selectedKeys[0] === 'sub22-7' ? true : false,
|
||||
circle: selectedKeys[0] === 'sub22-7' ? false : true,
|
||||
}"
|
||||
></span>
|
||||
<router-link to="/InstructorCertification">讲师认证</router-link>
|
||||
</a-menu-item>
|
||||
|
||||
<a-menu-item key="sub22-4" v-if="checkMenu('teachertopic')">
|
||||
<span
|
||||
:class="{
|
||||
@@ -929,6 +940,12 @@ export default {
|
||||
selectedKeys: "sub22-6",
|
||||
pagename: "意见",
|
||||
},
|
||||
{
|
||||
href: "/InstructorCertification",
|
||||
openKeys: "sub22",
|
||||
selectedKeys: "sub22-7",
|
||||
pagename: "讲师认证",
|
||||
},
|
||||
{
|
||||
href: "/articlemanage",
|
||||
openKeys: "sub13",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
>
|
||||
<div class="drawerMain" id="stuadd">
|
||||
<div class="header">
|
||||
<div class="headerTitle">添加学员</div>
|
||||
<div class="headerTitle">添加讲师</div>
|
||||
<img
|
||||
style="width: 29px; height: 29px; cursor: pointer"
|
||||
src="../../assets/images/basicinfo/close.png"
|
||||
|
||||
14
src/utils/qrCode2.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { createApp } from 'vue'
|
||||
import QrCode from "../views/gratefulteacher/QrCode.vue";
|
||||
import Antd from "ant-design-vue";
|
||||
|
||||
function mountContent (option = {}) {
|
||||
const dom = document.createElement('div')
|
||||
document.body.appendChild(dom)
|
||||
const app = createApp(QrCode, {
|
||||
close: () => { app.unmount(dom); document.body.removeChild(dom) },
|
||||
...option
|
||||
})
|
||||
app.use(Antd).mount(dom)
|
||||
}
|
||||
export default mountContent
|
||||
185
src/views/gratefulteacher/AddInstructor.vue
Normal file
@@ -0,0 +1,185 @@
|
||||
<script setup >
|
||||
import { ref } from 'vue'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
const props = defineProps(["AddSwitch"])
|
||||
console.log(1111,props.AddSwitch);
|
||||
const emit = defineEmits(['myClick'])
|
||||
const handleClose = (done) => {
|
||||
ElMessageBox.confirm('Are you sure to close this dialog?')
|
||||
.then(() => {
|
||||
|
||||
emit('myClick', false)
|
||||
done()
|
||||
})
|
||||
.catch(() => {
|
||||
// catch error
|
||||
})
|
||||
}
|
||||
const activeName = ref('first')
|
||||
const handleNodeClick = (data) => {
|
||||
console.log(data)
|
||||
}
|
||||
|
||||
const data= [
|
||||
{
|
||||
label: 'Level one 1',
|
||||
children: [
|
||||
{
|
||||
label: 'Level two 1-1',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 1-1-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Level one 2',
|
||||
children: [
|
||||
{
|
||||
label: 'Level two 2-1',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 2-1-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Level two 2-2',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 2-2-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Level one 3',
|
||||
children: [
|
||||
{
|
||||
label: 'Level two 3-1',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 3-1-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Level two 3-2',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 3-2-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'label',
|
||||
}
|
||||
const tags = ref([
|
||||
{ name: 'Tag 1', type: 'primary' },
|
||||
{ name: 'Tag 2', type: 'success' },
|
||||
{ name: 'Tag 3', type: 'info' },
|
||||
{ name: 'Tag 4', type: 'warning' },
|
||||
{ name: 'Tag 5', type: 'danger' },
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="-page">
|
||||
<el-drawer style="padding:0 10px;" :before-close="handleClose" v-model="props.AddSwitch" size="80%">
|
||||
<template #title>
|
||||
<h1 style="font-weight: 700;">添加讲师</h1>
|
||||
</template>
|
||||
<div style="width: 100%; height: 1px; background: #d8d8d8;margin-top: -16px; "></div>
|
||||
<div style="width: 100%; height: 70%; display: flex; ">
|
||||
<div style="width: 90%; height: 70%;">
|
||||
<div style="width: 100%; margin-top: 16px">
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane label="快速选人" name="first"></el-tab-pane>
|
||||
<el-tab-pane label="添加组织" name="second"></el-tab-pane>
|
||||
<el-tab-pane label="受众关联" name="thirdly"></el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
</div>
|
||||
<div style="display: flex; margin-bottom: 15px">
|
||||
<p style="width: 40px;">姓名:</p>
|
||||
<el-input style="width: 200px;" placeholder="请输入姓名"></el-input>
|
||||
<el-button type="primary" style="margin-left: 15px;">搜索</el-button>
|
||||
<el-button type="primary">重置</el-button>
|
||||
</div>
|
||||
|
||||
<div style="width: 100%; display: flex;">
|
||||
<div style="width: 24%;">
|
||||
<el-tree
|
||||
style="max-width: 600px; border: 1px solid #d8d8d8;"
|
||||
:data="data"
|
||||
:props="defaultProps"
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
</div>
|
||||
<div style="width: 74%; flex: 1;margin-left: 10px;"></div>
|
||||
<el-table :checked="true" :data="tableData" style="width: 100%">
|
||||
<el-table-column fixed type="selection" style="width: 2%;" >
|
||||
|
||||
|
||||
</el-table-column>
|
||||
<el-table-column prop="date" label="姓名" />
|
||||
|
||||
<el-table-column prop="date" label="工号" />
|
||||
|
||||
|
||||
<el-table-column prop="city" label="归属组织" />
|
||||
<el-table-column prop="city" label="部门" />
|
||||
|
||||
|
||||
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="width: 1px ;height: 70%;background-color: #f5f8fe; margin-left: 10px;margin-right: 10px;"></div>
|
||||
<div style="width: 10%; height: 70%; margin-top: 25px;">
|
||||
<div style="margin-bottom: 30px;">已选</div>
|
||||
<div style="width: 100% ;height: 1px;background-color: #f5f8fe; "></div>
|
||||
|
||||
<div>快速选人</div>
|
||||
<div class="flex gap-2">
|
||||
<el-tag v-for="tag in tags" :key="tag.name" closable :type="tag.type" color="#fff" style="width: 64px; margin-top: 10px; display: block; color: #4fa5f8; border: 1px solid #4fa5f8;">
|
||||
{{ tag.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div style="margin-top: 30px;">添加组织</div>
|
||||
<div style="width: 100% ;height: 1px;background-color: #f5f8fe; "></div>
|
||||
|
||||
<div style="margin-top: 30px;">受众关联</div>
|
||||
<div style="width: 100% ;height: 1px;background-color: #f5f8fe; "></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="width: 100%; text-align: center;" >
|
||||
<el-button type="primary" plain style="width: 100px; height: 40px; margin-right: 10px;">取消</el-button>
|
||||
<el-button type="primary" style="width: 100px; height: 40px; margin-left: 10px;">确认</el-button>
|
||||
|
||||
</div>
|
||||
</el-drawer>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::deep(.el-drawer__header){
|
||||
margin-bottom: 0;
|
||||
}
|
||||
::deep(.el-table .cell){
|
||||
color: #030303
|
||||
}
|
||||
|
||||
</style>
|
||||
645
src/views/gratefulteacher/AddLevelImportTec.vue
Normal file
@@ -0,0 +1,645 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
:visible="AddImpStuvisible"
|
||||
class="drawerStyle AddLevelImpStu"
|
||||
placement="right"
|
||||
width="800px"
|
||||
@after-visible-change="afterVisibleChange"
|
||||
>
|
||||
<div class="drawerMain">
|
||||
<div class="header">
|
||||
<div class="headerTitle">导入讲师</div>
|
||||
<img
|
||||
style="width: 29px; height: 29px; cursor: pointer"
|
||||
src="../../assets/images/basicinfo/close.png"
|
||||
@click="closeDrawer"
|
||||
/>
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="minatitl">
|
||||
<div class="up1">请下载</div>
|
||||
<a
|
||||
class="up2"
|
||||
:href="locationHref + template"
|
||||
target="_blank"
|
||||
style="cursor: pointer"
|
||||
>模板</a
|
||||
>
|
||||
<div class="up1">,按要求填写数据并导入</div>
|
||||
</div>
|
||||
<div class="upload">
|
||||
<div class="text">上传:</div>
|
||||
<div class="right">
|
||||
<div style="height: 176px; margin-bottom: 20px">
|
||||
<a-upload-dragger
|
||||
v-model:fileList="fileList"
|
||||
:action="importStudent"
|
||||
name="uploadFile"
|
||||
:headers="headers"
|
||||
:multiple="false"
|
||||
@change="handleChange"
|
||||
:data="{
|
||||
targetId: Number(courseId),
|
||||
type: courseType,
|
||||
userId: userInfo.userId,
|
||||
userName: userInfo.realName,
|
||||
}"
|
||||
:showUploadList="false"
|
||||
>
|
||||
<p class="ant-upload-drag-icon">
|
||||
<inbox-outlined></inbox-outlined>
|
||||
</p>
|
||||
<p class="ant-upload-text">点击或将文件拖拽到此处上传</p>
|
||||
<p class="ant-upload-hint">支持扩展名:.xls/.xlsx</p>
|
||||
</a-upload-dragger>
|
||||
</div>
|
||||
<!-- <div class="load">
|
||||
<div class="cloud"></div>
|
||||
<div class="tip">点击或将文件拖拽到此处上传</div>
|
||||
<div class="tipz">支持扩展名:.xls/.xlsx</div>
|
||||
</div> -->
|
||||
<div class="loadstate">
|
||||
<div v-if="uploadpercent !== -1" class="loadborder">
|
||||
<div class="content">
|
||||
<div class="img"></div>
|
||||
<div class="timebox">
|
||||
<div class="timetop">
|
||||
<div class="tit" :title="fileName">{{ fileName }}</div>
|
||||
<div
|
||||
v-if="uploadErr"
|
||||
class="stateloading"
|
||||
style="color: red"
|
||||
>
|
||||
上传失败
|
||||
</div>
|
||||
<div v-else class="stateloading">
|
||||
{{ uploadpercent == 100 ? "上传成功" : "正在上传" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="prog">
|
||||
<div
|
||||
class="inprogloading"
|
||||
:style="{
|
||||
width: uploadpercent == -1 ? 0 : uploadpercent + '%',
|
||||
background: uploadErr ? '#ff7474' : '#35ae69',
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="curloading">
|
||||
<div class="cur">
|
||||
{{ uploadpercent == -1 ? 0 : uploadpercent }}%
|
||||
</div>
|
||||
<div
|
||||
class="cancel"
|
||||
style="margin-left: 20px; cursor: pointer"
|
||||
@click="removeUpload"
|
||||
>
|
||||
删除
|
||||
</div>
|
||||
<div class="cancel" style="margin-left: 15px"></div>
|
||||
</div>
|
||||
<div v-if="downloadErrUrl !== ''" class="defeat">
|
||||
<div class="detext" @click="downloadEeeorData">
|
||||
下载失败数据
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="showBottomBar"
|
||||
:class="downloadErrUrl == '' ? 'succebox' : 'defeatbox'"
|
||||
>
|
||||
<div class="lefimg"></div>
|
||||
<div class="tacl">
|
||||
{{ succNum }}条数据导入成功,{{
|
||||
downloadErrUrl == "" ? 0 : errNum
|
||||
}}条数据导入失败
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="loadborder">
|
||||
<div class="content">
|
||||
<div class="img"></div>
|
||||
<div class="timebox">
|
||||
<div class="timetop">
|
||||
<div class="tit">{{ fileName }}</div>
|
||||
<div class="statedefeat">上传失败</div>
|
||||
</div>
|
||||
<div class="prog">
|
||||
<div class="inprogdefeat"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="curloading">
|
||||
<div class="cur">55%</div>
|
||||
<div class="cancel" style="margin-left: 20px">重传</div>
|
||||
<div class="cancel" style="margin-left: 15px">取消</div>
|
||||
</div>
|
||||
<div class="defeat">
|
||||
<div class="detext">下载失败数据</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="defeatbox">
|
||||
<div class="lefimg"></div>
|
||||
<div class="tacl">20条数据导入成功,5条数据导入失败</div>
|
||||
</div>
|
||||
<div class="loadborder">
|
||||
<div class="content">
|
||||
<div class="img"></div>
|
||||
<div class="timebox">
|
||||
<div class="timetop">
|
||||
<div class="tit">{{ fileName }}</div>
|
||||
<div class="statesucce">上传成功</div>
|
||||
</div>
|
||||
<div class="prog">
|
||||
<div class="inprogsucce"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="curloading">
|
||||
<div class="cur">55%</div>
|
||||
<div class="cancel" style="margin-left: 20px">删除</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="succebox">
|
||||
<div class="lefimg"></div>
|
||||
<div class="tacl">20条数据导入成功,5条数据导入失败</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btnn">
|
||||
<button class="btn2" @click="closeDrawer">取消</button>
|
||||
<button class="btn2" @click="closeDrawer">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 加载动画 -->
|
||||
<div class="aeLoading" :style="{ display: addLoading ? 'flex' : 'none' }">
|
||||
<a-spin :spinning="addLoading" tip="" />
|
||||
</div>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { computed, reactive, toRefs } from "vue";
|
||||
import { message } from "ant-design-vue";
|
||||
import * as api from "../../api/index1";
|
||||
import { BATCH_IMPORT_SCORE } from "@/api/config";
|
||||
import { useStore } from "vuex";
|
||||
import {getCookieForName} from "@/api/method";
|
||||
export default {
|
||||
name: "ImpStu",
|
||||
props: {
|
||||
AddImpStuvisible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
courseId: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
courseType: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
setup(props, ctx) {
|
||||
const store = useStore();
|
||||
const state = reactive({
|
||||
locationHref: process.env.VUE_APP_FILE_PATH,
|
||||
template: process.env.VUE_APP_UP_LOAD_STUDENT_TEMPLATE,
|
||||
importStudent:
|
||||
process.env.VUE_APP_BASE_API + "/admin/student/importStudent",
|
||||
timers: "", // 定时器,用于清空定时器使用
|
||||
isAddStudent: false, // 用于判断用户是否关闭弹框需要重新获取学员列表
|
||||
uploadpercent: -1,
|
||||
uploadErr: false, //上传失败
|
||||
addLoading: false,
|
||||
fileList: [],
|
||||
succNum: 0, //成功数据数
|
||||
errNum: 0, //失败数据数
|
||||
downloadErrUrl: "",
|
||||
showBottomBar: false, // 显示底部成功条数和失败条数
|
||||
fileName: "",
|
||||
});
|
||||
const headers = { token: getCookieForName("token") };
|
||||
const userInfo = computed(() => store.state.userInfo);
|
||||
|
||||
const closeDrawer = () => {
|
||||
clearInterval(state.timers);
|
||||
state.fileList = [];
|
||||
state.uploadpercent = -1;
|
||||
state.addLoading = false;
|
||||
state.uploadErr = false; //上传失败
|
||||
state.showBottomBar = false;
|
||||
state.succNum = 0;
|
||||
state.errNum = 0;
|
||||
state.downloadErrUrl = "";
|
||||
ctx.emit("update:AddImpStuvisible", false);
|
||||
// 通知父组件重新获取学员列表
|
||||
ctx.emit("AddImpStuvisibleClose", state.isAddStudent);
|
||||
state.isAddStudent = false;
|
||||
};
|
||||
|
||||
const afterVisibleChange = (bool) => {
|
||||
console.log("state", bool);
|
||||
console.log("store", store.state.userInfo);
|
||||
};
|
||||
//上传文件
|
||||
const handleChange = (info) => {
|
||||
console.log("info", info);
|
||||
|
||||
if (info) {
|
||||
var FileExt = info.file.name.replace(/.+\./, "");
|
||||
if (["xls", "xlsx"].indexOf(FileExt.toLowerCase()) === -1) {
|
||||
state.fileList = [];
|
||||
state.uploadpercent = -1;
|
||||
message.destroy();
|
||||
message.error("请上传正确的文件格式");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
state.addLoading = true;
|
||||
state.uploadErr = false;
|
||||
state.uploadpercent = parseInt(info.file.percent);
|
||||
console.log("我是文件上传的进度---------->", info.file.percent);
|
||||
const status = info.file.status;
|
||||
if (status !== "uploading") {
|
||||
console.log(info.file, info.fileList);
|
||||
}
|
||||
if (status === "done") {
|
||||
console.log("上传成功返回的UUID", info.file.response.data);
|
||||
console.log("上传成功返回的UUID----->", info);
|
||||
console.log("我是导入学员接口传递的参数", {
|
||||
uploadFile: info.file.originFileObj,
|
||||
targetId: props.courseId,
|
||||
type: 3,
|
||||
});
|
||||
state.fileName = info.file.name;
|
||||
let i = 0;
|
||||
state.timers = setInterval(() => {
|
||||
let uid = info.file.response.data;
|
||||
api
|
||||
.getImportStatus(uid)
|
||||
.then((res) => {
|
||||
console.log("查询导入状态", res);
|
||||
if (res.data.code === 200) {
|
||||
if (res.data.data.status !== "START") {
|
||||
i++;
|
||||
if (i === 1) {
|
||||
message.destroy();
|
||||
message.success(`${info.file.name}上传成功`);
|
||||
state.showBottomBar = true;
|
||||
state.addLoading = false;
|
||||
state.isAddStudent = true;
|
||||
}
|
||||
state.succNum = res.data.data.successNum;
|
||||
state.errNum = res.data.data.failedNum;
|
||||
state.downloadErrUrl = res.data.data.url;
|
||||
clearInterval(state.timers);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
clearInterval(state.timers);
|
||||
state.showBottomBar = true;
|
||||
state.addLoading = false;
|
||||
console.log("查询导入状态失败", err);
|
||||
});
|
||||
}, 500);
|
||||
} else if (status === "error") {
|
||||
state.addLoading = false;
|
||||
state.uploadErr = true;
|
||||
message.error(`${info.file.name}上传失败`);
|
||||
}
|
||||
};
|
||||
|
||||
// 下载失败数据
|
||||
const downloadEeeorData = () => {
|
||||
if (state.downloadErrUrl !== "") {
|
||||
window.open(process.env.VUE_APP_FILE_PATH + state.downloadErrUrl);
|
||||
}
|
||||
};
|
||||
|
||||
//删除
|
||||
const removeUpload = () => {
|
||||
state.isAddStudent = false;
|
||||
state.showBottomBar = false;
|
||||
state.fileList = [];
|
||||
state.uploadpercent = -1;
|
||||
state.addLoading = false;
|
||||
state.uploadErr = false; //上传失败
|
||||
state.succNum = 0;
|
||||
state.errNum = 0;
|
||||
state.downloadErrUrl = "";
|
||||
};
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
afterVisibleChange,
|
||||
userInfo,
|
||||
closeDrawer,
|
||||
// change,
|
||||
headers,
|
||||
handleChange,
|
||||
BATCH_IMPORT_SCORE,
|
||||
downloadEeeorData,
|
||||
removeUpload,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.AddLevelImpStu > .ant-drawer-content-wrapper {
|
||||
min-width: 800px !important;
|
||||
width: 800px !important;
|
||||
}
|
||||
.AddLevelImpStu {
|
||||
.drawerMain {
|
||||
min-width: 450px;
|
||||
margin: 0px 32px 0px 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.header {
|
||||
height: 73px;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
// background-color: red;
|
||||
margin-bottom: 20px;
|
||||
.headerTitle {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 25px;
|
||||
// margin-left: 24px;
|
||||
}
|
||||
}
|
||||
.main {
|
||||
overflow: auto;
|
||||
.minatitl {
|
||||
display: flex;
|
||||
.up1 {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
.up2 {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: #4ea6ff;
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
.upload {
|
||||
margin-top: 32px;
|
||||
display: flex;
|
||||
.text {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.right {
|
||||
margin-left: 6px;
|
||||
.load {
|
||||
width: 500px;
|
||||
height: 176px;
|
||||
background: #f5f9fd;
|
||||
border-radius: 4px;
|
||||
// opacity: 0.3;
|
||||
border: 1px dashed #caddfd;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
.cloud {
|
||||
margin-top: 52px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background-image: url(../../assets/images/basicinfo/cloud.png);
|
||||
}
|
||||
.tip {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #4ea6ff;
|
||||
margin-top: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tipz {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
.loadstate {
|
||||
width: 500px;
|
||||
margin-bottom: 100px;
|
||||
|
||||
.loadborder {
|
||||
width: 500px;
|
||||
height: 173px;
|
||||
border-radius: 4px;
|
||||
border: 1px dashed #eaeaea;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.content {
|
||||
display: flex;
|
||||
margin-left: 20px;
|
||||
position: relative;
|
||||
.defeat {
|
||||
position: absolute;
|
||||
left: 46px;
|
||||
top: 42px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
width: 120px;
|
||||
height: 32px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #387df7;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
.detext {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #387df7;
|
||||
}
|
||||
}
|
||||
.img {
|
||||
width: 30px;
|
||||
height: 34px;
|
||||
background-image: url(../../assets/images/basicinfo/exl.png);
|
||||
}
|
||||
.timebox {
|
||||
margin-left: 15px;
|
||||
margin-top: -5px;
|
||||
.timetop {
|
||||
display: flex;
|
||||
width: 262px;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
.tit {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
width: 200px;
|
||||
height: 21px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.stateloading {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #4ea6ff;
|
||||
}
|
||||
.statedefeat {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ff7474;
|
||||
}
|
||||
.statesucce {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #35ae69;
|
||||
}
|
||||
}
|
||||
.prog {
|
||||
width: 262px;
|
||||
height: 5px;
|
||||
background: #eaf1fe;
|
||||
border-radius: 4px;
|
||||
.inprogloading {
|
||||
width: 55%;
|
||||
height: 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
background: #4ea6ff;
|
||||
}
|
||||
//下载失败条
|
||||
.inprogdefeat {
|
||||
width: 55%;
|
||||
height: 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
background: #ff7474;
|
||||
}
|
||||
//下载成功条
|
||||
.inprogsucce {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
background: #57c887;
|
||||
}
|
||||
}
|
||||
}
|
||||
.curloading {
|
||||
margin-left: 15px;
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
.cur {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
.cancel {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #387df7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.defeatbox {
|
||||
width: 500px;
|
||||
height: 40px;
|
||||
background: rgba(255, 116, 116, 0.1);
|
||||
border: 1px solid #ff7474;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.lefimg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-left: 17px;
|
||||
margin-right: 8px;
|
||||
background-image: url(../../assets/images/leveladd/nodone.png);
|
||||
background-size: 100%;
|
||||
}
|
||||
.tacl {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ff7474;
|
||||
}
|
||||
}
|
||||
.succebox {
|
||||
width: 500px;
|
||||
height: 40px;
|
||||
background: rgba(53, 174, 105, 0.1);
|
||||
border: 1px solid #35ae69;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.lefimg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-left: 17px;
|
||||
margin-right: 8px;
|
||||
background-image: url(../../assets/images/leveladd/done.png);
|
||||
background-size: 100%;
|
||||
}
|
||||
.tacl {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.btnn {
|
||||
height: 72px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0px 1px 35px 0px rgba(118, 136, 166, 0.16);
|
||||
.btn1 {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
border: 1px solid #4ea6ff;
|
||||
border-radius: 8px;
|
||||
color: #4ea6ff;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
.btn2 {
|
||||
cursor: pointer;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
border: 0;
|
||||
margin-left: 15px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
126
src/views/gratefulteacher/EvaluationForm.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<script setup >
|
||||
import {ref} from 'vue'
|
||||
import ViewReview from "./ViewReview.vue";
|
||||
const column = [
|
||||
{
|
||||
name: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '评审名称',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
},
|
||||
{
|
||||
title: '认证讲师',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
},
|
||||
{
|
||||
title: '认证时间',
|
||||
key: 'tags',
|
||||
dataIndex: 'tags',
|
||||
},
|
||||
{
|
||||
title: '认证状态',
|
||||
key: 'tags',
|
||||
dataIndex: 'tags',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
},
|
||||
];
|
||||
|
||||
const datas = [
|
||||
{
|
||||
key: '1',
|
||||
name: 'John Brown',
|
||||
age: 32,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
tags: ['nice', 'developer'],
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: 'Jim Green',
|
||||
age: 42,
|
||||
address: 'London No. 1 Lake Park',
|
||||
tags: ['loser'],
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
name: 'Joe Black',
|
||||
age: 32,
|
||||
address: 'Sidney No. 1 Lake Park',
|
||||
tags: ['cool', 'teacher'],
|
||||
},
|
||||
];
|
||||
const InitiateReviewShow =ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="-page">
|
||||
<div class="table">
|
||||
<a-table :columns="column" :data-source="datas" :scroll="{ x: 1000 }" :pagination="false">
|
||||
<template #headerCell="{ column }">
|
||||
<template v-if="column.key === 'name'">
|
||||
<span>
|
||||
序号
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'name'">
|
||||
<a>
|
||||
{{ record.name }}
|
||||
</a>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'tags'">
|
||||
<span>
|
||||
<a-tag
|
||||
v-for="tag in record.tags"
|
||||
:key="tag"
|
||||
:color="tag === 'loser' ? 'volcano' : tag.length > 5 ? 'geekblue' : 'green'"
|
||||
>
|
||||
{{ tag.toUpperCase() }}
|
||||
</a-tag>
|
||||
</span>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'action'">
|
||||
<span style="text-align: center;">
|
||||
<a style="margin-right: 7px;" @click="centerDialogVisible=true">二维码</a>
|
||||
|
||||
<a style="margin-right: 7px;" @click='InitiateReviewShow=true'>查看</a>
|
||||
|
||||
<a style="margin-right: 7px;">
|
||||
编辑
|
||||
</a>
|
||||
<a style="color: #de2139">删除</a>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<div style="text-align: center; margin-top: 18px;">
|
||||
<a-pagination v-model:current="current1" show-quick-jumper :total="500" @change="onChange" />
|
||||
</div>
|
||||
<!-- <ViewReview :InitiateReviewShow="InitiateReviewShow"></ViewReview> -->
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.table {
|
||||
margin-left: 14px;
|
||||
|
||||
margin-top: 28px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
77
src/views/gratefulteacher/InitiateReview.vue
Normal file
@@ -0,0 +1,77 @@
|
||||
<script setup >
|
||||
const props = defineProps(['InitiateReviewShow'])
|
||||
import { reactive } from 'vue';
|
||||
import InitiateReviewTable from './InitiateReviewTable.vue'
|
||||
const formState = reactive({
|
||||
username: '',
|
||||
password: '',
|
||||
remember: true,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="-page">
|
||||
<el-drawer v-model="props.InitiateReviewShow" title="发起评审" size="45%">
|
||||
<div style="display: flex;flex-direction: column;">
|
||||
<div style="width: 100%;height: 1px;background-color: #b6b7b8;"></div>
|
||||
<div style="display: flex;">
|
||||
<div style="display: flex;flex-direction: column;">
|
||||
<a-form
|
||||
:model="formState"
|
||||
name="basic"
|
||||
:label-col="{ span: 8 }"
|
||||
:wrapper-col="{ span: 16 }"
|
||||
autocomplete="off"
|
||||
@finish="onFinish"
|
||||
@finishFailed="onFinishFailed"
|
||||
>
|
||||
<a-form-item
|
||||
style="margin-top: 29px;"
|
||||
label="评审名字"
|
||||
name="username"
|
||||
:rules="[{ required: true, message: 'Please input your username!' }]"
|
||||
>
|
||||
<a-input v-model:value="formState.username" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
label="评审时间"
|
||||
name="password"
|
||||
:rules="[{ required: true, message: 'Please input your password!' }]"
|
||||
>
|
||||
<a-date-picker v-model:value="value8" placeholder="请选择评审时间" />
|
||||
</a-form-item>
|
||||
<div>选择讲师</div>
|
||||
<div style="width: 430px; height: 1px;background-color: #e2e0e0;margin-top: 8px;"></div>
|
||||
<div style="display: flex;margin-top: 13px;">
|
||||
<a-input placeholder="请输入姓名/工号" style="width: 150px;"/>
|
||||
<a-button type="primary" style="width: 70px; height: 31px; border-radius: 5px;margin-left: 15px;">搜索</a-button>
|
||||
<a-button type="primary" style="width: 70px; height: 31px; border-radius: 5px;margin-left: 12px;" ghost>重置</a-button>
|
||||
</div>
|
||||
<p style="margin-top: 11px; color: #b6b7b8;">说明:列表仅显示终稿已上传且未认证的讲师</p>
|
||||
<div style="display: flex;flex-direction: column;">
|
||||
<InitiateReviewTable></InitiateReviewTable>
|
||||
</div>
|
||||
<a-pagination size="small" v-model:current="current1" show-quick-jumper :total="500" @change="onChange" />
|
||||
</a-form>
|
||||
</div>
|
||||
<div style="height: 500px; width: 1px; background: #b9e6fb;margin-left: 91px; margin-top: 10px"></div>
|
||||
<div style="display: flex; flex-direction: column;width: 160px;margin-left: 24px;margin-top: 20px;">
|
||||
<div style="font-size: 16px; font-weight: 900;">已选</div>
|
||||
<div style="width: 16opx; height: 1px;background-color: #b9e6fb;margin: 11px 0;"></div>
|
||||
<a-tag closable @close="log" style="border:1px solid #3da8f0; color: #3da8f0;">Tag 2</a-tag>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="width: 100%;text-align: center;margin-top: 65px">
|
||||
<a-button type="primary" style="width: 70px; height: 31px; border-radius: 5px ;margin: 0 15px 0 15px;" ghost>取消</a-button>
|
||||
<a-button type="primary" style="width: 70px; height: 31px; border-radius: 5px" >确认</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
109
src/views/gratefulteacher/InitiateReviewTable.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<script setup >
|
||||
const columns = [
|
||||
{
|
||||
name: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Tags',
|
||||
key: 'tags',
|
||||
dataIndex: 'tags',
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
key: 'action',
|
||||
},
|
||||
];
|
||||
const data = [
|
||||
{
|
||||
key: '1',
|
||||
|
||||
age: 32,
|
||||
address: 'New ',
|
||||
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
|
||||
age: 42,
|
||||
address: 'London ',
|
||||
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
|
||||
age: 32,
|
||||
|
||||
|
||||
},
|
||||
];
|
||||
const rowSelection = {
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
|
||||
},
|
||||
getCheckboxProps: record => ({
|
||||
disabled: record.name === 'Disabled User',
|
||||
// Column configuration not to be checked
|
||||
name: record.name,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="-page">
|
||||
<a-table
|
||||
|
||||
:row-selection="rowSelection"
|
||||
:pagination="false"
|
||||
:row-class-name="(_record, index) => (index % 2 === 1 ? 'table-striped' : null)"
|
||||
:columns="columns"
|
||||
:data-source="data"
|
||||
class="ant-table-striped"
|
||||
size="middle"
|
||||
>
|
||||
<template #headerCell="{ column }">
|
||||
<template v-if="column.key === 'name'">
|
||||
<span >
|
||||
<smile-outlined />
|
||||
Name
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'name'">
|
||||
<a>
|
||||
{{ record.name }}
|
||||
</a>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'tags'">
|
||||
<span>
|
||||
<a-tag
|
||||
v-for="tag in record.tags"
|
||||
:key="tag"
|
||||
:color="tag === 'loser' ? 'volcano' : tag.length > 5 ? 'geekblue' : 'green'"
|
||||
>
|
||||
{{ tag.toUpperCase() }}
|
||||
</a-tag>
|
||||
</span>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'action'">
|
||||
<span>
|
||||
|
||||
<a>Delete</a>
|
||||
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
// [data-doc-theme='light'] .ant-table-striped :deep(.ant-table-striped .table-striped ) td {
|
||||
// background-color: #fafafa;
|
||||
// }
|
||||
</style>
|
||||
505
src/views/gratefulteacher/InstructorCertification.vue
Normal file
@@ -0,0 +1,505 @@
|
||||
<script setup >
|
||||
import { ref,onMounted } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import {getexamineList,CreateAuthentication,delExamine} from '@/api/examineApi.js'
|
||||
import dialog from "@/utils/dialog";
|
||||
import DropDown from "@/components/common/DropDown";
|
||||
import OwnerTableModelStudent from "@/components/student/OwnerTableModelStudent";
|
||||
import CommonStudent from "@/components/student/CommonStudent";
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const visible = ref(false);
|
||||
const loading = ref(false);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: 'serial',
|
||||
dataIndex: 'serial',
|
||||
key: 'serial',
|
||||
},
|
||||
{
|
||||
title: '认证项目名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '创建人',
|
||||
dataIndex: 'createName',
|
||||
key: 'createName',
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
dataIndex: 'createTime',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
},
|
||||
];
|
||||
//认证审批项目列表数据
|
||||
const data = ref([{
|
||||
id: 1,
|
||||
"deleted": false,
|
||||
"createTime": "2024-05-10 13:38:37",
|
||||
"createId": null,
|
||||
"createName": null,
|
||||
"updateTime": "2024-05-10 13:49:16",
|
||||
"updateId": 965342027497607168,
|
||||
"updateName": "李玉冰",
|
||||
"number": 1,
|
||||
"name": "测试1",
|
||||
"description": "认证项目详情",
|
||||
"cover": "/www/elearning/upload/activityfile/blue.png"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"deleted": false,
|
||||
"createTime": "2024-05-10 13:24:50",
|
||||
"createId": null,
|
||||
"createName": null,
|
||||
"updateTime": null,
|
||||
"updateId": null,
|
||||
"updateName": null,
|
||||
"number": 2,
|
||||
"name": "认证项目003修改",
|
||||
"description": "认证项目详情",
|
||||
"cover": "/www/elearning/upload/activityfile/blue.png"
|
||||
},])
|
||||
const delVisible = ref(false)
|
||||
//页数
|
||||
const current1 = ref(1);
|
||||
//表格行数
|
||||
const pageSize = ref(10)
|
||||
//总条数
|
||||
const total = ref(0)
|
||||
//封面图
|
||||
const url = ref('http://localhost:8070/manage/img/50.34e94524.png')
|
||||
//搜索值
|
||||
const searchValue = ref('')
|
||||
//搜索功能
|
||||
const Administrator= ref(0)
|
||||
const search = async()=>{
|
||||
loading.value = true
|
||||
|
||||
const res = await getexamineList({
|
||||
pageNo: current1.value,
|
||||
pageSize: pageSize.value,
|
||||
name: searchValue.value,
|
||||
isSuper:Administrator.value
|
||||
})
|
||||
loading.value = false
|
||||
|
||||
data.value= res.data.records
|
||||
total.value = res.data.total
|
||||
console.log(999);
|
||||
}
|
||||
//重置
|
||||
const handleRest = ()=>{
|
||||
getlist()
|
||||
|
||||
}
|
||||
//删除认证
|
||||
const deleteExamine = async(id)=>{
|
||||
await delExamine({
|
||||
id
|
||||
})
|
||||
getlist()
|
||||
|
||||
|
||||
}
|
||||
|
||||
const onChange = (pageNo,pageSize) => {
|
||||
current1.value = pageNo
|
||||
getlist()
|
||||
|
||||
|
||||
};
|
||||
const ViewReviewShow =ref(null)
|
||||
|
||||
const centerDialogVisible = ref(false)
|
||||
const SkipManagement = (id)=>{
|
||||
|
||||
router.push({
|
||||
path: '/LecturerManagement',
|
||||
query: {id,
|
||||
description:data.value[0].description,
|
||||
name:data.value[0].name
|
||||
}
|
||||
})
|
||||
}
|
||||
//讲师认证列表数据
|
||||
const InstructorCertificationlist = ref([])
|
||||
const getlist = async() =>{
|
||||
loading.value = true
|
||||
const res = await getexamineList({
|
||||
pageNo: current1.value,
|
||||
pageSize: pageSize.value,
|
||||
name: "",
|
||||
isSuper:Administrator.value
|
||||
|
||||
})
|
||||
console.log(res.data,'认证列表数据');
|
||||
loading.value = false
|
||||
total.value = res.data.total
|
||||
data.value= res.data.records
|
||||
}
|
||||
|
||||
//创建认证
|
||||
const launchOrUpdate = async()=>{
|
||||
CreateAuthentication()
|
||||
}
|
||||
|
||||
onMounted(()=>{
|
||||
getlist()
|
||||
})
|
||||
|
||||
const customRow=(column) =>{
|
||||
column.forEach((e, index) => {
|
||||
column[index].className = 'tableClass'
|
||||
})
|
||||
}
|
||||
const handleMsg = {
|
||||
del: "你确定删除该教师信息吗?",
|
||||
};
|
||||
|
||||
function handleOper(record, type, status = "") {
|
||||
dialog({
|
||||
content: "确认删除吗?数据删除后不可恢复",
|
||||
// ok:deleteExamine(record.id)
|
||||
ok:()=>{
|
||||
|
||||
deleteExamine(record.id)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page">
|
||||
<!-- 线上学习课程设置 -->
|
||||
<a-drawer v-model:visible="ViewReviewShow"
|
||||
class="custom-class"
|
||||
|
||||
:closable="false"
|
||||
placement="right"
|
||||
width="726px">
|
||||
<div class="header">
|
||||
<div class="headerTitle">线上学习课程设置</div>
|
||||
<img
|
||||
style="width: 29px; height: 29px; cursor: pointer"
|
||||
src="../../assets/images/basicinfo/close.png"
|
||||
@click="closeDrawer"
|
||||
/>
|
||||
</div>
|
||||
<div style="display: flex;flex-direction: column;">
|
||||
<div @click="ViewReviewShow=true" style="margin-bottom: 15px; height: 38px; width: 150px;background: #4ea6ff;line-height: 40px;text-align: center;border-radius: 8px;color: #ffffff;">选择/新建课程</div>
|
||||
|
||||
<div>
|
||||
<a-table
|
||||
|
||||
:row-selection="rowSelection"
|
||||
:pagination="false"
|
||||
:row-class-name="(_record, index) => (index % 2 === 1 ? 'table-striped' : null)"
|
||||
:columns="ViewReviewcolumns"
|
||||
:data-source="ViewReviewdata"
|
||||
class="ant-table-striped"
|
||||
size="middle"
|
||||
/>
|
||||
</div>
|
||||
<div style=" display: flex;justify-content: center;">
|
||||
<div style="margin-right: 30px; border-radius: 8px; color: #fff;font-size: 16px; display: flex; justify-content: center;align-items: center; width: 100px; height: 38px; margin-top: 36px;background: #3da8f0;">取消</div>
|
||||
<div style="border-radius: 8px; color: #fff;font-size: 16px; display: flex; justify-content: center;align-items: center; width: 100px; height: 38px; margin-top: 36px;background: #3da8f0;">确定</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</a-drawer>
|
||||
<div class="filter">
|
||||
<div class="filterItems">
|
||||
<div style="display: flex;">
|
||||
<a-input :max="50" v-model:value="searchValue" style="width: 270px; height: 41px; border-radius: 8px"
|
||||
placeholder="请输入认证项目名称" />
|
||||
<div style="display: flex; margin-left: 20px">
|
||||
<div class="btn btn1" @click="search()">
|
||||
<div class="search"></div>
|
||||
<div class="btnText ">搜索</div>
|
||||
</div>
|
||||
<div class="btn btn2" style="width: 105px" @click="handleRest">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">重置</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="Administrator===0" @click="ViewReviewShow=true" style="height: 38px; width: 150px;background: #4ea6ff;line-height: 40px;text-align: center;border-radius: 8px;color: #ffffff;">线上学习课程设置</div>
|
||||
<div class="btns" @click="centerDialogVisible=true">
|
||||
<div class="btn btn3">
|
||||
<div class="search"></div>
|
||||
<div class="btnText" @click="visible=true">创建认证</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<div class="table">
|
||||
<a-table :columns="columns"
|
||||
:customHeaderRow="customRow"
|
||||
:data-source="data"
|
||||
:scroll="{ x: 1000 }"
|
||||
:loading="loading"
|
||||
class="ant-table"
|
||||
:row-class-name="(_record, index) => 'table' "
|
||||
:pagination="false">
|
||||
<template #headerCell="{ column }">
|
||||
<template v-if="column.key === 'serial'">
|
||||
<span>
|
||||
序号
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template #bodyCell="{ column, record,index }">
|
||||
<template v-if="column.key === 'serial'">
|
||||
<span>
|
||||
{{ index+1 }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'tags'">
|
||||
<span>
|
||||
{{ record.name }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'action'">
|
||||
<span style="text-align: center;">
|
||||
<a style="margin-right: 7px;" @click="visible=true">编辑</a>
|
||||
|
||||
<a style="margin-right: 7px;" @click='SkipManagement(record.id)'>管理</a>
|
||||
|
||||
<a style="margin-right: 7px;">
|
||||
评审
|
||||
</a>
|
||||
<DropDown v-if="Administrator===0" value="授权">
|
||||
<OwnerTableModelStudent
|
||||
:types="[7, 8, 9]"
|
||||
:id="record.id"
|
||||
:type="9"
|
||||
>权限名单</OwnerTableModelStudent
|
||||
>
|
||||
<CommonStudent :type="7" :id="record.id" title="查看权"
|
||||
>查看权</CommonStudent
|
||||
>
|
||||
<CommonStudent :type="8" :id="record.id" title="管理权"
|
||||
>管理权</CommonStudent
|
||||
>
|
||||
</DropDown>
|
||||
<a style="color: #de2139" @click="handleOper(record, 'del')">删除</a>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
|
||||
</div>
|
||||
<div style="text-align: center; margin-top: 18px;">
|
||||
|
||||
|
||||
<a-pagination :defaultPageSize="pageSize" :showSizeChanger="false" v-model:current="current1" show-quick-jumper :total="total" @change="onChange" />
|
||||
</div>
|
||||
<!--创建认证和编辑认证 -->
|
||||
<a-modal v-model:visible="visible" title="编辑认证" @ok="handleOk" width="610px">
|
||||
<a-form>
|
||||
|
||||
<a-form-item :rules="[{ required: true, message: 'Please input your password!' }]" label="Username" style="width: 381px;margin-left: 32px;margin-top: 24px">
|
||||
<a-input placeholder="认证项目名称" style=" border-radius: 8px;" />
|
||||
</a-form-item>
|
||||
<a-form-item :rules="[{ required: true, message: 'Please input your password!' }]" label="封面图" style="width: 560px;margin-left: 32px;margin-top: 24px">
|
||||
<img style="width: 127px; height: 70px;margin-bottom: 13px;" src="../../assets/50.png" alt="">
|
||||
<!-- <a-image style="width: 127px; height: 70px;margin-bottom: 13px;" src="../../assets/50.png"></a-image> -->
|
||||
<img style="width: 127px; height: 70px;margin-bottom: 13px;margin-left: 15px" src="../../assets/39.png" alt="">
|
||||
<img style="width: 127px; height: 70px;margin-bottom: 13px;margin-left: 15px" src="../../assets/46.png" alt="">
|
||||
<img style="width: 127px; height: 70px;margin-bottom: 13px;" src="../../assets/33.png" alt="">
|
||||
<img style="width: 127px; height: 70px;margin-bottom: 13px;margin-left: 15px" src="../../assets/47.png" alt="">
|
||||
<img style="width: 127px; height: 70px;margin-bottom: 13px;margin-left: 15px" src="../../assets/49.png" alt="">
|
||||
|
||||
</a-form-item>
|
||||
<a-form-item style="margin-left: 32px;margin-top: 24px" label="具体说明">
|
||||
<a-textarea
|
||||
style="width: 408px;"
|
||||
v-model:value="value2"
|
||||
:auto-size="{ minRows: 2, maxRows: 5 }"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.btn3 {
|
||||
margin-right: 0;
|
||||
|
||||
.search {
|
||||
width: 17px;
|
||||
height: 18px;
|
||||
background-image: url("@/assets/images/courseManage/add0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn3:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
.btn1 {
|
||||
.search {
|
||||
width: 15px;
|
||||
height: 17px;
|
||||
background-image: url("@/assets/images/courseManage/search0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn2 {
|
||||
.search {
|
||||
width: 16px;
|
||||
height: 18px;
|
||||
background-image: url("@/assets/images/courseManage/reset0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn1:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
|
||||
.btn2:active {
|
||||
background: rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
.btn {
|
||||
padding: 0 26px 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
.page {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
.filter {
|
||||
margin-left: 40px;
|
||||
margin-right: 62px;
|
||||
margin-top: 28px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
.filterItems{
|
||||
width: 100%;
|
||||
height: 41px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.table {
|
||||
margin-left: 40px;
|
||||
margin-right: 62px;
|
||||
margin-top: 28px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
:deep(.ant-table-container table > thead > tr:first-child th:first-child) {
|
||||
width: 83px;
|
||||
|
||||
}
|
||||
:deep(.ant-table-container table > thead > tr:first-child th:last-child) {
|
||||
width: 199px;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
:deep(.ant-table-container table > thead > tr:first-child th:last-child) {
|
||||
width: 199px;
|
||||
|
||||
}
|
||||
:deep(.ant-table-container table > thead > tr:first-child th:nth-last-child(2)) {
|
||||
width: 143px;
|
||||
|
||||
}
|
||||
:deep(.ant-table-container table > thead > tr:first-child th:nth-last-child(3)) {
|
||||
width: 113px;
|
||||
|
||||
}
|
||||
:deep(.ant-table-container table > thead > tr:first-child th:nth-last-child(4)) {
|
||||
width: 326px;
|
||||
|
||||
}
|
||||
|
||||
:deep(.ant-table-tbody > tr > td ){
|
||||
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
.custom-dialog-title {
|
||||
text-align: left; /* 让标题文本居左 */
|
||||
/* 其他你需要的样式 */
|
||||
}
|
||||
.imgs {
|
||||
width: 560px;
|
||||
margin-left: 44.5px;
|
||||
|
||||
}
|
||||
.explain {
|
||||
width: 560px;
|
||||
margin-left: 44.5px;
|
||||
|
||||
}
|
||||
:deep(.imgs .el-form-item__label){
|
||||
margin-top: 29px;
|
||||
}
|
||||
:deep(.demo-pagination-block) {
|
||||
width: 100%;
|
||||
}
|
||||
:deep(.ant-table-tbody > tr > td){
|
||||
text-align: center;
|
||||
} .header {
|
||||
margin-top: -20px;
|
||||
height: 73px;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
// background-color: red;
|
||||
margin-bottom: 20px;
|
||||
.headerTitle {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 25px;
|
||||
// margin-left: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
55
src/views/gratefulteacher/LeadInstructor.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<script setup >
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { UploadFilled } from '@element-plus/icons-vue'
|
||||
import { ref } from 'vue'
|
||||
const props = defineProps(["imprtlecturer"])
|
||||
const emit = defineEmits(['CloseImprt'])
|
||||
const Closeimprtlecturer = (done) => {
|
||||
ElMessageBox.confirm('Are you sure to close this dialog?')
|
||||
.then(() => {
|
||||
|
||||
emit('CloseImprt', false)
|
||||
done()
|
||||
})
|
||||
.catch(() => {
|
||||
// catch error
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="-page" >
|
||||
<el-drawer v-model="props.imprtlecturer" :before-close="Closeimprtlecturer" style="padding:0 10px; width: 100%;" size="65%">
|
||||
<template #title>
|
||||
<h1 style="font-weight: 700;">导入讲师</h1>
|
||||
</template>
|
||||
<div >
|
||||
<div style="width: 100%;">请下载 <span style="color: #409EFF;">模板</span> ,按要求填写数据并导入</div>
|
||||
</div>
|
||||
<div style="margin-left: 20px; margin-top: 37px;">
|
||||
<el-upload
|
||||
style="width: 33%;"
|
||||
class="upload-demo"
|
||||
drag
|
||||
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
|
||||
multiple
|
||||
>
|
||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||
<div class="el-upload__text">
|
||||
点击或将文件拖拽到此处上传件
|
||||
|
||||
</div>
|
||||
<div style="color: #d7d7d7;">支持.xls .xlsx</div>
|
||||
</el-upload>
|
||||
</div>
|
||||
<div style="text-align: center;">
|
||||
<el-button plain type="primary" style="width: 100px; height: 40px;margin-right: 20px;" >取消</el-button>
|
||||
<el-button type="primary" style="width: 100px; height: 40px;margin-left: 20px; ">确认</el-button>
|
||||
|
||||
</div>
|
||||
</el-drawer>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
1312
src/views/gratefulteacher/LecturerManagement.vue
Normal file
281
src/views/gratefulteacher/QrCode.vue
Normal file
@@ -0,0 +1,281 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:visible="true"
|
||||
:footer="null"
|
||||
:title="null"
|
||||
:centere="true"
|
||||
:closable="false"
|
||||
style="margin-top: 400px"
|
||||
:zIndex="9999"
|
||||
@cancel="close"
|
||||
>
|
||||
<div id="qrcode" class="QR">
|
||||
<div class="qr_header"></div>
|
||||
<div class="qr_main">
|
||||
<div class="qrm_header">
|
||||
<span>{{ title }}</span>
|
||||
<div class="close_exit" @click="close"></div>
|
||||
</div>
|
||||
<div class="downloadCode" style="">
|
||||
<div class="qrm_body">
|
||||
<div class="qrm_body_info">
|
||||
<div class="codename" v-if="courseName">项目:{{ courseName }}</div>
|
||||
<div class="codename">{{ name }}</div>
|
||||
<div class="codename" v-if="createName">讲师:{{ createName }}</div>
|
||||
</div>
|
||||
<QrcodeVue :value="url" :size="size" style="width: 200px; height: 200px"></QrcodeVue>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="copyAble" class="codeUrl" :style="{ display: 'flex'}">
|
||||
<div class="codeUrlLink">链接</div>
|
||||
<a-input :value="url" disabled class="codeUrlInp"/>
|
||||
<a-input
|
||||
:value="url"
|
||||
id="courseUrl"
|
||||
class="codeUrlInp"
|
||||
style="position: absolute; opacity: 0; z-index: -1"
|
||||
/>
|
||||
<div @click="copyUrl" class="codeUrlCopy">复制链接</div>
|
||||
</div>
|
||||
<div class="qrm_footer">
|
||||
<span style="color: #387df7; cursor: pointer" @click="download(200)">下载二维码</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
<script setup>
|
||||
import {defineProps, onMounted} from "vue";
|
||||
import html2canvas from "html2canvas";
|
||||
import QrcodeVue from "qrcode.vue";
|
||||
import {message} from "ant-design-vue";
|
||||
|
||||
const props = defineProps({
|
||||
close: {
|
||||
type: Function,
|
||||
default: () => ({})
|
||||
},
|
||||
ok: {
|
||||
type: Function,
|
||||
default: () => ({})
|
||||
},
|
||||
url: String,
|
||||
copyAble: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 800
|
||||
},
|
||||
name: String,
|
||||
createName: String,
|
||||
courseName: String,
|
||||
title: {
|
||||
type: String,
|
||||
default: "二维码"
|
||||
},
|
||||
cancel: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
});
|
||||
|
||||
onMounted(() => props.duration && setTimeout(() => props.close(), props.duration));
|
||||
|
||||
function download() {
|
||||
html2canvas(
|
||||
document.querySelector(".downloadCode"),
|
||||
{ useCORS: true,
|
||||
allowTaint: true,
|
||||
logging: true,
|
||||
}
|
||||
).then((canvas) => {
|
||||
let a = document.createElement("a");
|
||||
a.style.display = "none";
|
||||
a.download = `${new Date().getTime()}.png`;
|
||||
a.href = canvas.toDataURL("image/png");
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
}).catch((err) => console.log('html2canvas',err));
|
||||
}
|
||||
|
||||
function copyUrl() {
|
||||
const input = document.createElement("input"); // 创建input对象
|
||||
input.value = props.url;
|
||||
document.body.appendChild(input); // 添加临时实例
|
||||
input.select(); // 选择实例内容
|
||||
document.execCommand("Copy"); // 执行复制
|
||||
document.body.removeChild(input); // 删除临时实例
|
||||
message.success("复制成功!");
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.QR {
|
||||
z-index: 9999;
|
||||
width: 520px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0px 1px 35px 0px rgba(118, 136, 166, 0.21);
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 10%;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
.qr_header {
|
||||
position: absolute;
|
||||
width: calc(100%);
|
||||
height: 40px;
|
||||
background: linear-gradient(
|
||||
rgba(78, 166, 255, 0.2) 0%,
|
||||
rgba(78, 166, 255, 0) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.qr_main {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
.qrm_header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-top: 20px;
|
||||
padding-left: 26px;
|
||||
font-size: 16px;
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.close_exit {
|
||||
position: absolute;
|
||||
right: 42px;
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url(@/assets/images/coursewareManage/close.png);
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.qrm_body {
|
||||
width: 100%;
|
||||
padding-top: 22px;
|
||||
padding-bottom: 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.qrm_body_info{
|
||||
width: 100%;
|
||||
margin-left: 278px;
|
||||
}
|
||||
.codename {
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
line-height: 25px;
|
||||
margin-bottom: 5px;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
.codeUrl {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 24px;
|
||||
|
||||
.codeUrlLink {
|
||||
width: 72px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #c7cbd2;
|
||||
line-height: 20px;
|
||||
border: 1px solid #c7cbd2;
|
||||
border-right: 0px solid #c7cbd2;
|
||||
}
|
||||
|
||||
.codeUrlInp {
|
||||
width: 305px;
|
||||
height: 40px;
|
||||
border: 1px solid #c7cbd2;
|
||||
}
|
||||
|
||||
.ant-input-disabled {
|
||||
background-color: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
|
||||
.ant-input[disabled] {
|
||||
background-color: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
|
||||
.codeUrlCopy {
|
||||
width: 96px;
|
||||
height: 40px;
|
||||
background-color: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.qrm_footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 44px;
|
||||
|
||||
.qrmbtn {
|
||||
width: 80px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
line-height: 32px;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #387df7;
|
||||
cursor: pointer;
|
||||
|
||||
.btntext {
|
||||
color: #387df7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.codeModal {
|
||||
.ant-modal {
|
||||
.ant-modal-content {
|
||||
width: 479px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.ant-modal-body {
|
||||
padding: 0 !important;
|
||||
}
|
||||
</style>
|
||||
33
src/views/gratefulteacher/ViewInstructor.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
showViewInstructor: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:visible"]);
|
||||
|
||||
const afterVisibleChange = (bool) => {
|
||||
console.log("visible", bool);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="-page">
|
||||
<a-drawer
|
||||
v-model:visible="visible"
|
||||
class="custom-class"
|
||||
style="color: red"
|
||||
title="Basic Drawer"
|
||||
placement="right"
|
||||
@after-visible-change="afterVisibleChange"
|
||||
>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
</a-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
83
src/views/gratefulteacher/ViewReview.vue
Normal file
@@ -0,0 +1,83 @@
|
||||
<script setup >
|
||||
const props = defineProps(['ViewReviewShow'])
|
||||
import { reactive } from 'vue';
|
||||
import InitiateReviewTable from './InitiateReviewTable.vue'
|
||||
const formState = reactive({
|
||||
username: '',
|
||||
password: '',
|
||||
remember: true,
|
||||
});
|
||||
const ViewReviewcolumns = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
},
|
||||
{
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
},
|
||||
];
|
||||
const ViewReviewdata = [
|
||||
{
|
||||
key: '1',
|
||||
name: 'John Brown',
|
||||
age: 32,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: 'Jim Green',
|
||||
age: 42,
|
||||
address: 'London No. 1 Lake Park',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
name: 'Joe Black',
|
||||
age: 32,
|
||||
address: 'Sidney No. 1 Lake Park',
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
name: 'Ben Kang',
|
||||
age: 15,
|
||||
address: 'Sidney No. 1 Lake Park',
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="-page">
|
||||
<el-drawer v-model="props.ViewReviewShow" title="查看评审" size="65%">
|
||||
<div style="display: flex;flex-direction: column;">
|
||||
<div style="font-size: 16px;"> 评审名称:<span>第三场二次认证</span></div>
|
||||
<div style="font-size: 16px;margin: 20px 0;"> 评审时间:<span>2024.05.30 14:00</span></div>
|
||||
<div style="font-size: 16px;">评审结果:</div>
|
||||
<div>
|
||||
<a-table
|
||||
|
||||
:row-selection="rowSelection"
|
||||
:pagination="false"
|
||||
:row-class-name="(_record, index) => (index % 2 === 1 ? 'table-striped' : null)"
|
||||
:columns="ViewReviewcolumns"
|
||||
:data-source="ViewReviewdata"
|
||||
class="ant-table-striped"
|
||||
size="middle"
|
||||
/>
|
||||
</div>
|
||||
<div style="align-self: center;">
|
||||
<div style="border-radius: 8px; color: #fff;font-weight: 900;font-size: 16px; display: flex; justify-content: center;align-items: center; width: 176px; height: 55px; margin-top: 36px;background: #3da8f0;">结束评审并通知结果</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
|
||||
</style>
|
||||
929
src/views/gratefulteacher/teaAdd.vue
Normal file
@@ -0,0 +1,929 @@
|
||||
<!-- eslint-disable vue/no-parsing-error -->
|
||||
<!-- eslint-disable vue/require-v-for-key -->
|
||||
<template>
|
||||
<div class="CommonStudent">
|
||||
<a-drawer :visible="visiable" class="drawerStyle ProjCheckship CommonStudent" placement="right" width="60%">
|
||||
<div class="drawerMain" id="ProjCheckship" style="">
|
||||
<div class="header">
|
||||
<div class="headerTitle">
|
||||
{{ { 1: "添加学员", 2: "添加学员", 3: "添加学员" }[type] || title }}
|
||||
</div>
|
||||
<img style="width: 29px; height: 29px; cursor: pointer" src="../../assets/images/basicinfo/close.png"
|
||||
@click="closeDrawer"/>
|
||||
</div>
|
||||
<div style="display: flex; overflow-x: auto; overflow-y: auto">
|
||||
<div class="tabs" style="min-width: 800px">
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane v-if="infoType" :key="4" tab="项目内学员">
|
||||
<div :style="{ height: screenHeight - 235 + 'px' }">
|
||||
<div>
|
||||
<a-form-item label="姓名:">
|
||||
<a-input v-model:value="projectParams.studentName"
|
||||
style="width: 260px; height: 40px; border-radius: 8px"
|
||||
placeholder="请输入姓名"/>
|
||||
<a-button type="primary" @click="getProjectStu" style="margin-left: 20px; border-radius: 4px">
|
||||
<template #icon>
|
||||
<SearchOutlined/>
|
||||
</template>
|
||||
搜索
|
||||
</a-button>
|
||||
<a-button type="primary" @click="resetProjectStu" style="margin-left: 20px; border-radius: 4px">重置
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<div class="tableBox tabb">
|
||||
<BaseTable ref="projectStuTableRef" :columns="projectStuColumns" :url="STUDENT_LIST"
|
||||
v-model:params="projectParams" v-model:selectedRows="projectSelectRows"
|
||||
type="checkbox"></BaseTable>
|
||||
</div>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane :key="1" tab="快速选人">
|
||||
<div :style="{ height: screenHeight - 235 + 'px' }">
|
||||
<div class="tab1">
|
||||
<a-form-item label="姓名">
|
||||
<a-input v-model:value="nameSearch.keyword" style="width: 270px; height: 40px; border-radius: 8px"
|
||||
placeholder="请输入姓名"/>
|
||||
<a-button type="primary" @click="onSearchStu" style="margin-left: 20px; border-radius: 4px">
|
||||
<template #icon>
|
||||
<SearchOutlined/>
|
||||
</template>
|
||||
搜索
|
||||
</a-button>
|
||||
<a-button type="primary" @click="resetStu" style="margin-left: 20px; border-radius: 4px">重置
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<div class="chooseLeft" style="display: grid; grid-template-columns: 250px auto">
|
||||
<div :style="{
|
||||
height: screenHeight - 180 + 'px',
|
||||
overflowY: 'auto',
|
||||
}" style="border: 1px solid #f0f0f0">
|
||||
<div class="tree" style="margin: 10px 4px 220px 10px">
|
||||
<a-tree allow-clear tree-default-expand-all :tree-data="treeData" :loading="orgLoading"
|
||||
:load-data="onLoadData" v-model:selectedKeys="stuTreeSelectKeys"
|
||||
v-model:expandedKeys="stuTreeExpandedKeys" :fieldNames="{
|
||||
children: 'treeChildList',
|
||||
key: 'id',
|
||||
title: 'name',
|
||||
value: 'name',
|
||||
}" @select="stuStuOrgSelect">
|
||||
</a-tree>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tableBox tabb" style="
|
||||
margin: 0px 4px 120px 10px;
|
||||
border: 1px solid #f0f0f0;
|
||||
">
|
||||
<BaseTable ref="stuTableRef" :columns="stuColumns" :url="USER_LIST_PAGE" pageKey="pageNo"
|
||||
v-model:params="nameSearch" :request="useNewRowsPageNoInit"
|
||||
v-model:selectedRows="stuSelectRows" type="checkbox"></BaseTable>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane v-if="!selectStu" :key="2" tab="添加组织">
|
||||
<div :style="{ height: screenHeight - 235 + 'px' }">
|
||||
<div class="tab2">
|
||||
<a-form-item label="组织:">
|
||||
<a-input v-model:value="searchOrgName.keyword"
|
||||
style="width: 230px; height: 40px; border-radius: 8px" placeholder="请输入组织"
|
||||
@click="orgValue"/>
|
||||
<a-button type="primary" @click="searchOrg" style="margin-left: 20px; border-radius: 4px">
|
||||
<template #icon>
|
||||
<SearchOutlined/>
|
||||
</template>
|
||||
搜索
|
||||
</a-button>
|
||||
<a-button type="primary" @click="resetOrg" style="margin-left: 20px; border-radius: 4px">重置
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<div class="boeTree">
|
||||
<a-tree v-model:selectedKeys="selectedOrgKeys"
|
||||
:tree-data="searchOrgName.keyword ? orgData : treeOrgData" @select="onOrgSelectChange"
|
||||
:loading="orgOrgLoading" :load-data="onLoadOrgData" :fieldNames="{
|
||||
children: 'treeChildList',
|
||||
key: 'id',
|
||||
title: 'name',
|
||||
value: 'name',
|
||||
}" row-key="id" :row-selection="orgRowSelection" multiple>
|
||||
</a-tree>
|
||||
</div>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane v-if="!selectStu" :key="3" tab="受众关联">
|
||||
<div :style="{ height: screenHeight - 235 + 'px' }">
|
||||
<div>
|
||||
<a-form-item label="受众名称:">
|
||||
<a-input v-model:value="audienceName.keyword"
|
||||
style="width: 260px; height: 40px; border-radius: 8px"
|
||||
placeholder="请输入受众名称"/>
|
||||
<a-button type="primary" @click="searchAudi" style="margin-left: 20px; border-radius: 4px">
|
||||
<template #icon>
|
||||
<SearchOutlined/>
|
||||
</template>
|
||||
搜索
|
||||
</a-button>
|
||||
<a-button type="primary" @click="resetAudienceInfo" style="margin-left: 20px; border-radius: 4px">
|
||||
重置
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<div class="tableBox tabb">
|
||||
<BaseTable ref="auditTableRef" :columns="audiColums" :url="AUDIENCE_LIST" page-key="pageNo"
|
||||
v-model:params="audienceName" :request="useTotalPage"
|
||||
v-model:selectedRows="auditSelectRows" v-model:selectedRowKeys="auditSelectRowKeys"
|
||||
type="checkbox"></BaseTable>
|
||||
</div>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
<div class="right1" style="min-width: 200px">
|
||||
<div class="onerow">
|
||||
<div class="onleft">
|
||||
<div class="already">已选</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :style="{ 'max-height': screenHeight - 235 + 'px' }" style="overflow-y: auto">
|
||||
<div class="selecteds" v-if="infoType">
|
||||
<div class="person">项目内学员</div>
|
||||
<div v-for="(item, i) in projectSelectRows" :key="i">
|
||||
<div v-if="i < 11">
|
||||
<div class="chose">
|
||||
{{ item.studentName }}
|
||||
<div class="ch" @click="auditTableRef.remove(i)"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="person">
|
||||
<div class="chose">
|
||||
{{ item.studentName }}
|
||||
<div class="ch" @click="auditTableRef.remove(i)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!member && projectSelectRows?.length > 10" class="ifsw">
|
||||
<div @click="member = !member" class="“sw”">查看更多></div>
|
||||
</div>
|
||||
<div v-if="member && projectSelectRows?.length > 10" class="ifsw">
|
||||
<div @click="member = !member" class="sw">收起<</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="selecteds">
|
||||
<div class="person">快速选人</div>
|
||||
<div v-for="(item, i) in stuSelectRows" :key="i">
|
||||
<div v-if="i < 11">
|
||||
<div class="chose">
|
||||
{{ item.realName }}
|
||||
<div class="ch" @click="stuTableRef.remove(i)"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="person">
|
||||
<div class="chose">
|
||||
{{ item.realName }}
|
||||
<div class="ch" @click="stuTableRef.remove(i)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!person && stuSelectRows.length > 10" class="ifsw">
|
||||
<div @click="person = !person" class="“sw”">查看更多></div>
|
||||
</div>
|
||||
<div v-if="person && stuSelectRows.length > 10" class="ifsw">
|
||||
<div @click="person = !person" class="sw">收起<</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!selectStu" class="selecteds">
|
||||
<div class="dept">添加组织</div>
|
||||
<div v-for="(item, i) in deptList" :key="i">
|
||||
<div v-if="i < 11">
|
||||
<div class="chose1">
|
||||
<div class="span">{{ item.name }}</div>
|
||||
<div class="ch1" @click="orgDel(i)" style="cursor: pointer;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="dept">
|
||||
<div class="chose1">
|
||||
<div class="span">{{ item.name }}</div>
|
||||
<div class="ch1" @click="orgDel(i)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!dept && deptList.length > 10" class="ifsw">
|
||||
<div @click="dept = !dept" class="“sw”">查看更多></div>
|
||||
</div>
|
||||
<div v-if="dept && deptList.length > 10" class="ifsw">
|
||||
<div @click="dept = !dept" class="sw">收起<</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--受众-->
|
||||
<div v-if="!selectStu" class="selecteds">
|
||||
<div class="group">受众关联</div>
|
||||
<div v-for="(item, i) in auditSelectRows" :key="i">
|
||||
<div v-if="i < 11">
|
||||
<div class="chose2">
|
||||
<div class="span">{{ item.audienceName }}</div>
|
||||
<div class="ch2" @click="auditTableRef.remove(i)"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="group">
|
||||
<div class="chose2">
|
||||
<div class="span">{{ item.audienceName }}</div>
|
||||
<div class="ch2" @click="auditTableRef.remove(i)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!group && auditSelectRows.length > 10" class="ifsw">
|
||||
<div @click="group = !group" class="“sw”">查看更多></div>
|
||||
</div>
|
||||
<div v-if="group && auditSelectRows.length > 10" class="ifsw">
|
||||
<div @click="group = !group" class="sw">收起<</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btnn">
|
||||
<button class="btn2" style="width: 100px; height:38px;background:
|
||||
#4ea6ff;border: none;margin-right: 15px; border-radius: 8px;color:aliceblue" @click="closeDrawer">取消</button>
|
||||
<button class="btn2" style="width: 100px;
|
||||
height:38px;background: #4ea6ff;border: none; border-radius: 8px ;color:aliceblue" @click="submitAuth">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</a-drawer>
|
||||
<a-button @click="openDrawer" type="link">
|
||||
<slot></slot>
|
||||
</a-button>
|
||||
</div>
|
||||
<a-modal :style="{ padding: 0, position:'relative', right: '-20%' }" :closable="true" :visible="stageVisible"
|
||||
:footer="null" centered="true" @ok="handleStageOk" wrapClassName="changeModal">
|
||||
<div class="con">
|
||||
<div class="header">
|
||||
<div class="inhe">
|
||||
<div class="tz">{{ type === 1 ? "选择阶段" : "添加学员到关卡" }}</div>
|
||||
<div class="mg" @click="closeChangeModal"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mid">
|
||||
<div class="inher">
|
||||
<div class="select">
|
||||
<a-select style="width: 400px" :placeholder="type === 1 ? '选择阶段' : '选择关卡'" v-model:value="stageId"
|
||||
className="cus-select">
|
||||
<a-select-option v-for="(item, i) in stageIds" :key="i" :value="item.id">{{ item.name || "默认" }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</div>
|
||||
<span style="color: #999999; margin-left: 10px"><minus-circle-outlined/>已在其他关卡的学员,不会被添加到该关卡</span>
|
||||
<div class="btn" style="margin-top: 50px">
|
||||
<button class="sameb btn1" @click="closeChangeModal" style="cursor: pointer">
|
||||
取消
|
||||
</button>
|
||||
<button class="sameb btn2" @click="handleDialogOk" style="cursor: pointer">
|
||||
确定
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
<script setup>
|
||||
import {message} from "ant-design-vue";
|
||||
import {computed, defineEmits, defineProps, ref, watch} from "vue";
|
||||
import {useNewRowsPageNoInit, request, useRequest, useTotalPage} from "@/api/request";
|
||||
import {
|
||||
saveStu,
|
||||
} from "@/api/index1";
|
||||
import dialog from "@/utils/dialog";
|
||||
import BaseTable from "@/components/common/BaseTable";
|
||||
import {AUDIENCE_LIST, ORG_CHILD_LIST, ORG_LIST, STUDENT_LIST, USER_LIST_PAGE} from "@/api/apis";
|
||||
import {addTutor}from '@/api/examineApi.js'
|
||||
const emit = defineEmits({});
|
||||
const props = defineProps({
|
||||
|
||||
type: Number,
|
||||
infoType: Number,
|
||||
infoId: Number,
|
||||
id: String,
|
||||
|
||||
title: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
clear: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
selectStu: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
selectOne: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
stage: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
projectId: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
groupId: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
groupName: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
groupMemberCount: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
groupMemberNumber: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
activeKey1: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const projectSelectKeys = ref([]);
|
||||
const projectSelectRows = ref([]);
|
||||
const stuSelectRows = ref([]);
|
||||
const auditSelectRows = ref([]);
|
||||
const auditSelectRowKeys = ref([]);
|
||||
const deptList = ref([]);
|
||||
const member = ref(false);
|
||||
const dept = ref(false);
|
||||
const projectStuTableRef = ref();
|
||||
const stuTableRef = ref();
|
||||
const projectParams = ref({ pid: props.infoId, type: props.infoType, studentName: "" });
|
||||
|
||||
const getProjectStu = () => projectStuTableRef.value.fetch();
|
||||
const resetProjectStu = () => {
|
||||
projectParams.value.studentName = "";
|
||||
projectStuTableRef.value.reset();
|
||||
};
|
||||
const teaunm = ref([])
|
||||
watch(stuSelectRows,(val)=>{
|
||||
console.log(val,'val')
|
||||
teaunm.value = val.map((res,index)=>res.id)
|
||||
console.log(teaunm.value);
|
||||
})
|
||||
const person = ref(false);
|
||||
const group = ref(false);
|
||||
const visiable = ref(false);
|
||||
const activeKey = ref(props.infoType ? 4 : 1);
|
||||
const stageVisible = ref(false);
|
||||
const stageId = ref();
|
||||
|
||||
const nameSearch = ref({
|
||||
keyword: "",
|
||||
departId: '',
|
||||
});
|
||||
const stuTreeSelectKeys = ref([]);
|
||||
const stuTreeExpandedKeys = ref([]);
|
||||
const audienceName = ref({
|
||||
keyword: "",
|
||||
});
|
||||
const searchOrgName = ref({
|
||||
keyword: "",
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
const stageIds = computed(() => props.stage);
|
||||
|
||||
const { data: orgData, fetchData: searchOrg } = useRequest(
|
||||
ORG_LIST,
|
||||
searchOrgName.value,
|
||||
);
|
||||
const { data: treeData, loading: orgLoading } = useRequest(
|
||||
ORG_LIST,
|
||||
{ keyword: "" },
|
||||
);
|
||||
const { data: treeOrgData, loading: orgOrgLoading } = useRequest(
|
||||
ORG_LIST,
|
||||
{ keyword: "" },
|
||||
);
|
||||
|
||||
const projectStuColumns = ref([
|
||||
{
|
||||
title: "姓名",
|
||||
dataIndex: "studentName",
|
||||
key: "studentName",
|
||||
width: 80,
|
||||
align: "center",
|
||||
className: "h",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "工号",
|
||||
dataIndex: "studentUserNo",
|
||||
key: "studentUserNo",
|
||||
width: 80,
|
||||
align: "center",
|
||||
className: "h",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "归属组织",
|
||||
dataIndex: "studentOrgName",
|
||||
key: "studentOrgName",
|
||||
width: 80,
|
||||
align: "center",
|
||||
className: "h",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "部门",
|
||||
dataIndex: "studentDepartName",
|
||||
key: "studentDepartName",
|
||||
width: 80,
|
||||
align: "center",
|
||||
className: "h",
|
||||
ellipsis: true,
|
||||
},
|
||||
]);
|
||||
const stuColumns = ref([
|
||||
{
|
||||
title: "姓名",
|
||||
dataIndex: "realName",
|
||||
key: "realName",
|
||||
width: 80,
|
||||
align: "center",
|
||||
className: "h",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "工号",
|
||||
dataIndex: "userNo",
|
||||
key: "userNo",
|
||||
width: 80,
|
||||
align: "center",
|
||||
className: "h",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "归属组织",
|
||||
dataIndex: "orgName",
|
||||
key: "orgName",
|
||||
width: 80,
|
||||
align: "center",
|
||||
className: "h",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "部门",
|
||||
dataIndex: "departName",
|
||||
key: "departName",
|
||||
width: 80,
|
||||
align: "center",
|
||||
className: "h",
|
||||
ellipsis: true,
|
||||
},
|
||||
]);
|
||||
const audiColums = ref([
|
||||
{
|
||||
title: "受众名称",
|
||||
dataIndex: "audienceName",
|
||||
key: "audienceName",
|
||||
width: 30,
|
||||
align: "left",
|
||||
className: "h",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "人数",
|
||||
dataIndex: "totalMember",
|
||||
key: "totalMember",
|
||||
width: 30,
|
||||
align: "center",
|
||||
className: "h",
|
||||
},
|
||||
]);
|
||||
const orgSelectKeys = ref([]);
|
||||
const auditTableRef = ref();
|
||||
const screenHeight = ref(document.body.clientHeight);
|
||||
|
||||
const orgRowSelection = computed(() => ({
|
||||
columnWidth: 20,
|
||||
selectedRowKeys: orgSelectKeys.value,
|
||||
onChange: onOrgSelectChange,
|
||||
preserveSelectedRowKeys: true,
|
||||
}));
|
||||
|
||||
const closeDrawer = () => {
|
||||
deleteDepSelect();
|
||||
visiable.value = false;
|
||||
nameSearch.value.keyword = "";
|
||||
selectedOrgKeys.value = [];
|
||||
};
|
||||
|
||||
function searchAudi() {
|
||||
auditTableRef.value.reset(audienceName.value);
|
||||
}
|
||||
|
||||
function onLoadData(treeNode) {
|
||||
return request(ORG_CHILD_LIST, { keyword: "", orgId: treeNode.id }).then(
|
||||
(r) => {
|
||||
treeNode.dataRef.treeChildList = r.data;
|
||||
treeData.value = [...treeData.value];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function onLoadOrgData(treeNode) {
|
||||
return request(ORG_CHILD_LIST, { keyword: "", orgId: treeNode.id }).then(
|
||||
(r) => {
|
||||
treeNode.dataRef.treeChildList = r.data;
|
||||
treeOrgData.value = [...treeOrgData.value];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const closeChangeModal = () => {
|
||||
stageVisible.value = false;
|
||||
};
|
||||
const openDrawer = () => {
|
||||
visiable.value = true;
|
||||
};
|
||||
|
||||
function onSearchStu() {
|
||||
stuTableRef.value.reset(nameSearch.value);
|
||||
}
|
||||
|
||||
function stuStuOrgSelect(e) {
|
||||
nameSearch.value.departId = e.join("");
|
||||
stuTableRef.value.fetch();
|
||||
}
|
||||
|
||||
const selectedOrgKeys = ref([]);
|
||||
|
||||
watch(selectedOrgKeys, () => {
|
||||
console.log("selectedKeys", selectedOrgKeys);
|
||||
});
|
||||
|
||||
function orgDel(i) {
|
||||
orgSelectKeys.value = orgSelectKeys.value.filter(e => e !== deptList.value[i].id);
|
||||
selectedOrgKeys.value.splice(i, 1);
|
||||
deptList.value.splice(i, 1);
|
||||
}
|
||||
|
||||
function onOrgSelectChange(e, l) {
|
||||
orgRowSelection.value = e;
|
||||
deptList.value = l.selectedNodes;
|
||||
}
|
||||
|
||||
const resetStu = () => {
|
||||
nameSearch.value.keyword = "";
|
||||
stuTableRef.value.reset({ keyword: "", departId: '' });
|
||||
};
|
||||
//清空选择部门信息
|
||||
const deleteDepSelect = () => {
|
||||
stuSelectRows.value = [];
|
||||
selectedOrgKeys.value = [];
|
||||
projectSelectKeys.value = [];
|
||||
};
|
||||
//重置组织
|
||||
const resetOrg = () => {
|
||||
searchOrgName.value = { keyword: "" };
|
||||
};
|
||||
//重置受众
|
||||
const resetAudienceInfo = () => {
|
||||
audienceName.value.keyword = "";
|
||||
auditTableRef.value.reset({ keyword: "" });
|
||||
};
|
||||
|
||||
//确定添加授权
|
||||
const submitAuth = () => {
|
||||
if (props.type === 2) {
|
||||
stageVisible.value = true;
|
||||
} else {
|
||||
handleDialogOk();
|
||||
}
|
||||
};
|
||||
|
||||
function handleDialogOk() {
|
||||
if (auditSelectRowKeys.value.length || deptList.value.length) {
|
||||
dialog({ content: "您选择了组织或受众,此添加为异步添加,请稍后手动刷新学员!", ok: handleStageOk });
|
||||
return;
|
||||
}
|
||||
handleStageOk();
|
||||
}
|
||||
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
function handleStageOk() {
|
||||
if (props.type === 1 && props.groupId && (props.groupMemberCount < (props.groupMemberNumber * 1 + projectSelectRows.value.length + stuSelectRows.value.length))) {
|
||||
return message.warning("添加小组学员超过最大值");
|
||||
}
|
||||
stageVisible.value = false;
|
||||
visiable.value = false;
|
||||
emit("finash", false);
|
||||
nameSearch.value.keyword = "";
|
||||
addTutor({
|
||||
examineId:route.query.id.toString(),
|
||||
teacherIds: teaunm.value
|
||||
}).then(() => {
|
||||
deleteDepSelect();
|
||||
emit("finash", true);
|
||||
message.info('添加成功');
|
||||
|
||||
});
|
||||
// saveStu({
|
||||
// targetId: props.id,
|
||||
// type: props.type,
|
||||
// clear: props.clear,
|
||||
// deptIds: deptList.value?.map((e) => e.id),
|
||||
// stageId: stageId.value,
|
||||
// groupIds: auditSelectRows.value?.map((e) => e.id),
|
||||
// studentList: stuSelectRows.value,
|
||||
// projectList: projectSelectRows.value,
|
||||
// groupName: props.groupName,
|
||||
// groupId: props.groupId,
|
||||
// }).then(() => {
|
||||
// deleteDepSelect();
|
||||
// emit("finash", true);
|
||||
// });
|
||||
}
|
||||
// 搜索受众值发生变化
|
||||
function orgValue(value) {
|
||||
console.log("", value.target.value);
|
||||
searchOrgName.value.keyword = value.target.value;
|
||||
}
|
||||
|
||||
watch(visiable, () => {
|
||||
orgSelectKeys.value = [];
|
||||
deptList.value = [];
|
||||
audienceName.value.keyword = "";
|
||||
nameSearch.value.departId = '';
|
||||
stuTreeExpandedKeys.value = [];
|
||||
stuTreeSelectKeys.value = [];
|
||||
activeKey.value = props.isGroup ? 4 : 1;
|
||||
|
||||
projectParams.value.studentName = "";
|
||||
nameSearch.value.keyword = "";
|
||||
searchOrgName.value.keyword = "";
|
||||
audienceName.value.keyword = "";
|
||||
|
||||
if (!visiable.value) {
|
||||
auditTableRef.value && auditTableRef.value.clear();
|
||||
auditTableRef.value && auditTableRef.value.reset({ keyword: "" });
|
||||
stuTableRef.value && stuTableRef.value.clear();
|
||||
stuTableRef.value && stuTableRef.value.reset({ keyword: "", departId: '' });
|
||||
projectStuTableRef.value && projectStuTableRef.value.clear();
|
||||
projectStuTableRef.value && projectStuTableRef.value.reset({ pid: props.infoId, type: props.infoType, studentName: "" });
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.CommonStudent > .ant-drawer-content-wrapper {
|
||||
min-width: 1200px !important;
|
||||
width: 1200px !important;
|
||||
}
|
||||
|
||||
.CommonStudent {
|
||||
.ant-btn-primary {
|
||||
background-color: #4ea6ff !important;
|
||||
}
|
||||
|
||||
.cus-select {
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.tableBox .ant-table-row .ant-table-cell {
|
||||
height: 48px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #4f5156;
|
||||
line-height: 29px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.tableBox .ant-table-thead tr th {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ant-tabs-tabpane {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ant-tabs {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.right1 {
|
||||
border-left: 1px solid #f2f6fe;
|
||||
margin-left: 20px;
|
||||
|
||||
.onerow {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-right: 40px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
width: 100%;
|
||||
|
||||
.onleft {
|
||||
display: flex;
|
||||
text-align: center;
|
||||
|
||||
.already {
|
||||
color: rgba(51, 51, 51, 1);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
margin-left: 32px;
|
||||
white-space: nowrap;
|
||||
// margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.count {
|
||||
color: #4ea6ff;
|
||||
font-size: 16px;
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
.peo {
|
||||
color: rgba(51, 51, 51, 1);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.clbox {
|
||||
margin-right: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
width: 104px;
|
||||
height: 32px;
|
||||
border-radius: 4px;
|
||||
background: #4ea6ff;
|
||||
|
||||
.colose {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
// border-radius: 8px;
|
||||
// background: #ffffff;
|
||||
// position: relative;
|
||||
background-image: url(../../assets/images/basicinfo/ch.png);
|
||||
background-size: 100%;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.allclear {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.selecteds {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-left: 32px;
|
||||
|
||||
.person {
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
border-top: 1px solid #f2f6fe;
|
||||
}
|
||||
|
||||
.chose {
|
||||
width: 64px;
|
||||
height: 24px;
|
||||
margin-top: 25px;
|
||||
margin-right: 25px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 2px;
|
||||
border: 1px solid rgba(56, 139, 225, 1);
|
||||
color: rgba(56, 139, 225, 1);
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
|
||||
.ch {
|
||||
position: absolute;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-image: url(../../assets/images/basicinfo/ch.png);
|
||||
right: -8px;
|
||||
top: -8px;
|
||||
}
|
||||
}
|
||||
|
||||
.ifsw {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
justify-content: center;
|
||||
color: #4ea6ff;
|
||||
}
|
||||
|
||||
.sw {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: justify;
|
||||
color: #4ea6ff;
|
||||
margin-top: 23px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.dept {
|
||||
width: 100%;
|
||||
margin-top: 30px;
|
||||
border-top: 1px solid #f2f6fe;
|
||||
}
|
||||
|
||||
.chose1 {
|
||||
//width: 90px;
|
||||
height: 24px;
|
||||
margin-top: 25px;
|
||||
margin-right: 25px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 2px;
|
||||
border: 1px solid rgba(56, 139, 225, 1);
|
||||
color: rgba(56, 139, 225, 1);
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
|
||||
.span {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ch1 {
|
||||
position: absolute;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-image: url(../../assets/images/basicinfo/ch.png);
|
||||
right: -8px;
|
||||
top: -8px;
|
||||
}
|
||||
}
|
||||
|
||||
.group {
|
||||
width: 100%;
|
||||
margin-top: 30px;
|
||||
border-top: 1px solid #f2f6fe;
|
||||
}
|
||||
|
||||
.chose2 {
|
||||
//width: 120px;
|
||||
height: 24px;
|
||||
margin-top: 25px;
|
||||
margin-right: 25px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 2px;
|
||||
border: 1px solid rgba(56, 139, 225, 1);
|
||||
color: rgba(56, 139, 225, 1);
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
|
||||
.span {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ch2 {
|
||||
position: absolute;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-image: url(../../assets/images/basicinfo/ch.png);
|
||||
right: -8px;
|
||||
top: -8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||