fix:项目&学员管理改造支持社招新员工

This commit is contained in:
zxj
2025-11-13 14:50:16 +08:00
parent 09c4a6da80
commit ec03ab4427
9 changed files with 14520 additions and 671 deletions

13472
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,11 +6,11 @@
* @FilePath: /fe-manage/src/api/config.js * @FilePath: /fe-manage/src/api/config.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
import {message} from "ant-design-vue"; import { message } from "ant-design-vue";
import axios from "axios"; import axios from "axios";
import router from "@/router"; import router from "@/router";
import {REFRESH_TOKEN_API} from "@/api/ThirdApi"; import { REFRESH_TOKEN_API } from "@/api/ThirdApi";
import {boeRequest} from "@/api/request"; import { boeRequest } from "@/api/request";
// import { getCookie } from '../api/method' // import { getCookie } from '../api/method'
// const Qs = require("qs"); // const Qs = require("qs");
@@ -23,7 +23,7 @@ const http = axios.create({
baseURL: process.env.VUE_APP_BASE_API, baseURL: process.env.VUE_APP_BASE_API,
timeout: 1000 * 15, timeout: 1000 * 15,
// headers: { "Content-Type": "multipart/form-data" }, // headers: { "Content-Type": "multipart/form-data" },
headers: {"Content-Type": "application/json"}, headers: { "Content-Type": "application/json" },
}); });
http.interceptors.request.use( http.interceptors.request.use(
@@ -39,8 +39,8 @@ http.interceptors.request.use(
// // 此处测试默认配置token // // 此处测试默认配置token
// config.headers.token = // config.headers.token =
// "eyJ0eXBlIjoidG9rZW4iLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC91LmJvZS5jb20iLCJpYXQiOjE2NzAxNTMxMDMsImV4cCI6MTY3MDE2MDMwMywiR2l2ZW5OYW1lIjoiYm9ldSIsInVzZXJJZCI6IjZCMDQ5RkFGLUMzMTQtN0NDRi0wRDI4LTBEMjNGNEM0MjUzMSIsInVJZCI6Ijk2NTM0MjAyNzQ5NzYwNzE2OCIsInBlcm1pc3Npb24iOiIifQ==.c937b2d3a59cbab2136fdde55fd38f06bdff041212aab0fa6741bc4be41e28a7"; // "eyJ0eXBlIjoidG9rZW4iLCJhbGciOiJIUzI1NiJ9.eyJjb21wYW55Q29kZSI6IkMwMDEiLCJ1SWQiOiI5NjUzNDIwMjc0OTc2MDcxNjgiLCJjb21wYW55SWQiOiIxMDQxNjczOTc3Mzc5OTQ2NDk2IiwibG9naW5JZCI6IjE5MzgwNTQ2NDY2OTAxNzcwMjYiLCJpc3MiOiJodHRwOi8vdS5ib2UuY29tIiwiR2l2ZW5OYW1lIjoiYm9ldSIsImV4cCI6MTc1MDkxMDQwOTc0NiwidXNlck5hbWUiOiLmnY7njonlhrAiLCJ1c2VySWQiOiI2QjA0OUZBRi1DMzE0LTdDQ0YtMEQyOC0wRDIzRjRDNDI1MzEifQ==.7f03d1ce991253197f0e733ba554496e8de715595b169b505bed8831ede565a9";
// // } // }
return config; return config;
}, },
(err) => { (err) => {
@@ -53,7 +53,7 @@ http.interceptors.response.use(
(response) => { (response) => {
// console.log('response', response) // console.log('response', response)
const { const {
data: {code, msg ,show}, data: { code, msg, show },
} = response; } = response;
if (code === 0 || code === 200) { if (code === 0 || code === 200) {
return response; return response;
@@ -68,7 +68,10 @@ http.interceptors.response.use(
window.location.href = process.env.VUE_APP_LOGIN_URL + encodeURIComponent(window.location.protocol + process.env.VUE_APP_BOE_API_URL + process.env.VUE_APP_BASE + router.currentRoute.value.fullPath) window.location.href = process.env.VUE_APP_LOGIN_URL + encodeURIComponent(window.location.protocol + process.env.VUE_APP_BOE_API_URL + process.env.VUE_APP_BASE + router.currentRoute.value.fullPath)
return Promise.reject(response); return Promise.reject(response);
} }
show ? message.error(msg):message.error('系统接口数据异常,请联系管理员'); if (response.headers['content-type'].includes('pdf')) {
return response;
}
show ? message.error(msg) : message.error('系统接口数据异常,请联系管理员');
console.log("api %o", msg); console.log("api %o", msg);
return Promise.reject(response); return Promise.reject(response);
}, },
@@ -85,4 +88,4 @@ http.interceptors.response.use(
export default http; export default http;
export function setHttpTimeout(newTimeout) { export function setHttpTimeout(newTimeout) {
http.defaults.timeout = newTimeout; http.defaults.timeout = newTimeout;
} }

View File

@@ -8,7 +8,7 @@
*/ */
import http from "./config"; import http from "./config";
import qs from "qs"; import qs from "qs";
import {getCookieForName} from "@/api/method"; import { getCookieForName } from "@/api/method";
// import { getCookie } from '../api/method' // import { getCookie } from '../api/method'
/** /**
* 接口传参数方式get * 接口传参数方式get
@@ -133,7 +133,7 @@ export const getStuList = (obj) => http.post('/admin/orgStruct/getStudentRef', o
//获取用户登录 //获取用户登录
export const getUser = () => http.post('/admin/CheckUser/login', { withCredentials: true }) export const getUser = () => http.post('/admin/CheckUser/login', { withCredentials: true })
//公共信息--------------------------------------------------- //公共信息---------------------------------------------------
export const courseData =(obj)=> http.post("/admin/offcourse/allPlanList",obj); export const courseData = (obj) => http.post("/admin/offcourse/allPlanList", obj);
//添加项目学员 //添加项目学员
export const addStudentProject = (obj) => http.post('/admin/project/addStudent', obj) export const addStudentProject = (obj) => http.post('/admin/project/addStudent', obj)
//添加课程学员 //添加课程学员
@@ -190,7 +190,7 @@ export const auditStudentBatch = (obj) => http.post('/admin/student/auditStudent
// //面授课批量导入成绩 // //面授课批量导入成绩
export const batchImportScore = (obj) => export const batchImportScore = (obj) =>
http.post('/admin/student/importHomeWork', obj, { http.post('/admin/student/importHomeWork', obj, {
headers: { "Content-Type": "multipart/form-data",token:getCookieForName("token") }, headers: { "Content-Type": "multipart/form-data", token: getCookieForName("token") },
}); });
//数据导入状态 //数据导入状态
export const getImportStatus = (uuid) => http.get('/admin/student/getImportStatus', { params: { uuid: uuid } }) export const getImportStatus = (uuid) => http.get('/admin/student/getImportStatus', { params: { uuid: uuid } })
@@ -199,7 +199,7 @@ export const getImportStatus = (uuid) => http.get('/admin/student/getImportStatu
// export const exportHomeWork=(obj)=>http.get('admin/student/exportHomeWork',{params:obj}) // export const exportHomeWork=(obj)=>http.get('admin/student/exportHomeWork',{params:obj})
// 面授课导入学员 // 面授课导入学员
export const FaceTeachImportStudent = (obj) => http.post('/admin/student/importStudent', obj, { headers: { "Content-Type": "multipart/form-data" },token:getCookieForName("token") }) export const FaceTeachImportStudent = (obj) => http.post('/admin/student/importStudent', obj, { headers: { "Content-Type": "multipart/form-data" }, token: getCookieForName("token") })
//成绩录入 //成绩录入
export const updateStudent = (obj) => http.post('/admin/student/homeWorkScoreEntry', obj) export const updateStudent = (obj) => http.post('/admin/student/homeWorkScoreEntry', obj)
@@ -229,7 +229,7 @@ export const createExamination = (obj) => http.post('/examination/createExaminat
//催促考试 //催促考试
export const batchSendMessage = (obj) => http.post('/admin/taskmanage/batchSendMessage', obj) export const batchSendMessage = (obj) => http.post('/admin/taskmanage/batchSendMessage', obj)
// 外部考试导入成绩 // 外部考试导入成绩
export const ImportExternalExamScore = (obj) => http.post('/admin/external/exam/manage/importExternalExamScore', obj, { headers: { "Content-Type": "multipart/form-data",token:getCookieForName("token") } }) export const ImportExternalExamScore = (obj) => http.post('/admin/external/exam/manage/importExternalExamScore', obj, { headers: { "Content-Type": "multipart/form-data", token: getCookieForName("token") } })
//分组 //分组
export const changeGroupByStudentId = (obj) => http.post('/admin/student/changeGroupByStudentId', obj) export const changeGroupByStudentId = (obj) => http.post('/admin/student/changeGroupByStudentId', obj)
//导入小组 //导入小组
@@ -243,4 +243,8 @@ export const delGroupStudent = (obj) => http.post('/admin/studentGroup/delStuden
//随机分组 //随机分组
export const randomGroup = (obj, projectId) => http.post(`/admin/studentGroup/randomGroup/${projectId}`, obj) export const randomGroup = (obj, projectId) => http.post(`/admin/studentGroup/randomGroup/${projectId}`, obj)
// 更新考试分数 // 更新考试分数
export const updateScore = (data)=> http.post('/admin/student/updateStudentScore', data) export const updateScore = (data) => http.post('/admin/student/updateStudentScore', data)
// 成绩单下载
export const downloadTranscript = (obj) => http.get('/stu/project/socialRecruit/report/download', { params: obj, headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, responseType: 'arraybuffer', })
// 获取报名记录
export const getElnBoeEnrollListByStudent = (obj) => http.post('/boe/enroll/boeEnrollController/getElnBoeEnrollListByStudent', obj)

View File

@@ -1,6 +1,5 @@
<template> <template>
<div class="TableStudent"> <div class="TableStudent">
<a-row <a-row
type="flex" type="flex"
gutter="12" gutter="12"
@@ -48,6 +47,19 @@
</div> </div>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col v-if="isNewEmployee">
<a-form-item title="报名及HR审批结果">
<div class="select">
<a-select
v-model:value="tableParam.approvalResults"
style="width: 260px; height: 40px"
placeholder="报名及HR审批结果"
:options="hrAuditResultList"
allowClear
></a-select>
</div>
</a-form-item>
</a-col>
<a-col> <a-col>
<a-button <a-button
class="cus-btn" class="cus-btn"
@@ -64,7 +76,11 @@
</a-button> </a-button>
</a-col> </a-col>
<a-col :span="2"> <a-col :span="2">
<a-button class="cus-btn" style="width: 100px;background: #4ea6ff; color: #fff;" @click="reset"> <a-button
class="cus-btn"
style="width: 100px; background: #4ea6ff; color: #fff"
@click="reset"
>
<template #icon> <template #icon>
<img <img
style="margin-right: 10px" style="margin-right: 10px"
@@ -100,7 +116,11 @@
</a-col> </a-col>
<!-- 新加导入学员 批量换组 导出学习信息 --> <!-- 新加导入学员 批量换组 导出学习信息 -->
<a-col :span="1.5" v-if="type === 1 || type === 2"> <a-col :span="1.5" v-if="type === 1 || type === 2">
<a-button class="cus-btn" @click="showImpStu" style="background: #4ea6ff; color: #fff"> <a-button
class="cus-btn"
@click="showImpStu"
style="background: #4ea6ff; color: #fff"
>
<template #icon <template #icon
><img ><img
style="margin-right: 10px" style="margin-right: 10px"
@@ -111,23 +131,39 @@
</a-col> </a-col>
<a-col :span="1.5" v-if="type === 1"> <a-col :span="1.5" v-if="type === 1">
<a-button class="cus-btn" @click="showChangeGroupModal" style="background: #4ea6ff; color: #fff"> <a-button
class="cus-btn"
@click="showChangeGroupModal"
style="background: #4ea6ff; color: #fff"
>
批量换组 批量换组
</a-button> </a-button>
</a-col> </a-col>
<a-col :span="1.5" v-if="type === 1"> <a-col :span="1.5" v-if="type === 1">
<a-button class="cus-btn" @click="exportTaskStu" style="background: #4ea6ff; color: #fff"> <a-button
class="cus-btn"
@click="exportTaskStu"
style="background: #4ea6ff; color: #fff"
>
导出学习信息 导出学习信息
</a-button> </a-button>
</a-col> </a-col>
<a-col :span="1.5" v-if="type === 2"> <a-col :span="1.5" v-if="type === 2">
<a-button class="cus-btn" @click="exportTaskStuRouter" style="background: #4ea6ff; color: #fff"> <a-button
class="cus-btn"
@click="exportTaskStuRouter"
style="background: #4ea6ff; color: #fff"
>
导出学习信息 导出学习信息
</a-button> </a-button>
</a-col> </a-col>
<a-col :span="1.5"> <a-col :span="1.5">
<a-button class="cus-btn" @click="bathDel" style="background: #4ea6ff; color: #fff"> <a-button
class="cus-btn"
@click="bathDel"
style="background: #4ea6ff; color: #fff"
>
<template #icon <template #icon
><img ><img
style="margin-right: 10px" style="margin-right: 10px"
@@ -137,25 +173,44 @@
</a-button> </a-button>
</a-col> </a-col>
<a-col :span="1.5" v-if="type === 2"> <a-col :span="1.5" v-if="type === 2">
<a-button class="cus-btn" @click="showChangeModal" style="background: #4ea6ff; color: #fff"> <a-button
class="cus-btn"
@click="showChangeModal"
style="background: #4ea6ff; color: #fff"
>
<template #icon></template> <template #icon></template>
批量调整关卡 批量调整关卡
</a-button> </a-button>
</a-col> </a-col>
<!-- 新加批量操作导出导出作业 --> <!-- 新加批量操作导出导出作业 -->
<a-col :span="1.5" v-if="type === 3" class="batchOpera"> <a-col :span="1.5" v-if="type === 3" class="batchOpera">
<div class="stmm_btn btn4" @click="hideShow" style="background: #4ea6ff"> <div
class="stmm_btn btn4"
@click="hideShow"
style="background: #4ea6ff"
>
<div class="btn4_sub"> <div class="btn4_sub">
<span style="color: #fff; margin-right: 4px;"> 批量操作 </span> <span style="color: #fff; margin-right: 4px"> 批量操作 </span>
<div <div
class="b_zk" class="b_zk"
:style="{ display: hideshow ? 'block' : 'none', color: '#fff', lineHeight: '9px', transform: 'rotate(180deg)'}" :style="{
>^ display: hideshow ? 'block' : 'none',
color: '#fff',
lineHeight: '9px',
transform: 'rotate(180deg)',
}"
>
^
</div> </div>
<div <div
class="b_sq" class="b_sq"
:style="{ display: hideshow ? 'none' : 'block', color: '#fff', lineHeight: '12px'}" :style="{
>^ display: hideshow ? 'none' : 'block',
color: '#fff',
lineHeight: '12px',
}"
>
^
</div> </div>
</div> </div>
<div <div
@@ -178,13 +233,17 @@
</div> </div>
</div> </div>
</div> </div>
<div class="stmm_btn btn5" @click="exportStu" style="background: #4ea6ff; color: #fff;"> <div
class="stmm_btn btn5"
@click="exportStu"
style="background: #4ea6ff; color: #fff"
>
<div class="export"></div> <div class="export"></div>
<div class="btnText">导出</div> <div class="btnText">导出</div>
</div> </div>
<div <div
class="stmm_btn btn5" class="stmm_btn btn5"
style="margin-left: 15px;background: #4ea6ff; color: #fff;" style="margin-left: 15px; background: #4ea6ff; color: #fff"
@click="exportHomeWorkShow" @click="exportHomeWorkShow"
> >
<div class="btnText">导出作业</div> <div class="btnText">导出作业</div>
@@ -192,7 +251,7 @@
<div <div
class="stmm_btn btn5" class="stmm_btn btn5"
style="margin-left: 15px;background: #4ea6ff; color: #fff;" style="margin-left: 15px; background: #4ea6ff; color: #fff"
@click="handleUpdateScore" @click="handleUpdateScore"
> >
<div class="btnText">刷新</div> <div class="btnText">刷新</div>
@@ -230,14 +289,23 @@
<slot name="extension" v-bind:data="{ record }"></slot> <slot name="extension" v-bind:data="{ record }"></slot>
<a-button <a-button
v-if="type === 3 && record.status !== 2 && record.status !== 0 && checkPer(permissions)" v-if="
type === 3 &&
record.status !== 2 &&
record.status !== 0 &&
checkPer(permissions)
"
@click="auditStatus(0, record.id)" @click="auditStatus(0, record.id)"
type="link" type="link"
>通过 >通过
</a-button </a-button>
>
<a-button <a-button
v-if="type === 3 && record.status !== 2 && record.status !== 0 && checkPer(permissions)" v-if="
type === 3 &&
record.status !== 2 &&
record.status !== 0 &&
checkPer(permissions)
"
@click="auditStatus(2, record.id)" @click="auditStatus(2, record.id)"
type="link" type="link"
>拒绝 >拒绝
@@ -451,7 +519,11 @@ const props = defineProps({
remarksTrue: { remarksTrue: {
type: Boolean, type: Boolean,
default: false, default: false,
} },
isNewEmployee: {
type: Boolean,
default: false,
},
}); });
const { loading: stuAsyncLoading, start } = useAsyncStu(props.id, props.type, getStuList); const { loading: stuAsyncLoading, start } = useAsyncStu(props.id, props.type, getStuList);
@@ -469,6 +541,29 @@ const topFlagList = ref([
}, },
]); ]);
const hrAuditResultList = ref([
{
id: 1,
value: 1,
label: "报名失败",
},
{
id: 2,
value: 2,
label: "审核中",
},
{
id: 3,
value: 3,
label: "审核通过",
},
{
id: 4,
value: 4,
label: "审核不通过",
},
]);
const tablecolumns = ref([ const tablecolumns = ref([
{ {
title: "姓名", title: "姓名",
@@ -535,9 +630,9 @@ const tablecolumns = ref([
key: "source", key: "source",
width: "60px", width: "60px",
align: "center", align: "center",
customRender: ({ record: { source } }) => customRender: ({ record }) =>{
// ({ 1: "快速添加", 2: "组织", 3: "受众", 4: "报名" }[source]), // ({ 1: "快速添加", 2: "组织", 3: "受众", 4: "报名" }[source]),
({ return ({
0: "导入", 0: "导入",
1: "手动加入", 1: "手动加入",
2: "手动加入", 2: "手动加入",
@@ -546,14 +641,54 @@ const tablecolumns = ref([
5: "自主报名", 5: "自主报名",
6: "导入", 6: "导入",
8: "扫码报名", 8: "扫码报名",
}[source]), 9: "自主报名"
}[record.source])
}
},
{
title: "HR审批结果",
dataIndex: "approvalResults",
key: "approvalResults",
width: "60px",
align: "center",
customRender: ({ record: { hrAuditResult } }) =>
({
1: "报名失败",
2: "审核中",
3: "审核通过",
4: "审核不通过",
}[hrAuditResult]),
},
{
title: "必修课进度",
dataIndex: "required",
key: "required",
width: "60px",
align: "center",
customRender: ({ record }) => (
<div>
{ record.requiredFinishTaskNum}/{ record.requiredTotalTaskNum}
</div>
),
},
{
title: "选修课进度",
dataIndex: "elective",
key: "elective",
width: "60px",
align: "center",
customRender: ({ record }) => (
<div>
{ record.electiveFinishTaskNum}/{ record.electiveTotalTaskNum}
</div>
),
}, },
...props.columns, ...props.columns,
{ {
title: "操作", title: "操作",
dataIndex: "operation", dataIndex: "operation",
key: "operation", key: "operation",
width: '120px', width: '220px',
fixed: "right", fixed: "right",
align: "center", align: "center",
slots: { customRender: "action" }, slots: { customRender: "action" },
@@ -696,6 +831,7 @@ function reset() {
tableParam.value.studentDepartId = null; //部门 tableParam.value.studentDepartId = null; //部门
tableParam.value.studentDepartName = null; //部门 tableParam.value.studentDepartName = null; //部门
tableParam.value.topFlag = null; //是否是优秀学员 tableParam.value.topFlag = null; //是否是优秀学员
tableParam.value.hrAuditResult = null; //报名及HR审批结果
getStuList(); getStuList();
} }

View File

@@ -16,10 +16,10 @@ import 'element-plus/dist/index.css'
import "@/assets/scss/common.scss" import "@/assets/scss/common.scss"
import Antd from 'ant-design-vue'; import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css'; import 'ant-design-vue/dist/antd.css';
import {request} from "@/api/request"; import { request } from "@/api/request";
import {USER_INFO, USER_PERMISSION, VALIDATE_TOKEN} from "@/api/apis"; import { USER_INFO, USER_PERMISSION, VALIDATE_TOKEN } from "@/api/apis";
import * as api1 from "@/api/index1"; import * as api1 from "@/api/index1";
import {getCookieForName} from "@/api/method"; import { getCookieForName } from "@/api/method";
import components from './components' import components from './components'
import axios from 'axios' import axios from 'axios'
import Cookies from "vue-cookies"; import Cookies from "vue-cookies";
@@ -35,18 +35,18 @@ app.config.warnHandler = () => null;
// }) // })
router.beforeEach(async (to, from, next) => { router.beforeEach(async (to, from, next) => {
if (!getCookieForName("token")) { // if (!getCookieForName("token")) {
window.location.href = process.env.VUE_APP_LOGIN_URL + encodeURIComponent(window.location.protocol + process.env.VUE_APP_BOE_API_URL + process.env.VUE_APP_BASE + router.currentRoute.value.fullPath) // window.location.href = process.env.VUE_APP_LOGIN_URL + encodeURIComponent(window.location.protocol + process.env.VUE_APP_BOE_API_URL + process.env.VUE_APP_BASE + router.currentRoute.value.fullPath)
return // return
} // }
//第一次进入 没有用户信息 //第一次进入 没有用户信息
if(!store.state.userInfo.userId){ if (!store.state.userInfo.userId) {
try{ try {
await request(VALIDATE_TOKEN) await request(VALIDATE_TOKEN)
await getUserInfo() await getUserInfo()
await getUserPermission(); await getUserPermission();
init() init()
}catch (e){ } catch (e) {
console.log('token失效 跳转到登录页') console.log('token失效 跳转到登录页')
} }
} }
@@ -57,7 +57,7 @@ app.use(router);
app.use(store); app.use(store);
app.mount('#app'); app.mount('#app');
async function getUserPermission() { async function getUserPermission() {
return request(USER_PERMISSION, {permissionType: 'PAGE'}).then(res => { return request(USER_PERMISSION, { permissionType: 'PAGE' }).then(res => {
store.commit("SET_PERMISSION", res.data?.map(s => s.url)); store.commit("SET_PERMISSION", res.data?.map(s => s.url));
}) })
} }
@@ -68,20 +68,20 @@ async function getUserInfo() {
method: "get", method: "get",
url: "/userbasic/orgHrbp/reportOrgs", url: "/userbasic/orgHrbp/reportOrgs",
params: { params: {
workNum:userInfo.data.userNo workNum: userInfo.data.userNo
}, },
headers: { headers: {
"XBOR-Access-token": Cookies.get("token"), "XBOR-Access-token": Cookies.get("token"),
}, },
}).then(res=>{ }).then(res => {
store.commit("SET_USER_ORGS", res.data); store.commit("SET_USER_ORGS", res.data);
}) })
} }
async function initDict(key) { async function initDict(key) {
const list = await getDictList(key); const list = await getDictList(key);
store.commit("SET_DICT", {key, data: list}); store.commit("SET_DICT", { key, data: list });
} }
const getDictList = (param) => api1.getDictTree({code: param,}).then((res) => res.data.data); const getDictList = (param) => api1.getDictTree({ code: param, }).then((res) => res.data.data);
const initDictTree = (key) => { const initDictTree = (key) => {
axios({ axios({
method: "get", method: "get",
@@ -95,17 +95,17 @@ const initDictTree = (key) => {
}, },
}).then( }).then(
(res) => { (res) => {
console.log(res.data.result,'课程分类接口') console.log(res.data.result, '课程分类接口')
store.commit("SET_DICT", {key, data: res.data.result}); store.commit("SET_DICT", { key, data: res.data.result });
//转化为map放到状态中 //转化为map放到状态中
let map=new Map(); let map = new Map();
res.data.result.forEach(item=>{ res.data.result.forEach(item => {
map.set(item.id, item.name); map.set(item.id, item.name);
if(item.children && item.children!=''){ if (item.children && item.children != '') {
item.children.forEach(child=>{ item.children.forEach(child => {
map.set(child.id, child.name); map.set(child.id, child.name);
if(child.children && child.children!=''){ if (child.children && child.children != '') {
child.children.forEach(last=>{ child.children.forEach(last => {
map.set(last.id, last.name); map.set(last.id, last.name);
}) })
} }

View File

@@ -2,10 +2,16 @@
<template xmlns:display="http://www.w3.org/1999/xhtml"> <template xmlns:display="http://www.w3.org/1999/xhtml">
<div class="projectAdd"> <div class="projectAdd">
<div class="header"> <div class="header">
<span class="title">{{ <span class="title"
projectInfo.id ? "编辑" : "创建" >{{ projectInfo.id ? "编辑" : "创建"
}}{{ ptojectType == "3" ? "班级" : "项目" }}</span> }}{{ ptojectType == "3" ? "班级" : "项目" }}</span
<div @click="backPage" style="cursor: pointer" to="/projectmanage" class="goback"> >
<div
@click="backPage"
style="cursor: pointer"
to="/projectmanage"
class="goback"
>
<span class="return"></span><span class="returntext">返回</span> <span class="return"></span><span class="returntext">返回</span>
</div> </div>
</div> </div>
@@ -13,7 +19,10 @@
<div class="main"> <div class="main">
<div class="name" v-if="projectInfo.parentName"> <div class="name" v-if="projectInfo.parentName">
<div class="namebox"> <div class="namebox">
<img class="nameimg" src="../../assets/images/basicinfo/asterisk.png"/> <img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname">项目归属</div> <div class="inname">项目归属</div>
</div> </div>
<div class="in"> <div class="in">
@@ -24,24 +33,43 @@
</div> </div>
<div class="name"> <div class="name">
<div class="namebox"> <div class="namebox">
<img class="nameimg" src="../../assets/images/basicinfo/asterisk.png"/> <img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname"> <div class="inname">
{{ ptojectType == 3 ? "班级名称" : "项目名称" }} {{ ptojectType == 3 ? "班级名称" : "项目名称" }}
</div> </div>
</div> </div>
<div class="in"> <div class="in">
<NameInput :placeholder="ptojectType == 3 ? '请输入班级名称':'请输入项目名称'" v-model:value="projectInfo.name" <NameInput
v-model:validated="projectInfo.validated" :type="1" :placeholder="
:maxlength="30" show-count :id="projectInfo.id"></NameInput> ptojectType == 3 ? '请输入班级名称' : '请输入项目名称'
"
v-model:value="projectInfo.name"
v-model:validated="projectInfo.validated"
:type="1"
:maxlength="30"
show-count
:id="projectInfo.id"
></NameInput>
</div> </div>
</div> </div>
<div class="name flex-top"> <div class="name flex-top">
<div class="namebox" style="margin-top: 10px"> <div class="namebox" style="margin-top: 10px">
<img class="nameimg" src="../../assets/images/basicinfo/asterisk.png"/> <img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname">封面图</div> <div class="inname">封面图</div>
</div> </div>
<div class="in select" style="flex: 1; display: flex; flex-wrap: wrap;"> <div
<div :class="`box ${projectInfo.picUrl === src.value ? 'active' : ''}`" style=" class="in select"
style="flex: 1; display: flex; flex-wrap: wrap"
>
<div
:class="`box ${projectInfo.picUrl === src.value ? 'active' : ''}`"
style="
width: 100px; width: 100px;
height: 100px; height: 100px;
border-radius: 5px; border-radius: 5px;
@@ -49,17 +77,29 @@
position: relative; position: relative;
overflow: hidden; overflow: hidden;
margin-bottom: 14px; margin-bottom: 14px;
" v-for="(src, index) in projectPic" :style="{ "
v-for="(src, index) in projectPic"
:style="{
display: index >= 3 ? 'none' : 'flex', display: index >= 3 ? 'none' : 'flex',
}" :key="index" @click="() => (projectInfo.picUrl = src.value)"> }"
<img style=" :key="index"
@click="() => (projectInfo.picUrl = src.value)"
>
<img
style="
width: 100px; width: 100px;
height: 100px; height: 100px;
margin-bottom: 4px; margin-bottom: 4px;
margin-right: 4px; margin-right: 4px;
" :src="src.value" alt="avatar"/> "
:src="src.value"
alt="avatar"
/>
</div> </div>
<div @click="showLearnBgMore" v-if="projectPic.length > 3" style=" <div
@click="showLearnBgMore"
v-if="projectPic.length > 3"
style="
width: 100px; width: 100px;
height: 100px; height: 100px;
padding-left: 15px; padding-left: 15px;
@@ -76,51 +116,78 @@
color: #4ea6ff; color: #4ea6ff;
line-height: 36px; line-height: 36px;
margin-left: 14px; margin-left: 14px;
"> "
>
查看更多 查看更多
<img src="../../assets/images/projectadd/go.png" alt=""/> <img src="../../assets/images/projectadd/go.png" alt="" />
</div> </div>
</div> </div>
</div> </div>
<div class="name"> <div class="name">
<div class="namebox"> <div class="namebox">
<img class="nameimg" src="../../assets/images/basicinfo/asterisk.png"/> <img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname">项目时间</div> <div class="inname">项目时间</div>
</div> </div>
<div class="in"> <div class="in">
<a-range-picker separator="至" :show-time="{ format: 'HH:mm' }" <a-range-picker
separator="至"
:show-time="{ format: 'HH:mm' }"
:placeholder="[' 开始时间', ' 结束时间']" :placeholder="[' 开始时间', ' 结束时间']"
v-model:value="timeRange" @calendarChange="calendarChange" v-model:value="timeRange"
style="width: 100%; height: 40px; border-radius: 5px" :allowClear="false" @calendarChange="calendarChange"
style="width: 100%; height: 40px; border-radius: 5px"
:allowClear="false"
format="YYYY-MM-DD HH:mm" format="YYYY-MM-DD HH:mm"
valueFormat="YYYY-MM-DD HH:mm" @change="timeChange" :disabled="!!viewDetail"/> valueFormat="YYYY-MM-DD HH:mm"
@change="timeChange"
:disabled="!!viewDetail"
/>
</div> </div>
</div> </div>
<div class="name"> <div class="name">
<div class="namebox"> <div class="namebox">
<img class="nameimg" src="../../assets/images/basicinfo/asterisk.png"/> <img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname">项目经理</div> <div class="inname">项目经理</div>
</div> </div>
<div class="in"> <div class="in">
<ProjectManager v-model:value="projectInfo.managerId" v-model:name="projectInfo.manager" <ProjectManager
@onChange="managerChange" mode="multiple"></ProjectManager> v-model:value="projectInfo.managerId"
v-model:name="projectInfo.manager"
@onChange="managerChange"
mode="multiple"
></ProjectManager>
</div> </div>
</div> </div>
<div class="name"> <div class="name">
<div class="namebox"> <div class="namebox">
<img class="nameimg" src="../../assets/images/basicinfo/asterisk.png"/> <img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname">资源归属</div> <div class="inname">资源归属</div>
</div> </div>
<div class="in select"> <div class="in select">
<OrgClass v-model:value="projectInfo.sourceBelongId" v-model:name="projectInfo.sourceBelongName" <OrgClass
v-model:fullName="projectInfo.sourceBelongFullName"></OrgClass> v-model:value="projectInfo.sourceBelongId"
v-model:name="projectInfo.sourceBelongName"
v-model:fullName="projectInfo.sourceBelongFullName"
></OrgClass>
</div> </div>
</div> </div>
<div class="name"> <div class="name">
<div class="namebox"> <div class="namebox">
<img class="nameimg" src="../../assets/images/basicinfo/asterisk.png"/> <img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname">项目级别</div> <div class="inname">项目级别</div>
</div> </div>
<div class="in select"> <div class="in select">
@@ -129,7 +196,10 @@
</div> </div>
<div class="name"> <div class="name">
<div class="namebox"> <div class="namebox">
<img class="nameimg" src="../../assets/images/basicinfo/asterisk.png"/> <img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname">培训分类</div> <div class="inname">培训分类</div>
</div> </div>
<div class="in select"> <div class="in select">
@@ -137,12 +207,19 @@
</div> </div>
</div> </div>
<div class="name"> <div class="name">
<div class="namebox" style="width:157px;margin-left:-38px;"> <div class="namebox" style="width: 157px; margin-left: -38px">
<img class="nameimg" src="../../assets/images/basicinfo/asterisk.png"/> <img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname">关联BOEU立项审批单</div> <div class="inname">关联BOEU立项审批单</div>
</div> </div>
<div class="in"> <div class="in">
<a-radio-group style="width:108px;" v-model:value="projectInfo.boeFlag" :disabled="viewDetail ? true : false"> <a-radio-group
style="width: 108px"
v-model:value="projectInfo.boeFlag"
:disabled="viewDetail ? true : false"
>
<a-radio :style="radioStyle" :value="1"></a-radio> <a-radio :style="radioStyle" :value="1"></a-radio>
<a-radio :style="radioStyle" :value="0"></a-radio> <a-radio :style="radioStyle" :value="0"></a-radio>
</a-radio-group> </a-radio-group>
@@ -155,14 +232,81 @@
</div> </div>
</div> --> </div> -->
</div> </div>
<div class="name name2 num" style="flex:3" v-if="projectInfo.boeFlag === 1"> <div v-if="isNewEmployee" class="name">
<div class="namebox" style="width: 157px; margin-left: -38px">
<img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname" style="margin-top: 13px">选修课程数量</div>
</div>
<div class="in">
<a-input-number
v-model:value="projectInfo.electiveCourseCount"
:min="0"
:max="1000"
/>
</div>
</div>
<!-- <div v-if="isNewEmployee" class="name">
<div class="namebox" style="width: 157px; margin-left: -38px">
<img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname" style="margin-top: 13px">必修课程数量</div>
</div>
<div class="in">
<a-input-number
v-model:value="projectInfo.requiredCourseCount"
:min="0"
:max="1000"
/>
</div>
</div> -->
<div v-if="isNewEmployee" class="name name3">
<div class="namebox">
<img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname" style="margin-top: 13px">转正攻略配置</div>
</div>
<div class="in" style="border: 1px solid #ccc">
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editorRef"
:defaultConfig="toolbarConfig"
:mode="mode"
/>
<Editor
style="height: 350px; overflow-y: hidden"
v-model:value="valueHtml"
:defaultConfig="editorConfig"
:mode="mode"
@onCreated="handleCreated"
@onChange="handleOnChange"
/>
<div style="text-align: right; padding: 10px; color: #a6a6a6">
字数统计:
<span id="word-count">{{ currentCount }}/{{ maxCount }}</span>
</div>
</div>
</div>
<div
class="name name2 num"
style="flex: 3"
v-if="projectInfo.boeFlag === 1"
>
<div class="namebox"> <div class="namebox">
<div class="num_text">项目编号</div> <div class="num_text">项目编号</div>
</div> </div>
<div class="in ggysxz"> <div class="in ggysxz">
<div class="num_input"> <div class="num_input">
<!-- <a-input style="border-radius: 8px;" show-count allowClear maxlength="30" v-model:value="projectInfo.numValue" placeholder="请输入项目编号" /> --> <!-- <a-input style="border-radius: 8px;" show-count allowClear maxlength="30" v-model:value="projectInfo.numValue" placeholder="请输入项目编号" /> -->
<ProjectNumber v-model:value="projectInfo.numValue"></ProjectNumber> <ProjectNumber
v-model:value="projectInfo.numValue"
></ProjectNumber>
</div> </div>
</div> </div>
</div> </div>
@@ -173,11 +317,13 @@
</div> </div>
<div class="in ggysxz"> <div class="in ggysxz">
<a-checkbox v-model:checked="courseSyncFlag"> <a-checkbox v-model:checked="courseSyncFlag">
<span style=" <span
style="
width: 100%; width: 100%;
color: rgba(109, 117, 132, 1); color: rgba(109, 117, 132, 1);
font-size: 14px; font-size: 14px;
"> "
>
同步课程学习记录如学员在课程库中拥有课程的学习记录自动免修该课程 同步课程学习记录如学员在课程库中拥有课程的学习记录自动免修该课程
</span> </span>
</a-checkbox> </a-checkbox>
@@ -189,11 +335,13 @@
</div> </div>
<div class="in ggysxz"> <div class="in ggysxz">
<a-checkbox v-model:checked="rankFlag"> <a-checkbox v-model:checked="rankFlag">
<span style=" <span
style="
width: 100%; width: 100%;
color: rgba(109, 117, 132, 1); color: rgba(109, 117, 132, 1);
font-size: 14px; font-size: 14px;
"> "
>
是否显示积分 是否显示积分
</span> </span>
</a-checkbox> </a-checkbox>
@@ -204,8 +352,14 @@
<div class="inname" style="margin-top: 13px">项目说明</div> <div class="inname" style="margin-top: 13px">项目说明</div>
</div> </div>
<div class="in"> <div class="in">
<a-textarea v-model:value="projectInfo.remark" style="height: 80px" placeholder="请输入说明" show-count <a-textarea
:maxlength="200" :disabled="viewDetail ? true : false"/> v-model:value="projectInfo.remark"
style="height: 80px"
placeholder="请输入说明"
show-count
:maxlength="200"
:disabled="viewDetail ? true : false"
/>
</div> </div>
</div> </div>
@@ -222,13 +376,21 @@
<div class="name"> <div class="name">
<div class="inname" style="width: 50px">模版</div> <div class="inname" style="width: 50px">模版</div>
<div class="in select" style="margin-left: 2px"> <div class="in select" style="margin-left: 2px">
<a-select :allowClear="true" :getPopupContainer=" <a-select
:allowClear="true"
:getPopupContainer="
(triggerNode) => triggerNode.parentNode || document.body (triggerNode) => triggerNode.parentNode || document.body
" placeholder="请选择模版" style="width: 100%" :options="classifyList5" @change="classificationChange5" "
@popupScroll="templateScroll" :fieldNames="{ placeholder="请选择模版"
style="width: 100%"
:options="classifyList5"
@change="classificationChange5"
@popupScroll="templateScroll"
:fieldNames="{
label: 'name', label: 'name',
value: 'id', value: 'id',
}"> }"
>
</a-select> </a-select>
</div> </div>
</div> </div>
@@ -237,13 +399,26 @@
<div class="footer"> <div class="footer">
<div class="btn"> <div class="btn">
<a-button @click="backPage" class="btn1">取消</a-button> <a-button @click="backPage" class="btn1">取消</a-button>
<a-button :loading="loading" v-on:click="createProject" type="primary" class="btn1" style="margin-left: 20px">确定 <a-button
:loading="loading"
v-on:click="createProject"
type="primary"
class="btn1"
style="margin-left: 20px"
>确定
</a-button> </a-button>
</div> </div>
</div> </div>
<!-- 更多背景图 v-model:visible="learnBgMore" --> <!-- 更多背景图 v-model:visible="learnBgMore" -->
<a-modal :closable="sh" centered="true" v-model:visible="learnBgMore" :footer="null" :width="650" <a-modal
wrapClassName="learnBgMoreModal" :z-index="9999"> :closable="sh"
centered="true"
v-model:visible="learnBgMore"
:footer="null"
:width="650"
wrapClassName="learnBgMoreModal"
:z-index="9999"
>
<div class="main"> <div class="main">
<div class="top"> <div class="top">
<div class="topc">封面图</div> <div class="topc">封面图</div>
@@ -255,39 +430,60 @@
:key="item.code" :key="item.code"
class="learnBgItem" class="learnBgItem"
> --> > -->
<div @click="chooseImg2(item)" v-for="item in projectPic" :key="item.code" class="learnBgItem" :style="{ <div
@click="chooseImg2(item)"
v-for="item in projectPic"
:key="item.code"
class="learnBgItem"
:style="{
border: border:
projectInfo.picUrl === item.value projectInfo.picUrl === item.value
? '3px solid rgba(78, 166, 255, 1)' ? '3px solid rgba(78, 166, 255, 1)'
: '1px solid #ccc', : '1px solid #ccc',
'background-image': 'url(' + item.value.split(',')[0] + ')', 'background-image': 'url(' + item.value.split(',')[0] + ')',
}"> }"
>
<!-- <img class="im" :src="item.source" /> --> <!-- <img class="im" :src="item.source" /> -->
</div> </div>
</div> </div>
<div class="btn"> <div class="btn">
<button class="samtn btn2" @click="closeLearnBgMore">取消</button> <button class="samtn btn2" @click="closeLearnBgMore">取消</button>
<a-button class="samtn btn2" @click="closeLearnBgMore" :loading="projectInfo.validated===1">确定</a-button> <a-button
class="samtn btn2"
@click="closeLearnBgMore"
:loading="projectInfo.validated === 1"
>确定</a-button
>
</div> </div>
</div> </div>
</a-modal> </a-modal>
</div> </div>
</template> </template>
<script> <script>
import {onMounted, reactive, toRefs, watch} from "vue"; import "@wangeditor/editor/dist/css/style.css"; // 引入 css
import {message} from "ant-design-vue"; import {
import {useRoute, useRouter} from "vue-router"; onBeforeUnmount,
onMounted,
reactive,
ref,
shallowRef,
toRefs,
watch,
} from "vue";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { message } from "ant-design-vue";
import { useRoute, useRouter } from "vue-router";
import * as api from "../../api/index"; import * as api from "../../api/index";
import {useStore} from "vuex"; import { useStore } from "vuex";
import TrainClass from "@/components/project/TrainClass"; import TrainClass from "@/components/project/TrainClass";
import OrgClass from "@/components/project/OrgClass"; import OrgClass from "@/components/project/OrgClass";
import ProjectManager from "@/components/project/ProjectManagerNew"; import ProjectManager from "@/components/project/ProjectManagerNew";
import NameInput from "@/components/project/NameInput"; import NameInput from "@/components/project/NameInput";
import ProjectLevel from "@/components/project/ProjectLevel"; import ProjectLevel from "@/components/project/ProjectLevel";
import * as api2 from "../../api/indexAudit"; import * as api2 from "../../api/indexAudit";
import {validateName} from "@/api/index1"; import { validateName } from "@/api/index1";
import dayjs from "dayjs"; import dayjs from "dayjs";
import {scrollLoad} from "@/api/method"; import { scrollLoad } from "@/api/method";
import ProjectNumber from "@/components/project/ProjectNumber"; import ProjectNumber from "@/components/project/ProjectNumber";
export default { export default {
name: "projectAdd", name: "projectAdd",
@@ -298,7 +494,9 @@ export default {
TrainClass, TrainClass,
NameInput, NameInput,
OrgClass, OrgClass,
ProjectNumber ProjectNumber,
Editor,
Toolbar,
}, },
setup() { setup() {
const store = useStore(); const store = useStore();
@@ -312,7 +510,7 @@ export default {
pageSize: 10, //每页10条数据 pageSize: 10, //每页10条数据
totalPages: 0, //总页数 totalPages: 0, //总页数
viewDetail: null, viewDetail: null,
projectInfo: { id: "", validated: 0 ,boeFlag :0}, projectInfo: { id: "", validated: 0, boeFlag: 0 },
projectPic: [], projectPic: [],
memberParam: { memberParam: {
pageNo: 1, pageNo: 1,
@@ -321,7 +519,7 @@ export default {
}, },
classifyList5: [], classifyList5: [],
courseSyncFlag: true, courseSyncFlag: true,
rankFlag:false, rankFlag: false,
auditDescription: "", auditDescription: "",
ptojectType: "", ptojectType: "",
changeCondition: false, changeCondition: false,
@@ -329,6 +527,7 @@ export default {
timeRange: [], timeRange: [],
learnBgMore: false, learnBgMore: false,
pathBgId: null, pathBgId: null,
isNewEmployee: false,
}); });
// 封面图选择 // 封面图选择
@@ -336,6 +535,36 @@ export default {
console.log(value); console.log(value);
state.projectInfo.picUrl = value; state.projectInfo.picUrl = value;
}; };
// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef(null);
// 内容 HTML
const valueHtml = ref("");
//富文本编辑器:配置工具栏,排除不需要的功能 add by zhengsongbo
const toolbarConfig = {
excludeKeys: [
"group-image", // 图片相关按钮
"insertVideo", // 视频相关按钮
"insertTable", // 表格
"insertLink", // 链接
"codeBlock", // 代码块
],
};
//富文本编辑器:编辑器配置 add by zhengsongbo
const editorConfig = { placeholder: "请输入转正攻略配置" };
// 编辑器创建完成回调
const handleCreated = (editor) => {
editorRef.value = editor; // 记录 editor 实例,重要!
loadRemoteContent();
};
const loadRemoteContent = async () => {
await getProjectInfo();
};
onMounted(() => { onMounted(() => {
state.projectPic = store.state.project_pic.map((e) => ({ state.projectPic = store.state.project_pic.map((e) => ({
code: e.id, code: e.id,
@@ -343,23 +572,96 @@ export default {
label: e.name, label: e.name,
})); }));
state.viewDetail = routers.query.viewDetail; state.viewDetail = routers.query.viewDetail;
if (!editorRef.value) loadRemoteContent();
getProjectInfo(); getProjectInfo();
getTemplate(); getTemplate();
state.ptojectType = routers.query.ptojectType; state.ptojectType = routers.query.ptojectType;
console.log("获取封面图", state.projectPic); console.log("获取封面图", state.projectPic);
}); });
// 设置编辑器内容
const setEditorContent = (content) => {
if (editorRef.value) {
editorRef.value.setHtml(content);
}
};
// 获取编辑器内容
const getEditorContent = () => {
if (editorRef.value) {
return editorRef.value.getHtml();
}
};
// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor == null) return;
editor.destroy();
});
// 计算纯文本字数
const calculateWordCount = (html) => {
return html.replace(/<[^>]*>/g, "").length;
};
const handleOnChange = (editor) => {
const html = editor.getHtml();
const contentLength = calculateWordCount(html);
const maxLength = 500; // 最大字数限制
if (contentLength > maxLength) {
// 截断超出的内容
const truncatedHtml = truncateHtmlContent(editor, maxLength);
editor.setHtml(truncatedHtml);
contentLength.value = maxLength;
}
// 更新字数显示(可选)
document.getElementById(
"word-count"
).textContent = `${contentLength}/${maxLength}`;
state.projectInfo.learningGuideConfig = getEditorContent();
console.log(getEditorContent());
};
function truncateHtmlContent(editor, maxLength) {
const html = editor.getHtml();
const tempDiv = document.createElement("div");
tempDiv.innerHTML = html;
let textContent = "";
let charCount = 0;
// 递归遍历DOM节点
const walkNodes = (node) => {
if (charCount >= maxLength) return;
if (node.nodeType === Node.TEXT_NODE) {
const remaining = maxLength - charCount;
const fragment = node.textContent.substring(0, remaining);
textContent += fragment;
charCount += fragment.length;
} else if (node.nodeType === Node.ELEMENT_NODE) {
const tagName = node.tagName.toLowerCase();
textContent += `<${tagName}>`;
Array.from(node.childNodes).forEach(walkNodes);
textContent += `</${tagName}>`;
}
};
walkNodes(tempDiv);
return textContent;
}
watch(routers.query, () => { watch(routers.query, () => {
state.projectInfo.name = routers.query.name; state.projectInfo.name = routers.query.name;
state.projectInfo.id = routers.query.id; state.projectInfo.id = routers.query.id;
state.projectInfo.parentName = routers.query.parentName; state.projectInfo.parentName = routers.query.parentName;
state.projectInfo.parentId = routers.query.parentId; state.projectInfo.parentId = routers.query.parentId;
}); });
watch(()=>state.projectInfo.boeFlag,(val)=>{ watch(
if(!val){ () => state.projectInfo.boeFlag,
state.projectInfo.numValue = '' (val) => {
if (!val) {
state.projectInfo.numValue = "";
} }
}) }
);
function getProjectInfo() { function getProjectInfo() {
state.projectInfo.name = routers.query.name; state.projectInfo.name = routers.query.name;
@@ -372,6 +674,14 @@ export default {
projectId: state.projectInfo.id || state.projectInfo.parentId, projectId: state.projectInfo.id || state.projectInfo.parentId,
}) })
.then((res) => { .then((res) => {
if (res.data.data.projectInfo.szxygProjectFlag == "1") {
state.isNewEmployee = true;
if (editorRef.value) {
return editorRef.value.setHtml(
res.data.data.projectInfo.learningGuideConfig
);
}
}
state.projectInfo = { state.projectInfo = {
...res.data.data.projectInfo, ...res.data.data.projectInfo,
...state.projectInfo, ...state.projectInfo,
@@ -417,9 +727,9 @@ export default {
}; };
const classificationChange5 = (key, option) => { const classificationChange5 = (key, option) => {
if(key==undefined || option==undefined){ if (key == undefined || option == undefined) {
// 标识清空选择的模版 // 标识清空选择的模版
state.timeRange = [] state.timeRange = [];
state.projectInfo = { state.projectInfo = {
name: "", name: "",
picUrl: "", picUrl: "",
@@ -429,9 +739,9 @@ export default {
managerId: "", managerId: "",
sourceBelongId: null, sourceBelongId: null,
level: "", level: "",
systemId: null systemId: null,
} };
return return;
} }
state.projectInfo = option; state.projectInfo = option;
state.projectInfo.projectTemplateId = option.id; state.projectInfo.projectTemplateId = option.id;
@@ -477,6 +787,8 @@ export default {
level: "请填写项目级别", level: "请填写项目级别",
systemId: "请填写项目培训体系", systemId: "请填写项目培训体系",
boeFlag: "请选择关联BOEU立项审批单", boeFlag: "请选择关联BOEU立项审批单",
electiveCourseCount: "请输入选修课程数量",
// requiredCourseCount: "请输入必修课程数量",
}; };
function timeChange(e) { function timeChange(e) {
@@ -514,10 +826,11 @@ export default {
name: state.projectInfo.name, name: state.projectInfo.name,
type: 1, type: 1,
id: state.projectInfo.id, id: state.projectInfo.id,
}).then((res) => { })
.then((res) => {
return res.data.data == 1; return res.data.data == 1;
}).catch((err) => { })
}); .catch((err) => {});
if (offName) { if (offName) {
message.destroy(); message.destroy();
state.loading = false; state.loading = false;
@@ -526,7 +839,9 @@ export default {
state.projectInfo.type = 3; state.projectInfo.type = 3;
state.projectInfo.courseSyncFlag = state.courseSyncFlag ? 1 : 0; state.projectInfo.courseSyncFlag = state.courseSyncFlag ? 1 : 0;
state.projectInfo.rankFlag = state.rankFlag ? 1 : 0; state.projectInfo.rankFlag = state.rankFlag ? 1 : 0;
api.createProject(state.projectInfo).then((res) => { api
.createProject(state.projectInfo)
.then((res) => {
state.loading = false; state.loading = false;
message.destroy(); message.destroy();
message.success(state.projectInfo.id ? "编辑成功" : "创建成功"); message.success(state.projectInfo.id ? "编辑成功" : "创建成功");
@@ -534,10 +849,11 @@ export default {
path: "/taskpage", path: "/taskpage",
query: { projectId: res.data.data }, query: { projectId: res.data.data },
}); });
}).catch((err) => { })
.catch((err) => {
state.loading = false; state.loading = false;
message.destroy(); message.destroy();
message.error('创建项目失败,请重新创建'); message.error("创建项目失败,请重新创建");
}); });
}; };
@@ -596,6 +912,15 @@ export default {
showLearnBgMore, showLearnBgMore,
closeLearnBgMore, closeLearnBgMore,
chooseImg2, chooseImg2,
editorRef,
valueHtml,
mode: "simple", //简洁模式
toolbarConfig,
editorConfig,
handleCreated,
handleOnChange,
setEditorContent,
getEditorContent,
}; };
}, },
}; };
@@ -804,17 +1129,17 @@ export default {
} }
} }
.num{ .num {
display: flex; display: flex;
justify-content: left; justify-content: left;
align-items: center; align-items: center;
.num_text{ .num_text {
color: #6f6f6f; color: #6f6f6f;
font-size: 14px; font-size: 14px;
min-width: 70px; min-width: 70px;
// margin-right: 7px; // margin-right: 7px;
} }
.num_input{ .num_input {
width: 100%; width: 100%;
} }
} }
@@ -862,6 +1187,22 @@ export default {
} }
} }
} }
.name3 {
display: flex;
align-items: flex-start;
.description {
margin-top: 14px;
margin-left: 11px;
}
.ant-input-textarea {
.ant-input {
height: 250px;
}
}
}
} }
.template { .template {
@@ -1061,7 +1402,6 @@ export default {
} }
.treeDropdown { .treeDropdown {
// width: 240px !important; // width: 240px !important;
// border-radius: 5px; // border-radius: 5px;
// min-height: 600px !important; // min-height: 600px !important;

View File

@@ -390,7 +390,10 @@
type="dashboard" type="dashboard"
gapDegree="0" gapDegree="0"
:percent=" :percent="
fixDoublePer( stageOverviewList[choosedStageIndex]?.completeCourseRatio || 0) fixDoublePer(
stageOverviewList[choosedStageIndex]
?.completeCourseRatio || 0
)
" "
:width="140" :width="140"
/> />
@@ -401,7 +404,10 @@
type="dashboard" type="dashboard"
gapDegree="0" gapDegree="0"
:percent=" :percent="
fixDoublePer(stageOverviewList[choosedStageIndex]?.completeExamRatio || 0) fixDoublePer(
stageOverviewList[choosedStageIndex]?.completeExamRatio ||
0
)
" "
:width="140" :width="140"
/> />
@@ -411,39 +417,67 @@
<a-progress <a-progress
type="dashboard" type="dashboard"
gapDegree="0" gapDegree="0"
:percent="fixDoublePer(stageOverviewList[choosedStageIndex]?.completeRatio || 0)" :percent="
fixDoublePer(
stageOverviewList[choosedStageIndex]?.completeRatio || 0
)
"
:width="140" :width="140"
/> />
<div class="protext">作业完成率</div> <div class="protext">作业完成率</div>
</div> </div>
<div class="proright"> <div class="proright">
<div class="pronub" style="margin-left: 142px"> <div class="pronub" style="margin-left: 142px">
{{ stageOverviewList[choosedStageIndex]?.completeTaskCnt || 0}} {{
stageOverviewList[choosedStageIndex]?.completeTaskCnt || 0
}}
</div> </div>
<div class="proright1"> <div class="proright1">
<span class="textpro">阶段任务总数</span> <span class="textpro">阶段任务总数</span>
<a-progress <a-progress
:percent="fixDoublePer(stageOverviewList[choosedStageIndex]?.completeTaskCnt/(stageOverviewList[choosedStageIndex]?.totalTaskCnt || 0))" :percent="
fixDoublePer(
stageOverviewList[choosedStageIndex]?.completeTaskCnt /
(stageOverviewList[choosedStageIndex]?.totalTaskCnt ||
0)
)
"
style="width: 369px" style="width: 369px"
/> />
</div> </div>
<div class="pronub" style="margin-left: 142px"> <div class="pronub" style="margin-left: 142px">
{{ stageOverviewList[choosedStageIndex]?.completeReqCnt || 0}} {{
stageOverviewList[choosedStageIndex]?.completeReqCnt || 0
}}
</div> </div>
<div class="proright1"> <div class="proright1">
<span class="textpro">必修任务</span> <span class="textpro">必修任务</span>
<a-progress <a-progress
:percent="fixDoublePer(stageOverviewList[choosedStageIndex]?.completeReqCnt/(stageOverviewList[choosedStageIndex]?.totalReqCnt || 0))" :percent="
fixDoublePer(
stageOverviewList[choosedStageIndex]?.completeReqCnt /
(stageOverviewList[choosedStageIndex]?.totalReqCnt ||
0)
)
"
style="width: 369px" style="width: 369px"
/> />
</div> </div>
<div class="pronub" style="margin-left: 142px"> <div class="pronub" style="margin-left: 142px">
{{ stageOverviewList[choosedStageIndex]?.completeOptCnt || 0}} {{
stageOverviewList[choosedStageIndex]?.completeOptCnt || 0
}}
</div> </div>
<div class="proright1"> <div class="proright1">
<span class="textpro">选修任务</span> <span class="textpro">选修任务</span>
<a-progress <a-progress
:percent="fixDoublePer(stageOverviewList[choosedStageIndex]?.completeOptCnt/(stageOverviewList[choosedStageIndex]?.totalOptCnt || 0))" :percent="
fixDoublePer(
stageOverviewList[choosedStageIndex]?.completeOptCnt /
(stageOverviewList[choosedStageIndex]?.totalOptCnt ||
0)
)
"
style="width: 369px" style="width: 369px"
/> />
</div> </div>
@@ -585,10 +619,27 @@
<div class="time"> <div class="time">
<div class="timetext">开始时间</div> <div class="timetext">开始时间</div>
<div class="timetext"> <div class="timetext">
{{ item.type==2 ? item.createTime !== null ? item.createTime : "-" : item.startTime !== null ? item.startTime : "-" }} {{
item.type == 2
? item.createTime !== null
? item.createTime
: "-"
: item.startTime !== null
? item.startTime
: "-"
}}
</div> </div>
</div> </div>
<div class="progress" v-if="item.averageScore" style="display: flex;flex-grow: 0;margin: 0;min-width: 66px;"> <div
class="progress"
v-if="item.averageScore"
style="
display: flex;
flex-grow: 0;
margin: 0;
min-width: 66px;
"
>
<!-- <div class="progresstext"> <!-- <div class="progresstext">
{{ item.finishStuCnt || 0 }}/{{ {{ item.finishStuCnt || 0 }}/{{
item.totalStuCnt || 0 item.totalStuCnt || 0
@@ -613,24 +664,45 @@
}}%</span }}%</span
> >
</div> --> </div> -->
<div> <div>{{ item.averageScore }}分</div>
{{ item.averageScore}}分
</div>
<div class="img_daoc" @click="exportScore(item)"></div> <div class="img_daoc" @click="exportScore(item)"></div>
</div> </div>
<div class="progress" v-if="!item.averageScore" style="display: flex;flex-grow: 0;margin: 0;min-width: 60px;"> <div
class="progress"
</div> v-if="!item.averageScore"
style="
display: flex;
flex-grow: 0;
margin: 0;
min-width: 60px;
"
></div>
<div class="operations"> <div class="operations">
<div class="operations_dropdown"> <div class="operations_dropdown">
<a-dropdown :getPopupContainer='triggerNode=> triggerNode.parentNode' v-if="item.assessmentIds.filter(id => id !== null).length>1&&item.type == 2" :trigger="['click']" v-model:visible="visibleEwmpg[item.id]"> <a-dropdown
<a class="ant-dropdown-link" @click="qrcodeAssement(item)"> :getPopupContainer="
(triggerNode) => triggerNode.parentNode
"
v-if="
item.assessmentIds.filter((id) => id !== null)
.length > 1 && item.type == 2
"
:trigger="['click']"
v-model:visible="visibleEwmpg[item.id]"
>
<a
class="ant-dropdown-link"
@click="qrcodeAssement(item)"
>
评估二维码 评估二维码
<DownOutlined /> <DownOutlined />
</a> </a>
<template #overlay> <template #overlay>
<a-menu @click="handleMenuClickpg"> <a-menu @click="handleMenuClickpg">
<template v-for="(item, index) in qrCodeItemspg" :key="index"> <template
v-for="(item, index) in qrCodeItemspg"
:key="index"
>
<a-menu-item> <a-menu-item>
<div> <div>
<p>{{ item.name }}</p> <p>{{ item.name }}</p>
@@ -640,23 +712,47 @@
</a-menu> </a-menu>
</template> </template>
</a-dropdown> </a-dropdown>
<div v-if="item.assessmentIds.filter(id => id !== null).length==1&&item.type == 2"> <div
<a class="ant-dropdown-link" @click="qrcodeAssement(item)"> v-if="
item.assessmentIds.filter((id) => id !== null)
.length == 1 && item.type == 2
"
>
<a
class="ant-dropdown-link"
@click="qrcodeAssement(item)"
>
评估二维码 评估二维码
<DownOutlined /> <DownOutlined />
</a> </a>
</div> </div>
</div> </div>
<div class="operations_dropdown" v-if="item.assessmentIds.length!=1"> <div
<a-dropdown :getPopupContainer='(triggerNode) => triggerNode.parentNode' v-if="item.type == 2" :trigger="['click']" v-model:visible="visibleEwm[item.id]"> class="operations_dropdown"
<a class="ant-dropdown-link" @click="qrcodeVisible(item)"> v-if="item.assessmentIds.length != 1"
>
<a-dropdown
:getPopupContainer="
(triggerNode) => triggerNode.parentNode
"
v-if="item.type == 2"
:trigger="['click']"
v-model:visible="visibleEwm[item.id]"
>
<a
class="ant-dropdown-link"
@click="qrcodeVisible(item)"
>
签到二维码 签到二维码
<DownOutlined /> <DownOutlined />
</a> </a>
<template #overlay v-if="qrCodeItems.length>0"> <template #overlay v-if="qrCodeItems.length > 0">
<a-menu @click="handleMenuClick"> <a-menu @click="handleMenuClick">
<template v-for="(item, index) in qrCodeItems" :key="index"> <template
v-for="(item, index) in qrCodeItems"
:key="index"
>
<a-menu-item> <a-menu-item>
<div> <div>
<p>{{ item.name }}</p> <p>{{ item.name }}</p>
@@ -667,8 +763,16 @@
</template> </template>
</a-dropdown> </a-dropdown>
</div> </div>
<div class="operations_dropdown" v-if="item.type == 2&&item.assessmentIds.length==1"> <div
<a class="ant-dropdown-link" @click="qrcodeVisible(item)"> class="operations_dropdown"
v-if="
item.type == 2 && item.assessmentIds.length == 1
"
>
<a
class="ant-dropdown-link"
@click="qrcodeVisible(item)"
>
签到二维码 签到二维码
<DownOutlined /> <DownOutlined />
</a> </a>
@@ -676,7 +780,7 @@
<div <div
class="operation" class="operation"
style="cursor: pointer" style="cursor: pointer"
@click="openCourse(item,key,index)" @click="openCourse(item, key, index)"
v-if="item.type == 2" v-if="item.type == 2"
> >
开课 开课
@@ -828,11 +932,26 @@
:visable="tabFlag" :visable="tabFlag"
:groupList="groupList" :groupList="groupList"
:remarksTrue="remarksTrue" :remarksTrue="remarksTrue"
:isNewEmployee="isNewEmployee"
> >
<template #extension="{ data: { record } }"> <template #extension="{ data: { record } }">
<a-button @click="showStudent(record)" type="link" <a-button @click="showStudent(record)" type="link"
>查看 >查看
</a-button> </a-button>
<!-- 查看报名记录 -->
<a-button
v-if="isNewEmployee"
@click="showSignUpRecord(record)"
type="link"
>查看报名记录</a-button
>
<!-- 成绩单下载 -->
<a-button
v-if="isNewEmployee"
@click="downloadReport(record)"
type="link"
>成绩单下载
</a-button>
<a-button <a-button
@click="settingTopFlag(record)" @click="settingTopFlag(record)"
v-if="checkPer(permissions, createId)" v-if="checkPer(permissions, createId)"
@@ -846,9 +965,7 @@
@click="showChangeGroupModal(record)" @click="showChangeGroupModal(record)"
>换组 >换组
</a-button> </a-button>
<a-button <a-button type="link" @click="modifyRemarks(record)"
type="link"
@click="modifyRemarks(record)"
>修改备注 >修改备注
</a-button> </a-button>
</template> </template>
@@ -972,7 +1089,15 @@
</div> </div>
</div> </div>
<!-- 小组列表分页 --> <!-- 小组列表分页 -->
<div style="width: 100%;display:flex;justify-content:center;align-items:center;margin-top: 12px;"> <div
style="
width: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-top: 12px;
"
>
<a-pagination <a-pagination
:showSizeChanger="false" :showSizeChanger="false"
showQuickJumper="true" showQuickJumper="true"
@@ -2352,7 +2477,11 @@
/> />
<!-- 换组弹窗 --> <!-- 换组弹窗 -->
<!-- 面授课开课弹框 --> <!-- 面授课开课弹框 -->
<AddOpenCourse @call-parent-method="getTaskListAll" ref="coursePlanRef" :type="1"/> <AddOpenCourse
@call-parent-method="getTaskListAll"
ref="coursePlanRef"
:type="1"
/>
<!-- 修改备注弹窗 --> <!-- 修改备注弹窗 -->
<a-modal <a-modal
v-model:visible="showRemarks" v-model:visible="showRemarks"
@@ -2361,7 +2490,10 @@
style="margin-top: 400px" style="margin-top: 400px"
@cancel="of_remarks" @cancel="of_remarks"
> >
<div class="selectonlineface" :style="{ display: showRemarks ? 'block' : 'none' }"> <div
class="selectonlineface"
:style="{ display: showRemarks ? 'block' : 'none' }"
>
<div class="bg_headers"></div> <div class="bg_headers"></div>
<div class="bg_main"> <div class="bg_main">
<div class="bg_main_header"> <div class="bg_main_header">
@@ -2369,7 +2501,7 @@
<div class="bg_main_header_close" @click="of_remarks"></div> <div class="bg_main_header_close" @click="of_remarks"></div>
</div> </div>
<div class="bg_body"> <div class="bg_body">
<div class="bg_body_bt" style="align-items: flex-start;"> <div class="bg_body_bt" style="align-items: flex-start">
<!-- <div class="bg_body_bttext" style="margin-top: 5px;">修改备注</div> --> <!-- <div class="bg_body_bttext" style="margin-top: 5px;">修改备注</div> -->
<div class="bg_body_input"> <div class="bg_body_input">
<a-input v-model:value="remarks" placeholder="请输入" /> <a-input v-model:value="remarks" placeholder="请输入" />
@@ -2379,10 +2511,7 @@
<div class="btn btn6" @click="of_remarks"> <div class="btn btn6" @click="of_remarks">
<div class="btnText">取消</div> <div class="btnText">取消</div>
</div> </div>
<a-button <a-button class="btn btn6" @click="RemarksUpdata">
class="btn btn6"
@click="RemarksUpdata"
>
确定 确定
</a-button> </a-button>
</div> </div>
@@ -2390,6 +2519,38 @@
</div> </div>
</div> </div>
</a-modal> </a-modal>
<!-- 查看报名记录 -->
<a-modal
v-model:visible="showSignUpRecordModal"
title="报名记录"
:footer="null"
width="700px"
>
<div style="padding: 20px">
<a-table
:columns="signupRecordColumns"
:data-source="signupRecordList"
:pagination="true"
:loading="signupRecordLoading"
row-key="id"
bordered
>
<template #status="{ text, record }">
<span
:style="{
color:
record.enrollStatusCode === 3
? '#52c41a'
: record.enrollStatusCode === 2
? '#1890ff'
: '#ff4d4f',
}"
>{{ text }}</span
>
</template>
</a-table>
</div>
</a-modal>
</div> </div>
</template> </template>
<script lang="jsx"> <script lang="jsx">
@@ -2436,7 +2597,7 @@ import { getTask } from "../../api/indexTaskadd";
import { editProjDoc } from "../../api/indexTaskadd"; import { editProjDoc } from "../../api/indexTaskadd";
import {getCookieForName, toDate} from "../../api/method"; import {getCookieForName, toDate} from "../../api/method";
import projSet from "../../components/Modals/projSet"; import projSet from "../../components/Modals/projSet";
import { overview } from "../../api/indexProjStu"; import { overview,downloadTranscript } from "../../api/indexProjStu";
import TwoDimensionalCode from "../../components/TwoDimensionalCode.vue"; import TwoDimensionalCode from "../../components/TwoDimensionalCode.vue";
import ProjectScore from "../../components/drawers/ProjectScore"; import ProjectScore from "../../components/drawers/ProjectScore";
import { useStore } from "vuex"; import { useStore } from "vuex";
@@ -2450,7 +2611,7 @@ import ChangeGroupModal from "@/components/student/ChangeGroupModal.vue";
import { checkPer,fixDoublePer } from "@/utils/utils"; import { checkPer,fixDoublePer } from "@/utils/utils";
import ImpoterGroupLeader from "@/components/drawers/project/ImpoterGroupLeader.vue"; import ImpoterGroupLeader from "@/components/drawers/project/ImpoterGroupLeader.vue";
import qrCode from "@/utils/qrCode"; import qrCode from "@/utils/qrCode";
import {request} from "@/api/request"; import {request, boeRequest} from "@/api/request";
import { PROJECT_RELEASE} from "@/api/apis"; import { PROJECT_RELEASE} from "@/api/apis";
export default { export default {
name: "taskPage", name: "taskPage",
@@ -2498,6 +2659,70 @@ export default {
coursePlanRef.value.openDrawer(res.data.data.stageList[index].taskDraftDtoList.find(fin=>fin.projectTaskId === item.id)); coursePlanRef.value.openDrawer(res.data.data.stageList[index].taskDraftDtoList.find(fin=>fin.projectTaskId === item.id));
}) })
} }
// 报名记录弹窗与列配置
const showSignUpRecordModal = ref(false);
const signupRecordLoading = ref(false);
const signupRecordColumns = [
{ title: "姓名", dataIndex: "name", align: "center" },
{ title: "工号", dataIndex: "workNo", align: "center" },
{
title: "状态",
dataIndex: "status",
align: "center",
slots: { customRender: "status" },
},
{ title: "报名时间", dataIndex: "applierAtStr", align: "center" },
{ title: "描述", dataIndex: "desc", align: "left" },
];
const signupRecordList = ref([]);
// 状态码映射
const getStatusText = (code) => {
const statusMap = {
1: "报名失败",
2: "审核中",
3: "审核通过",
4: "审核不通过"
};
return statusMap[code] || "未知";
};
const showSignUpRecord = async (record) => {
if (!state.projectId || !record.studentId) {
message.warning("缺少必要参数");
return;
}
showSignUpRecordModal.value = true;
signupRecordLoading.value = true;
signupRecordList.value = [];
try {
const params = {
pid: state.projectId,
stuId: record.studentId
};
const res = await api.getElnBoeEnrollListByStudent(params);
if (res.data.code === 200 && res.data.success && res.data.data) {
// 将接口返回的数据映射到表格列
signupRecordList.value = res.data.data.map((item, index) => ({
id: index + 1,
name: record.studentName ||"",
workNo: record.studentUserNo || "",
status: getStatusText(item.enrollStatusCode),
enrollStatusCode: item.enrollStatusCode,
applierAtStr: item.applierAtStr || "",
desc: item.enrollMark || ""
}));
} else {
message.error(res.msg || "获取报名记录失败");
signupRecordList.value = [];
}
} catch (error) {
console.error("获取报名记录失败:", error);
message.error("获取报名记录失败,请稍后重试");
signupRecordList.value = [];
} finally {
signupRecordLoading.value = false;
}
};
const qrCodeItems = ref([]); const qrCodeItems = ref([]);
const visibleEwm = ref({}); const visibleEwm = ref({});
const qrcodeVisible = async (item)=>{ const qrcodeVisible = async (item)=>{
@@ -2593,6 +2818,7 @@ export default {
const headers = { token: getCookieForName("token") }; const headers = { token: getCookieForName("token") };
const state = reactive({ const state = reactive({
isNewEmployee: false,
createId: "", createId: "",
permissions: "", permissions: "",
screenHeight: document.body.clientHeight, screenHeight: document.body.clientHeight,
@@ -4243,6 +4469,9 @@ export default {
getTask({ getTask({
projectId: state.projectId, projectId: state.projectId,
}).then((res) => { }).then((res) => {
if(res.data.data.projectInfo.szxygProjectFlag == "1"){
state.isNewEmployee = true;
}
if ( if (
res.data.data.projectAuditLogDtoList && res.data.data.projectAuditLogDtoList &&
res.data.data.projectAuditLogDtoList.length res.data.data.projectAuditLogDtoList.length
@@ -5113,6 +5342,25 @@ export default {
state.Seevisible = true; state.Seevisible = true;
state.checkStuId = record.studentId; state.checkStuId = record.studentId;
} }
function downloadReport(record) {
// window.open(
// window.location.protocol +
// process.env.VUE_APP_BASE_API +'/stu/project/socialRecruit/report/download?projectId='+state.projectId+'&studentId='+record.studentId
// );
api.downloadTranscript({projectId:state.projectId,studentId:record.studentId}).then(async (res) => {
console.log(res,"@@@");
// const binaryData = [];
// binaryData.push(res);
// console.log(binaryData);
// var pdfUrl = window.URL.createObjectURL(new Blob(binaryData, { type: 'application/pdf' }));
const pdfBlob = new Blob([res.data], { type: 'application/pdf' });
// 2. 生成前端临时预览 URL
const pdfUrl = URL.createObjectURL(pdfBlob);
window.open(pdfUrl);
})
}
// 共享文档文件下载 // 共享文档文件下载
const downloadFile = (url) => { const downloadFile = (url) => {
console.log(url); console.log(url);
@@ -5203,6 +5451,7 @@ export default {
headers, headers,
stageChange, stageChange,
showStudent, showStudent,
downloadReport,
settingTopFlag, settingTopFlag,
totask, totask,
tostudent, tostudent,
@@ -5339,6 +5588,13 @@ export default {
coursePlanRef, coursePlanRef,
openCourse, openCourse,
exportScore, exportScore,
// 报名记录相关
showSignUpRecordModal,
signupRecordColumns,
signupRecordList,
showSignUpRecord,
signupRecordLoading,
}; };
}, },
}; };
@@ -6177,7 +6433,7 @@ export default {
} }
} }
} }
.selectonlineface{ .selectonlineface {
z-index: 999; z-index: 999;
width: 679px; width: 679px;
background: #ffffff; background: #ffffff;
@@ -6234,7 +6490,7 @@ export default {
.bg_body_input { .bg_body_input {
flex: 1; flex: 1;
position: relative; position: relative;
.ant-upload-picture-card-wrapper{ .ant-upload-picture-card-wrapper {
width: 200px; width: 200px;
margin-right: 18px; margin-right: 18px;
} }
@@ -6271,19 +6527,19 @@ export default {
} }
} }
} }
.headers{ .headers {
margin-left: 38px; margin-left: 38px;
margin-right: 38px; margin-right: 38px;
margin-top: 30px; margin-top: 30px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
flex-wrap: wrap; flex-wrap: wrap;
.btn{ .btn {
display: flex; display: flex;
} }
} }
} }
} }
.taskpage { .taskpage {
width: 100%; width: 100%;
display: flex; display: flex;
@@ -6972,7 +7228,7 @@ export default {
display: flex; display: flex;
width: 420px; width: 420px;
flex-grow: 1; flex-grow: 1;
.operations_dropdown{ .operations_dropdown {
padding: 10px; padding: 10px;
text-align: center; text-align: center;
position: relative; position: relative;

View File

@@ -25,25 +25,30 @@ module.exports = defineConfig({
// changeOrigin: true, // changeOrigin: true,
// }, // },
"/growth": { "/growth": {
target: 'https:' + process.env.VUE_APP_BOE_API_URL, // target: 'https:' + process.env.VUE_APP_BOE_API_URL,
target: 'http://10.10.176.17:81/',
changeOrigin: true, changeOrigin: true,
}, },
"/manageApi": { "/manageApi": {
target: 'https:' + process.env.VUE_APP_PROXY_URL, // target: 'https:' + process.env.VUE_APP_PROXY_URL,
target: 'http://10.10.176.17:81/',
changeOrigin: true, //表示是否改变原域名 changeOrigin: true, //表示是否改变原域名
pathRewrite: { pathRewrite: {
"^/manageApi": "", "^/manageApi": "/manageApi",
}, },
}, "/userbasic": { }, "/userbasic": {
target: 'https:' + process.env.VUE_APP_BOE_API_URL, // target: 'https:' + process.env.VUE_APP_BOE_API_URL,
target: 'http://10.10.176.17:81/',
changeOrigin: true, //表示是否改变原域名 changeOrigin: true, //表示是否改变原域名
}, },
"/systemapi": { "/systemapi": {
target: 'https:' + process.env.VUE_APP_BOE_API_URL, // target: 'https:' + process.env.VUE_APP_BOE_API_URL,
target: 'http://10.10.176.17:81/',
changeOrigin: true, //表示是否改变原域名 changeOrigin: true, //表示是否改变原域名
}, },
"/api": { "/api": {
target: 'https:' + process.env.VUE_APP_BOE_API_URL, // target: 'https:' + process.env.VUE_APP_BOE_API_URL,
target: 'http://10.10.176.17:81/',
changeOrigin: true, //表示是否改变原域名 changeOrigin: true, //表示是否改变原域名
}, },
// "/reportsnake": { // "/reportsnake": {
@@ -54,7 +59,8 @@ module.exports = defineConfig({
// }, // },
// }, // },
"/reportsnake": { "/reportsnake": {
target: 'http://127.0.0.1:32004', // target: 'http://127.0.0.1:32004',
target: 'http://10.10.176.17:81/',
changeOrigin: true, //表示是否改变原域名 changeOrigin: true, //表示是否改变原域名
pathRewrite: { pathRewrite: {
"^/reportsnake": "", "^/reportsnake": "",
@@ -64,7 +70,8 @@ module.exports = defineConfig({
} }
}, },
"/report": { "/report": {
target: 'https:' + process.env.VUE_APP_BOE_API_URL, // target: 'https:' + process.env.VUE_APP_BOE_API_URL,
target: 'http://10.10.176.17:81/',
changeOrigin: true, //表示是否改变原域名 changeOrigin: true, //表示是否改变原域名
pathRewrite: { pathRewrite: {
// "^/manageApi": "", // "^/manageApi": "",
@@ -80,7 +87,8 @@ module.exports = defineConfig({
// }, // },
// }, // },
"/activityApi": { "/activityApi": {
target: 'https:' + process.env.VUE_APP_BOE_API_URL, // target: 'https:' + process.env.VUE_APP_BOE_API_URL,
target: 'http://10.10.176.17:81/',
changeOrigin: true, changeOrigin: true,
}, },