--demand 面授课

This commit is contained in:
yuping
2023-03-17 03:08:28 +08:00
parent fa431338c8
commit e68aeb246b
20 changed files with 3670 additions and 3599 deletions

View File

@@ -1,10 +1,25 @@
export const STUDENT_LIST = '/admin/student/getStudent';
export const ONLINE_COURSE_PAGE = '/onlineClasses/queryOnlineList';
export const ASSESSMENT_PAGE = '/assessment/queryAssessmentDetailList post';
export const PROJECT_AUDIT_PAGE = '/admin/project/auditedlistV2 post';
export const ROUTER_DETAIL_MODIFY = '/admin/router/routerInfoTemp post';
export const PROJECT_DETAIL_MODIFY = '/admin/project/projectInfoTemp post';
export const PROJECT_TEMPLATE_DETAIL_MODIFY = '/admin/project/template/editStageAndTask post';
export const PROJECT_RELEASE = '/admin/project/realease';
export const ASYNC_STUDENT_STATUS = '/admin/cache/getStudentAsyncStatus';
export const ONLINE_COURSE_TEACHER = '/admin/offcourse/getTeacherNamesByCourseId';
export const STUDENT_LIST = "/admin/student/getStudent";
export const TASK_STUDENT_LIST = "/admin/student/getTaskStudent";
export const ONLINE_COURSE_PAGE = "/onlineClasses/queryOnlineList";
export const ASSESSMENT_PAGE = "/assessment/queryAssessmentDetailList post";
export const PROJECT_AUDIT_PAGE = "/admin/project/auditedlistV2 post";
export const ROUTER_DETAIL_MODIFY = "/admin/router/routerInfoTemp post";
export const PROJECT_DETAIL_MODIFY = "/admin/project/projectInfoTemp post";
export const PROJECT_TEMPLATE_DETAIL_MODIFY = "/admin/project/template/editStageAndTask post";
export const PROJECT_RELEASE = "/admin/project/realease";
export const ASYNC_STUDENT_STATUS = "/admin/cache/getStudentAsyncStatus";
export const ONLINE_COURSE_TEACHER = "/admin/offcourse/getTeacherNamesByCourseId";
//开课列表
export const COURSE_PLAN_PAGE = "/admin/offcourse/planList post";
//开课所有列表
export const COURSE_PLAN_LIST = "/admin/offcourse/allPlanList post";
//开课保存/编辑
export const COURSE_PLAN_EDIT = "/admin/offcourse/editPlan post";
//删除开课
export const DEL_PLAN = id => `/admin/offcourse/deletePlan?offcoursePlanId=${id} delete`;
//作业详情
export const WORK_DETAIL = "/work/queryWorkDetailById post";
//考试
export const EXAM_DETAIL = "/examination/queryExaminationDetailById post";
//评估
export const ASSESSMENT_DETAIL = "/assessment/queryAssessmentDetailById post";

View File

@@ -1,298 +1,350 @@
import {isRef, reactive, ref, toRefs, unref, watch, watchEffect} from "vue";
import {getCookieForName, throttle} from "@/api/method";
import JSONBigInt from 'json-bigint';
import JSONBigInt from "json-bigint";
const JSONBigIntStr = JSONBigInt({storeAsString: true});
const JSONBigIntStr = JSONBigInt({ storeAsString: true });
export function useBoeApiAuditPage(_url, params = {}) {
return useBoeApiPage(_url, params, {
init: true,
result: (res) => res.result.audienceList.map((e) => ({ ...e, id: e.id + "" })),
totalPage: (res) => res.result.totalPage,
total: (res) => res.result.totalElement,
});
}
export function useBoeApiUserInfoPage(_url, params = {}) {
return useBoeApiPage(_url, params, {
init: false,
result: (res) => res.result.userInfoList,
totalPage: (res) => res.result.totalPage,
total: (res) => res.result.totalElement,
});
}
export function useBoeApiPage(_url, params = {}, config = {
init: true,
result: res => res.result,
totalPage: res => res.result.totalPage,
total: res => res.result.totalElement
init: true,
result: res => res.result,
totalPage: res => res.result.totalPage,
total: res => res.result.totalElement
}) {
const state = reactive({
data: [],
loading: false,
page: 1,
pageSize: 10,
totalPage: 0,
total: 0
})
const state = reactive({
data: [],
loading: false,
page: 1,
pageSize: 10,
totalPage: 0,
total: 0
});
if (isRef(params)) {
watch(params.value, () => {
fetch()
})
}
if (isRef(params)) {
watch(params.value, () => {
fetch();
});
}
if (isRef(_url)) {
watchEffect(fetch)
} else {
fetch()
}
if (isRef(_url)) {
watchEffect(fetch);
} else {
fetch();
}
function fetch() {
state.loading = true
return boeRequest(unref(_url), unref(params)).then(r => {
state.data = config.result(r)
state.totalPage = config.totalPage(r)
state.total = config.total(r)
state.loading = false
state.page = params.page
})
}
function fetch() {
state.loading = true;
return boeRequest(unref(_url), unref(params)).then(r => {
state.data = config.result(r);
state.totalPage = config.totalPage(r);
state.total = config.total(r);
state.loading = false;
state.page = params.page;
});
}
function reset() {
state.data = []
state.loading = false
state.page = 1
state.totalPage = 0
state.total = 0
}
function reset() {
state.data = [];
state.loading = false;
state.page = 1;
state.totalPage = 0;
state.total = 0;
}
config.init && fetch()
return {
...toRefs(state),
fetch,
reset
};
config.init && fetch();
return {
...toRefs(state),
fetch,
reset
};
}
export function useBoeApi(_url, params = {}, config = {
init: true,
result: res => res.result,
init: true,
result: res => res.result,
}) {
const state = reactive({
data: [],
loading: false,
})
watch(() => params, () => {
fetch()
})
const state = reactive({
data: [],
loading: false,
});
watch(() => params, () => {
fetch();
});
function fetch() {
state.loading = true
return boeRequest(_url, params).then(r => {
state.data = config.result(r)
state.loading = false
})
}
function fetch() {
state.loading = true;
return boeRequest(_url, params).then(r => {
state.data = config.result(r);
state.loading = false;
});
}
config.init && fetch()
return {
...toRefs(state),
fetch,
};
config.init && fetch();
return {
...toRefs(state),
fetch,
};
}
export function useBoeUserListPage(_url, params = {}, init = true) {
const state = reactive({
data: [],
loading: false,
total: 0,
totalPage: 0,
page: 1,
...params
})
const state = reactive({
data: [],
loading: false,
total: 0,
totalPage: 0,
page: 1,
...params
});
watch(() => params.keyword, throttle(fetch, 600))
watch(() => params.page, fetch)
watch(() => params.keyword, throttle(fetch, 600));
watch(() => params.page, fetch);
function fetch() {
state.loading = true
if (!params.keyword) {
state.loading = false
return
}
return boeRequest(_url, params).then(r => {
state.data = params.page === 1 ? r.result.userInfoList : [...state.data, ...r.result.userInfoList]
state.totalPage = r.result.totalPage
state.total = r.result.totalElement
state.loading = false
})
function fetch() {
state.loading = true;
if (!params.keyword) {
state.loading = false;
return;
}
return boeRequest(_url, params).then(r => {
state.data = params.page === 1 ? r.result.userInfoList : [...state.data, ...r.result.userInfoList];
state.totalPage = r.result.totalPage;
state.total = r.result.totalElement;
state.loading = false;
});
}
init && fetch()
return {
...toRefs(state),
fetch,
};
init && fetch();
return {
...toRefs(state),
fetch,
};
}
export function useRowsPageNoInit(_url, params) {
const state = reactive({
data: [],
total: 1,
current: 1,
pages: 1,
loading: false
});
function reset() {
state.data = [];
state.loading = false;
}
function fetch() {
state.loading = true;
return request(unref(_url), unref(params)).then(r => {
state.data = r.data.rows || r.data.records;
state.current = r.data.current || r.data.current;
state.pages = r.data.pages;
state.total = r.data.total;
state.loading = false;
});
}
return {
...toRefs(state),
fetch,
reset,
};
}
export function useRowsPage(_url, params, init = true) {
const state = reactive({
data: [],
total: 1,
current: 1,
pages: 1,
loading: false
})
const state = reactive({
data: [],
total: 1,
current: 1,
pages: 1,
loading: false
});
if (isRef(params)) {
watch(params.value, () => {
fetch()
})
}
if (isRef(params)) {
watch(params.value, () => {
fetch();
});
}
if (isRef(_url)) {
watchEffect(fetch)
} else {
init && fetch()
}
if (isRef(_url)) {
watchEffect(fetch);
} else {
init && fetch();
}
function reset() {
state.data = []
state.loading = false
}
function reset() {
state.data = [];
state.loading = false;
}
function fetch() {
state.loading = true
return request(unref(_url), unref(params)).then(r => {
state.data = r.data.rows
state.current = r.data.current
state.pages = r.data.pages
state.total = r.data.total
state.loading = false
})
}
function fetch() {
state.loading = true;
return request(unref(_url), unref(params)).then(r => {
state.data = r.data.rows;
state.current = r.data.current;
state.pages = r.data.pages;
state.total = r.data.total;
state.loading = false;
});
}
return {
...toRefs(state),
fetch,
reset,
};
return {
...toRefs(state),
fetch,
reset,
};
}
export function usePage(_url, params, init = true) {
const state = reactive({
data: [],
total: 1,
current: 1,
pages: 1,
loading: false
})
const state = reactive({
data: [],
total: 1,
current: 1,
pages: 1,
loading: false
});
if (isRef(params)) {
watch(params.value, () => {
fetch()
})
}
if (isRef(params)) {
watch(params.value, () => {
fetch();
});
}
if (isRef(_url)) {
watchEffect(fetch)
} else {
init && fetch()
}
if (isRef(_url)) {
watchEffect(fetch);
} else {
init && fetch();
}
function reset() {
state.data = []
state.loading = false
}
function reset() {
state.data = [];
state.loading = false;
}
function fetch() {
state.loading = true
return request(unref(_url), unref(params)).then(r => {
state.data = r.data.records
state.current = r.data.current
state.pages = r.data.pages
state.total = r.data.total
state.loading = false
})
}
function fetch() {
state.loading = true;
return request(unref(_url), unref(params)).then(r => {
state.data = r.data.records;
state.current = r.data.current;
state.pages = r.data.pages;
state.total = r.data.total;
state.loading = false;
});
}
return {
...toRefs(state),
fetch,
reset,
};
return {
...toRefs(state),
fetch,
reset,
};
}
export function useRequest(_url, params = {}, init = true) {
export function useRequest(_url, params, init = true) {
const data = ref({})
const loading = ref(false)
const data = ref({});
const loading = ref(false);
watch(params, () => {
fetchData()
})
if (isRef(params)) {
watch(params.value, () => {
fetchData();
});
}
function fetchData() {
loading.value = true
request(_url, params).then(r => {
data.value = r
loading.value = false
})
}
function fetchData() {
loading.value = true;
request(_url, unref(params)).then(r => {
data.value = r.data;
loading.value = false;
});
}
init && fetchData()
return {
data,
loading,
fetchData,
};
init && fetchData();
return {
data,
loading,
fetchData,
};
}
export async function boeRequest(_url, params = {}) {
const s = _url.split(' ')
let url = s[0]
const method = s[1]?.toLowerCase() || 'get'
if (method === 'get') {
url.includes('?') ? (url.endsWith('&') || (url += '&')) : (url += '?')
url += Object.keys(params).map(key => key + '=' + params[key]).join('&')
}
const body = method !== 'get' ? s[2] === 'formData' ? formatFormData(params) : params : {}
url = process.env.NODE_ENV === 'development' ? url : window.location.protocol + process.env.VUE_APP_BOE_API_URL + url
return fetch(url, {
method,
headers: {
token: getCookieForName('token'),
...method !== 'get' && s[2] !== 'formData' ? {'Content-Type': 'application/json'} : {}
},
...method !== 'get' ? {body: s[2] === 'formData' ? body : JSON.stringify(body)} : {}
}).then(res => {
return res.text()
}).then(res => {
return JSONBigIntStr.parse(res)
})
const s = _url.split(" ");
let url = s[0];
const method = s[1]?.toLowerCase() || "get";
if (method === "get") {
url.includes("?") ? (url.endsWith("&") || (url += "&")) : (url += "?");
url += Object.keys(params).map(key => key + "=" + params[key]).join("&");
}
const body = method !== "get" ? s[2] === "formData" ? formatFormData(params) : params : {};
url = process.env.NODE_ENV === "development" ? url : window.location.protocol + process.env.VUE_APP_BOE_API_URL + url;
return fetch(url, {
method,
headers: {
token: getCookieForName("token"),
...method !== "get" && s[2] !== "formData" ? { "Content-Type": "application/json" } : {}
},
...method !== "get" ? { body: s[2] === "formData" ? body : JSON.stringify(body) } : {}
}).then(res => {
return res.text();
}).then(res => {
return JSONBigIntStr.parse(res);
});
}
function formatFormData(data) {
const formData = new FormData();
Object.keys(data).forEach(k => formData.append(k, data[k]))
return formData
const formData = new FormData();
Object.keys(data).forEach(k => formData.append(k, data[k]));
return formData;
}
export async function request(_url, params) {
const s = _url.split(' ')
let url = s[0]
const method = s[1]?.toLowerCase() || 'get'
if (method === 'get') {
let paramsArray = [];
if (params) {
Object.keys(params).forEach(key => paramsArray.push(key + '=' + params[key]))
if (url.search(/\?/) === -1) {
url += '?' + paramsArray.join('&')
} else {
url += '&' + paramsArray.join('&')
}
}
const s = _url.split(" ");
let url = s[0];
const method = s[1]?.toLowerCase() || "get";
if (method === "get") {
let paramsArray = [];
if (params) {
Object.keys(params).forEach(key => paramsArray.push(key + "=" + params[key]));
if (url.search(/\?/) === -1) {
url += "?" + paramsArray.join("&");
} else {
url += "&" + paramsArray.join("&");
}
}
const body = method !== 'get' ? params || {} : {}
return fetch(process.env.VUE_APP_BASE_API + url, {
method,
headers: {
token: getCookieForName('token'),
...method !== 'get' ? {'Content-Type': 'application/json'} : {}
},
...method !== 'get' ? {body: JSON.stringify(body)} : {}
}).then(res => {
return res.text()
}).then(res => {
return JSONBigIntStr.parse(res)
})
}
const body = method !== "get" ? params || {} : {};
return fetch(process.env.VUE_APP_BASE_API + url, {
method,
headers: {
token: getCookieForName("token"),
...method !== "get" ? { "Content-Type": "application/json" } : {}
},
...method !== "get" ? { body: JSON.stringify(body) } : {}
}).then(res => {
return res.text();
}).then(res => {
return JSONBigIntStr.parse(res);
});
}

View File

@@ -0,0 +1,134 @@
<template>
<a-table
:customRow="customRow"
class="ant-table-striped"
:row-class-name="(_, index) => (index % 2 === 1 ? 'table-striped' : null)"
row-key="id"
:columns="columns"
:data-source="data"
:loading="loading"
:pagination="pagination"
:row-selection="rowSelection"
/>
</template>
<script setup>
import {defineProps, defineExpose, ref, computed, onMounted, defineEmits} from "vue";
import {useRowsPageNoInit} from "@/api/request";
const props = defineProps({
type: {
type: String,
default: ""
},
columns: {
type: Array,
default: () => []
},
url: {
type: String,
default: ""
},
params: {
type: Object,
default: () => ({})
},
init: {
type: Boolean,
default: true
},
request: {
type: Function,
default: useRowsPageNoInit
}
});
const emit = defineEmits(["update:params", "update:selectedRowKeys", "update:selectedRows"]);
const rowSelectKeys = ref([]);
const selectsData = ref([]);
const params = ref({ pageNo: 1, pageSize: 10 });
const postParam = computed(() => ({ ...params.value, ...props.params }));
const { data, loading, total, fetch } = props.request(props.url, postParam);
const rowSelection = computed(() => (props.type ? {
type: props.type,
columnWidth: 20,
selectedRowKeys: rowSelectKeys.value,
onChange: onSelectChange,
preserveSelectedRowKeys: true,
} : null));
const customRow = (record) => ({
onClick: () => {
if (props.type === "checkbox") {
if (rowSelectKeys.value.some(t => t === record.id)) {
rowSelectKeys.value = rowSelectKeys.value.filter(t => t !== record.id);
selectsData.value = selectsData.value.filter(t => t.id !== record.id);
} else {
rowSelectKeys.value.push(record.id);
selectsData.value.push(record);
}
} else {
rowSelectKeys.value = [record.id];
selectsData.value = [record];
}
emit("update:selectedRowKeys", [...rowSelectKeys.value]);
emit("update:selectedRows", [...selectsData.value]);
}
});
function onSelectChange(e, l) {
rowSelectKeys.value = e;
selectsData.value = l;
emit("update:selectedRowKeys", e);
emit("update:selectedRows", l);
}
const pagination = computed(() => ({
total: total.value,
showSizeChanger: false,
current: params.value.pageNo,
pageSize: params.value.pageSize,
onChange: changePagination,
}));
const changePagination = (e) => {
params.value.pageNo = e;
fetch();
};
onMounted(() => props.init && fetch());
function reset(v = {}) {
params.value = { pageNo: 1, pageSize: 10, ...v };
emit("update:params", { ...v });
fetch();
}
function resetSelected() {
rowSelectKeys.value = [];
selectsData.value = [];
emit("update:selectedRowKeys", []);
emit("update:selectedRows", []);
}
function clear() {
rowSelectKeys.value = [];
selectsData.value = [];
params.value = { pageNo: 1, pageSize: 10 };
emit("update:params", {});
emit("update:selectedRowKeys", []);
emit("update:selectedRows", []);
}
function toLoading() {
loading.value = true;
}
function remove(i) {
rowSelectKeys.value.splice(i, 1);
selectsData.value.splice(i, 1);
emit("update:selectedRowKeys", rowSelectKeys.value);
emit("update:selectedRows", selectsData.value);
}
defineExpose({ fetch, reset, resetSelected, clear, toLoading, remove });
</script>

View File

@@ -0,0 +1,24 @@
<template>
<a-checkbox @change="change">
<slot></slot>
</a-checkbox>
</template>
<script setup>
import {defineEmits, defineProps} from "vue";
const props = defineProps({
checkValue: {
type: Boolean,
default: true
},
unCheckValue: {
type: Boolean,
default: false
},
});
const emit = defineEmits(['update:modelValue']);
function change({ target: { checked } }) {
emit("update:modelValue", checked ? props.checkValue : props.unCheckValue);
}
</script>

View File

@@ -0,0 +1,489 @@
<template>
<div @click="openDrawer">
<slot></slot>
</div>
<a-drawer
:visible="visible"
class="drawerStyle impotergroupleader"
placement="right"
width="800px"
>
<div class="drawerMain">
<div class="header">
<div class="headerTitle">{{ title }}</div>
<img
style="width: 29px; height: 29px; cursor: pointer"
src="../../assets/images/basicinfo/close.png"
@click="closeDrawer"
/>
</div>
<div class="main">
<div class="minatitl" v-if="templateUrl">
<div class="up1">请下载</div>
<a class="up2" :href="templateUrl" 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
:data="data"
:multiple="true"
:name="name"
:accept="accept"
:action="uploadUrl"
@change="handleChange"
v-model:file-list="fileList"
>
<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>
<template #itemRender="{ file }">
<div class="loadstate">
<div class="loadborder">
<div class="content">
<div class="img"></div>
<div class="timebox">
<div class="timetop">
<div class="tit">{{ file.name }}</div>
<div class="stateloading">{{
{
done: "上传成功",
uploading: "正在上传",
error: "上传失败",
removed: "正在上传",
}[file.status]
}}
</div>
</div>
<a-progress :percent="file.percent"/>
</div>
<div class="curloading">
<div style="color: #387df7; margin-left: 20px; cursor: pointer"
v-if="file.uploadState?.status === 'FAILED'"
@click="downloadErrorData(file.uploadState?.url)">下载失败数据
</div>
</div>
</div>
<a-spin :spinning="true" v-if="file.uploadState?.status === 'START'"/>
<div :class="file.uploadState?.status === 'SUCCESS'?'succebox':'defeatbox'"
v-if="file.uploadState?.status === 'FAILED'">
<img style="width: 14px; height: 14px; margin-left: 16px"
:src="file.uploadState?.status === 'SUCCESS' ? success:err"/>
<div class="tacl">
{{ file.uploadState?.successNum || 0 }}条数据导入成功{{
file.uploadState?.failedNum || 0
}}条数据导入失败
</div>
</div>
</div>
</div>
</template>
</a-upload-dragger>
</div>
</div>
</div>
</div>
<div class="btnn">
<button class="btn2" @click="closeDrawer">取消</button>
<button class="btn2" @click="closeDrawer">确定</button>
</div>
</div>
</a-drawer>
</template>
<script setup>
import {defineEmits, defineProps, ref} from "vue";
import {getImportStatus} from "@/api/index1";
import {useTimeout} from "@/utils/useCommon";
import err from "@/assets/images/err.png";
import success from "@/assets/images/success.png";
const props = defineProps({
url: String,
name: {
type: String,
defalut: "file"
},
title: String,
accept: String,
fileType: Object,
data: Object,
templateUrl: String,
});
const emit = defineEmits({});
const visible = ref(false);
const fileList = ref([]);
const uploadUrl = ref(process.env.VUE_APP_BASE_API + props.url);
const { start } = useTimeout(async ({ uuid, file }) => {
const { data: { data: upData } } = await getImportStatus(uuid);
file.uploadState = upData;
fileList.value = [...fileList.value];
if (upData && upData.status !== "START" && upData.status !== "NULL") {
emit("change", "end");
throw Error("查询任务结束");
}
}, 1000);
const closeDrawer = () => {
visible.value = false;
fileList.value = [];
};
function openDrawer() {
visible.value = true;
}
function downloadErrorData(url) {
window.open(process.env.VUE_APP_FILE_PATH + url);
}
function handleChange({ file }) {
emit("change", "start");
file && file.response && start({ uuid: file.response.data, file });
}
</script>
<style scoped lang="scss">
.impotergroupleader {
.drawerMain {
min-width: 600px;
margin: 0px 32px 0px 32px;
overflow-x: auto;
display: flex;
flex-direction: column;
.header {
height: 73px;
border-bottom: 1px solid #e8e8e8;
display: flex;
justify-content: space-between;
align-items: center;
// background-color: red;
margin-bottom: 20px;
flex-shrink: 0;
.headerTitle {
font-size: 18px;
font-weight: 600;
color: #333333;
line-height: 25px;
// margin-left: 24px;
}
}
.main {
.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;
}
.right {
margin-left: 6px;
width: 500px;
.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: 50px;
.loadborder {
width: 500px;
height: 173px;
border-radius: 4px;
border: 1px dashed #eaeaea;
margin-bottom: 30px;
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
.content {
display: flex;
margin-left: 20px;
position: relative;
.defeat {
width: 262px;
padding: 10px 20px;
position: absolute;
left: 46px;
top: 42px;
font-size: 14px;
font-weight: 500;
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;
}
.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;
}
}
}
.downloadErr {
width: 120px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 2px;
border: 1px solid #387df7;
font-size: 14px;
font-weight: 400;
color: #387df7;
line-height: 20px;
cursor: pointer;
margin-left: 66px;
margin-top: 16px;
position: absolute;
bottom: 28px;
}
}
.defeatbox {
width: 500px;
height: 40px;
margin-top: 20px;
background: rgba(255, 116, 116, 0.1);
border: 1px solid #ff7474;
display: flex;
align-items: center;
.lefimg {
width: 14px;
height: 14px;
margin-right: 8px;
background-size: 100%;
}
.tacl {
font-size: 14px;
font-weight: 400;
margin-left: 17px;
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-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>

View File

@@ -0,0 +1,266 @@
<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="codename">{{ name }}</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,
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 }
).then((canvas) => {
let filename = `${new Date().getTime()}.png`;
let imageUrl = canvas.toDataURL("image/png");
let a = document.createElement("a");
a.style.display = "none";
a.download = filename;
a.href = imageUrl;
document.body.appendChild(a);
a.click();
});
}
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;
.codename {
font-size: 18px;
font-weight: 400;
color: #333333;
line-height: 25px;
margin-bottom: 20px;
margin-left: 20px;
margin-right: 20px;
}
}
.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>

View File

@@ -0,0 +1,47 @@
<template>
<div class="select">
<div class="select addTimeBox">
<div class="addTime">创建时间</div>
<a-range-picker
style="width: 420px"
format="YYYY-MM-DD"
valueFormat="YYYY-MM-DD"
separator="至"
:placeholder="[' 开始时间', ' 结束时间']"
@change="change"
/>
</div>
</div>
</template>
<script setup>
import {defineEmits} from "vue";
const emit = defineEmits(["update:beginTime", "update:endTime"]);
function change(e) {
emit("update:beginTime", e[0]);
emit("update:endTime", e[1]);
}
</script>
<style lang="scss">
.addTimeBox {
position: relative;
display: flex;
align-items: center;
.addTime {
position: absolute;
z-index: 10;
margin-left: 10px;
color: rgba(0, 0, 0, 0.4);
}
.ant-picker {
padding-left: 85px;
}
.ant-picker-range .ant-picker-active-bar {
margin-left: 85px;
}
}
</style>

View File

@@ -1,278 +1,271 @@
<template>
<div @click="openDrawer">
<slot></slot>
</div>
<a-drawer :visible="visible" class="drawerStyle addinvistDrawer" width="70%" title="添加面授" placement="right">
<div class="drawerMain">
<div class="header">
<div v-if="taskIndex>=0" class="headerTitle">编辑面授</div>
<div v-else class="headerTitle">添加面授</div>
<img style="width: 29px; height: 29px; cursor: pointer" src="../../assets/images/basicinfo/close.png"
@click="closeDrawer"/>
</div>
<div class="contentMain">
<div class="main">
<div class="main_left">
<FaceClassAll v-model:id="formData.courseId" v-model:name="formData.courseName"/>
</div>
<div @click="openDrawer">
<slot></slot>
</div>
<a-drawer :visible="visible" class="drawerStyle addinvistDrawer" width="70%" title="添加面授" placement="right">
<div class="drawerMain">
<div class="header">
<div v-if="taskIndex>=0" class="headerTitle">编辑面授</div>
<div v-else class="headerTitle">添加面授</div>
<img style="width: 29px; height: 29px; cursor: pointer" src="../../assets/images/basicinfo/close.png"
@click="closeDrawer"/>
</div>
<div class="contentMain">
<div class="main">
<div class="main_left">
<FaceClassAll v-model:id="formData.courseId" v-model:name="formData.courseName"/>
</div>
</div>
<div class="main_btns">
<button class="btn2" @click="closeDrawer">取消</button>
<button class="btn2" @click="confirm">确定</button>
</div>
</div>
</a-drawer>
</template>
<script setup>
import {defineEmits, defineProps, ref} from "vue";
import {Form, message} from "ant-design-vue";
import FaceClassAll from "@/components/drawers/FeaceClassAll.vue";
const props = defineProps({
type: Number,
taskList: []
})
const visible = ref(false)
const formData = ref({
courseId: '',
courseName: '',
})
const emit = defineEmits({})
const taskIndex = ref(-1);
const rulesRef = ref({
courseId: [
{
required: true,
message: '请选择课程',
},
],
courseName: [
{
required: true,
message: '请选择课程',
},
],
<div class="main_btns">
<button class="btn2" @click="closeDrawer">取消</button>
<button class="btn2" @click="confirm">确定</button>
</div>
</div>
</a-drawer>
</template>
<script setup>
import {defineEmits, defineProps, ref} from "vue";
import {Form, message} from "ant-design-vue";
import FaceClassAll from "@/components/drawers/FeaceClassAll.vue";
const props = defineProps({
type: Number,
taskList: []
});
const visible = ref(false);
const formData = ref({
courseId: "",
courseName: "",
});
const emit = defineEmits({});
const taskIndex = ref(-1);
const rulesRef = ref({
courseId: [
{
required: true,
message: "请选择课程",
},
],
courseName: [
{
required: true,
message: "请选择课程",
},
],
});
const { resetFields, validate } = Form.useForm(formData, rulesRef);
const closeDrawer = () => {
visible.value = false;
taskIndex.value = -1;
resetFields();
};
async function confirm() {
await validate().catch(({ errorFields }) => {
message.warning(errorFields[0].errors.join());
throw Error("数据校验不通过");
});
const {resetFields, validate} = Form.useForm(formData, rulesRef);
const closeDrawer = () => {
visible.value = false
taskIndex.value = -1
resetFields()
};
async function confirm() {
await validate().catch(({errorFields}) => {
message.warning(errorFields[0].errors.join());
throw Error("数据校验不通过")
if (taskIndex.value === -1) {
const list = props.taskList;
list.push({
name: formData.value.courseName,
type: props.type,
courseId: formData.value.courseId,
info: { ...formData.value }
});
if (taskIndex.value === -1) {
const list = props.taskList
list.push({
name: formData.value.courseName,
type: props.type,
courseId: formData.value.courseId,
info: {...formData.value}
})
console.log('新建',{
name: formData.value.courseName,
type: props.type,
courseId: formData.value.courseId,
info: {...formData.value}
})
} else {
const data = props.taskList[taskIndex.value]
data.name = formData.value.courseName
data.courseId = formData.value.courseId
data.info = {...formData.value}
}
emit('update:taskList', [...props.taskList])
closeDrawer()
} else {
const data = props.taskList[taskIndex.value];
data.name = formData.value.courseName;
data.courseId = formData.value.courseId;
data.info = { ...formData.value };
}
function openDrawer(i, row) {
console.log(row)
row && (formData.value = {courseId: row.info?row.info.courseId:row.id, courseName: row.info?row.info.courseName:row.name});
(i >= 0) && (taskIndex.value = i);
visible.value = true
console.log('11111',formData.value)
}
defineExpose({openDrawer})
</script>
<style lang="scss">
.ant-table-striped :deep(.table-striped) td {
background-color: #fafafa !important;
}
.addinvistDrawer {
.drawerMain {
.header {
height: 73px;
border-bottom: 1px solid #e8e8e8;
display: flex;
justify-content: space-between;
align-items: center;
.headerTitle {
font-size: 18px;
font-weight: 600;
color: #333333;
line-height: 25px;
margin-left: 24px;
}
emit("update:taskList", [...props.taskList]);
closeDrawer();
}
function openDrawer(i, row) {
row && (formData.value = {
courseId: row.courseId,
courseName: row.name
});
(i >= 0) && (taskIndex.value = i);
visible.value = true;
}
defineExpose({ openDrawer });
</script>
<style lang="scss">
.ant-table-striped :deep(.table-striped) td {
background-color: #fafafa !important;
}
.addinvistDrawer {
.drawerMain {
.header {
height: 73px;
border-bottom: 1px solid #e8e8e8;
display: flex;
justify-content: space-between;
align-items: center;
.headerTitle {
font-size: 18px;
font-weight: 600;
color: #333333;
line-height: 25px;
margin-left: 24px;
}
.contentMain {
.main {
width: 100%;
.main_left {
padding-right: 30px;
margin-top: 32px;
.main_item {
}
.contentMain {
.main {
width: 100%;
.main_left {
padding-right: 30px;
margin-top: 32px;
.main_item {
display: flex;
align-items: center;
.fi_input {
margin-right: 20px;
}
.btns {
padding: 0 26px 0 26px;
height: 38px;
background: #4ea6ff;
border-radius: 8px;
display: flex;
align-items: center;
.fi_input {
margin-right: 20px;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.search {
width: 15px;
height: 17px;
background-image: url("../../assets/images/courseManage/search0.png");
background-size: 100% 100%;
}
.btns {
margin-right: 20px;
padding: 0px 26px 0px 26px;
height: 38px;
background: #4ea6ff;
border-radius: 8px;
//border: 1px solid rgba(64, 158, 255, 1);
display: flex;
align-items: center;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.search {
width: 15px;
height: 17px;
background-image: url("../../assets/images/courseManage/search0.png");
background-size: 100% 100%;
}
.btnText {
font-size: 14px;
font-weight: 400;
color: #ffffff;
line-height: 36px;
margin-left: 5px;
}
}
.btnsn {
padding: 0px 26px 0px 26px;
height: 38px;
background: #ffffff;
border-radius: 8px;
border: 1px solid rgba(64, 158, 255, 1);
display: flex;
align-items: center;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.search {
width: 16px;
height: 18px;
background-image: url("../../assets/images/courseManage/reset1.png");
background-size: 100% 100%;
}
.btnText {
font-size: 14px;
font-weight: 400;
color: #4ea6ff;
line-height: 36px;
margin-left: 5px;
}
.btnText {
font-size: 14px;
font-weight: 400;
color: #ffffff;
line-height: 36px;
margin-left: 5px;
}
}
.main_notice {
.btnsn {
padding: 0 26px 0 26px;
height: 38px;
background: #ffffff;
border-radius: 8px;
border: 1px solid rgba(64, 158, 255, 1);
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 3px;
height: 40px;
background-color: #e9f6fe;
.mntc_left {
display: flex;
align-items: center;
.title {
color: rgba(0, 0, 0, 0.65);
margin-right: 17px;
}
.data {
color: #4ea6ff;
}
.notice_icon {
width: 14px;
height: 14px;
margin-right: 9px;
margin-left: 9px;
background-image: url(@/assets/images/coursewareManage/gan.png);
background-size: 100% 100%;
}
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.search {
width: 16px;
height: 18px;
background-image: url("../../assets/images/courseManage/reset1.png");
background-size: 100% 100%;
}
.mntc_right {
cursor: pointer;
.btnText {
font-size: 14px;
font-weight: 400;
color: #4ea6ff;
line-height: 36px;
margin-left: 5px;
}
}
}
.main_notice {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 3px;
height: 40px;
background-color: #e9f6fe;
.mntc_left {
display: flex;
align-items: center;
.title {
color: rgba(0, 0, 0, 0.65);
margin-right: 17px;
}
.data {
color: #4ea6ff;
}
.notice_icon {
width: 14px;
height: 14px;
margin-right: 9px;
margin-left: 9px;
background-image: url(@/assets/images/coursewareManage/gan.png);
background-size: 100% 100%;
}
}
.mntc_right {
cursor: pointer;
}
}
}
}
.main_btns {
height: 72px;
width: 100%;
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;
}
}
.main_btns {
height: 72px;
width: 100%;
bottom: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 1px 35px 0 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>
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -50,6 +50,8 @@
<CommonStudent
v-if="checkPer(permissions,createId)"
:type="1"
:info-type="1"
:info-id="projectId"
title="添加组员"
@finash="submitCall"
:isGroup="true"

View File

@@ -36,7 +36,6 @@
:action="uploadUrl"
@change="handleChange"
v-model:file-list="fileList"
:before-upload="beforeUpload"
>
<p class="ant-upload-drag-icon">
<inbox-outlined></inbox-outlined>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -14,26 +14,27 @@
<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="isGroup" :key="4" tab="项目内学员">
<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="proStudentName" style="width: 260px; height: 40px; border-radius: 8px"
<a-input v-model:value="projectParams.studentName"
style="width: 260px; height: 40px; border-radius: 8px"
placeholder="请输入姓名"/>
<a-button type="primary" @click="getStu" style="margin-left: 20px; border-radius: 4px">
<a-button type="primary" @click="getProjectStu" style="margin-left: 20px; border-radius: 4px">
<template #icon>
<SearchOutlined/>
</template>
搜索
</a-button>
<a-button @click="getStu" style="margin-left: 20px; border-radius: 4px">重置
<a-button @click="resetProjectStu" style="margin-left: 20px; border-radius: 4px">重置
</a-button>
</a-form-item>
</div>
<div class="tableBox tabb">
<a-table style="border: 1px solid #f2f6fe; width: 800px" row-key="id" :columns="stuColumns"
:data-source="projectList" :loading="projectListTotal" :pagination="projectPagination"
:row-selection="projectRowSelection"/>
<BaseTable ref="projectStuTableRef" :columns="projectStuColumns" :url="STUDENT_LIST"
:params="projectParams" v-model:selectedRows="projectSelectRows"
type="checkbox"></BaseTable>
</div>
</div>
</a-tab-pane>
@@ -42,7 +43,7 @@
<div class="tab1">
<a-form-item label="姓名">
<a-input v-model:value="nameSearch.keyword" style="width: 270px; height: 40px; border-radius: 8px"
placeholder="请输入姓名" @change="peopleName"/>
placeholder="请输入姓名"/>
<a-button type="primary" @click="onSearchStu" style="margin-left: 20px; border-radius: 4px">
<template #icon>
<SearchOutlined/>
@@ -74,8 +75,9 @@
margin: 0px 4px 120px 10px;
border: 1px solid #f0f0f0;
">
<a-table :columns="stuColumns" :data-source="stuData" :pagination="stuPagination"
:loading="stuLoading" row-key="id" :row-selection="stuRowSelection"/>
<BaseTable ref="stuTableRef" :columns="stuColumns" :url="USER_LIST_PAGE"
:request="useBoeApiUserInfoPage" :params="nameSearch"
v-model:selectedRows="stuSelectRows" type="checkbox"></BaseTable>
</div>
</div>
</div>
@@ -123,14 +125,16 @@
</template>
搜索
</a-button>
<a-button type="primary" @click="resetAudienceInfo" style="margin-left: 20px; border-radius: 4px">重置
<a-button type="primary" @click="resetAudienceInfo" style="margin-left: 20px; border-radius: 4px">
重置
</a-button>
</a-form-item>
</div>
<div class="tableBox tabb">
<a-table style="border: 1px solid #f2f6fe; width: 800px" row-key="id" :columns="audiColums"
:data-source="audiData" :loading="audiLoading" :pagination="auditPagination"
:row-selection="auditRowSelection"/>
<BaseTable ref="auditTableRef" :columns="audiColums" :url="AUDIENCE_LIST"
:request="useBoeApiAuditPage" :params="audienceName"
v-model:selectedRows="auditSelectRows" v-model:selectedRowKeys="auditSelectRowKeys"
type="checkbox"></BaseTable>
</div>
</div>
</a-tab-pane>
@@ -143,59 +147,59 @@
</div>
</div>
<div :style="{ 'max-height': screenHeight - 235 + 'px' }" style="overflow-y: auto">
<div class="selecteds" v-if="isGroup">
<div class="selecteds" v-if="infoType">
<div class="person">项目内学员</div>
<div v-for="(item, i) in selectsData.projectMemberList" :key="i">
<div v-for="(item, i) in projectSelectRows" :key="i">
<div v-if="i < 11">
<div class="chose">
{{ item.realName }}
<div class="ch" @click="memberDel(i)"></div>
{{ item.studentName }}
<div class="ch" @click="auditTableRef.remove(i)"></div>
</div>
</div>
<div v-else>
<div v-if="person">
<div class="chose">
{{ item.realName }}
<div class="ch" @click="memberDel(i)"></div>
{{ item.studentName }}
<div class="ch" @click="auditTableRef.remove(i)"></div>
</div>
</div>
</div>
</div>
<div v-if="!member && selectsData.projectMemberList?.length > 10" class="ifsw">
<div v-if="!member && projectSelectRows?.length > 10" class="ifsw">
<div @click="member = !member" class="“sw”">查看更多></div>
</div>
<div v-if="member && selectsData.projectMemberList?.length > 10" class="ifsw">
<div v-if="member && projectSelectRows?.length > 10" class="ifsw">
<div @click="member = !member" class="sw">收起&lt;</div>
</div>
</div>
<div class="selecteds">
<div class="person">快速选人</div>
<div v-for="(item, i) in selectsData.studentList" :key="i">
<div v-for="(item, i) in stuSelectRows" :key="i">
<div v-if="i < 11">
<div class="chose">
{{ item.realName }}
<div class="ch" @click="stuDel(i)"></div>
<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="stuDel(i)"></div>
<div class="ch" @click="stuTableRef.remove(i)"></div>
</div>
</div>
</div>
</div>
<div v-if="!person && selectsData.studentList.length > 10" class="ifsw">
<div v-if="!person && stuSelectRows.length > 10" class="ifsw">
<div @click="person = !person" class="“sw”">查看更多></div>
</div>
<div v-if="person && selectsData.studentList.length > 10" class="ifsw">
<div v-if="person && stuSelectRows.length > 10" class="ifsw">
<div @click="person = !person" class="sw">收起&lt;</div>
</div>
</div>
<div v-if="!selectStu" class="selecteds">
<div class="dept">添加组织</div>
<div v-for="(item, i) in selectsData.deptList" :key="i">
<div v-for="(item, i) in deptList" :key="i">
<div v-if="i < 11">
<div class="chose1">
<div class="span">{{ item.name }}</div>
@@ -211,36 +215,36 @@
</div>
</div>
</div>
<div v-if="!dept && selectsData.deptList.length > 10" class="ifsw">
<div v-if="!dept && deptList.length > 10" class="ifsw">
<div @click="dept = !dept" class="“sw”">查看更多></div>
</div>
<div v-if="dept && selectsData.deptList.length > 10" class="ifsw">
<div v-if="dept && deptList.length > 10" class="ifsw">
<div @click="dept = !dept" class="sw">收起&lt;</div>
</div>
</div>
<!--受众-->
<div v-if="!selectStu" class="selecteds">
<div class="group">受众关联</div>
<div v-for="(item, i) in selectsData.groupList" :key="i">
<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="AuditDel(i)"></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="AuditDel(i)"></div>
<div class="ch2" @click="auditTableRef.remove(i)"></div>
</div>
</div>
</div>
</div>
<div v-if="!group && selectsData.groupList.length > 10" class="ifsw">
<div v-if="!group && auditSelectRows.length > 10" class="ifsw">
<div @click="group = !group" class="“sw”">查看更多></div>
</div>
<div v-if="group && selectsData.groupList > 10" class="ifsw">
<div v-if="group && auditSelectRows.length > 10" class="ifsw">
<div @click="group = !group" class="sw">收起&lt;</div>
</div>
</div>
@@ -257,7 +261,7 @@
<slot></slot>
</a-button>
</div>
<a-modal :style="{ padding: 0, position: relative, right: '-20%' }" :closable="true" :visible="stageVisible"
<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">
@@ -268,11 +272,8 @@
</div>
<div class="mid">
<div class="inher">
<!-- <div class="cur">当前关卡关卡2</div> -->
<div class="select">
<a-select style="width: 400px" :placeholder="type === 1 ? '选择阶段' : '选择关卡'"
v-model:value="selectsData.stageId"
className="cus-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>
@@ -294,25 +295,25 @@
<script setup>
import {message} from "ant-design-vue";
import {computed, defineEmits, defineProps, ref, watch} from "vue";
import {boeRequest, useBoeApi, useBoeApiPage} from "@/api/request";
import {boeRequest, useBoeApi, useBoeApiPage, useBoeApiUserInfoPage, useBoeApiAuditPage} from "@/api/request";
import {
AUDIENCE_LIST,
ORG_CHILD_LIST,
ORG_LIST,
// USER_LIST,
USER_LIST_PAGE,
AUDIENCE_LIST,
} from "@/api/ThirdApi";
import {
saveStu,
getAllStudentByProjectId,
// addGroupMember,
getStuPage,
} from "@/api/index1";
import dialog from "@/utils/dialog";
// import { getProjStu } from "@/api/indexProjStu";
import BaseTable from "@/components/common/BaseTable";
import {STUDENT_LIST} from "@/api/apis";
const emit = defineEmits({});
const props = defineProps({
type: Number,
infoType: Number,
infoId: Number,
id: String,
title: {
type: String,
@@ -363,108 +364,31 @@ const props = defineProps({
default: null,
},
});
console.log("props.activeKey1" + props.activeKey1);
// 获取项目学员;
const procurrentPage = ref(1);
const projectList = ref([]);
const allProjectStudent = ref([]);
const proStudentName = ref("");
const projectListTotal = ref(-1);
const projectPageSize = ref(10);
const projectSelectKeys = ref([]);
const projectSelectRows = ref([]);
const stuSelectRows = ref([]);
const auditSelectRows = ref([]);
const auditSelectRowKeys = ref([]);
const deptList = ref([]);
const member = ref(false);
const projectPagination = computed(() => ({
total: projectListTotal.value,
showSizeChanger: false,
current: procurrentPage.value,
pageSize: projectPageSize.value,
onChange: projectChangePagination,
}));
const projectRowSelection = computed(() => ({
columnWidth: 20,
selectedRowKeys: projectSelectKeys.value,
onChange: onProjectSelectChange,
preserveSelectedRowKeys: true,
}));
const dept = ref(false);
const projectStuTableRef = ref();
const stuTableRef = ref();
const projectParams = ref({ pid: props.infoId, type: props.infoType });
const getAllStudent = () => {
let params = {
projectId:props.id
};
getAllStudentByProjectId(params).then(res => {
allProjectStudent.value = res.data.data;
})
};
getAllStudent();
const getStu = () => {
let obj = {
studentName: proStudentName.value,
pageNo: procurrentPage.value,
pageSize: 10,
pid: props.id,
type: props.type
};
projectListTotal.value = -1;
console.log("获取项目学员", obj);
getStuPage(obj).then((res) => {
console.log("获取项目学员", res);
let arr = res.data.data.records;
let array = [];
arr.map((value) => {
let obj = {
id: value.studentId,
studentId: value.studentId,
realName: value.studentName,
userNo: value.studentUserNo,
isLeader: value.isLeader,
groupId: value.groupId,
orgName: value.studentOrgName ? value.studentOrgName : "-",
departName: value.studentDepartName ? value.studentDepartName : "-",
};
array.push(obj);
});
projectList.value = array;
projectListTotal.value = res.data.data.total;
});
};
getStu();
const projectChangePagination = (page) => {
procurrentPage.value = page;
getStu();
};
function onProjectSelectChange(e, l) {
console.log("eeeee", e, l);
projectSelectKeys.value = e;
selectsData.value.projectMemberList = l;
}
function memberDel(i) {
projectSelectKeys.value = projectSelectKeys.value.filter(
(e) => e !== selectsData.value.projectMemberList[i].id
);
selectsData.value.projectMemberList.splice(i, 1);
}
const getProjectStu = () => projectStuTableRef.value.fetch();
const resetProjectStu = () => projectStuTableRef.value.reset();
const person = ref(false);
// const dept =ref(false)
const group = ref(false);
const visiable = ref(false);
const activeKey = ref(props.isGroup ? 4 : 1);
// const activeKey = ref(1);
const activeKey = ref(props.infoType ? 4 : 1);
const stageVisible = ref(false);
const selectsData = ref({
stageId: "",
studentList: [],
deptList: [],
groupList: [],
projectMemberList: [],
});
const stageId = ref();
const nameSearch = ref({
keyword: "",
departId: null,
page: 1,
pageSize: 10,
});
const stuTreeSelectKeys = ref([]);
const stuTreeExpandedKeys = ref([]);
@@ -479,20 +403,7 @@ const searchOrgName = ref({
pageSize: 10,
});
const stageIds = computed(() => props.stage);
const {
data: stuData,
page: stuPageNo,
fetch: searchStu,
pageSize: stuPageSize,
loading: stuLoading,
total: stuTotal,
reset: stuReset,
} = useBoeApiPage(USER_LIST_PAGE, nameSearch.value, {
init: false,
result: (res) => res.result.userInfoList,
totalPage: (res) => res.result.totalPage,
total: (res) => res.result.totalElement,
});
const { data: orgData, fetch: searchOrg } = useBoeApiPage(
ORG_LIST,
searchOrgName.value
@@ -514,21 +425,44 @@ const { data: treeOrgData, loading: orgOrgLoading } = useBoeApi(
}
);
const {
data: audiData,
fetch: searchAudi,
page: audiPageNo,
pageSize: audiPageSize,
loading: audiLoading,
total: audiTotal,
reset: auditReset,
} = useBoeApiPage(AUDIENCE_LIST, audienceName.value, {
init: true,
result: (res) =>
res.result.audienceList.map((e) => ({ ...e, id: e.id + "" })),
totalPage: (res) => res.result.totalPage,
total: (res) => res.result.totalElement,
});
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: "姓名",
@@ -594,52 +528,28 @@ const audiColums = ref([
className: "h",
},
]);
const stuSelectKeys = ref([]);
const orgSelectKeys = ref([]);
const auditSelectKeys = ref([]);
const auditTableRef = ref();
const screenHeight = ref(document.body.clientHeight);
//const screenWidth = ref(document.body.clientWidth);
const stuRowSelection = computed(() => ({
type: props.selectOne ? "radio" : "checkbox",
columnWidth: 20,
selectedRowKeys: stuSelectKeys.value,
onChange: onStuSelectChange,
preserveSelectedRowKeys: true,
}));
const orgRowSelection = computed(() => ({
columnWidth: 20,
selectedRowKeys: orgSelectKeys.value,
onChange: onOrgSelectChange,
preserveSelectedRowKeys: true,
}));
const stuPagination = computed(() => ({
total: stuTotal.value,
showSizeChanger: false,
current: stuPageNo.value,
pageSize: stuPageSize.value,
onChange: changePagination,
}));
const auditPagination = computed(() => ({
total: audiTotal.value,
showSizeChanger: false,
current: audiPageNo.value,
pageSize: audiPageSize.value,
onChange: auditChangePagination,
}));
const auditRowSelection = computed(() => ({
columnWidth: 20,
selectedRowKeys: auditSelectKeys.value,
onChange: onAuditSelectChange,
preserveSelectedRowKeys: true,
}));
const closeDrawer = () => {
deleteDepSelect();
visiable.value = false;
stuData.value = [];
nameSearch.value.keyword = "";
selectedOrgKeys.value = [];
};
function searchAudi() {
auditTableRef.value.fetch();
}
function onLoadData(treeNode) {
return boeRequest(ORG_CHILD_LIST, { keyword: "", orgId: treeNode.id }).then(
(r) => {
@@ -664,26 +574,15 @@ const closeChangeModal = () => {
const openDrawer = () => {
visiable.value = true;
};
//获取组织树
// const treeData = computed(() => {
// return store.state.orgtreeList ? store.state.orgtreeList : [];
// });
function onSearchStu() {
nameSearch.value.page = 1;
searchStu();
stuTableRef.value.fetch();
}
function stuStuOrgSelect(e) {
nameSearch.value.departId = e.join("");
searchStu();
}
function stuDel(i) {
stuSelectKeys.value = stuSelectKeys.value.filter(
(e) => e !== selectsData.value.studentList[i].id
);
selectsData.value.studentList.splice(i, 1);
stuTableRef.value.fetch();
}
const selectedOrgKeys = ref([]);
@@ -693,77 +592,19 @@ watch(selectedOrgKeys, () => {
});
function orgDel(i) {
console.log(selectedOrgKeys.value);
orgSelectKeys.value = orgSelectKeys.value.filter(e => e !== selectsData.value.deptList[i].id);
orgSelectKeys.value = orgSelectKeys.value.filter(e => e !== deptList.value[i].id);
selectedOrgKeys.value.splice(i, 1);
selectsData.value.deptList.splice(i, 1);
}
function AuditDel(i) {
auditSelectKeys.value = auditSelectKeys.value.filter(
(e) => e !== selectsData.value.groupList[i].id
);
selectsData.value.groupList.splice(i, 1);
}
// function orgSelect(key, obj) {
// console.log(obj)
//request(ORG_CHILD_LIST, {orgId: null}).then(res => {
//console.log(res.result)
//})
//}
function onStuSelectChange(e, l) {
stuSelectKeys.value = e;
selectsData.value.studentList = l;
deptList.value.splice(i, 1);
}
function onOrgSelectChange(e, l) {
orgRowSelection.value = e;
selectsData.value.deptList = l.selectedNodes;
// 获取被点击的树节点
deptList.value = l.selectedNodes;
}
function onAuditSelectChange(e, l) {
auditSelectKeys.value = e;
selectsData.value.groupList = l;
}
// const stuDepartmentSelect = (e) => {
// nameSearch.value.orgId = e.join('')
// searchStu()
// };
//分页获取学员
const changePagination = (page) => {
nameSearch.value.page = page;
searchStu();
};
const auditChangePagination = (page) => {
audienceName.value.page = page;
searchAudi();
};
//重置
function peopleName(name) {
console.log("people-name", name.target.value);
nameSearch.value.keyword = name.target.value;
}
const resetStu = () => {
// deleteDepSelect();
nameSearch.value.keyword = "";
nameSearch.value.page = 1;
nameSearch.value.pageSize = 10;
nameSearch.value.departId = null;
stuTreeExpandedKeys.value = [];
stuTreeSelectKeys.value = [];
stuReset();
};
const resetStu = () => stuTableRef.value.reset({ keyword: "", departId: null });
//清空选择部门信息
const deleteDepSelect = () => {
stuSelectKeys.value = [];
selectedOrgKeys.value = [];
projectSelectKeys.value = [];
};
@@ -772,21 +613,8 @@ const resetOrg = () => {
searchOrgName.value = { keyword: "", page: 1, pageSize: 10 };
};
//重置受众
const resetAudienceInfo = () => {
audienceName.value.keyword = "";
audienceName.value.page = 1;
audienceName.value.pageSize = 10;
auditReset();
searchAudi();
};
//全部清除
// const deleteAll = () => {
// selectsData.value = {
// studentList: [],
// deptList: [],
// groupList: []
// }
// };
const resetAudienceInfo = () => auditTableRef.value.reset({ keyword: "" });
//确定添加授权
const submitAuth = () => {
if (props.type === 2) {
@@ -797,7 +625,7 @@ const submitAuth = () => {
};
function handleDialogOk() {
if (selectsData.value.groupList.length || selectsData.value.deptList.length) {
if (auditSelectRowKeys.value.length || deptList.value.length) {
dialog({ content: "您选择了组织或受众,此添加为异步添加,请稍后手动刷新学员!", ok: handleStageOk });
return;
}
@@ -805,40 +633,8 @@ function handleDialogOk() {
}
function handleStageOk() {
// 判断添加人数是否已超过限制人数 限制 = 本次添加的人 + 原有的人
if (props.type === 1) {
if (props.groupMemberCount !== null) { // 只有添加组员的时候判断
let selectMember = 0;
if (activeKey.value === 4) { // 项目内选人
selectMember = selectsData.value.projectMemberList.length;
// 对选中的人员进行判断是否已经分组了
let haveGroupNum = selectsData.value.projectMemberList.filter(item => item.groupId !== null);
if (haveGroupNum.length > 0) {
message.warning("部分学员已经有小组,再次添加会被添加到当前小组.");
}
// 判断是否是组长,组长不能添加
const leaderArray = selectsData.value.projectMemberList.filter(item => item.isLeader === "1");
if (leaderArray.length > 0) {
return message.warning("当前选中学员" + leaderArray[0].realName + "已是小组长,请勿重复选择。");
}
} else if (activeKey.value === 1) {
selectMember = selectsData.value.studentList.length;
let arr = [...allProjectStudent.value].filter(x => [...selectsData.value.studentList].some(y => y.id === x.studentId));
if (arr.length > 0) {
message.warning("部分学员已经有小组,再次添加会被添加到当前小组.");
}
} else if (activeKey.value === 2) {
selectMember = selectsData.value.groupList.length;
} else if (activeKey.value === 3) {
selectMember = selectsData.value.deptList.length;
}
if (props.groupMemberCount < selectMember + Number(props.groupMemberNumber)) {
return message.warning("添加小组学员超过最大值");
}
}
if (props.type === 1 && props.groupId && props.groupMemberCount < projectSelectRows.value.length + stuSelectRows.value.length) {
return message.warning("添加小组学员超过最大值");
}
stageVisible.value = false;
visiable.value = false;
@@ -848,43 +644,17 @@ function handleStageOk() {
targetId: props.id,
type: props.type,
clear: props.clear,
deptIds: selectsData.value.deptList?.map((e) => e.id),
stageId: selectsData.value.stageId,
groupIds: selectsData.value.groupList?.map((e) => e.id),
studentList: selectsData.value.studentList.concat(
selectsData.value.projectMemberList
),
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);
});
// //添加小组学员
// if (props.isGroup) {
// console.log("添加组员传参", selectsData.value, {
// groupId: props.groupId,
// pid: props.projectId,
// groupName: props.groupName,
// ids: selectsData.value.studentList?.map((e) => e.id),
// });
// addGroupMember({
// groupId: props.groupId,
// pid: props.projectId,
// groupName: props.groupName,
// studentIds: selectsData.value.studentList?.map((e) => e.id),
// })
// .then((res) => {
// console.log("添加小组学员", res);
// deleteDepSelect();
// emit("finash", true);
// })
// .catch((err) => {
// console.log("添加小组学员失败", err);
// });
// } else {
// }
}
// 搜索受众值发生变化
@@ -894,28 +664,18 @@ function orgValue(value) {
}
watch(visiable, () => {
stuSelectKeys.value = [];
orgSelectKeys.value = [];
auditSelectKeys.value = [];
deptList.value = [];
audienceName.value.keyword = "";
audienceName.value.page = 1;
audienceName.value.pageSize = 10;
nameSearch.value.departId = null;
stuTreeExpandedKeys.value = [];
stuTreeSelectKeys.value = [];
activeKey.value = props.isGroup ? 4 : 1;
// activeKey.value = 1;
selectsData.value = {
stageId: "",
studentList: [],
deptList: [],
groupList: [],
projectMemberList: [],
};
stuReset();
auditReset();
searchAudi();
if (!visiable.value) {
auditTableRef.value && auditTableRef.value.clear();
stuTableRef.value && stuTableRef.value.clear();
projectStuTableRef.value && projectStuTableRef.value.clear();
}
});
</script>
<style lang="scss">

14
src/utils/qrCode.js Normal file
View File

@@ -0,0 +1,14 @@
import { createApp } from 'vue'
import QrCode from "@/components/common/QrCode";
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

View File

@@ -3368,6 +3368,7 @@ export default defineComponent({
beginTime: beginTime,
endTime: endTime,
offcourseId: state.offcourseId,
type:3
};
console.log("获取开obj", obj, state.selectTime);
let res = await planList(obj);

View File

@@ -1316,11 +1316,11 @@
<!-- 二维码弹窗 -->
<!-- 面授管理抽屉 开始 -->
<router-face-teach-manage
<ProjectFaceTaskManage
:permissions="permissions"
:createId="createId"
v-model:FaceTeachModelVisible="faceTeachModelVisible"
:title="faceTeachModelVisibleTitle"
:type="2"
v-model:visible="faceTeachModelVisibleTitle"
:datasource="faceData"
/>
<!-- 面授管理抽屉 结束-->
@@ -1435,10 +1435,10 @@ import { editRouteredDoc } from "../../api/indexLearningPath";
import TwoDimensionalCode from "../../components/TwoDimensionalCode.vue";
import TableStudent from "@/components/student/TableStudent";
import { getStuPage, moveStudent } from "@/api/index1";
import RouterFaceTeachManage from "../../components/drawers/router/RouterFaceTeachManage";
import RouterExaminationManage from "../../components/drawers/router/RouterExaminationManage";
import RouterExaminationExternalManage from "../../components/drawers/router/RouterExaminationExternalManage";
import RouterEvaluationManage from "../../components/drawers/router/RouterEvaluationManage";
import ProjectFaceTaskManage from "../../components/drawers/project/ProjectFaceTaskManage";
import RouterHomeworkManage from "../../components/drawers/router/RouterHomeworkManage";
import RouterCommonManage from "../../components/drawers/router/RouterCommonManage";
import RouterVoteManage from "../../components/drawers/router/RouterVoteManage";
@@ -1452,6 +1452,7 @@ export default {
name: "LevelAdd",
components: {
// ImpoterGroupLeader,
ProjectFaceTaskManage,
ProjCheckShip,
ImpStu,
CheckStu,
@@ -1465,7 +1466,6 @@ export default {
TwoDimensionalCode,
TableStudent,
TaskImpStu,
RouterFaceTeachManage,
RouterExaminationManage,
RouterExaminationExternalManage,
RouterEvaluationManage,

View File

@@ -140,8 +140,10 @@
</div>
<div class="mid">
<div class="item" v-for="(value,key) in TASK_TYPE" :key="key">
<component :is="value.component" :ref="el=>courseRef['el'+key]=el" :type="key" :infoType="2" :id="routerInfo.routerInfo?.id" :courseSyncFlag="routerInfo.routerInfo?.courseSyncFlag"
v-model:task-list="routerInfo.chapterList[activeIndex].draftTaskList" :chapter-list="routerInfo.chapterList">
<component :is="value.component" :ref="el=>courseRef['el'+key]=el" :type="key" :infoType="2"
:id="routerInfo.routerInfo?.id" :courseSyncFlag="routerInfo.routerInfo?.courseSyncFlag"
v-model:task-list="routerInfo.chapterList[activeIndex].draftTaskList"
:chapter-list="routerInfo.chapterList">
<div class="itcon">
<div class="img">
<img :src="value.img"/>
@@ -279,15 +281,15 @@
margin-right: 20px;">
<div class="opa">
<div class="opacation">
<span
v-if="element.type==2"
style="color: #4ea6ff; cursor: pointer"
<span
v-if="element.id && element.type===2"
style="color: #4ea6ff; cursor: pointer"
@click="openCourse(element,index)">
开课
</span>
<span
style="color: #4ea6ff;cursor: pointer;"
:style="{marginRight:element.type==2?6+'px':25+'px',marginLeft:element.type==2?6+'px':0+'px'}"
:style="{marginRight:element.type===2?`6px`:`25px`,marginLeft:element.type===2?`6px`:`0px`}"
@click="editTaskForType(element,index)">
编辑
</span>
@@ -366,7 +368,7 @@
</div>
</a-modal>
<!-- 面授课开课弹框 -->
<AddOpenCourse v-model:visible="opencourseVisible"/>
<AddOpenCourse ref="coursePlanRef" :type="2"/>
</div>
</template>
<script setup>
@@ -391,7 +393,8 @@ const moveChapterIndex = ref("");
const activeIndex = ref(0);
const types = 1; // 1 路径图 2 项目
const courseRef = ref({});
const courseRef = ref([]);
const coursePlanRef = ref();
const formValue = ref({ draftTaskList: [] });
const routerInfo = ref({ chapterList: [{ name: "关卡一", draftTaskList: [] }], routerInfo: {} });
@@ -416,13 +419,15 @@ watch(() => routerInfo.value.chapterList, () => {
}, { deep: true });
const showModal = () => {
formValue.value = {draftTaskList: []}
formValue.value = { draftTaskList: [] };
modal.value = true;
};
function showEditModal(ele){
formValue.value =ele;
function showEditModal(ele) {
formValue.value = ele;
modal.value = true;
}
const closeModal = () => {
modal.value = false;
};
@@ -432,12 +437,12 @@ const editChapter = () => {
if (!formValue.value.name) {
return message.warning("请输入关卡名称");
}
if(formValue.value.id){
if (formValue.value.id) {
closeModal();
return
return;
}
routerInfo.value.chapterList.push({ ...formValue.value, draftTaskList: [] });
activeIndex.value = activeIndex.value + 1
activeIndex.value = activeIndex.value + 1;
formValue.value = { draftTaskList: [] };
closeModal();
};
@@ -586,10 +591,9 @@ const cancelStorage = async () => {
};
// 开课按钮
const opencourseVisible = ref(false);
const openCourse = async () => {
opencourseVisible.value = true;
}
const openCourse = (ele) => {
coursePlanRef.value.openDrawer(ele);
};
</script>
<style lang="scss">

View File

@@ -252,7 +252,7 @@
<div class="opa">
<div class="opacation">
<span
v-if="element.type==2"
v-if="element.type==2 && element.id"
style="color: #4ea6ff; cursor: pointer;"
@click="openCourse(element,index)">
开课
@@ -393,7 +393,7 @@
</div>
</a-modal>
<!-- 面授课开课弹框 -->
<AddOpenCourse v-model:visible="opencourseVisible"/>
<AddOpenCourse ref="coursePlanRef" :type="1"/>
</div>
</template>
@@ -416,6 +416,7 @@ const visiblene = ref(false);
const stage = ref(false);
const confirmLoading = ref(false);
const cancleLoading = ref(false);
const coursePlanRef = ref();
const projectInfo = ref({stageList: [{taskDraftDtoList: [{}]}], projectInfo: {}});
const activeIndex = ref(0);
const moveChapterIndex = ref(0);
@@ -634,10 +635,8 @@ const cancelStorage = async () => {
cancleLoading.value = false
};
// 开课按钮
const opencourseVisible = ref(false);
const openCourse = async () => {
opencourseVisible.value = true;
const openCourse = (ele) => {
coursePlanRef.value.openDrawer(ele);
}
</script>

View File

@@ -1515,10 +1515,9 @@
<ProjectFaceTaskManage
:permissions="permissions"
:createId="createId"
v-model:Fvisible="FaceVisivle"
:projectTaskId="projectTaskId"
:title="showFaceText"
:projectTaskInfo="projectTaskInfo"
:type="1"
v-model:visible="FaceVisivle"
:datasource="projectTaskInfo"
/>
<!-- 作业管理抽屉 -->
<ProjectHomeWorkManage
@@ -1642,11 +1641,12 @@
:createId="createId"
/>
<!-- 面授学员抽屉 -->
<ProjectFaceStu
<RouterFaceStu
:permissions="permissions"
:createId="createId"
v-model:FSvisible="FSvisible"
:projectTaskInfo="facestudent"
:datasource="facestudent"
:type="1"
/>
<!-- 活动直播考勤抽屉 -->
<active-attendance
@@ -2274,9 +2274,9 @@ import ProjectVoteManage from "../../components/drawers/project/ProjectVoteManag
import SubsetManage from "../../components/drawers/SubsetManage";
import MemberList from "../../components/drawers/MemberList";
import ActiveAttendance from "../../components/drawers/ActiveAttendance";
import ProjectFaceStu from "../../components/drawers/project/ProjectFaceStu";
import ProjCheckShip from "../../components/drawers/ProjCheckPower";
import ImportStu from "../../components/drawers/ImportStu";
import RouterFaceStu from "../../components/drawers/router/RouterFaceStu";
import SeeStu from "../../components/drawers/SeeStu";
import ChangeGroup from "../../components/drawers/ChangeGroup";
import NoticePub from "../../components/drawers/NoticePub";
@@ -2318,6 +2318,7 @@ export default {
components: {
ProjectLevel,
TrainClass,
RouterFaceStu,
TimeManage,
ProjectFaceTaskManage,
ProjectOnlineManage,
@@ -2327,7 +2328,6 @@ export default {
ProjectEvalManage,
SubsetManage,
MemberList,
ProjectFaceStu,
ActiveAttendance,
// StuAdd,
ProjCheckShip,
@@ -2835,7 +2835,7 @@ export default {
voteData: "",
voteModelVisibleTitle: "",
voteLevelName: "",
facestudent: "",
facestudent: {},
modal1Visible: false, // 证书预览
changegroupV: false, //换组弹窗
checkgroupStuId: null, //换组id
@@ -4614,11 +4614,6 @@ export default {
item.courseId;
}
if (item.type == 2) {
let date1 = new Date(item.endTime).getTime();
let date2 = new Date().getTime();
if (date1 < date2) return message.warning("当前面授课已结束");
// if (item.taskStatus == 1 || item.taskStatus == 2)
// return message.error("该任务无法学习,请联系管理员进行替换。");
codeUrl =
window.location.protocol +
process.env.VUE_APP_H5 +