# Conflicts:
#	src/App.vue
This commit is contained in:
dongruihua
2023-03-17 10:54:49 +08:00
41 changed files with 4749 additions and 2691 deletions

6
.env
View File

@@ -7,7 +7,7 @@ VUE_APP_FILE_PATH=/upload/
# 代理url 本地调试,不可以用在其他地方
VUE_APP_PROXY_URL=//43.143.139.204/manageApi
# 登录url
VUE_APP_LOGIN_URL=//u-pre.boe.com/web
VUE_APP_LOGIN_URL=//u-pre.boe.com/web?returnUrl=
# boe域名
VUE_APP_BOE_API_URL=//u-pre.boe.com
#打包路径
@@ -36,4 +36,6 @@ VUE_APP_EXAM_DETAIL_URL=//u-pre.boe.com/mobile/pages/exam/exam?id=
#h5的基本url
VUE_APP_H5=//u-pre.boe.com/student-h5
#用户头像
VUE_APP_AVATAR_PATH=/upload/
VUE_APP_AVATAR_PATH=/upload/
# 旧版管理员界面
VUE_APP_OLD_MANAGE=//u-pre.boe.com/resource/index.html

View File

@@ -2,7 +2,7 @@ NODE_ENV=boe
VUE_APP_BASE=/manage
VUE_APP_BASE_API=/manageApi
VUE_APP_LOGIN_URL=//u-pre.boe.com/web
VUE_APP_LOGIN_URL=//u-pre.boe.com/web?returnUrl=
VUE_APP_BOE_API_URL=//u-pre.boe.com

View File

@@ -4,7 +4,7 @@ VUE_APP_BASE_API=/manageApi
VUE_APP_PROXY_URL=//u.boe.com/
VUE_APP_LOGIN_URL=//u.boe.com/web
VUE_APP_LOGIN_URL=//u.boe.com/web?returnUrl=
VUE_APP_BOE_API_URL=//u.boe.com
@@ -27,4 +27,6 @@ VUE_APP_H5=//u.boe.com/student-h5
#文件基础路径调试 只在生产做了变更
VUE_APP_FILE_PATH=/upload/boe/file/
#用户头像
VUE_APP_AVATAR_PATH=/upload/
VUE_APP_AVATAR_PATH=/upload/
# 旧版管理员界面
VUE_APP_OLD_MANAGE=//u.boe.com/resource/index.html

View File

@@ -3,7 +3,7 @@ VUE_APP_BASE=/manage-release
VUE_APP_BASE_API=/manageApi-release
VUE_APP_PROXY_URL=//u-pre.boe.com/
VUE_APP_LOGIN_URL=//u.boe.com/web-release
VUE_APP_LOGIN_URL=//u.boe.com/web-release?returnUrl=
VUE_APP_BOE_API_URL=//u.boe.com
@@ -23,4 +23,6 @@ VUE_APP_EXAM_DETAIL_URL=//u.boe.com/mobile-release/pages/exam/exam?id=
#h5的基本url
VUE_APP_H5=//u.boe.com/student-h5-release
#用户头像
VUE_APP_AVATAR_PATH=/upload/
VUE_APP_AVATAR_PATH=/upload/
# 旧版管理员界面
VUE_APP_OLD_MANAGE=//u-pre.boe.com/resource/index.html

View File

@@ -33,7 +33,7 @@ import {USER_PERMISSION} from "@/api/ThirdApi";
const store = useStore();
const isLogin = ref(false);
console.log("版本1.4.5------------");
console.log("版本2.1.7------------");
// 监听关闭浏览器
let time1 = ref(0);

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

@@ -58,7 +58,9 @@ http.interceptors.response.use(
return response;
}
if (code === 1000) {
(process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'alpine') ? router.push({path: 'login'}) : (window.location.href = process.env.VUE_APP_LOGIN_URL)
(process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'alpine') ?
router.push({path: 'login', query: { returnUrl: router.currentRoute.value.fullPath }}) :
(window.location.href = process.env.VUE_APP_LOGIN_URL + encodeURIComponent(window.location.protocol + import.meta.env.VUE_APP_BOE_API_URL + import.meta.env.VUE_APP_BASE + router.currentRoute.value.fullPath))
return Promise.reject(response);
}
show && message.error(msg);

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);
});
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@@ -437,7 +437,7 @@
src="../assets/images/navleft/review.png"
/>
</div>
<a target="_blank" href="https://u-pre.boe.com/web/">旧版管理员界面</a>
<a target="_blank" :href="oldManage">旧版管理员界面</a>
<!-- <router-link target="_blank" to="/oldsystemmanage">旧版管理员界面</router-link> -->
</a-menu-item>
<a-menu-item key="sub17" v-if="checkMenu('ReadingClubManage')">
@@ -832,6 +832,7 @@ export default {
},
],
oldManage: window.location.protocol + process.env.VUE_APP_OLD_MANAGE
});
const onOpenChange = (openKeys) => {

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

@@ -23,7 +23,11 @@
{{
item.name.indexOf('http')!==-1?
item.name.slice(item.name.lastIndexOf('/') + 1)
:item.name.indexOf('-')!==-1?item.name.slice(0,item.name.indexOf('-')) + item.name.slice(item.name.indexOf('.')) :item.name
:item.name.indexOf('-')!==-1?
item.name.indexOf('/')!==-1?
item.name.slice(item.name.lastIndexOf('/') + 1).slice(0,item.name.slice(item.name.lastIndexOf('/') + 1).indexOf('-')) + item.name.slice(item.name.indexOf('.'))
:item.name.slice(0,item.name.indexOf('-')) + item.name.slice(item.name.indexOf('.'))
:item.name
}}
</span>
</div>

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

@@ -126,6 +126,21 @@
}"
/>
</div>
<div class="tableBox" style="display: flex;justify-content:center;align-items:center;margin-top:12px;">
<div class="pa">
<a-pagination
v-if="tableDataTotal>10"
:showSizeChanger="false"
showQuickJumper="true"
hideOnSinglePage="true"
:pageSize="pageSize"
:current="currentPage"
:total="tableDataTotal"
class="pagination"
@change="changePagination"
/>
</div>
</div>
</div>
<div class="btnn">
<button class="btn1" @click="closeDrawer">取消</button>
@@ -459,6 +474,13 @@ export default {
}
};
//分页
const changePagination = (page) => {
state.tableDataTotalLoading = true;
state.currentPage = page;
getTableData();
};
const getTableData = () => {
// debugger
console.log("当前是项目还是路径图 1 项目 2 路径图", props);
@@ -510,6 +532,7 @@ export default {
.catch((err) => {
console.log(err);
state.tableDataTotalLoading = false;
state.tableDataTotal = 0;
state.tableData = [];
});
} else if (
@@ -560,10 +583,12 @@ export default {
console.log(err);
state.tableDataTotalLoading = false;
state.tableData = [];
state.tableDataTotal = 0;
});
} else {
state.tableDataTotalLoading = false;
state.tableData = [];
state.tableDataTotal = 0;
}
// let arr = state.tableData;
@@ -1047,6 +1072,7 @@ export default {
searchTaskList,
resetTaskList,
exportTaskStu,
changePagination
};
},
};

View File

@@ -0,0 +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>
</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: "请选择课程",
},
],
});
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 }
});
} 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();
}
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 {
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;
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: 0 26px 0 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;
}
}
}
.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: 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>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,470 @@
<!-- 面授列表 -->
<template>
<div class="main_item">
<div class="fi_input">
<a-input
v-model:value="params.courseName"
style="width: 220px; height: 40px; border-radius: 8px;margin-right: 32px;"
placeholder="请输入课程名称/编号"
maxlength="20"
/>
<a-tree-select
:getPopupContainer="triggerNode => triggerNode.parentNode || document.body"
v-model:value="valueproj"
show-search
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
:fieldNames="{
children: 'children',
label: 'name',
value: 'code',
}"
placeholder="请选择内容分类"
allow-clear
tree-default-expand-all
:tree-data="sysTypeOptions">
</a-tree-select>
</div>
<div class="btns" @click="search" style="margin-left: 16px;">
<div class="search"></div>
<div class="btnText">搜索</div>
</div>
<div class="btnsn" @click="reset">
<div class="search"></div>
<div class="btnText">重置</div>
</div>
</div>
<div class="main_item">
<button class="xkbtn" style="margin: 0" @click="goResearchmanage">
新建课程
</button>
</div>
<div class="main_notice" style="display: none">
<div class="mntc_left">
<div class="notice_icon"></div>
</div>
</div>
<div class="main_table">
<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"
/>
</div>
<!-- 新建面授课 -->
<CourseModal
ref="CourseModalRef"
v-model:xzinputV1="xzinputV1"
@visibleClose="visibleClose"
/>
</template>
<script setup>
import { computed, defineEmits, defineProps, ref, watch } from "vue";
import { courseListView } from "../../api/indexAudit";
import CourseModal from "../../views/courselibrary/courseModal.vue";
import {useStore} from "vuex";
const props = defineProps({
id: String,
name: String,
});
const emit = defineEmits([]);
const store = useStore();
const sysTypeOptions = computed(() => store.state.content_type);
const valueproj = ref(null);
const columns = ref([
{
title: "课程编号",
dataIndex: "id",
key: "id",
width: "40%",
ellipsis: true,
},
{
title: "名称",
dataIndex: "name",
key: "name",
width: "40%",
ellipsis: true,
},
{
title: "内容分类",
dataIndex: "sysTypeId",
key: "sysTypeId",
width: "20%",
align: "center",
ellipsis: true,
customRender: (text) => (
<div>
{sHX(text.record.sysTypeId)}
</div>
),
},
{
title: "创建人",
dataIndex: "createName",
key: "createName",
width: "20%",
align: "center",
ellipsis: true,
},
{
title: "创建时间",
dataIndex: "createTime",
key: "createTime",
width: "20%",
align: "center",
ellipsis: true,
},
]);
const initParams = {
courseName: "",
pageNo: 1,
pageSize: 10,
releaseStatus: 2,
};
// const router = useRouter();
const params = ref(initParams);
const rowSelectKeys = ref([]);
const selectsData = ref([]);
const total = ref(0);
const data = ref([]);
const loading = ref(false);
const sysTypeOption = computed(() => store.state.content_type);
function findClassFullName(list,classify,name=''){
return list && list.length && list.map(e=>{
return classify == e.code ? name?name+'-'+e.name:e.name : findClassFullName(e.children,classify,name?name+'-'+e.name:e.name)
}).filter(name=>name).join('')
}
// 课程三级分类回显
const sHX = (classify) => {
return findClassFullName(sysTypeOption.value,classify) || '-'
}
const getList = () => {
loading.value = true
let objn = {
auditStatus: 0,
sysTypeId: valueproj.value,
name: params.value.courseName,
pageNo: params.value.pageNo,
pageSize: 10,
};
console.log(objn);
courseListView(objn)
.then((res) => {
console.log("获取已审核课程成功", res.data.data);
data.value = res.data.data.rows;
total.value = Number(res.data.data.total);
loading.value = false;
})
.catch((err) => {
console.log("获取已审核课程失败", err);
loading.value = false;
});
};
getList()
// 新建面授课
const CourseModalRef = ref(null);
const visibleClose = () => {
getList()
};
watch(
() => props.id,
() => {
if (props.id) {
console.log(props)
rowSelectKeys.value = [props.id];
selectsData.value = [{ id: props.id, name: props.name }];
} else {
rowSelectKeys.value = [];
selectsData.value = [];
}
}
);
const customRow = (record) => ({
onClick: () => {
rowSelectKeys.value = [record.id];
selectsData.value = [record];
emit("update:id", selectsData.value[0].id);
emit("update:name", selectsData.value[0].name);
},
});
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;
getList();
};
const rowSelection = computed(() => ({
type: "radio",
columnWidth: 20,
selectedRowKeys: rowSelectKeys.value,
onChange: onSelectChange,
preserveSelectedRowKeys: true,
getCheckboxProps: getCheckboxProps,
}));
const getCheckboxProps = () => ({
// 某几项默认禁止选中(R: 当state等于1时)
disabled: false,
});
function onSelectChange(e, l) {
console.log(e,l)
rowSelectKeys.value = e;
selectsData.value = l;
console.log('112233',selectsData.value)
emit("update:id", selectsData.value[0].id);
emit("update:name", selectsData.value[0].name);
}
function search() {
params.value.pageIndex = 1;
getList();
}
function reset() {
rowSelectKeys.value = [];
selectsData.value = [];
params.value.pageIndex = 1;
params.value.keyWord = "";
params.value.courseName = "";
valueproj.value = null;
getList();
}
const goResearchmanage = () => {
CourseModalRef.value.visibleOpen(null, "");
};
</script>
<style lang="scss">
.ant-select-selector {
border-radius: 8px !important;
align-items: center !important;
width: 220px !important;
height: 40px !important;
padding-top: 5px;
margin-right: 32px;
}
.ant-select-show-search {
width: 220px !important;
}
.xkbtn {
cursor: pointer;
width: 130px;
height: 40px;
margin-top: 32px;
margin-bottom: 32px;
background: #4ea6ff;
border-radius: 8px;
border: 0;
margin-right: 8px;
color: #fff;
}
.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_left {
padding-right: 30px;
margin-top: 32px;
.main_item {
display: flex;
align-items: center;
margin-top: 20px;
margin-bottom: 20px;
.fi_input {
margin-right: 20px;
}
.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: rgba(64, 158, 255, 1) !important;
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/reset0.png") !important;
background-size: 100% 100%;
}
.btnText {
font-size: 14px;
font-weight: 400;
color: #fff !important;
line-height: 36px;
margin-left: 5px;
}
}
}
.main_item2 {
.pa {
width: 100%;
margin: 15px auto;
display: flex;
justify-content: center;
}
}
}
}
.main_table {
position: relative;
padding-bottom: 80px;
.ant-checkbox-wrapper {
align-items: center;
margin-top: -2px;
}
.ant-table-selection-column {
padding: 0px !important;
padding-left: 5px !important;
}
.ant-table-thead > tr > th {
background-color: rgba(239, 244, 252, 1);
}
th.h {
background-color: #eff4fc !important;
}
.ant-table-tbody
> tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected)
> td {
background: #f6f9fd;
}
.pa {
left: 0;
width: 100%;
display: flex;
justify-content: center;
position: absolute;
bottom: 20px;
}
}
.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;
}
}
}
}
</style>

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

@@ -158,89 +158,73 @@
</div>
<div v-if="edit" class="pjcb_content">
<div class="content content1">
<span>当前设计下学员可以获得 </span
><span class="scoretext">{{ scoresum }}</span
><span>积分</span>
</div>
<div class="content content2">
<span>完成必修/选修获得 </span
><span class="scoretext">{{ score1 }} </span><span>积分</span>
<span>完成一项任务则可获得 </span
><span class="scoretext">{{ score1 }} </span><span>积分,除此以外:</span>
</div>
<!--
<div class="content">
<span>完成作业成绩不低于 </span
<span>作业完成作业成绩不低于 </span
><span class="scoretext">{{ done2 }}</span
><span>分获得</span> <span class="scoretext">{{ done3 }}</span
><span>积分</span>
</div>
</div>-->
<div class="content">
<span></span><span class="scoretext">{{ four1 }}</span
><span>名学完在线课程获得</span>
<span class="scoretext">{{ four2 }}</span
><span style="margin-right: 50px">积分</span> <span></span
<span>作业最早完成任意一项目作业的前</span
><span class="scoretext">{{ four3 }}</span
><span>提交作业且成绩不低于</span>
><span>学员且成绩不低于</span>
<span class="scoretext">{{ four4 }}</span
><span>分获得</span> <span class="scoretext">{{ four5 }}</span
><span>积分</span>
</div>
<div class="content">
<span>考试成绩高于</span
<span>在线最早完成任意一门课程的</span><span class="scoretext">{{ four1 }}</span
><span>名学员获得</span>
<span class="scoretext">{{ four2 }}</span
><span style="margin-right: 50px">积分</span>
</div>
<div class="content">
<span>考试完成任意一场考试且成绩高于</span
><span class="scoretext">{{ five1 }}</span
><span>分获得</span> <span class="scoretext">{{ five2 }}</span
><span>积分</span>
</div>
<div class="content">
<span>考勤正常学员获得 </span
<span>面授直播活动完成任意一面授课直播活动且考勤正常学员获得 </span
><span class="scoretext">{{ six1 }}</span
><span>积分</span>
</div>
<div class="content">
<span>成为小组长获得</span
><span class="scoretext">{{ seven1 }}</span
><span style="margin-right: 50px">积分</span>
><span style="margin-right: 50px">积分同一项目只加一次</span>
</div> <div class="content">
<span>优秀学员可获得</span>
<span class="scoretext">{{ seven2 }}</span
><span>积分</span>
><span>积分同一项目只加一次</span>
</div>
</div>
<div v-else class="pjcb_content">
<div class="content content1">
<span>当前设计下学员可以获得 </span
><span class="scoretext">{{ scoresum }}</span
><span>积分</span>
</div>
<div class="content content2">
<span>完成必修/选修获得 </span
<span>完成一项任务则可获得 </span
><span
><a-input
v-model:value="score1"
:bordered="false"
@change="getScore"
/> </span
><span>积分</span>
><span>积分除此以外</span>
</div>
<div class="content">
<span>完成作业成绩不低于 </span
><a-input v-model:value="done2" :bordered="false" /><span
>分获得</span
>
<a-input v-model:value="done3" :bordered="false" /><span
>积分</span
>
</div>
<div class="content">
<span></span
><a-input v-model:value="four1" :bordered="false" /><span
>名学完在线课程获得</span
>
<a-input v-model:value="four2" :bordered="false" /><span
style="margin-right: 50px"
>积分</span
>
<span></span
<span>作业最早完成任意一项作业的</span
><a-input v-model:value="four3" :bordered="false" /><span
>提交作业且成绩不低于</span
>学员且成绩不低于</span
>
<a-input v-model:value="four4" :bordered="false" /><span
>分获得</span
@@ -250,7 +234,18 @@
>
</div>
<div class="content">
<span>考试成绩高于</span
<span>在线最早完成任意一门课程的</span
><a-input v-model:value="four1" :bordered="false" /><span
>名学完在线课程获得</span
>
<a-input v-model:value="four2" :bordered="false" /><span
style="margin-right: 50px"
>积分</span
>
</div>
<div class="content">
<span>考试完成任意一场考试且成绩高于</span
><a-input v-model:value="five1" :bordered="false" /><span
>分获得</span
>
@@ -259,20 +254,21 @@
>
</div>
<div class="content">
<span>考勤正常学员获得 </span
<span>面授直播活动完成任意一面授课直播活动且考勤正常学员获得 </span
><a-input v-model:value="six1" :bordered="false" /><span
>积分</span
>
</div>
<div class="content">
<span>成为小组长获得</span
><a-input v-model:value="seven1" :bordered="false" /><span
style="margin-right: 50px"
>积分</span
>
>积分同一项目只加一次</span
> </div> <div class="content">
<span>优秀学员可获得</span>
<a-input v-model:value="seven2" :bordered="false" /><span
>积分</span
>积分同一项目只加一次</span
>
</div>
</div>

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>

View File

@@ -1,14 +1,14 @@
<template>
<a-drawer
:visible="FSvisible"
class="drawerStyle ProjectFaceStu"
class="drawerStyle RouterFaceStu"
placement="right"
width="80%"
@after-visible-change="afterVisibleChange"
>
<div class="drawerMain">
<div class="header">
<div class="headerTitle">面授{{ projectTaskInfo?.name }}</div>
<div class="headerTitle">面授{{ datasource?.name }}</div>
<img
style="width: 29px; height: 29px; cursor: pointer"
src="../../../assets/images/basicinfo/close.png"
@@ -17,21 +17,29 @@
</div>
<div class="main">
<div class="titl">
<div class="endtime">
起止时间{{
projectTaskInfo && projectTaskInfo.startTime
? projectTaskInfo.startTime
: "-"
}}
{{
projectTaskInfo && projectTaskInfo.endTime
? projectTaskInfo.endTime
: "-"
}}
</div>
<div class="endtime" style="margin-left: 64px">
允许签到时段{{ beginTime }}~{{ endTime }}
<div
style="width: 100%;height:220px;display: flex;flex-wrap: nowrap;overflow-x: scroll;">
<div v-for="item,n in [1,2,3]" :key="n" style="cursor: pointer;">
<div
@click="ChoiceCourse(item)"
style="width: 360px;height:180px;margin-right: 32px;display: flex;flex-direction: column;padding: 16px;"
:style="{background:item==currentCourse?'rgb(247, 251, 253)':'rgb(250, 250, 250)'}">
<div style="font-size: 16px;">{{item}}次开课</div>
<div style="font-size: 14px;margin-top: 12px;">2023年管理者面授课程{{item}}</div>
<div style="font-size: 14px;">
<img src="../../../assets/images/courseManage/time.png" alt="" srcset="" style="width:16px;height:16px;">
2023.3.14 12:34 ~ 2023.3.17 12:34
</div>
<div style="font-size: 14px;margin-top: 6px;margin-bottom: 6px;">
<img src="../../../assets/images/courseManage/position.png" alt="" srcset="" style="width:16px;height:16px;">
京东方大厦{{item}}号楼
</div>
<div style="font-size: 14px;">
<img src="../../../assets/images/courseManage/persion.png" alt="" srcset="" style="width:16px;height:16px;">
董瑞华
</div>
</div>
</div>
</div>
</div>
@@ -45,12 +53,12 @@
placeholder="请输入姓名"
/>
</div>
<!-- <div class="namecon" style="margin-right: 30px">
<div class="namecon" style="margin-right: 30px">
<div class="name">考勤</div>
<div class="select">
<a-select
v-model:value="projectName"
style="width: 160px"
style="width: 200px"
placeholder="请选择"
:options="projectNameList"
@change="selectProjectName"
@@ -58,7 +66,7 @@
showSearch
></a-select>
</div>
</div> -->
</div>
<div class="namecon">
<div class="name">签到状态</div>
<div class="select">
@@ -82,13 +90,13 @@
<div class="img1"></div>
<div class="wz">搜索</div>
</div>
<div class="btn btn2" @click="resetTaskList">
<div class="btn btn1" @click="resetTaskList">
<div class="img2"></div>
<div class="wz">重置</div>
</div>
</div>
</div>
<div class="btnss" style="margin-top: 20px">
<div class="btnss" style="margin-top: 20px" v-if="checkPer(permissions,createId)">
<div
class="btn btn1"
style="margin-right: 20px"
@@ -100,10 +108,10 @@
<div class="img1"></div>
<div class="wz">导入学员</div>
</div>
<div class="btn btn2" @click="showCopyModal">
<div class="btn btn1" @click="showCopyModal" style="margin-right: 20px">
<div class="wz">批量签到</div>
</div>
<div class="btn btn2" @click="exportTaskStu">
<div class="btn btn1" @click="exportTaskStu">
<div class="img2"></div>
<div class="wz">导出数据</div>
</div>
@@ -121,14 +129,13 @@
<div class="right" @click="clearLine">清空</div>
</div>
</div>
<div class="pad"></div> -->
<div class="pad"></div> -->
<div class="tableBox" style="margin-top: 30px">
<a-table
style="border: 1px solid #f2f6fe"
:columns="tableDataFunc()"
:data-source="tabledata"
:loading="tableDataTotal === -1 ? true : false"
expandRowByClick="true"
@expand="expandTable"
:scroll="{ x: 1300 }"
@@ -185,7 +192,7 @@
<imp-stu
v-model:AddImpStuvisible="AddImpStuvisible"
@AddImpStuvisibleClose="AddImpStuvisibleClose"
:courseId="projectTaskInfo.courseId"
:courseId="datasource.courseId"
:courseType="3"
/>
<!-- 批量签到弹窗 -->
@@ -237,6 +244,8 @@ import * as api from "../../../api/index1";
import TwoDimensionalCode from "../../../components/TwoDimensionalCode";
import { message } from "ant-design-vue";
import { toDate } from "../../../api/method";
import {checkPer} from "@/utils/utils";
export default {
name: "FaceManage",
components: {
@@ -245,11 +254,19 @@ export default {
TwoDimensionalCode,
},
props: {
createId: {
type: Number,
default: null,
},
permissions: {
type: String,
default: null,
},
FSvisible: {
type: Boolean,
default: false,
},
projectTaskInfo: {
datasource: {
type: Object,
default: function () {
return {};
@@ -267,6 +284,7 @@ export default {
closeStop: false, //签退弹窗关闭图标
signQRvisible: false, //二维码弹窗
name: null,
projectName: undefined,
projectName2: undefined,
showmodal: false, //勾选提示框
closable: false, //modal右上角的关闭按钮
@@ -279,23 +297,23 @@ export default {
projectNameList: [
{
id: 1,
value: "项目一",
label: "项目一",
value: "签到",
label: "签到",
},
{
id: 2,
value: "项目二",
label: "项目二",
value: "缺勤",
label: "缺勤",
},
{
id: 3,
value: "项目三",
label: "项目三",
value: "迟到",
label: "迟到",
},
{
id: 4,
value: "项目四",
label: "项目四",
value: "请假",
label: "请假",
},
],
projectNameList2: [
@@ -339,17 +357,24 @@ export default {
value: "3",
},
],
// selectOption: [],
codevisible: false, //二维码弹窗
codeType: null,
codeIndex: null,
codeInfo: null, //二维码内容
// selectOption: [],
beginTime: null, //签到开始时间
endTime: null, //签到结束时间
currentCourse: 1,
});
const ChoiceCourse = (n) => {
state.currentCourse = n;
}
const afterVisibleChange = (bol) => {
if (bol == true) {
getStudent();
console.log("1111");
isSignClick();
}
};
@@ -391,14 +416,13 @@ export default {
//批量签到
const batchSign = () => {
let obj = {
courseId: Number(props.projectTaskInfo.courseId),
projectId: Number(props.projectTaskInfo.projectId),
// routerId: Number(props.projectTaskInfo.projectId),
courseId: Number(props.datasource.courseId),
// projectId: 0,
routerId: Number(props.datasource.routerId),
ids: state.selectedStudents,
taskId: Number(props.projectTaskInfo.projectTaskId),
taskType: Number(props.projectTaskInfo.type),
type: 3,
// userName: "",
taskId: Number(props.datasource.routerTaskId),
taskType: Number(props.datasource.type),
type: 2,
};
api
.attendanceSign(obj)
@@ -418,32 +442,17 @@ export default {
console.log("签到失败", err, obj);
});
};
// const closeStopModal = () => {
// state.stopModal = false;
// };
//显示签到二维码弹窗
//二维码
const qrcodeVisible = () => {
state.codevisible = true;
state.codeInfo = {
title: "【签到】二维码",
name: props.projectTaskInfo?.name,
url:
process.env.VUE_APP_BASE_API +
`/admin/student/studentSign?taskId=${
props.projectTaskInfo.projectTaskId
}&taskType=${props.projectTaskInfo.type}&type=${1}`,
};
console.log("codeInfo", state.codeInfo);
state.codeIndex = 0;
state.codeType = 1;
const signQR = () => {
state.signQRvisible = true;
};
const onSelectChange = (selectedRowKeys, e) => {
console.log("selectedRowKeys changed: ", selectedRowKeys, e);
console.log("selectedRowKeys changed: ", selectedRowKeys);
state.selectedRowKeys = selectedRowKeys;
// state.selectedStudents=e
let array = [];
for (let i = 0; i < e.length; i++) {
array.push(e[i].studentId);
@@ -455,44 +464,7 @@ export default {
state.selectedRowKeys = [];
state.selectedStudents = [];
};
// const getTableData = () => {
// let arr = state.tabledata;
// arr.map((value) => {
// // console.log("value", value);
// value.opacation = (
// <div class="opa">
// <a-checkbox
// checked={value.signIn}
// onChange={(e) => {
// console.log("点击签到", e);
// }}
// >
// 签到
// </a-checkbox>
// {/**
// <a-checkbox
// checked={value.signOut}
// onChange={(e) => {
// console.log("点击签退", e);
// }}
// >
// 签退
// </a-checkbox>
// */}
// <a-checkbox
// checked={value.leave}
// onChange={(e) => {
// console.log("点击请假", e);
// }}
// >
// 请假
// </a-checkbox>
// </div>
// );
// });
// state.tabledata = arr;
// };
// getTableData();
const tableDataFunc = () => {
const columns = [
{
@@ -500,7 +472,7 @@ export default {
dataIndex: "studentUserNo",
// width: "30%",
key: "studentUserNo",
width: 50,
width: 120,
align: "center",
ellipsis: true,
className: "h",
@@ -538,10 +510,10 @@ export default {
dataIndex: "studentDepartName",
// width: "30%",
key: "studentDepartName",
width: 50,
width: 60,
ellipsis: true,
align: "center",
className: "h",
ellipsis: true,
customRender: (text) => {
return (
<div class="racona">
@@ -590,6 +562,38 @@ export default {
);
},
},
{
title: "考勤",
dataIndex: "signTime",
key: "signTime",
width: 110,
align: "center",
ellipsis: true,
className: "h",
customRender: (text) => {
return (
<div class="racona">
<span>{text.record.signTime ? text.record.signTime : "-"}</span>
</div>
);
},
},
{
title: "签到状态",
dataIndex: "signTime",
key: "signTime",
width: 110,
align: "center",
ellipsis: true,
className: "h",
customRender: (text) => {
return (
<div class="racona">
<span>{text.record.signTime ? text.record.signTime : "-"}</span>
</div>
);
},
},
// {
// title: "签退时间",
// dataIndex: "jin",
@@ -598,45 +602,6 @@ export default {
// align: "center",
// className: "h",
// },
{
title: "考勤",
dataIndex: "signStatus",
key: "signStatus",
width: 50,
align: "center",
ellipsis: true,
className: "h",
customRender: (text) => {
// console.log("text", text);
return (
<div class="racona">
<span>
{text.record.signStatus
? "签到"
: text.record.leaveStatus
? "请假"
: "-"}
</span>
</div>
);
},
},
{
title: "签到状态",
dataIndex: "signStatus",
key: "signStatus",
width: 50,
align: "center",
ellipsis: true,
className: "h",
customRender: (text) => {
return (
<div class="racona">
<span>{ text.record.signStatus == null && new Date().getTime() > new Date(state.endTime).getTime() ? "异常" : text.record.signStatus ? "正常" : text.record.leaveStatus ? "异常" : text.record.signStatus == null ? "-" : "异常" }</span>
</div>
);
},
},
{
title: "考勤情况",
ellipsis: true,
@@ -648,6 +613,7 @@ export default {
// scopedSlots: { customRender: "action" }, //引入的插槽
customRender: (text) => {
// console.log("text.record.signStatus", text.record.signStatus);
return (
<div class="opa">
<a-radio
@@ -656,15 +622,14 @@ export default {
onChange={(e) => {
console.log("点击签到", e);
let obj = {
courseId: Number(props.projectTaskInfo.courseId),
projectId: Number(props.projectTaskInfo.projectId),
// routerId: Number(props.projectTaskInfo.projectId),
courseId: Number(props.datasource.courseId),
// projectId: 0,
routerId: Number(props.datasource.routerId),
ids: [text.record.studentId],
studentName: text.record.studentName,
taskId: Number(props.projectTaskInfo.projectTaskId),
taskType: Number(props.projectTaskInfo.type),
type: 3,
// userName: "",
taskId: Number(props.datasource.routerTaskId),
taskType: Number(props.datasource.type),
type: 2,
};
api
.attendanceSign(obj)
@@ -688,16 +653,17 @@ export default {
value="2"
checked={text.record.leaveStatus}
onChange={(e) => {
console.log("点击请假", e, props.projectTaskInfo);
console.log("点击请假", e, props.datasource);
let obj = {
courseId: Number(props.projectTaskInfo.courseId),
projectId: Number(props.projectTaskInfo.projectId),
// routerId: Number(props.projectTaskInfo.projectId),
courseId: Number(props.datasource.courseId),
// projectId: 0,
routerId: Number(props.datasource.routerId),
ids: [text.record.studentId],
studentName: text.record.studentName,
taskId: Number(props.projectTaskInfo.projectTaskId),
taskType: Number(props.projectTaskInfo.type),
type: 3,
taskId: Number(props.datasource.routerTaskId),
taskType: Number(props.datasource.type),
type: 2,
// userName: "",
};
api
.attendanceLeave(obj)
@@ -717,76 +683,6 @@ export default {
>
请假
</a-radio>
{/**
<a-checkbox
checked={text.record.signIn}
onChange={(e) => {
console.log("点击签到", e);
let obj = {
courseId: Number(props.projectTaskInfo.courseId),
projectId: Number(props.projectTaskInfo.projectId),
// routerId: Number(props.projectTaskInfo.projectId),
ids: [Number(text.record.studentId)],
studentName: text.record.studentName,
taskId: Number(props.projectTaskInfo.projectTaskId),
taskType: Number(props.projectTaskInfo.type),
type: 1,
// userName: "",
};
api
.attendanceSign(obj, (res) => {
console.log("签到结果", res, obj, e);
if (res.data.code === 200) {
text.record.signIn = true;
}
})
.catch((err) => {
console.log("签到失败", err, obj);
text.record.signIn = false;
});
}}
>
签到
</a-checkbox>
<a-checkbox
checked={text.record.leave}
onChange={(e) => {
console.log("点击请假", e, props.projectTaskInfo);
let obj = {
courseId: Number(props.projectTaskInfo.courseId),
projectId: Number(props.projectTaskInfo.projectId),
// routerId: Number(props.projectTaskInfo.projectId),
studentId: Number(text.record.studentId),
studentName: text.record.studentName,
taskId: Number(props.projectTaskInfo.projectTaskId),
taskType: Number(props.projectTaskInfo.type),
type: 1,
};
api
.attendanceLeave(obj, (res) => {
console.log("请假结果", res, obj, e);
if (res.data.code === 200) {
text.record.leave = true;
}
})
.catch((err) => {
console.log("请假结果", err, obj);
text.record.leave = false;
});
}}
>
请假
</a-checkbox>
<a-checkbox
checked={value.signOut}
onChange={(e) => {
console.log("点击签退", e);
}}
>
签退
</a-checkbox>
*/}
</div>
);
},
@@ -797,18 +693,30 @@ export default {
//获取学员
const getStudent = () => {
console.log("我是传递的查询参数222", props.datasource, {
pageNo: state.currentPage,
pageSize: state.pageSize,
currentStageId: props.datasource.chapterId,
type: 2,
pid: props.datasource.routerId,
// status: Number(state.name),
studentName: state.name,
signStatus: state.projectName2,
taskId: props.datasource.routerTaskId,
taskType: props.datasource.type,
});
api
.AssessmentManagementMessage({
pageNo: state.currentPage,
pageSize: state.pageSize,
currentStageId: props.projectTaskInfo.stageId,
// currentStageId: props.datasource.chapterId,
type: 3,
pid: props.projectTaskInfo.courseId,
pid: props.datasource.courseId,
// status: Number(state.name),
studentName: state.name,
// taskId: props.projectTaskInfo.projectTaskId,
signStatus: state.projectName2,
// taskType: props.projectTaskInfo.type,
studentName: state.name,
// taskId: props.datasource.routerTaskId,
// taskType: props.datasource.type,
})
.then((res) => {
console.log("获取面授管理学员", res);
@@ -826,6 +734,7 @@ export default {
.catch((err) => {
console.log(err);
state.tabledata = [];
state.tabledata = [{name:'测试数据'}];
});
};
//搜索学员
@@ -837,6 +746,7 @@ export default {
};
// 重置按钮
function resetTaskList() {
state.projectName = undefined;
state.currentPage = 1;
state.name = null;
state.projectName2 = undefined;
@@ -853,27 +763,33 @@ export default {
};
// 导出数据
function exportTaskStu() {
console.log("props.projectTaskInfo", props.projectTaskInfo);
console.log("props.datasource", props.datasource);
window.open(
`${process.env.VUE_APP_BASE_API}/admin/student/exportTaskStudent?currentStageId=${props.projectTaskInfo.stageId}&type=3&pid=${props.projectTaskInfo.courseId}&thirdType=6`
`${
process.env.VUE_APP_BASE_API
}/admin/student/exportTaskStudent?currentStageId=${
props.datasource.chapterId
}&type=3&pid=${props.datasource.courseId}&thirdType=7&taskId=${props.datasource.routerTaskId}`
);
// api
// .exportTaskStudent({
// pageNo: state.currentPage,
// pageSize: state.pageSize,
// currentStageId: props.projectTaskInfo.stageId,
// currentTaskId: props.projectTaskInfo.projectTaskId,
// type: 1,
// pid: props.projectTaskInfo.projectId,
// })
// .then((res) => {
// console.log(res);
// })
// .catch((err) => {
// console.log(err);
// });
}
//二维码
const qrcodeVisible = () => {
state.codevisible = true;
state.codeInfo = {
title: "【签到】二维码",
name: props.datasource?.name,
url:
process.env.VUE_APP_BASE_API +
`/admin/student/studentSign?taskId=${
props.datasource.routerTaskId
}&taskType=${props.datasource.type}&type=${2}`,
};
console.log("codeInfo", state.codeInfo);
state.codeIndex = 0;
state.codeType = 1;
};
{
/* 添加学员弹框关闭,重新获取学员列表 */
}
@@ -886,42 +802,35 @@ export default {
getStudent();
}
};
// 计算签到时间
const isSignClick = () => {
console.log("props.projectTaskInfo.startTime", props.projectTaskInfo);
let beginTime = new Date(props.projectTaskInfo.startTime).getTime();
let endTime = !props.projectTaskInfo.afterStart
? new Date(props.projectTaskInfo.endTime).getTime()
: new Date(props.projectTaskInfo.startTime).getTime();
console.log("beginTimeendTime", beginTime, endTime);
if (
props.projectTaskInfo.beforeStart &&
props.projectTaskInfo.afterStart
) {
console.log("计算签到时间", props.datasource);
let beginTime = new Date(props.datasource.startTime).getTime();
let endTime = !props.datasource.afterStart
? new Date(props.datasource.endTime).getTime()
: new Date(props.datasource.startTime).getTime();
if (props.datasource.beforeStart && props.datasource.afterStart) {
//有开始前有开始后
beginTime = beginTime - props.projectTaskInfo.beforeStart * 60 * 1000;
endTime = endTime + props.projectTaskInfo.afterStart * 60 * 1000;
console.log("1111");
} else if (
props.projectTaskInfo.beforeStart &&
!props.projectTaskInfo.afterStart
) {
beginTime = beginTime - props.datasource.beforeStart * 60 * 1000;
endTime = endTime + props.datasource.afterStart * 60 * 1000;
console.log("1111", beginTime, endTime);
} else if (props.datasource.beforeStart && !props.datasource.afterStart) {
//只有开始前无开始后
beginTime = beginTime - props.projectTaskInfo.beforeStart * 60 * 1000;
console.log("11112222");
} else if (
!props.projectTaskInfo.beforeStart &&
props.projectTaskInfo.afterStart
) {
beginTime = beginTime - props.datasource.beforeStart * 60 * 1000;
console.log("11112222", beginTime);
} else if (!props.datasource.beforeStart && props.datasource.afterStart) {
//无开始前有开始后
endTime = endTime + props.projectTaskInfo.afterStart * 60 * 1000;
console.log("1111333");
endTime = endTime + props.datasource.afterStart * 60 * 1000;
console.log("1111333", endTime);
}
state.beginTime = toDate(beginTime / 1000, "Y/M/D h:m");
state.endTime = toDate(endTime / 1000, "Y/M/D h:m");
console.log("beginTime,endTime", state.beginTime, state.endTime);
};
return {
...toRefs(state),
selectProjectName,
@@ -933,16 +842,18 @@ export default {
showCopyModal,
closeCopyModal,
// closeStopModal,
qrcodeVisible,
signQR,
afterVisibleChange,
checkPer,
searchTaskList,
resetTaskList,
changePaginationStu,
exportTaskStu,
clearLine,
qrcodeVisible,
AddImpStuvisibleClose,
batchSign,
ChoiceCourse,
};
},
};
@@ -1065,7 +976,7 @@ export default {
}
}
}
.ProjectFaceStu {
.RouterFaceStu {
// // width: 80%;
// .ant-drawer-content-wrapper {
// // max-width: 1000px;
@@ -1161,7 +1072,7 @@ export default {
.img2 {
width: 16px;
height: 18px;
background-image: url(../../../assets/images/courseManage/reset1.png);
background-image: url(../../../assets/images/courseManage/reset0.png);
background-size: 100% 100%;
margin-right: 7px;
}
@@ -1202,7 +1113,7 @@ export default {
.img2 {
width: 17px;
height: 16px;
background-image: url(../../../assets/images/coursewareManage/export.png);
background-image: url(../../../assets/images/coursewareManage/export1.png);
background-size: 100% 100%;
margin-right: 7px;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -18,11 +18,30 @@
</div>
<div class="main">
<div class="endtime">
起止时间{{
datasource && datasource.startTime ? datasource.startTime : "-"
}}
{{ datasource && datasource.endTime ? datasource.endTime : "-" }}
<div
style="width: 100%;height:220px;display: flex;flex-wrap: nowrap;overflow-x: scroll;">
<div v-for="item,n in [1,2,3]" :key="n" style="cursor: pointer;">
<div
@click="ChoiceCourse(item)"
style="width: 360px;height:180px;margin-right: 32px;display: flex;flex-direction: column;padding: 16px;"
:style="{background:item==currentCourse?'rgb(247, 251, 253)':'rgb(250, 250, 250)'}">
<div style="font-size: 16px;">{{item}}次开课</div>
<div style="font-size: 14px;margin-top: 12px;">2023年管理者面授课程{{item}}</div>
<div style="font-size: 14px;">
<img src="../../../assets/images/courseManage/time.png" alt="" srcset="" style="width:16px;height:16px;">
2023.3.14 12:34 ~ 2023.3.17 12:34
</div>
<div style="font-size: 14px;margin-top: 6px;margin-bottom: 6px;">
<img src="../../../assets/images/courseManage/position.png" alt="" srcset="" style="width:16px;height:16px;">
京东方大厦{{item}}号楼
</div>
<div style="font-size: 14px;">
<img src="../../../assets/images/courseManage/persion.png" alt="" srcset="" style="width:16px;height:16px;">
董瑞华
</div>
</div>
</div>
</div>
</div>
<div class="search">
<div class="namecon" style="margin-right: 30px">
@@ -55,28 +74,28 @@
<div class="img1"></div>
<div class="wz">搜索</div>
</div>
<div class="btn btn2" @click="resetTaskList">
<div class="btn btn1" @click="resetTaskList">
<div class="img2"></div>
<div class="wz">重置</div>
</div>
</div>
</div>
<div class="btnss" style="margin-top: 20px" v-if="checkPer(permissions,createId)">
<!--<div class="btn btn1" style="margin-right: 20px" @click="godie">
<div class="btn btn1" style="margin-right: 20px" @click="godie">
<div class="img1"></div>
<div class="wz">催促学习</div>
</div> -->
<div class="btn btn2" @click="allStuOver">
</div>
<div class="btn btn1" @click="allStuOver" style="margin-right: 16px;">
<div class="wz">批量标注完成</div>
</div>
<div class="btn btn2">
<div class="btn btn1" style="margin-right: 16px;">
<div class="wz" @click="showEntryScore">批量录入成绩</div>
</div>
<div class="btn btn2" @click="exportTaskStu">
<div class="btn btn1" @click="exportTaskStu" style="margin-right: 16px;">
<div class="img2"></div>
<div class="wz">导出数据</div>
</div>
<div class="btn btn2" @click="exportHomeWorkShow">
<div class="btn btn1" @click="exportHomeWorkShow">
<div class="wz">导出作业</div>
</div>
</div>
@@ -98,7 +117,6 @@
style="border: 1px solid #f2f6fe"
:columns="tablecolumns"
:data-source="tabledata"
:loading="tableDataTotal === -1 ? true : false"
:scroll="{ x: 1300 }"
:pagination="false"
:row-selection="{
@@ -242,18 +260,7 @@ export default {
currentPage: 1,
tableDataTotal: -1,
tableDataTotal2: 0,
tabledata: [
// {
// workNum: "123",
// userName: "li",
// deptName: "开发",
// jobName: "前端开发",
// score: 89,
// exam: 98,
// testscore: 80,
// status: "已完成",
// },
],
tabledata: [],
tablecolumns: [
{
title: "工号",
@@ -433,12 +440,33 @@ export default {
align: "center",
ellipsis: true,
className: "h",
customRender: () => {
return (
<div class="racona">
<a
onClick={()=>{
state.CWvisible = true;
}}
style="margin-right:12px;">查看作业</a>
<a
onClick={()=>{
state.CAvisible = true;
}}>查看答卷</a>
</div>
);
},
},
],
exportHomeWorkV: false,
downloadUrl: null,
CAvisible: false
CAvisible: false,
currentCourse: 1
});
const ChoiceCourse = (n) => {
state.currentCourse = n;
}
//面授直播管理列表操作
const ListOpera = () => {
let arr = state.tabledata;
@@ -540,7 +568,6 @@ export default {
newData.push(res.data.data.records[i]);
}
state.tabledata = newData;
state.tabledata = [{name:'小星星',workStatus:1}];
ListOpera();
state.tableDataTotal = res.data.data.total;
state.tableDataTotal2 = res.data.data.total;
@@ -549,6 +576,7 @@ export default {
.catch((err) => {
console.log(err);
state.tabledata = [];
state.tabledata = [{name:'测试数据',workStatus:1}];
});
};
//搜索学员
@@ -652,6 +680,7 @@ export default {
checkPer,
clearLine,
searchTaskList,
ChoiceCourse,
resetTaskList,
changePaginationStu,
exportTaskStu,
@@ -742,7 +771,7 @@ export default {
.img2 {
width: 16px;
height: 18px;
background-image: url(../../../assets/images/courseManage/reset1.png);
background-image: url(../../../assets/images/courseManage/reset0.png);
background-size: 100% 100%;
margin-right: 7px;
}
@@ -787,7 +816,7 @@ export default {
.img2 {
width: 17px;
height: 16px;
background-image: url(../../../assets/images/coursewareManage/export.png);
background-image: url(../../../assets/images/coursewareManage/export1.png);
background-size: 100% 100%;
margin-right: 7px;
}

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">

View File

@@ -8,6 +8,8 @@
*/
import { createRouter, createWebHistory } from 'vue-router';
import routesConfig from './config';
import store from "@/store";
const routes = [
{
path: '/',
@@ -21,4 +23,26 @@ const router = createRouter({
routes,
})
let count = 0;
const timers = setInterval(() => {
count ++
let pathArr = store.state.menus
let currentPath = router.options.history.location
console.log(pathArr, currentPath, pathArr.indexOf(currentPath))
if(pathArr.length!==0){
// 刷新界面是否重新执行
if(pathArr.indexOf(currentPath)==-1){
clearInterval(timers)
router.push({path: pathArr[0]})
}else{
clearInterval(timers)
}
}
// 30s超时结束
if(count==60&&pathArr.length==0){
clearInterval(timers)
}
}, 500);
export default router

View File

@@ -12,14 +12,7 @@ export default createStore({
state: {
openpages: localStorage.getItem("openpages")
? JSON.parse(localStorage.getItem("openpages"))
: [
{
pagename: "学习路径图",
href: "/learningpath",
active: true,
},
],
: [],
assessmentName: "",
routerId: null,
projectTemplateId: null,

View File

@@ -1,5 +1,5 @@
import onLineImg from '@/assets/images/leveladd/zai.png'
// import faceCourseImg from '@/assets/images/leveladd/mian.png'
import faceCourseImg from '@/assets/images/leveladd/mian.png'
import caseImg from '@/assets/images/leveladd/an.png'
import workImg from '@/assets/images/leveladd/zuo.png'
import exaImg from '@/assets/images/leveladd/kao.png'
@@ -24,7 +24,7 @@ import AddVote from "@/components/vote/AddVote.vue";
import AddLive from "@/components/drawers/AddLive.vue";
import AddRef from "@/components/drawers/AddRef.vue";
import AddProject from "@/components/drawers/AddProject.vue";
// import AddFaceteach from "@/components/drawers/AddFaceteach.vue";
import AddFaceClass from "@/components/drawers/AddFaceClass.vue";
export const TASK_TYPE = {
1: {
@@ -32,11 +32,11 @@ export const TASK_TYPE = {
img: onLineImg,
component: AddOnline
},
// 2: {
// name: '面授',
// img: faceCourseImg,
// component: AddFaceteach
// },
2: {
name: '面授',
img: faceCourseImg,
component: AddFaceClass
},
3: {
name: '案例',
img: caseImg,

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

@@ -321,7 +321,7 @@
:scroll="{ x: 'max-content' }"
>
<template #operation="{ text, record, index }">
<a-space>
<a-space :key="record.id">
<a-button
v-if="(record.auditStatus === 2 || record.auditStatus === 3) && !record.publishStatus && checkPer(record.permissions,createId)"
@click="() => handlePush(text, index)"
@@ -417,7 +417,8 @@
>启用</a-button
>
<a-button
@click="() => handleDelete(text, index)"
v-if="record.publishStatus!==1"
@click="() => handleDelete(text, index, record)"
type="link"
danger
>删除
@@ -1165,7 +1166,7 @@
<span style="margin-right: 3px"></span>
</div>
<div class="b_input">
<FJUpload v-model:value="attachName" @changevalue="changevalue" />
<FJUpload v-model:value="attach" @changevalue="changevalue" />
</div>
</div>
@@ -2591,7 +2592,6 @@ export default defineComponent({
imgList: [],
validated: 0,
attach: "",
attachName: "",
pageSize2: 10,
currentPage2: 0,
tableDataTotal2: 0,
@@ -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);
@@ -3739,15 +3740,6 @@ export default defineComponent({
console.log("获取面授课开课详情", item);
state.xjkkinputV2 = item.address;
state.checked1 = item.applyFlag === 1 ? true : false;
let arrss = item.attach.split(",");
let str = "";
for (let i = 0; i < arrss.length; i++) {
i == arrss.length - 1
? (str += arrss[i].slice(arrss[i].lastIndexOf("/") + 1))
: (str += arrss[i].slice(arrss[i].lastIndexOf("/") + 1) + ",");
}
console.log(str);
state.attachName = str;
state.attach = item.attach;
state.xjkkinputV3 = [

View File

@@ -1010,15 +1010,15 @@ export default defineComponent({
state.qdms_inputV6 = item.intro;
state.member = { value: item.teacherId, name: item.teacher };
valueHtml.value = item.outline;
let arrss = item.attach.split(",");
let str = "";
for (let i = 0; i < arrss.length; i++) {
i == arrss.length - 1
? (str += arrss[i].slice(arrss[i].lastIndexOf("/") + 1))
: (str += arrss[i].slice(arrss[i].lastIndexOf("/") + 1) + ",");
}
console.log(str);
state.attach = str;
// let arrss = item.attach.split(",");
// let str = "";
// for (let i = 0; i < arrss.length; i++) {
// i == arrss.length - 1
// ? (str += arrss[i].slice(arrss[i].lastIndexOf("/") + 1))
// : (str += arrss[i].slice(arrss[i].lastIndexOf("/") + 1) + ",");
// }
// console.log(str);
state.attach = item.attach;
if (item.jobTypeIds) {
state.selectJobId = item.jobTypeIds.split(",");

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"/>
@@ -280,9 +282,14 @@
<div class="opa">
<div class="opacation">
<span
style="color: #4ea6ff;
margin-right: 25px;
cursor: pointer;"
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?`6px`:`25px`,marginLeft:element.type===2?`6px`:`0px`}"
@click="editTaskForType(element,index)">
编辑
</span>
@@ -360,6 +367,8 @@
</div>
</div>
</a-modal>
<!-- 面授课开课弹框 -->
<AddOpenCourse ref="coursePlanRef" :type="2"/>
</div>
</template>
<script setup>
@@ -368,6 +377,7 @@ import {GetRouterDraftDetail, releaseRouter} from "@/api/indexTask";
import {message} from "ant-design-vue";
import {useRoute} from "vue-router";
import UnlockMode from "@/components/drawers/UnlockMode.vue";
import AddOpenCourse from "@/components/drawers/AddOpenCourse.vue";
import {TASK_TYPE} from "@/utils/const";
import Draggable from "vuedraggable";
import {ROUTER_DETAIL_MODIFY} from "@/api/apis";
@@ -383,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: {} });
@@ -408,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;
};
@@ -424,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();
};
@@ -577,6 +590,11 @@ const cancelStorage = async () => {
cancleLoading.value = false;
};
// 开课按钮
const openCourse = (ele) => {
coursePlanRef.value.openDrawer(ele);
};
</script>
<style lang="scss">
.ConfirmModal {

View File

@@ -359,60 +359,51 @@
</div>
<div v-if="edit" class="pjcb_content">
<div class="content content1">
<span>当前设计下学员可以获得 </span
><span class="scoretext">{{ scoresum }}</span
><span>积分</span>
</div>
<div class="content content2">
<span>完成必修/选修获得 </span
><span class="scoretext">{{ score1 }} </span><span>积分</span>
<span>完成一项任务则可获得 </span
><span class="scoretext">{{ score1 }}</span
><span>积分除此以外</span>
</div>
<div class="content">
<span>完成作业成绩不低于 </span
><span class="scoretext">{{ done2 }}</span
><span>分获得</span> <span class="scoretext">{{ done3 }}</span
><span>积分</span>
</div>
<div class="content">
<span></span><span class="scoretext">{{ four1 }}</span
><span>名学完在线课程获得</span>
<span class="scoretext">{{ four2 }}</span
><span style="margin-right: 50px">积分</span> <span></span
<span>作业最早完成任意一项作业的</span
><span class="scoretext">{{ four3 }}</span
><span>提交作业且成绩不低于</span>
><span>学员且成绩不低于</span>
<span class="scoretext">{{ four4 }}</span
><span>分获得</span> <span class="scoretext">{{ four5 }}</span
><span>积分</span>
</div>
<div class="content">
<span>考试成绩高于</span
<span>在线最早完成任意一门课程的</span><span class="scoretext">{{ four1 }}</span
><span>名学员获得</span>
<span class="scoretext">{{ four2 }}</span
><span style="margin-right: 50px">积分</span>
</div>
<div class="content">
<span>考试:完成任意 一场考试且成绩高于</span
><span class="scoretext">{{ five1 }}</span
><span>分获得</span> <span class="scoretext">{{ five2 }}</span
><span>积分</span>
</div>
<div class="content">
<span>考勤正常学员获得 </span
<span>面授直播活动完成任意一面授课直播活动且考勤正常学员获得 </span
><span class="scoretext">{{ six1 }}</span
><span>积分</span>
</div>
<div class="content">
<span>成为小组长获得</span
><span class="scoretext">{{ seven1 }}</span
><span style="margin-right: 50px">积分</span>
><span style="margin-right: 50px">积分同一项目只加一次</span>
</div> <div class="content">
<span>优秀学员可获得</span>
<span class="scoretext">{{ seven2 }}</span
><span>积分</span>
><span>积分同一项目只加一次</span>
</div>
</div>
<div v-else class="pjcb_content">
<div class="content content1">
<span>当前设计下学员可以获得 </span
><span class="scoretext">{{ scoresum }}</span
><span>积分</span>
</div>
<div class="content content2">
<span>完成必修/选修获得 </span
<span>完成一项任务则可获得 </span
><span
><a-input
v-model:value="score1"
@@ -422,34 +413,11 @@
><span>积分</span>
</div>
<div class="content">
<span>完成作业成绩不低于 </span
>
<a-input v-model:value="done2" :bordered="false"/>
<span
>分获得</span
>
<a-input v-model:value="done3" :bordered="false"/>
<span
>积分</span
>
</div>
<div class="content">
<span></span
>
<a-input v-model:value="four1" :bordered="false"/>
<span
>名学完在线课程获得</span
>
<a-input v-model:value="four2" :bordered="false"/>
<span
style="margin-right: 50px"
>积分</span
>
<span></span
<span>作业:最早完成任意一项作业的</span
>
<a-input v-model:value="four3" :bordered="false"/>
<span
>提交作业且成绩不低于</span
>学员且成绩不低于</span
>
<a-input v-model:value="four4" :bordered="false"/>
<span
@@ -461,7 +429,21 @@
>
</div>
<div class="content">
<span>考试成绩高于</span
<span>在线:最早完成任意一门课程的</span
>
<a-input v-model:value="four1" :bordered="false"/>
<span
>名学员获得</span
>
<a-input v-model:value="four2" :bordered="false"/>
<span
style="margin-right: 50px"
>积分</span
>
</div>
<div class="content">
<span>考试:完成任意一场考试且成绩高于</span
>
<a-input v-model:value="five1" :bordered="false"/>
<span
@@ -473,7 +455,7 @@
>
</div>
<div class="content">
<span>考勤正常学员获得 </span
<span>面授直播活动完成任意一面授课直播活动且考勤正常学员获得 </span
>
<a-input v-model:value="six1" :bordered="false"/>
<span
@@ -486,12 +468,12 @@
<a-input v-model:value="seven1" :bordered="false"/>
<span
style="margin-right: 50px"
>积分</span
>
>积分同一项目只加一次</span
> </div> <div class="content">
<span>优秀学员可获得</span>
<a-input v-model:value="seven2" :bordered="false"/>
<span
>积分</span
>积分同一项目只加一次</span
>
</div>
</div>

View File

@@ -251,11 +251,16 @@
">
<div class="opa">
<div class="opacation">
<span style="
color: #4ea6ff;
margin-right: 25px;
cursor: pointer;
" @click="editTaskForType(element,index)">
<span
v-if="element.type==2 && element.id"
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'}"
@click="editTaskForType(element,index)">
编辑
</span>
<span style="color: #4ea6ff; cursor: pointer" @click="confirmDelTask(index)">
@@ -387,6 +392,8 @@
</div>
</div>
</a-modal>
<!-- 面授课开课弹框 -->
<AddOpenCourse ref="coursePlanRef" :type="1"/>
</div>
</template>
@@ -395,6 +402,7 @@ import {computed, onMounted, ref, watch,} from "vue";
import {message} from "ant-design-vue";
import * as api from "../../api/indexTaskadd";
import UnlockMode from "../../components/drawers/UnlockMode.vue";
import AddOpenCourse from "@/components/drawers/AddOpenCourse.vue";
import Draggable from "vuedraggable";
import {useRoute} from "vue-router";
import {TASK_TYPE} from "@/utils/const";
@@ -408,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);
@@ -625,6 +634,11 @@ const cancelStorage = async () => {
message.success("取消成功");
cancleLoading.value = false
};
const openCourse = (ele) => {
coursePlanRef.value.openDrawer(ele);
}
</script>
<style lang="scss">

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 +