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
* @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 router from "@/router";
import {REFRESH_TOKEN_API} from "@/api/ThirdApi";
import {boeRequest} from "@/api/request";
import { REFRESH_TOKEN_API } from "@/api/ThirdApi";
import { boeRequest } from "@/api/request";
// import { getCookie } from '../api/method'
// const Qs = require("qs");
@@ -23,7 +23,7 @@ const http = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 1000 * 15,
// headers: { "Content-Type": "multipart/form-data" },
headers: {"Content-Type": "application/json"},
headers: { "Content-Type": "application/json" },
});
http.interceptors.request.use(
@@ -39,8 +39,8 @@ http.interceptors.request.use(
// // 此处测试默认配置token
// config.headers.token =
// "eyJ0eXBlIjoidG9rZW4iLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC91LmJvZS5jb20iLCJpYXQiOjE2NzAxNTMxMDMsImV4cCI6MTY3MDE2MDMwMywiR2l2ZW5OYW1lIjoiYm9ldSIsInVzZXJJZCI6IjZCMDQ5RkFGLUMzMTQtN0NDRi0wRDI4LTBEMjNGNEM0MjUzMSIsInVJZCI6Ijk2NTM0MjAyNzQ5NzYwNzE2OCIsInBlcm1pc3Npb24iOiIifQ==.c937b2d3a59cbab2136fdde55fd38f06bdff041212aab0fa6741bc4be41e28a7";
// // }
// "eyJ0eXBlIjoidG9rZW4iLCJhbGciOiJIUzI1NiJ9.eyJjb21wYW55Q29kZSI6IkMwMDEiLCJ1SWQiOiI5NjUzNDIwMjc0OTc2MDcxNjgiLCJjb21wYW55SWQiOiIxMDQxNjczOTc3Mzc5OTQ2NDk2IiwibG9naW5JZCI6IjE5MzgwNTQ2NDY2OTAxNzcwMjYiLCJpc3MiOiJodHRwOi8vdS5ib2UuY29tIiwiR2l2ZW5OYW1lIjoiYm9ldSIsImV4cCI6MTc1MDkxMDQwOTc0NiwidXNlck5hbWUiOiLmnY7njonlhrAiLCJ1c2VySWQiOiI2QjA0OUZBRi1DMzE0LTdDQ0YtMEQyOC0wRDIzRjRDNDI1MzEifQ==.7f03d1ce991253197f0e733ba554496e8de715595b169b505bed8831ede565a9";
// }
return config;
},
(err) => {
@@ -53,7 +53,7 @@ http.interceptors.response.use(
(response) => {
// console.log('response', response)
const {
data: {code, msg ,show},
data: { code, msg, show },
} = response;
if (code === 0 || code === 200) {
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)
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);
return Promise.reject(response);
},
@@ -85,4 +88,4 @@ http.interceptors.response.use(
export default http;
export function setHttpTimeout(newTimeout) {
http.defaults.timeout = newTimeout;
}
}

View File

@@ -8,7 +8,7 @@
*/
import http from "./config";
import qs from "qs";
import {getCookieForName} from "@/api/method";
import { getCookieForName } from "@/api/method";
// import { getCookie } from '../api/method'
/**
* 接口传参数方式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 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)
//添加课程学员
@@ -190,7 +190,7 @@ export const auditStudentBatch = (obj) => http.post('/admin/student/auditStudent
// //面授课批量导入成绩
export const batchImportScore = (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 } })
@@ -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 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)
@@ -229,7 +229,7 @@ export const createExamination = (obj) => http.post('/examination/createExaminat
//催促考试
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)
//导入小组
@@ -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 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

@@ -48,4 +48,4 @@ export const studentScoreList = (obj) => http.post('/admin/project/studentScoreL
//添加项目学员
export const addStudent = (obj) => http.post('/admin/project/addStudent', obj)
//获取组员名单
export const groupMemberList = (obj) => http.post('/admin/studentGroup/groupMemberList', obj)
export const groupMemberList = (obj) => http.post('/admin/studentGroup/groupMemberList', obj)

View File

@@ -1,6 +1,5 @@
<template>
<div class="TableStudent">
<a-row
type="flex"
gutter="12"
@@ -48,6 +47,19 @@
</div>
</a-form-item>
</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-button
class="cus-btn"
@@ -59,17 +71,21 @@
<img
style="margin-right: 10px"
src="../../assets/images/courseManage/search0.png"
/></template>
/></template>
搜索
</a-button>
</a-col>
<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>
<img
style="margin-right: 10px"
src="../../assets/images/courseManage/reset0.png"
/></template>
/></template>
重置
</a-button>
</a-col>
@@ -90,9 +106,9 @@
>
<a-button class="cus-btn" style="background: #4ea6ff; color: #fff">
<template #icon
><img
style="margin-right: 10px"
src="../../assets/images/courseManage/add0.png"
><img
style="margin-right: 10px"
src="../../assets/images/courseManage/add0.png"
/></template>
添加学员
</a-button>
@@ -100,62 +116,101 @@
</a-col>
<!-- 新加导入学员 批量换组 导出学习信息 -->
<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
><img
style="margin-right: 10px"
src="../../assets/images/basicinfo/in.png"
><img
style="margin-right: 10px"
src="../../assets/images/basicinfo/in.png"
/></template>
导入学员
</a-button>
</a-col>
<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-col>
<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-col>
<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-col>
<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
><img
style="margin-right: 10px"
src="../../assets/images/projectadd/delete1.png"
><img
style="margin-right: 10px"
src="../../assets/images/projectadd/delete1.png"
/></template>
批量删除
</a-button>
</a-col>
<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>
批量调整关卡
</a-button>
</a-col>
<!-- 新加批量操作导出导出作业 -->
<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">
<span style="color: #fff; margin-right: 4px;"> 批量操作 </span>
<span style="color: #fff; margin-right: 4px"> 批量操作 </span>
<div
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
class="b_sq"
:style="{ display: hideshow ? 'none' : 'block', color: '#fff', lineHeight: '12px'}"
>^
:style="{
display: hideshow ? 'none' : 'block',
color: '#fff',
lineHeight: '12px',
}"
>
^
</div>
</div>
<div
@@ -178,13 +233,17 @@
</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="btnText">导出</div>
</div>
<div
class="stmm_btn btn5"
style="margin-left: 15px;background: #4ea6ff; color: #fff;"
style="margin-left: 15px; background: #4ea6ff; color: #fff"
@click="exportHomeWorkShow"
>
<div class="btnText">导出作业</div>
@@ -192,7 +251,7 @@
<div
class="stmm_btn btn5"
style="margin-left: 15px;background: #4ea6ff; color: #fff;"
style="margin-left: 15px; background: #4ea6ff; color: #fff"
@click="handleUpdateScore"
>
<div class="btnText">刷新</div>
@@ -230,17 +289,26 @@
<slot name="extension" v-bind:data="{ record }"></slot>
<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)"
type="link"
>通过
</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)"
type="link"
>拒绝
>拒绝
</a-button>
<a-button
v-if="checkPer(permissions)"
@@ -248,7 +316,7 @@
@click="del(record.id, record)"
type="link"
danger
>删除
>删除
</a-button>
</a-space>
</template>
@@ -451,7 +519,11 @@ const props = defineProps({
remarksTrue: {
type: Boolean,
default: false,
}
},
isNewEmployee: {
type: Boolean,
default: false,
},
});
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([
{
title: "姓名",
@@ -535,9 +630,9 @@ const tablecolumns = ref([
key: "source",
width: "60px",
align: "center",
customRender: ({ record: { source } }) =>
customRender: ({ record }) =>{
// ({ 1: "快速添加", 2: "组织", 3: "受众", 4: "报名" }[source]),
({
return ({
0: "导入",
1: "手动加入",
2: "手动加入",
@@ -546,14 +641,54 @@ const tablecolumns = ref([
5: "自主报名",
6: "导入",
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,
{
title: "操作",
dataIndex: "operation",
key: "operation",
width: '120px',
width: '220px',
fixed: "right",
align: "center",
slots: { customRender: "action" },
@@ -696,6 +831,7 @@ function reset() {
tableParam.value.studentDepartId = null; //部门
tableParam.value.studentDepartName = null; //部门
tableParam.value.topFlag = null; //是否是优秀学员
tableParam.value.hrAuditResult = null; //报名及HR审批结果
getStuList();
}
@@ -1041,8 +1177,8 @@ defineExpose({ getStuList, startLoading });
width: calc(100%);
height: 40px;
background: linear-gradient(
rgba(78, 166, 255, 0.2) 0%,
rgba(78, 166, 255, 0) 100%
rgba(78, 166, 255, 0.2) 0%,
rgba(78, 166, 255, 0) 100%
);
}
@@ -1175,8 +1311,8 @@ defineExpose({ getStuList, startLoading });
width: calc(100%);
height: 68px;
background: linear-gradient(
rgba(78, 166, 255, 0.2) 0%,
rgba(78, 166, 255, 0) 100%
rgba(78, 166, 255, 0.2) 0%,
rgba(78, 166, 255, 0) 100%
);
}

View File

@@ -16,10 +16,10 @@ import 'element-plus/dist/index.css'
import "@/assets/scss/common.scss"
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
import {request} from "@/api/request";
import {USER_INFO, USER_PERMISSION, VALIDATE_TOKEN} from "@/api/apis";
import { request } from "@/api/request";
import { USER_INFO, USER_PERMISSION, VALIDATE_TOKEN } from "@/api/apis";
import * as api1 from "@/api/index1";
import {getCookieForName} from "@/api/method";
import { getCookieForName } from "@/api/method";
import components from './components'
import axios from 'axios'
import Cookies from "vue-cookies";
@@ -35,102 +35,102 @@ app.config.warnHandler = () => null;
// })
router.beforeEach(async (to, from, next) => {
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)
return
// 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)
// return
// }
//第一次进入 没有用户信息
if (!store.state.userInfo.userId) {
try {
await request(VALIDATE_TOKEN)
await getUserInfo()
await getUserPermission();
init()
} catch (e) {
console.log('token失效 跳转到登录页')
}
//第一次进入 没有用户信息
if(!store.state.userInfo.userId){
try{
await request(VALIDATE_TOKEN)
await getUserInfo()
await getUserPermission();
init()
}catch (e){
console.log('token失效 跳转到登录页')
}
}
next();
}
next();
})
app.use(Antd);
app.use(router);
app.use(store);
app.mount('#app');
async function getUserPermission() {
return request(USER_PERMISSION, {permissionType: 'PAGE'}).then(res => {
store.commit("SET_PERMISSION", res.data?.map(s => s.url));
})
return request(USER_PERMISSION, { permissionType: 'PAGE' }).then(res => {
store.commit("SET_PERMISSION", res.data?.map(s => s.url));
})
}
async function getUserInfo() {
const userInfo = await request(USER_INFO);
store.commit("SET_USER", userInfo.data);
axios({
method: "get",
url: "/userbasic/orgHrbp/reportOrgs",
params: {
workNum:userInfo.data.userNo
},
headers: {
"XBOR-Access-token": Cookies.get("token"),
},
}).then(res=>{
store.commit("SET_USER_ORGS", res.data);
})
const userInfo = await request(USER_INFO);
store.commit("SET_USER", userInfo.data);
axios({
method: "get",
url: "/userbasic/orgHrbp/reportOrgs",
params: {
workNum: userInfo.data.userNo
},
headers: {
"XBOR-Access-token": Cookies.get("token"),
},
}).then(res => {
store.commit("SET_USER_ORGS", res.data);
})
}
async function initDict(key) {
const list = await getDictList(key);
store.commit("SET_DICT", {key, data: list});
const list = await getDictList(key);
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) => {
axios({
method: "get",
url: "/systemapi/xboe/type/tree-list",
params: {
sysResType: "1",
status: "1",
},
headers: {
"XBOR-Access-token": Cookies.get("token"),
},
}).then(
(res) => {
console.log(res.data.result,'课程分类接口')
store.commit("SET_DICT", {key, data: res.data.result});
//转化为map放到状态中
let map=new Map();
res.data.result.forEach(item=>{
map.set(item.id, item.name);
if(item.children && item.children!=''){
item.children.forEach(child=>{
map.set(child.id, child.name);
if(child.children && child.children!=''){
child.children.forEach(last=>{
map.set(last.id, last.name);
})
}
})
}
});
store.commit("SET_SYSTYPEMAP", map);
},
(err) => {
message.error(err);
axios({
method: "get",
url: "/systemapi/xboe/type/tree-list",
params: {
sysResType: "1",
status: "1",
},
headers: {
"XBOR-Access-token": Cookies.get("token"),
},
}).then(
(res) => {
console.log(res.data.result, '课程分类接口')
store.commit("SET_DICT", { key, data: res.data.result });
//转化为map放到状态中
let map = new Map();
res.data.result.forEach(item => {
map.set(item.id, item.name);
if (item.children && item.children != '') {
item.children.forEach(child => {
map.set(child.id, child.name);
if (child.children && child.children != '') {
child.children.forEach(last => {
map.set(last.id, last.name);
})
}
})
}
);
});
store.commit("SET_SYSTYPEMAP", map);
},
(err) => {
message.error(err);
}
);
}
async function init() {
// initDict("content_type"); //内容分类
initDictTree("content_type"); //内容分类换成type/tree-list接口
initDict("project_level"); //项目级别
initDict("project_sys"); //培训分类
initDict("project_pic"); //项目封面
initDict("router_pic"); //路径图封面
initDict("course_pic"); //课程封面
initDict("job_type"); //岗位
initDict("band"); //band
initDict("examine_cover") //讲师认证封面图
initDict("project_number") //项目编号
// initDict("content_type"); //内容分类
initDictTree("content_type"); //内容分类换成type/tree-list接口
initDict("project_level"); //项目级别
initDict("project_sys"); //培训分类
initDict("project_pic"); //项目封面
initDict("router_pic"); //路径图封面
initDict("course_pic"); //课程封面
initDict("job_type"); //岗位
initDict("band"); //band
initDict("examine_cover") //讲师认证封面图
initDict("project_number") //项目编号
}

View File

@@ -2,10 +2,16 @@
<template xmlns:display="http://www.w3.org/1999/xhtml">
<div class="projectAdd">
<div class="header">
<span class="title">{{
projectInfo.id ? "编辑" : "创建"
}}{{ ptojectType == "3" ? "班级" : "项目" }}</span>
<div @click="backPage" style="cursor: pointer" to="/projectmanage" class="goback">
<span class="title"
>{{ projectInfo.id ? "编辑" : "创建"
}}{{ ptojectType == "3" ? "班级" : "项目" }}</span
>
<div
@click="backPage"
style="cursor: pointer"
to="/projectmanage"
class="goback"
>
<span class="return"></span><span class="returntext">返回</span>
</div>
</div>
@@ -13,7 +19,10 @@
<div class="main">
<div class="name" v-if="projectInfo.parentName">
<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>
<div class="in">
@@ -24,103 +33,161 @@
</div>
<div class="name">
<div class="namebox">
<img class="nameimg" src="../../assets/images/basicinfo/asterisk.png"/>
<img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname">
{{ ptojectType == 3 ? "班级名称" : "项目名称" }}
</div>
</div>
<div class="in">
<NameInput :placeholder="ptojectType == 3 ? '请输入班级名称':'请输入项目名称'" v-model:value="projectInfo.name"
v-model:validated="projectInfo.validated" :type="1"
:maxlength="30" show-count :id="projectInfo.id"></NameInput>
<NameInput
:placeholder="
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 class="name flex-top">
<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>
<div class="in select" style="flex: 1; display: flex; flex-wrap: wrap;">
<div :class="`box ${projectInfo.picUrl === src.value ? 'active' : ''}`" style="
<div
class="in select"
style="flex: 1; display: flex; flex-wrap: wrap"
>
<div
:class="`box ${projectInfo.picUrl === src.value ? 'active' : ''}`"
style="
width: 100px;
height: 100px;
border-radius: 5px;
cursor: pointer;
position: relative;
overflow: hidden;
margin-bottom: 14px;
"
v-for="(src, index) in projectPic"
:style="{
display: index >= 3 ? 'none' : 'flex',
}"
:key="index"
@click="() => (projectInfo.picUrl = src.value)"
>
<img
style="
width: 100px;
height: 100px;
border-radius: 5px;
cursor: pointer;
position: relative;
overflow: hidden;
margin-bottom: 14px;
" v-for="(src, index) in projectPic" :style="{
display: index >= 3 ? 'none' : 'flex',
}" :key="index" @click="() => (projectInfo.picUrl = src.value)">
<img style="
width: 100px;
height: 100px;
margin-bottom: 4px;
margin-right: 4px;
" :src="src.value" alt="avatar"/>
margin-bottom: 4px;
margin-right: 4px;
"
:src="src.value"
alt="avatar"
/>
</div>
<div @click="showLearnBgMore" v-if="projectPic.length > 3" style="
width: 100px;
height: 100px;
padding-left: 15px;
border-radius: 5px;
cursor: pointer;
position: relative;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #c7cbd2;
font-size: 14px;
font-weight: 400;
color: #4ea6ff;
line-height: 36px;
margin-left: 14px;
">
<div
@click="showLearnBgMore"
v-if="projectPic.length > 3"
style="
width: 100px;
height: 100px;
padding-left: 15px;
border-radius: 5px;
cursor: pointer;
position: relative;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #c7cbd2;
font-size: 14px;
font-weight: 400;
color: #4ea6ff;
line-height: 36px;
margin-left: 14px;
"
>
查看更多
<img src="../../assets/images/projectadd/go.png" alt=""/>
<img src="../../assets/images/projectadd/go.png" alt="" />
</div>
</div>
</div>
<div class="name">
<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>
<div class="in">
<a-range-picker separator="至" :show-time="{ format: 'HH:mm' }"
:placeholder="[' 开始时间', ' 结束时间']"
v-model:value="timeRange" @calendarChange="calendarChange"
style="width: 100%; height: 40px; border-radius: 5px" :allowClear="false"
format="YYYY-MM-DD HH:mm"
valueFormat="YYYY-MM-DD HH:mm" @change="timeChange" :disabled="!!viewDetail"/>
<a-range-picker
separator="至"
:show-time="{ format: 'HH:mm' }"
:placeholder="[' 开始时间', ' 结束时间']"
v-model:value="timeRange"
@calendarChange="calendarChange"
style="width: 100%; height: 40px; border-radius: 5px"
:allowClear="false"
format="YYYY-MM-DD HH:mm"
valueFormat="YYYY-MM-DD HH:mm"
@change="timeChange"
:disabled="!!viewDetail"
/>
</div>
</div>
<div class="name">
<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>
<div class="in">
<ProjectManager v-model:value="projectInfo.managerId" v-model:name="projectInfo.manager"
@onChange="managerChange" mode="multiple"></ProjectManager>
<ProjectManager
v-model:value="projectInfo.managerId"
v-model:name="projectInfo.manager"
@onChange="managerChange"
mode="multiple"
></ProjectManager>
</div>
</div>
<div class="name">
<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>
<div class="in select">
<OrgClass v-model:value="projectInfo.sourceBelongId" v-model:name="projectInfo.sourceBelongName"
v-model:fullName="projectInfo.sourceBelongFullName"></OrgClass>
<OrgClass
v-model:value="projectInfo.sourceBelongId"
v-model:name="projectInfo.sourceBelongName"
v-model:fullName="projectInfo.sourceBelongFullName"
></OrgClass>
</div>
</div>
<div class="name">
<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>
<div class="in select">
@@ -129,7 +196,10 @@
</div>
<div class="name">
<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>
<div class="in select">
@@ -137,12 +207,19 @@
</div>
</div>
<div class="name">
<div class="namebox" style="width:157px;margin-left:-38px;">
<img class="nameimg" src="../../assets/images/basicinfo/asterisk.png"/>
<div class="namebox" style="width: 157px; margin-left: -38px">
<img
class="nameimg"
src="../../assets/images/basicinfo/asterisk.png"
/>
<div class="inname">关联BOEU立项审批单</div>
</div>
<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="0"></a-radio>
</a-radio-group>
@@ -150,34 +227,103 @@
<!-- <div class="num" style="flex:3" v-if="projectInfo.boeFlag === 1">
<div class="num_text">项目编号</div>
<div class="num_input"> -->
<!-- <a-input style="border-radius: 8px;" show-count allowClear maxlength="30" v-model:value="projectInfo.numValue" placeholder="请输入项目编号" /> -->
<!-- <ProjectNumber v-model:value="projectInfo.numValue"></ProjectNumber>
<!-- <a-input style="border-radius: 8px;" show-count allowClear maxlength="30" v-model:value="projectInfo.numValue" placeholder="请输入项目编号" /> -->
<!-- <ProjectNumber v-model:value="projectInfo.numValue"></ProjectNumber>
</div>
</div> -->
</div>
<div class="name name2 num" style="flex:3" v-if="projectInfo.boeFlag === 1">
<div class="namebox">
<div class="num_text">项目编号</div>
</div>
<div class="in ggysxz">
<div class="num_input">
<!-- <a-input style="border-radius: 8px;" show-count allowClear maxlength="30" v-model:value="projectInfo.numValue" placeholder="请输入项目编号" /> -->
<ProjectNumber v-model:value="projectInfo.numValue"></ProjectNumber>
</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.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="num_text">项目编号</div>
</div>
<div class="in ggysxz">
<div class="num_input">
<!-- <a-input style="border-radius: 8px;" show-count allowClear maxlength="30" v-model:value="projectInfo.numValue" placeholder="请输入项目编号" /> -->
<ProjectNumber
v-model:value="projectInfo.numValue"
></ProjectNumber>
</div>
</div>
</div>
<div class="name name2">
<div class="namebox">
<div class="inname">同步学习记录</div>
</div>
<div class="in ggysxz">
<a-checkbox v-model:checked="courseSyncFlag">
<span style="
width: 100%;
color: rgba(109, 117, 132, 1);
font-size: 14px;
">
<span
style="
width: 100%;
color: rgba(109, 117, 132, 1);
font-size: 14px;
"
>
同步课程学习记录如学员在课程库中拥有课程的学习记录自动免修该课程
</span>
</a-checkbox>
@@ -189,11 +335,13 @@
</div>
<div class="in ggysxz">
<a-checkbox v-model:checked="rankFlag">
<span style="
width: 100%;
color: rgba(109, 117, 132, 1);
font-size: 14px;
">
<span
style="
width: 100%;
color: rgba(109, 117, 132, 1);
font-size: 14px;
"
>
是否显示积分
</span>
</a-checkbox>
@@ -204,8 +352,14 @@
<div class="inname" style="margin-top: 13px">项目说明</div>
</div>
<div class="in">
<a-textarea v-model:value="projectInfo.remark" style="height: 80px" placeholder="请输入说明" show-count
:maxlength="200" :disabled="viewDetail ? true : false"/>
<a-textarea
v-model:value="projectInfo.remark"
style="height: 80px"
placeholder="请输入说明"
show-count
:maxlength="200"
:disabled="viewDetail ? true : false"
/>
</div>
</div>
@@ -222,13 +376,21 @@
<div class="name">
<div class="inname" style="width: 50px">模版</div>
<div class="in select" style="margin-left: 2px">
<a-select :allowClear="true" :getPopupContainer="
(triggerNode) => triggerNode.parentNode || document.body
" placeholder="请选择模版" style="width: 100%" :options="classifyList5" @change="classificationChange5"
@popupScroll="templateScroll" :fieldNames="{
<a-select
:allowClear="true"
:getPopupContainer="
(triggerNode) => triggerNode.parentNode || document.body
"
placeholder="请选择模版"
style="width: 100%"
:options="classifyList5"
@change="classificationChange5"
@popupScroll="templateScroll"
:fieldNames="{
label: 'name',
value: 'id',
}">
}"
>
</a-select>
</div>
</div>
@@ -237,13 +399,26 @@
<div class="footer">
<div class="btn">
<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>
</div>
</div>
<!-- 更多背景图 v-model:visible="learnBgMore" -->
<a-modal :closable="sh" centered="true" v-model:visible="learnBgMore" :footer="null" :width="650"
wrapClassName="learnBgMoreModal" :z-index="9999">
<a-modal
:closable="sh"
centered="true"
v-model:visible="learnBgMore"
:footer="null"
:width="650"
wrapClassName="learnBgMoreModal"
:z-index="9999"
>
<div class="main">
<div class="top">
<div class="topc">封面图</div>
@@ -255,39 +430,60 @@
:key="item.code"
class="learnBgItem"
> -->
<div @click="chooseImg2(item)" v-for="item in projectPic" :key="item.code" class="learnBgItem" :style="{
border:
projectInfo.picUrl === item.value
? '3px solid rgba(78, 166, 255, 1)'
: '1px solid #ccc',
'background-image': 'url(' + item.value.split(',')[0] + ')',
}">
<div
@click="chooseImg2(item)"
v-for="item in projectPic"
:key="item.code"
class="learnBgItem"
:style="{
border:
projectInfo.picUrl === item.value
? '3px solid rgba(78, 166, 255, 1)'
: '1px solid #ccc',
'background-image': 'url(' + item.value.split(',')[0] + ')',
}"
>
<!-- <img class="im" :src="item.source" /> -->
</div>
</div>
<div class="btn">
<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>
</a-modal>
</div>
</template>
<script>
import {onMounted, reactive, toRefs, watch} from "vue";
import {message} from "ant-design-vue";
import {useRoute, useRouter} from "vue-router";
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
import {
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 {useStore} from "vuex";
import { useStore } from "vuex";
import TrainClass from "@/components/project/TrainClass";
import OrgClass from "@/components/project/OrgClass";
import ProjectManager from "@/components/project/ProjectManagerNew";
import NameInput from "@/components/project/NameInput";
import ProjectLevel from "@/components/project/ProjectLevel";
import * as api2 from "../../api/indexAudit";
import {validateName} from "@/api/index1";
import { validateName } from "@/api/index1";
import dayjs from "dayjs";
import {scrollLoad} from "@/api/method";
import { scrollLoad } from "@/api/method";
import ProjectNumber from "@/components/project/ProjectNumber";
export default {
name: "projectAdd",
@@ -298,7 +494,9 @@ export default {
TrainClass,
NameInput,
OrgClass,
ProjectNumber
ProjectNumber,
Editor,
Toolbar,
},
setup() {
const store = useStore();
@@ -312,7 +510,7 @@ export default {
pageSize: 10, //每页10条数据
totalPages: 0, //总页数
viewDetail: null,
projectInfo: { id: "", validated: 0 ,boeFlag :0},
projectInfo: { id: "", validated: 0, boeFlag: 0 },
projectPic: [],
memberParam: {
pageNo: 1,
@@ -321,7 +519,7 @@ export default {
},
classifyList5: [],
courseSyncFlag: true,
rankFlag:false,
rankFlag: false,
auditDescription: "",
ptojectType: "",
changeCondition: false,
@@ -329,6 +527,7 @@ export default {
timeRange: [],
learnBgMore: false,
pathBgId: null,
isNewEmployee: false,
});
// 封面图选择
@@ -336,6 +535,36 @@ export default {
console.log(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(() => {
state.projectPic = store.state.project_pic.map((e) => ({
code: e.id,
@@ -343,23 +572,96 @@ export default {
label: e.name,
}));
state.viewDetail = routers.query.viewDetail;
if (!editorRef.value) loadRemoteContent();
getProjectInfo();
getTemplate();
state.ptojectType = routers.query.ptojectType;
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, () => {
state.projectInfo.name = routers.query.name;
state.projectInfo.id = routers.query.id;
state.projectInfo.parentName = routers.query.parentName;
state.projectInfo.parentId = routers.query.parentId;
});
watch(()=>state.projectInfo.boeFlag,(val)=>{
if(!val){
state.projectInfo.numValue = ''
watch(
() => state.projectInfo.boeFlag,
(val) => {
if (!val) {
state.projectInfo.numValue = "";
}
}
})
);
function getProjectInfo() {
state.projectInfo.name = routers.query.name;
@@ -367,44 +669,52 @@ export default {
state.projectInfo.parentId = routers.query.parentId;
state.projectInfo.id = routers.query.projectId;
(state.projectInfo.id || state.projectInfo.parentId) &&
api
.getProjectDetail({
projectId: state.projectInfo.id || state.projectInfo.parentId,
})
.then((res) => {
state.projectInfo = {
...res.data.data.projectInfo,
...state.projectInfo,
};
!routers.query.projectId &&
!!routers.query.parentId &&
(state.projectInfo.name = "");
state.timeRange = [
state.projectInfo.beginTime,
state.projectInfo.endTime,
];
state.courseSyncFlag = !!state.projectInfo.courseSyncFlag;
state.rankFlag = !!state.projectInfo.rankFlag;
if (Number(state.projectInfo.status) === -5) {
let obj = {
project_id: state.projectInfo.id,
type: 1,
pageNo: 1,
pageSize: 1,
};
api2.auditList(obj).then((d) => {
if (d.data.code === 200) {
let res = d.data.data;
if (res.rows && res.rows.length > 0) {
let i = res.rows.length;
state.auditDescription = res.rows[i - 1].description
? res.rows[i - 1].description
: "-";
}
api
.getProjectDetail({
projectId: state.projectInfo.id || state.projectInfo.parentId,
})
.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 = {
...res.data.data.projectInfo,
...state.projectInfo,
};
!routers.query.projectId &&
!!routers.query.parentId &&
(state.projectInfo.name = "");
state.timeRange = [
state.projectInfo.beginTime,
state.projectInfo.endTime,
];
state.courseSyncFlag = !!state.projectInfo.courseSyncFlag;
state.rankFlag = !!state.projectInfo.rankFlag;
if (Number(state.projectInfo.status) === -5) {
let obj = {
project_id: state.projectInfo.id,
type: 1,
pageNo: 1,
pageSize: 1,
};
api2.auditList(obj).then((d) => {
if (d.data.code === 200) {
let res = d.data.data;
if (res.rows && res.rows.length > 0) {
let i = res.rows.length;
state.auditDescription = res.rows[i - 1].description
? res.rows[i - 1].description
: "-";
}
}
});
}
});
}
const backPage = () => {
@@ -417,9 +727,9 @@ export default {
};
const classificationChange5 = (key, option) => {
if(key==undefined || option==undefined){
if (key == undefined || option == undefined) {
// 标识清空选择的模版
state.timeRange = []
state.timeRange = [];
state.projectInfo = {
name: "",
picUrl: "",
@@ -429,9 +739,9 @@ export default {
managerId: "",
sourceBelongId: null,
level: "",
systemId: null
}
return
systemId: null,
};
return;
}
state.projectInfo = option;
state.projectInfo.projectTemplateId = option.id;
@@ -477,7 +787,9 @@ export default {
level: "请填写项目级别",
systemId: "请填写项目培训体系",
boeFlag: "请选择关联BOEU立项审批单",
};
electiveCourseCount: "请输入选修课程数量",
// requiredCourseCount: "请输入必修课程数量",
};
function timeChange(e) {
if (e && e.length === 2) {
@@ -514,10 +826,11 @@ export default {
name: state.projectInfo.name,
type: 1,
id: state.projectInfo.id,
}).then((res) => {
return res.data.data == 1;
}).catch((err) => {
});
})
.then((res) => {
return res.data.data == 1;
})
.catch((err) => {});
if (offName) {
message.destroy();
state.loading = false;
@@ -526,19 +839,22 @@ export default {
state.projectInfo.type = 3;
state.projectInfo.courseSyncFlag = state.courseSyncFlag ? 1 : 0;
state.projectInfo.rankFlag = state.rankFlag ? 1 : 0;
api.createProject(state.projectInfo).then((res) => {
state.loading = false;
message.destroy();
message.success(state.projectInfo.id ? "编辑成功" : "创建成功");
router.push({
path: "/taskpage",
query: { projectId: res.data.data },
api
.createProject(state.projectInfo)
.then((res) => {
state.loading = false;
message.destroy();
message.success(state.projectInfo.id ? "编辑成功" : "创建成功");
router.push({
path: "/taskpage",
query: { projectId: res.data.data },
});
})
.catch((err) => {
state.loading = false;
message.destroy();
message.error("创建项目失败,请重新创建");
});
}).catch((err) => {
state.loading = false;
message.destroy();
message.error('创建项目失败,请重新创建');
});
};
function managerChange(e, l, d, t, orgName) {
@@ -596,6 +912,15 @@ export default {
showLearnBgMore,
closeLearnBgMore,
chooseImg2,
editorRef,
valueHtml,
mode: "simple", //简洁模式
toolbarConfig,
editorConfig,
handleCreated,
handleOnChange,
setEditorContent,
getEditorContent,
};
},
};
@@ -804,17 +1129,17 @@ export default {
}
}
.num{
.num {
display: flex;
justify-content: left;
align-items: center;
.num_text{
.num_text {
color: #6f6f6f;
font-size: 14px;
min-width: 70px;
// margin-right: 7px;
}
.num_input{
.num_input {
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 {
@@ -1061,7 +1402,6 @@ export default {
}
.treeDropdown {
// width: 240px !important;
// border-radius: 5px;
// min-height: 600px !important;

View File

@@ -350,7 +350,7 @@
<div class="nubbox">
<div>
<span class="nub1" style="color: #a497ff">{{
((projectInfoOverview.completeRatio || 0) * 100).toFixed(2)
((projectInfoOverview.completeRatio || 0) * 100).toFixed(2)
}}</span
><span style="color: #a497ff; font-size: 14px">%</span>
</div>
@@ -390,7 +390,10 @@
type="dashboard"
gapDegree="0"
:percent="
fixDoublePer( stageOverviewList[choosedStageIndex]?.completeCourseRatio || 0)
fixDoublePer(
stageOverviewList[choosedStageIndex]
?.completeCourseRatio || 0
)
"
:width="140"
/>
@@ -401,7 +404,10 @@
type="dashboard"
gapDegree="0"
:percent="
fixDoublePer(stageOverviewList[choosedStageIndex]?.completeExamRatio || 0)
fixDoublePer(
stageOverviewList[choosedStageIndex]?.completeExamRatio ||
0
)
"
:width="140"
/>
@@ -411,39 +417,67 @@
<a-progress
type="dashboard"
gapDegree="0"
:percent="fixDoublePer(stageOverviewList[choosedStageIndex]?.completeRatio || 0)"
:percent="
fixDoublePer(
stageOverviewList[choosedStageIndex]?.completeRatio || 0
)
"
:width="140"
/>
<div class="protext">作业完成率</div>
</div>
<div class="proright">
<div class="pronub" style="margin-left: 142px">
{{ stageOverviewList[choosedStageIndex]?.completeTaskCnt || 0}}
{{
stageOverviewList[choosedStageIndex]?.completeTaskCnt || 0
}}
</div>
<div class="proright1">
<span class="textpro">阶段任务总数</span>
<a-progress
:percent="fixDoublePer(stageOverviewList[choosedStageIndex]?.completeTaskCnt/(stageOverviewList[choosedStageIndex]?.totalTaskCnt || 0))"
:percent="
fixDoublePer(
stageOverviewList[choosedStageIndex]?.completeTaskCnt /
(stageOverviewList[choosedStageIndex]?.totalTaskCnt ||
0)
)
"
style="width: 369px"
/>
</div>
<div class="pronub" style="margin-left: 142px">
{{ stageOverviewList[choosedStageIndex]?.completeReqCnt || 0}}
{{
stageOverviewList[choosedStageIndex]?.completeReqCnt || 0
}}
</div>
<div class="proright1">
<span class="textpro">必修任务</span>
<a-progress
:percent="fixDoublePer(stageOverviewList[choosedStageIndex]?.completeReqCnt/(stageOverviewList[choosedStageIndex]?.totalReqCnt || 0))"
:percent="
fixDoublePer(
stageOverviewList[choosedStageIndex]?.completeReqCnt /
(stageOverviewList[choosedStageIndex]?.totalReqCnt ||
0)
)
"
style="width: 369px"
/>
</div>
<div class="pronub" style="margin-left: 142px">
{{ stageOverviewList[choosedStageIndex]?.completeOptCnt || 0}}
{{
stageOverviewList[choosedStageIndex]?.completeOptCnt || 0
}}
</div>
<div class="proright1">
<span class="textpro">选修任务</span>
<a-progress
:percent="fixDoublePer(stageOverviewList[choosedStageIndex]?.completeOptCnt/(stageOverviewList[choosedStageIndex]?.totalOptCnt || 0))"
:percent="
fixDoublePer(
stageOverviewList[choosedStageIndex]?.completeOptCnt /
(stageOverviewList[choosedStageIndex]?.totalOptCnt ||
0)
)
"
style="width: 369px"
/>
</div>
@@ -585,10 +619,27 @@
<div class="time">
<div class="timetext">开始时间</div>
<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 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">
{{ item.finishStuCnt || 0 }}/{{
item.totalStuCnt || 0
@@ -613,24 +664,45 @@
}}%</span
>
</div> -->
<div>
{{ item.averageScore}}分
</div>
<div>{{ item.averageScore }}分</div>
<div class="img_daoc" @click="exportScore(item)"></div>
</div>
<div class="progress" v-if="!item.averageScore" style="display: flex;flex-grow: 0;margin: 0;min-width: 60px;">
</div>
<div
class="progress"
v-if="!item.averageScore"
style="
display: flex;
flex-grow: 0;
margin: 0;
min-width: 60px;
"
></div>
<div class="operations">
<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 class="ant-dropdown-link" @click="qrcodeAssement(item)">
<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
class="ant-dropdown-link"
@click="qrcodeAssement(item)"
>
评估二维码
<DownOutlined />
</a>
<template #overlay>
<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>
<div>
<p>{{ item.name }}</p>
@@ -640,23 +712,47 @@
</a-menu>
</template>
</a-dropdown>
<div v-if="item.assessmentIds.filter(id => id !== null).length==1&&item.type == 2">
<a class="ant-dropdown-link" @click="qrcodeAssement(item)">
<div
v-if="
item.assessmentIds.filter((id) => id !== null)
.length == 1 && item.type == 2
"
>
<a
class="ant-dropdown-link"
@click="qrcodeAssement(item)"
>
评估二维码
<DownOutlined />
</a>
</div>
</div>
<div class="operations_dropdown" 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)">
<div
class="operations_dropdown"
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 />
</a>
<template #overlay v-if="qrCodeItems.length>0">
<template #overlay v-if="qrCodeItems.length > 0">
<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>
<div>
<p>{{ item.name }}</p>
@@ -667,16 +763,24 @@
</template>
</a-dropdown>
</div>
<div class="operations_dropdown" v-if="item.type == 2&&item.assessmentIds.length==1">
<a class="ant-dropdown-link" @click="qrcodeVisible(item)">
签到二维码
<DownOutlined />
</a>
<div
class="operations_dropdown"
v-if="
item.type == 2 && item.assessmentIds.length == 1
"
>
<a
class="ant-dropdown-link"
@click="qrcodeVisible(item)"
>
签到二维码
<DownOutlined />
</a>
</div>
<div
class="operation"
style="cursor: pointer"
@click="openCourse(item,key,index)"
@click="openCourse(item, key, index)"
v-if="item.type == 2"
>
开课
@@ -828,11 +932,26 @@
:visable="tabFlag"
:groupList="groupList"
:remarksTrue="remarksTrue"
:isNewEmployee="isNewEmployee"
>
<template #extension="{ data: { record } }">
<a-button @click="showStudent(record)" type="link"
>查看
</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
@click="settingTopFlag(record)"
v-if="checkPer(permissions, createId)"
@@ -846,9 +965,7 @@
@click="showChangeGroupModal(record)"
>换组
</a-button>
<a-button
type="link"
@click="modifyRemarks(record)"
<a-button type="link" @click="modifyRemarks(record)"
>修改备注
</a-button>
</template>
@@ -972,7 +1089,15 @@
</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
:showSizeChanger="false"
showQuickJumper="true"
@@ -1736,14 +1861,14 @@
:createId="createId"
/>
<!-- 面授学员抽屉 -->
<RouterFaceStu
:permissions="permissions"
:createId="createId"
v-model:FSvisible="FSvisible"
:datasource="facestudent"
:type="1"
:courseName="name"
/>
<RouterFaceStu
:permissions="permissions"
:createId="createId"
v-model:FSvisible="FSvisible"
:datasource="facestudent"
:type="1"
:courseName="name"
/>
<!-- 活动直播考勤抽屉 -->
<active-attendance
:permissions="permissions"
@@ -2352,24 +2477,31 @@
/>
<!-- 换组弹窗 -->
<!-- 面授课开课弹框 -->
<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"
:footer="null"
closable="false"
style="margin-top: 400px"
@cancel="of_remarks"
>
<div class="selectonlineface" :style="{ display: showRemarks ? 'block' : 'none' }">
<div class="bg_headers"></div>
<div
class="selectonlineface"
:style="{ display: showRemarks ? 'block' : 'none' }"
>
<div class="bg_headers"></div>
<div class="bg_main">
<div class="bg_main_header">
<div>修改备注</div>
<div class="bg_main_header_close" @click="of_remarks"></div>
</div>
<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_input">
<a-input v-model:value="remarks" placeholder="请输入" />
@@ -2379,10 +2511,7 @@
<div class="btn btn6" @click="of_remarks">
<div class="btnText">取消</div>
</div>
<a-button
class="btn btn6"
@click="RemarksUpdata"
>
<a-button class="btn btn6" @click="RemarksUpdata">
确定
</a-button>
</div>
@@ -2390,6 +2519,38 @@
</div>
</div>
</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>
</template>
<script lang="jsx">
@@ -2436,7 +2597,7 @@ import { getTask } from "../../api/indexTaskadd";
import { editProjDoc } from "../../api/indexTaskadd";
import {getCookieForName, toDate} from "../../api/method";
import projSet from "../../components/Modals/projSet";
import { overview } from "../../api/indexProjStu";
import { overview,downloadTranscript } from "../../api/indexProjStu";
import TwoDimensionalCode from "../../components/TwoDimensionalCode.vue";
import ProjectScore from "../../components/drawers/ProjectScore";
import { useStore } from "vuex";
@@ -2450,7 +2611,7 @@ import ChangeGroupModal from "@/components/student/ChangeGroupModal.vue";
import { checkPer,fixDoublePer } from "@/utils/utils";
import ImpoterGroupLeader from "@/components/drawers/project/ImpoterGroupLeader.vue";
import qrCode from "@/utils/qrCode";
import {request} from "@/api/request";
import {request, boeRequest} from "@/api/request";
import { PROJECT_RELEASE} from "@/api/apis";
export default {
name: "taskPage",
@@ -2498,6 +2659,70 @@ export default {
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 visibleEwm = ref({});
const qrcodeVisible = async (item)=>{
@@ -2593,6 +2818,7 @@ export default {
const headers = { token: getCookieForName("token") };
const state = reactive({
isNewEmployee: false,
createId: "",
permissions: "",
screenHeight: document.body.clientHeight,
@@ -4243,6 +4469,9 @@ export default {
getTask({
projectId: state.projectId,
}).then((res) => {
if(res.data.data.projectInfo.szxygProjectFlag == "1"){
state.isNewEmployee = true;
}
if (
res.data.data.projectAuditLogDtoList &&
res.data.data.projectAuditLogDtoList.length
@@ -5113,6 +5342,25 @@ export default {
state.Seevisible = true;
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) => {
console.log(url);
@@ -5203,6 +5451,7 @@ export default {
headers,
stageChange,
showStudent,
downloadReport,
settingTopFlag,
totask,
tostudent,
@@ -5339,6 +5588,13 @@ export default {
coursePlanRef,
openCourse,
exportScore,
// 报名记录相关
showSignUpRecordModal,
signupRecordColumns,
signupRecordList,
showSignUpRecord,
signupRecordLoading,
};
},
};
@@ -6177,113 +6433,113 @@ export default {
}
}
}
.selectonlineface{
z-index: 999;
width: 679px;
background: #ffffff;
box-shadow: 0px 1px 35px 0px rgba(118, 136, 166, 0.21);
.selectonlineface {
z-index: 999;
width: 679px;
background: #ffffff;
box-shadow: 0px 1px 35px 0px rgba(118, 136, 166, 0.21);
position: absolute;
left: 50%;
top: -100%;
transform: translate(-50%, -50%);
.bg_headers {
position: absolute;
left: 50%;
top: -100%;
transform: translate(-50%, -50%);
.bg_headers {
position: absolute;
width: 100%;
height: 40px;
background: linear-gradient(
rgba(78, 166, 255, 0.2) 0%,
rgba(78, 166, 255, 0) 100%
);
width: 100%;
height: 40px;
background: linear-gradient(
rgba(78, 166, 255, 0.2) 0%,
rgba(78, 166, 255, 0) 100%
);
}
.bg_main {
width: 100%;
position: relative;
.bg_main_header {
display: flex;
align-items: center;
padding-top: 20px;
padding-left: 26px;
font-size: 16px;
.bg_main_header_close {
position: absolute;
right: 42px;
cursor: pointer;
width: 20px;
height: 20px;
background-image: url(@/assets/images/coursewareManage/close.png);
background-size: 100% 100%;
}
}
.bg_main {
width: 100%;
position: relative;
.bg_main_header {
.bg_body {
width: 80%;
margin: 3px auto;
.bg_body_bt {
display: flex;
align-items: center;
padding-top: 20px;
padding-left: 26px;
font-size: 16px;
.bg_main_header_close {
position: absolute;
right: 42px;
cursor: pointer;
width: 20px;
height: 20px;
background-image: url(@/assets/images/coursewareManage/close.png);
background-size: 100% 100%;
justify-content: end;
margin: 14px auto;
.bg_body_bttext {
width: 110px;
display: flex;
justify-content: end;
margin-right: 20px;
}
}
.bg_body {
width: 80%;
margin: 3px auto;
.bg_body_input {
flex: 1;
position: relative;
.ant-upload-picture-card-wrapper {
width: 200px;
margin-right: 18px;
}
}
.bg_footer {
width: 100%;
margin-left: 174px;
margin-top: 25px;
margin-bottom: 20px;
display: flex;
.bg_body_bt {
.btn {
width: 100px;
height: 40px;
background: rgba(64, 158, 255, 0);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: end;
margin: 14px auto;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.bg_body_bttext {
width: 110px;
display: flex;
justify-content: end;
margin-right: 20px;
.btnText {
font-size: 14px;
font-weight: 400;
line-height: 40px;
}
}
.bg_body_input {
flex: 1;
position: relative;
.ant-upload-picture-card-wrapper{
width: 200px;
margin-right: 18px;
}
}
.bg_footer {
width: 100%;
margin-left: 174px;
margin-top: 25px;
margin-bottom: 20px;
display: flex;
.btn {
width: 100px;
height: 40px;
background: rgba(64, 158, 255, 0);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.btnText {
font-size: 14px;
font-weight: 400;
line-height: 40px;
}
}
.btn6 {
background-color: #4ea6ff;
color: #ffffff;
}
.btn6 {
background-color: #4ea6ff;
color: #ffffff;
}
}
.headers{
margin-left: 38px;
margin-right: 38px;
margin-top: 30px;
}
.headers {
margin-left: 38px;
margin-right: 38px;
margin-top: 30px;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.btn {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.btn{
display: flex;
}
}
}
}
}
.taskpage {
width: 100%;
display: flex;
@@ -6954,14 +7210,14 @@ export default {
margin-right: 50px;
flex-grow: 1;
.img_daoc {
cursor: pointer;
width: 16px;
height: 18px;
background-image: url(@/assets/images/coursewareManage/export.png);
background-size: 100% 100%;
// background-color: #4ea6ff;
margin-left: 7px;
}
cursor: pointer;
width: 16px;
height: 18px;
background-image: url(@/assets/images/coursewareManage/export.png);
background-size: 100% 100%;
// background-color: #4ea6ff;
margin-left: 7px;
}
.progresstext {
color: #ffc067;
font-size: 14px;
@@ -6972,7 +7228,7 @@ export default {
display: flex;
width: 420px;
flex-grow: 1;
.operations_dropdown{
.operations_dropdown {
padding: 10px;
text-align: center;
position: relative;

View File

@@ -25,25 +25,30 @@ module.exports = defineConfig({
// changeOrigin: true,
// },
"/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,
},
"/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, //表示是否改变原域名
pathRewrite: {
"^/manageApi": "",
"^/manageApi": "/manageApi",
},
}, "/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, //表示是否改变原域名
},
"/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, //表示是否改变原域名
},
"/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, //表示是否改变原域名
},
// "/reportsnake": {
@@ -54,7 +59,8 @@ module.exports = defineConfig({
// },
// },
"/reportsnake": {
target: 'http://127.0.0.1:32004',
// target: 'http://127.0.0.1:32004',
target: 'http://10.10.176.17:81/',
changeOrigin: true, //表示是否改变原域名
pathRewrite: {
"^/reportsnake": "",
@@ -64,7 +70,8 @@ module.exports = defineConfig({
}
},
"/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, //表示是否改变原域名
pathRewrite: {
// "^/manageApi": "",
@@ -80,7 +87,8 @@ module.exports = defineConfig({
// },
// },
"/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,
},