mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/learning-system-portal.git
synced 2025-12-23 17:55:37 +08:00
Compare commits
25 Commits
251114-fea
...
251114-fea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2e188c0e6 | ||
|
|
a9b36884c3 | ||
|
|
e176769174 | ||
|
|
5f518b713a | ||
|
|
b2395fd3a2 | ||
|
|
100ad78c9b | ||
|
|
4831da0c47 | ||
|
|
6bee4e8e87 | ||
|
|
4ebd8f5225 | ||
|
|
79f068198d | ||
|
|
6cfd0e8720 | ||
|
|
ed672905f2 | ||
|
|
2f1ea68c70 | ||
|
|
7a28e362f7 | ||
|
|
e12437484b | ||
|
|
78be53013b | ||
|
|
c9c714ddfa | ||
|
|
ffeb5bf0b6 | ||
|
|
f680e1c394 | ||
|
|
ef926e6418 | ||
|
|
2d06dde984 | ||
|
|
5cd85a3e15 | ||
|
|
89364b1aef | ||
|
|
a34f87410f | ||
|
|
361675c369 |
@@ -46,6 +46,14 @@ const getUserInfoById = function(id) {
|
|||||||
return ajax.postJson(baseURL,'/user/list',{id});
|
return ajax.postJson(baseURL,'/user/list',{id});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取全量机构树
|
||||||
|
* GET /userbasic/organization/all/tree
|
||||||
|
*/
|
||||||
|
const getAllOrgTree = function () {
|
||||||
|
return ajax.get(baseURL, '/organization/all/tree');
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://u-pre.boe.com/userbasic/audience/userAudiences
|
* https://u-pre.boe.com/userbasic/audience/userAudiences
|
||||||
* 【当前代码中未查询到】获取当前用户受众信息
|
* 【当前代码中未查询到】获取当前用户受众信息
|
||||||
@@ -111,6 +119,7 @@ const selectUser = function(keyword = '') {
|
|||||||
return ajax.postJson(baseURL,'/user/selectuser',{ keyword });
|
return ajax.postJson(baseURL,'/user/selectuser',{ keyword });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
userParentOrg,
|
userParentOrg,
|
||||||
findOrgsByKeyword,
|
findOrgsByKeyword,
|
||||||
@@ -125,5 +134,6 @@ export default {
|
|||||||
getUsersByIds,
|
getUsersByIds,
|
||||||
updateUser,
|
updateUser,
|
||||||
logout,
|
logout,
|
||||||
|
getAllOrgTree,
|
||||||
selectUser
|
selectUser
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const hasSignup = function(courseId) {
|
|||||||
* 课程报名,微课,录播课
|
* 课程报名,微课,录播课
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* {
|
* {
|
||||||
courseId:
|
courseId:
|
||||||
courseName:
|
courseName:
|
||||||
courseType: 课程类型,对应微课,录播课
|
courseType: 课程类型,对应微课,录播课
|
||||||
signType:1,后名方式,默认是1自主报名,可以不传
|
signType:1,后名方式,默认是1自主报名,可以不传
|
||||||
@@ -367,6 +367,15 @@ const deleteSignUp=function(id,courseId){
|
|||||||
return ajax.post(`/xboe/school/study/course/delete-signup?id=${id}&couserId=${courseId}`);
|
return ajax.post(`/xboe/school/study/course/delete-signup?id=${id}&couserId=${courseId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
删除课程学习记录
|
||||||
|
@param id 学习id
|
||||||
|
@param courseId 课程id 用于删除课程报名信息和修改课程学习人数
|
||||||
|
*/
|
||||||
|
const deleteNewSignUp=function(data){
|
||||||
|
return ajax.post(`/xboe/school/study/course/delete-signup`, data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 二次查询 用于个人主页/他人主页
|
* 二次查询 用于个人主页/他人主页
|
||||||
* {
|
* {
|
||||||
@@ -432,6 +441,7 @@ export default {
|
|||||||
signup,
|
signup,
|
||||||
findSignup,
|
findSignup,
|
||||||
deleteSignup,
|
deleteSignup,
|
||||||
|
deleteNewSignUp,
|
||||||
importSignup,
|
importSignup,
|
||||||
countSignup,
|
countSignup,
|
||||||
studyIndex,
|
studyIndex,
|
||||||
|
|||||||
@@ -402,7 +402,7 @@ li{
|
|||||||
|
|
||||||
.el-message-box__header {
|
.el-message-box__header {
|
||||||
// padding: 0 0 16px 0;
|
// padding: 0 0 16px 0;
|
||||||
padding: 2px 8px 2px 16px;
|
padding: 8px 8px 2px 16px;
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
.el-message-box__title {
|
.el-message-box__title {
|
||||||
@@ -412,7 +412,7 @@ li{
|
|||||||
}
|
}
|
||||||
|
|
||||||
.el-message-box__headerbtn {
|
.el-message-box__headerbtn {
|
||||||
top: 8px;
|
top: 14px;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
.el-message-box__close {
|
.el-message-box__close {
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
@@ -461,17 +461,47 @@ li{
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
margin-top: 0px;
|
margin-top: 8px;
|
||||||
padding-bottom: 20px;
|
|
||||||
|
|
||||||
.el-button {
|
.el-button {
|
||||||
width: 70px;
|
width: 78px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
padding: 0 18px;
|
padding: 0 18px;
|
||||||
|
&:nth-child(2){
|
||||||
|
margin-left: 10px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.el-button--default {
|
||||||
|
color: rgba(0, 0, 0, .3);
|
||||||
|
border-color: rgba(0, 0, 0, .3);
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button--primary {
|
||||||
|
background-color: #3b7cff;
|
||||||
|
border-color: #3b7cff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.common-course-dialog {
|
||||||
|
.el-dialog__footer {
|
||||||
|
padding: 10px 20px 16px;
|
||||||
|
.el-button {
|
||||||
|
width: 78px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 0 18px;
|
||||||
|
&:nth-child(2){
|
||||||
|
margin-left: 10px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
.el-button--default {
|
.el-button--default {
|
||||||
color: rgba(0, 0, 0, .3);
|
color: rgba(0, 0, 0, .3);
|
||||||
border-color: rgba(0, 0, 0, .3);
|
border-color: rgba(0, 0, 0, .3);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
|
class="common-course-dialog"
|
||||||
title="置顶排序"
|
title="置顶排序"
|
||||||
:visible.sync="dialogVisible"
|
:visible.sync="dialogVisible"
|
||||||
custom-class="g-dialog top-course-sorter-dialog"
|
|
||||||
width="820px"
|
width="820px"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
@closed="handleClosed"
|
@closed="handleClosed"
|
||||||
@@ -13,10 +13,9 @@
|
|||||||
v-if="topList.length"
|
v-if="topList.length"
|
||||||
ref="sortTable"
|
ref="sortTable"
|
||||||
:data="topList"
|
:data="topList"
|
||||||
class="top-course-sorter__table"
|
class="top-course-sorter__table use-table"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
:row-class-name="getRowClassName"
|
:row-class-name="getRowClassName"
|
||||||
:header-cell-style="{ background: '#f5f7fa', color: '#303133', fontWeight: '600' }"
|
|
||||||
>
|
>
|
||||||
<el-table-column width="60" align="center">
|
<el-table-column width="60" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
@@ -262,39 +261,8 @@ export default {
|
|||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
}
|
}
|
||||||
|
::v-deep .el-dialog__body {
|
||||||
.top-course-sorter__table {
|
padding: 10px 20px 20px;
|
||||||
::v-deep .el-table__row {
|
|
||||||
cursor: move;
|
|
||||||
transition: background-color 0.2s ease;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #f9fbff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-dragging {
|
|
||||||
opacity: 0.7;
|
|
||||||
background-color: #ecf5ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.drag-over {
|
|
||||||
border-top: 2px solid #409eff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .el-table__body-wrapper {
|
|
||||||
.el-table__row {
|
|
||||||
&:last-child {
|
|
||||||
.el-table__cell {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .el-table__cell {
|
|
||||||
padding: 12px 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.drag-handle {
|
.drag-handle {
|
||||||
|
|||||||
@@ -1,20 +1,41 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog title="添加报名" :visible.sync="visibleSync" width="1200px" top="8vh" append-to-body @close="handleClose">
|
<el-dialog title="添加报名" class="common-course-dialog" :visible.sync="visibleSync" width="1000px" top="8vh" append-to-body @close="handleClose">
|
||||||
<el-tabs v-model="activeTab">
|
<el-tabs v-model="activeTab">
|
||||||
<el-tab-pane label="从受众中选择" name="quick">
|
<el-tab-pane label="从受众中选择" name="quick">
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
<div class="tab-search">
|
<div class="tab-search">
|
||||||
<el-input
|
<el-select
|
||||||
v-model="keyword"
|
class="member-select"
|
||||||
placeholder="姓名"
|
ref="memberSelect"
|
||||||
size="small"
|
v-model="memberSelected"
|
||||||
|
multiple
|
||||||
|
filterable
|
||||||
|
remote
|
||||||
clearable
|
clearable
|
||||||
class="input"
|
reserve-keyword
|
||||||
@keyup.enter.native="onSearch"
|
placeholder="姓名"
|
||||||
/>
|
:multiple-limit="5"
|
||||||
<el-button type="primary" size="small" @click="onSearch">查询</el-button>
|
:remote-method="remoteSearchMember"
|
||||||
<el-button type="primary" size="small" @click="onReset">重置</el-button>
|
:loading="memberLoading"
|
||||||
|
@input.native="limitMemberInput"
|
||||||
|
@visible-change="handleMemberVisibleChange"
|
||||||
|
@change="handleMemberChange"
|
||||||
|
@clear="handleMemberClear"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in memberOptions"
|
||||||
|
:key="item.userId"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.userId"
|
||||||
|
>
|
||||||
|
<span>{{ item.name }}</span>
|
||||||
|
<span v-if="item.code" class="option-code">({{ item.code }})</span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-button type="primary" size="small" @click="onSearch" style="margin-left: 8px;">查询</el-button>
|
||||||
|
<el-button size="small" @click="onReset" style="margin-left: 4px;">重置</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table
|
<el-table
|
||||||
class="use-table"
|
class="use-table"
|
||||||
@@ -51,6 +72,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fetchAudienceList, saveStu } from "@/api/signup/commonStudent";
|
import { fetchAudienceList, saveStu } from "@/api/signup/commonStudent";
|
||||||
|
import apiUserbasic from "@/api/boe/userbasic.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "AudienceModal",
|
name: "AudienceModal",
|
||||||
@@ -74,6 +96,10 @@ export default {
|
|||||||
total: 0,
|
total: 0,
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
selectedRows: [],
|
selectedRows: [],
|
||||||
|
// 成员远程搜索多选
|
||||||
|
memberSelected: [],
|
||||||
|
memberOptions: [],
|
||||||
|
memberLoading: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -89,15 +115,18 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
resetAndFetch() {
|
resetAndFetch() {
|
||||||
this.keyword = "";
|
|
||||||
this.pageNo = 1;
|
this.pageNo = 1;
|
||||||
this.selectedRows = [];
|
this.selectedRows = [];
|
||||||
|
this.keyword = "";
|
||||||
|
this.memberSelected = [];
|
||||||
|
this.memberOptions = [];
|
||||||
this.fetchList();
|
this.fetchList();
|
||||||
},
|
},
|
||||||
fetchList() {
|
fetchList() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
fetchAudienceList({
|
fetchAudienceList({
|
||||||
keyword: this.keyword,
|
// memberList 为多选成员 ID 列表
|
||||||
|
memberList: this.memberSelected || [],
|
||||||
pageNo: this.pageNo,
|
pageNo: this.pageNo,
|
||||||
pageSize: this.pageSize,
|
pageSize: this.pageSize,
|
||||||
audienceIdList: this.audienceIds || [],
|
audienceIdList: this.audienceIds || [],
|
||||||
@@ -117,6 +146,8 @@ export default {
|
|||||||
},
|
},
|
||||||
onReset() {
|
onReset() {
|
||||||
this.keyword = "";
|
this.keyword = "";
|
||||||
|
this.memberSelected = [];
|
||||||
|
this.memberOptions = [];
|
||||||
this.onSearch();
|
this.onSearch();
|
||||||
},
|
},
|
||||||
onPageChange(page) {
|
onPageChange(page) {
|
||||||
@@ -126,6 +157,79 @@ export default {
|
|||||||
onSelectionChange(list) {
|
onSelectionChange(list) {
|
||||||
this.selectedRows = list;
|
this.selectedRows = list;
|
||||||
},
|
},
|
||||||
|
// ===== 成员远程搜索,多选逻辑(参考 ManageListRemote.vue 的创建人筛选) =====
|
||||||
|
async remoteSearchMember(keyword) {
|
||||||
|
const limited = (keyword || "").slice(0, 50);
|
||||||
|
if (this.$refs.memberSelect && this.$refs.memberSelect.query !== limited) {
|
||||||
|
this.$refs.memberSelect.query = limited;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (
|
||||||
|
this.$refs.memberSelect &&
|
||||||
|
this.$refs.memberSelect.$refs &&
|
||||||
|
this.$refs.memberSelect.$refs.input
|
||||||
|
) {
|
||||||
|
this.$refs.memberSelect.$refs.input.value = limited;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const query = limited.trim();
|
||||||
|
if (!query || query.length <= 1) {
|
||||||
|
this.memberOptions = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.memberLoading = true;
|
||||||
|
try {
|
||||||
|
const res = await apiUserbasic.selectUser(query);
|
||||||
|
if (res && res.status === 200) {
|
||||||
|
const resultList = res.result || [];
|
||||||
|
this.memberOptions = resultList
|
||||||
|
.map((item) => this.formatMemberItem(item))
|
||||||
|
.filter((item) => item.userId);
|
||||||
|
} else {
|
||||||
|
this.memberOptions = [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.memberOptions = [];
|
||||||
|
} finally {
|
||||||
|
this.memberLoading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
formatMemberItem(item = {}) {
|
||||||
|
return {
|
||||||
|
userId: item.id,
|
||||||
|
name: item.realName,
|
||||||
|
code: item.userNo,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
handleMemberChange(value = []) {
|
||||||
|
// 限制最多 5 个,保持与 ManageListRemote 中创建人筛选一致
|
||||||
|
this.memberSelected = (value || []).slice(0, 5);
|
||||||
|
},
|
||||||
|
handleMemberClear() {
|
||||||
|
this.memberSelected = [];
|
||||||
|
this.memberOptions = [];
|
||||||
|
},
|
||||||
|
handleMemberVisibleChange(visible) {
|
||||||
|
if (!visible) return;
|
||||||
|
const select = this.$refs.memberSelect;
|
||||||
|
const query = (select && select.query) || "";
|
||||||
|
if (!query) {
|
||||||
|
this.memberOptions = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
limitMemberInput(event) {
|
||||||
|
const limited =
|
||||||
|
(event && event.target && event.target.value
|
||||||
|
? event.target.value
|
||||||
|
: ""
|
||||||
|
).slice(0, 50);
|
||||||
|
if (event && event.target && event.target.value !== limited) {
|
||||||
|
event.target.value = limited;
|
||||||
|
}
|
||||||
|
if (this.$refs.memberSelect) {
|
||||||
|
this.$refs.memberSelect.query = limited;
|
||||||
|
}
|
||||||
|
},
|
||||||
handleClose() {
|
handleClose() {
|
||||||
this.visibleSync = false;
|
this.visibleSync = false;
|
||||||
},
|
},
|
||||||
@@ -181,29 +285,5 @@ export default {
|
|||||||
left: 12px;
|
left: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
::v-deep .el-dialog__footer {
|
|
||||||
|
|
||||||
.el-button {
|
|
||||||
min-width: 120px;
|
|
||||||
height: 40px;
|
|
||||||
font-size: 16px;
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 0 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-button--default {
|
|
||||||
color: rgba(0, 0, 0, 0.3);
|
|
||||||
border-color: rgba(0, 0, 0, 0.3);
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-button--primary {
|
|
||||||
background-color: #3b7cff;
|
|
||||||
border-color: #3b7cff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="visible">
|
<div v-if="visible">
|
||||||
<el-dialog :visible="visible" :title="dialogTitle" width="1200px" top="8vh" append-to-body destroy-on-close
|
<el-dialog class="signup-dialog common-course-dialog" :visible="visible" :title="dialogTitle" width="1200px" top="8vh" append-to-body destroy-on-close
|
||||||
class="signup-dialog" @close="handleClose">
|
@close="handleClose">
|
||||||
<div class="signup-wrap">
|
<div class="signup-wrap">
|
||||||
<el-tabs v-model="activeTab">
|
<el-tabs v-model="activeTab">
|
||||||
<!-- <el-tab-pane v-if="infoType" label="项目内学员" name="project">
|
<!-- <el-tab-pane v-if="infoType" label="项目内学员" name="project">
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
<el-button type="primary" size="small" @click="onSearchStu">
|
<el-button type="primary" size="small" @click="onSearchStu">
|
||||||
搜索
|
搜索
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" size="small" @click="resetStu">重置</el-button>
|
<el-button size="small" @click="resetStu">重置</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="split">
|
<div class="split">
|
||||||
<div class="left-tree">
|
<div class="left-tree">
|
||||||
@@ -43,8 +43,15 @@
|
|||||||
@node-click="onOrgSelect" />
|
@node-click="onOrgSelect" />
|
||||||
</div>
|
</div>
|
||||||
<div class="table-area">
|
<div class="table-area">
|
||||||
<el-table class="use-table" border :data="stuTable.list"
|
<el-table
|
||||||
@selection-change="onStuSelectionChange" :row-key="row => row.id || row.userId">
|
ref="stuTable"
|
||||||
|
class="use-table"
|
||||||
|
border
|
||||||
|
:data="stuTable.list"
|
||||||
|
@selection-change="onStuSelectionChange"
|
||||||
|
:row-key="row => row.id || row.userId"
|
||||||
|
:reserve-selection="true"
|
||||||
|
>
|
||||||
<el-table-column type="selection" width="50" />
|
<el-table-column type="selection" width="50" />
|
||||||
<el-table-column prop="realName" label="姓名" width="120" />
|
<el-table-column prop="realName" label="姓名" width="120" />
|
||||||
<el-table-column prop="userNo" label="工号" width="120" />
|
<el-table-column prop="userNo" label="工号" width="120" />
|
||||||
@@ -70,7 +77,14 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
<el-button size="small" @click="resetOrg">重置</el-button>
|
<el-button size="small" @click="resetOrg">重置</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-tree class="org-tree" show-checkbox node-key="id" :data="orgList" :props="orgTreeProps" lazy
|
<el-tree
|
||||||
|
ref="orgTree"
|
||||||
|
class="org-tree"
|
||||||
|
show-checkbox
|
||||||
|
node-key="id"
|
||||||
|
:data="orgList"
|
||||||
|
:props="orgTreeProps"
|
||||||
|
lazy
|
||||||
:load="loadOrgNodeFull" @check-change="onOrgCheckChange" :default-checked-keys="selectedOrgKeys" />
|
:load="loadOrgNodeFull" @check-change="onOrgCheckChange" :default-checked-keys="selectedOrgKeys" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
@@ -83,8 +97,15 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
<el-button size="small" @click="resetAudienceInfo">重置</el-button>
|
<el-button size="small" @click="resetAudienceInfo">重置</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table class="use-table" border :data="audienceTable.list" @selection-change="onAudienceSelectionChange"
|
<el-table
|
||||||
:row-key="row => row.id">
|
ref="audienceTable"
|
||||||
|
class="use-table"
|
||||||
|
border
|
||||||
|
:data="audienceTable.list"
|
||||||
|
@selection-change="onAudienceSelectionChange"
|
||||||
|
:row-key="row => row.id"
|
||||||
|
:reserve-selection="true"
|
||||||
|
>
|
||||||
<el-table-column type="selection" width="50" />
|
<el-table-column type="selection" width="50" />
|
||||||
<el-table-column prop="audienceName" label="受众名称" min-width="220" />
|
<el-table-column prop="audienceName" label="受众名称" min-width="220" />
|
||||||
<el-table-column prop="totalMember" label="总人数" width="100" />
|
<el-table-column prop="totalMember" label="总人数" width="100" />
|
||||||
@@ -104,7 +125,7 @@
|
|||||||
<div class="already">已选</div>
|
<div class="already">已选</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :style="{ 'max-height': screenHeight - 235 + 'px' }" style="overflow-y: auto">
|
<div class="selected-area" :style="{ 'max-height': screenHeight - 235 + 'px' }" style="overflow-y: auto">
|
||||||
<div class="selecteds" v-if="infoType">
|
<div class="selecteds" v-if="infoType">
|
||||||
<div class="person">项目内学员</div>
|
<div class="person">项目内学员</div>
|
||||||
<div v-for="(item, i) in projectSelectRows" :key="item.id || item.studentId">
|
<div v-for="(item, i) in projectSelectRows" :key="item.id || item.studentId">
|
||||||
@@ -309,6 +330,8 @@ export default {
|
|||||||
visible(val) {
|
visible(val) {
|
||||||
if (val) {
|
if (val) {
|
||||||
this.initData();
|
this.initData();
|
||||||
|
} else {
|
||||||
|
this.resetState();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -318,6 +341,30 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 参考 CommonStudent.vue,在关闭弹窗时清空各种选中与搜索条件
|
||||||
|
resetState() {
|
||||||
|
this.projectParams.studentName = "";
|
||||||
|
this.nameSearch = { keyword: "", departId: "" };
|
||||||
|
this.audienceName = { keyword: "" };
|
||||||
|
this.searchOrgName = { keyword: "", pageNo: 1, pageSize: 200 };
|
||||||
|
this.projectSelectRows = [];
|
||||||
|
this.stuSelectRows = [];
|
||||||
|
this.auditSelectRows = [];
|
||||||
|
this.deptList = [];
|
||||||
|
this.selectedOrgKeys = [];
|
||||||
|
this.member = false;
|
||||||
|
this.dept = false;
|
||||||
|
this.person = false;
|
||||||
|
this.group = false;
|
||||||
|
|
||||||
|
// 清空表格勾选
|
||||||
|
if (this.$refs.stuTable && this.$refs.stuTable.clearSelection) {
|
||||||
|
this.$refs.stuTable.clearSelection();
|
||||||
|
}
|
||||||
|
if (this.$refs.audienceTable && this.$refs.audienceTable.clearSelection) {
|
||||||
|
this.$refs.audienceTable.clearSelection();
|
||||||
|
}
|
||||||
|
},
|
||||||
initData() {
|
initData() {
|
||||||
this.courseDetail = JSON.parse(sessionStorage.getItem("courseDetail") || "{}");
|
this.courseDetail = JSON.parse(sessionStorage.getItem("courseDetail") || "{}");
|
||||||
this.projectParams = {
|
this.projectParams = {
|
||||||
@@ -374,6 +421,10 @@ export default {
|
|||||||
console.log("res", res);
|
console.log("res", res);
|
||||||
this.stuTable.list = res.data?.list || [];
|
this.stuTable.list = res.data?.list || [];
|
||||||
this.stuTable.total = res.data?.total || 0;
|
this.stuTable.total = res.data?.total || 0;
|
||||||
|
// 根据右侧已选,恢复当前页的勾选状态
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.syncStuTableSelection();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onStuPageChange(page) {
|
onStuPageChange(page) {
|
||||||
@@ -381,7 +432,22 @@ export default {
|
|||||||
this.onSearchStu();
|
this.onSearchStu();
|
||||||
},
|
},
|
||||||
onStuSelectionChange(list) {
|
onStuSelectionChange(list) {
|
||||||
this.stuSelectRows = list;
|
// Element 表格在翻页时会把当前页的 selection 通过 list 传进来
|
||||||
|
// 为了保留其他页已选,这里做合并而不是直接覆盖
|
||||||
|
const currentPageIds = this.stuTable.list.map((r) => r.id || r.userId);
|
||||||
|
// 先保留非当前页的已选
|
||||||
|
const otherPageSelected = this.stuSelectRows.filter(
|
||||||
|
(r) => !currentPageIds.includes(r.id || r.userId)
|
||||||
|
);
|
||||||
|
const merged = [...otherPageSelected, ...list];
|
||||||
|
// 根据 id/userId 去重
|
||||||
|
const seen = new Set();
|
||||||
|
this.stuSelectRows = merged.filter((r) => {
|
||||||
|
const key = r.id || r.userId;
|
||||||
|
if (!key || seen.has(key)) return false;
|
||||||
|
seen.add(key);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
resetStu() {
|
resetStu() {
|
||||||
this.nameSearch = { keyword: "", departId: "" };
|
this.nameSearch = { keyword: "", departId: "" };
|
||||||
@@ -444,6 +510,10 @@ export default {
|
|||||||
console.log('searchAudience', res);
|
console.log('searchAudience', res);
|
||||||
this.audienceTable.list = res.data?.list || [];
|
this.audienceTable.list = res.data?.list || [];
|
||||||
this.audienceTable.total = res.data?.total || 0;
|
this.audienceTable.total = res.data?.total || 0;
|
||||||
|
// 根据右侧已选,恢复当前页的受众勾选状态
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.syncAudienceTableSelection();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onAudiencePageChange(page) {
|
onAudiencePageChange(page) {
|
||||||
@@ -451,7 +521,50 @@ export default {
|
|||||||
this.searchAudience();
|
this.searchAudience();
|
||||||
},
|
},
|
||||||
onAudienceSelectionChange(list) {
|
onAudienceSelectionChange(list) {
|
||||||
this.auditSelectRows = list;
|
const currentPageIds = this.audienceTable.list.map((r) => r.id);
|
||||||
|
const otherPageSelected = this.auditSelectRows.filter(
|
||||||
|
(r) => !currentPageIds.includes(r.id)
|
||||||
|
);
|
||||||
|
const merged = [...otherPageSelected, ...list];
|
||||||
|
const seen = new Set();
|
||||||
|
this.auditSelectRows = merged.filter((r) => {
|
||||||
|
const key = r.id;
|
||||||
|
if (!key || seen.has(key)) return false;
|
||||||
|
seen.add(key);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 根据 stuSelectRows 恢复当前页表格里的勾选
|
||||||
|
syncStuTableSelection() {
|
||||||
|
if (!this.$refs.stuTable) return;
|
||||||
|
const table = this.$refs.stuTable;
|
||||||
|
if (!table.clearSelection || !table.toggleRowSelection) return;
|
||||||
|
const selectedMap = new Set(
|
||||||
|
(this.stuSelectRows || []).map((r) => r.id || r.userId)
|
||||||
|
);
|
||||||
|
table.clearSelection();
|
||||||
|
this.stuTable.list.forEach((row) => {
|
||||||
|
const key = row.id || row.userId;
|
||||||
|
if (key && selectedMap.has(key)) {
|
||||||
|
table.toggleRowSelection(row, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 根据 auditSelectRows 恢复当前页受众表格里的勾选
|
||||||
|
syncAudienceTableSelection() {
|
||||||
|
if (!this.$refs.audienceTable) return;
|
||||||
|
const table = this.$refs.audienceTable;
|
||||||
|
if (!table.clearSelection || !table.toggleRowSelection) return;
|
||||||
|
const selectedMap = new Set(
|
||||||
|
(this.auditSelectRows || []).map((r) => r.id)
|
||||||
|
);
|
||||||
|
table.clearSelection();
|
||||||
|
this.audienceTable.list.forEach((row) => {
|
||||||
|
const key = row.id;
|
||||||
|
if (key && selectedMap.has(key)) {
|
||||||
|
table.toggleRowSelection(row, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
resetAudienceInfo() {
|
resetAudienceInfo() {
|
||||||
this.audienceName.keyword = "";
|
this.audienceName.keyword = "";
|
||||||
@@ -467,13 +580,25 @@ export default {
|
|||||||
this.stuSelectRows = this.stuSelectRows.filter(
|
this.stuSelectRows = this.stuSelectRows.filter(
|
||||||
(i) => (i.id || i.userId) !== (item.id || item.userId)
|
(i) => (i.id || i.userId) !== (item.id || item.userId)
|
||||||
);
|
);
|
||||||
|
// 同步左侧快速选人表格的勾选状态
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.syncStuTableSelection();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
removeOrg(item) {
|
removeOrg(item) {
|
||||||
this.deptList = this.deptList.filter((i) => i.id !== item.id);
|
this.deptList = this.deptList.filter((i) => i.id !== item.id);
|
||||||
this.selectedOrgKeys = this.deptList.map((d) => d.id);
|
this.selectedOrgKeys = this.deptList.map((d) => d.id);
|
||||||
|
// 同步左侧组织树的勾选状态
|
||||||
|
if (this.$refs.orgTree && this.$refs.orgTree.setCheckedKeys) {
|
||||||
|
this.$refs.orgTree.setCheckedKeys(this.selectedOrgKeys);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
removeAudience(item) {
|
removeAudience(item) {
|
||||||
this.auditSelectRows = this.auditSelectRows.filter((i) => i.id !== item.id);
|
this.auditSelectRows = this.auditSelectRows.filter((i) => i.id !== item.id);
|
||||||
|
// 同步左侧受众表格的勾选状态
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.syncAudienceTableSelection();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
submitAuth() {
|
submitAuth() {
|
||||||
if (this.type === 2) {
|
if (this.type === 2) {
|
||||||
@@ -524,28 +649,6 @@ export default {
|
|||||||
background-color: #3b7cff;
|
background-color: #3b7cff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.signup-dialog ::v-deep .el-dialog__footer {
|
|
||||||
|
|
||||||
.el-button {
|
|
||||||
min-width: 120px;
|
|
||||||
height: 40px;
|
|
||||||
font-size: 16px;
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 0 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-button--default {
|
|
||||||
color: rgba(0, 0, 0, 0.3);
|
|
||||||
border-color: rgba(0, 0, 0, 0.3);
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-button--primary {
|
|
||||||
background-color: #3b7cff;
|
|
||||||
border-color: #3b7cff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.signup-wrap {
|
.signup-wrap {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -596,8 +699,23 @@ export default {
|
|||||||
.right1 {
|
.right1 {
|
||||||
border-left: 1px solid #f2f6fe;
|
border-left: 1px solid #f2f6fe;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
max-width: 200px;
|
width: 200px;
|
||||||
|
.selected-area {
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #4284F7;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
background-color:rgba(0, 0, 0, .1);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #4284F7
|
||||||
|
}
|
||||||
|
}
|
||||||
.onerow {
|
.onerow {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
@@ -722,14 +722,18 @@ export default {
|
|||||||
this.getSignupList();
|
this.getSignupList();
|
||||||
},
|
},
|
||||||
handleDeleteSignup(row) {
|
handleDeleteSignup(row) {
|
||||||
this.$confirm(`<i class="el-icon-warning-outline"></i>确认删除${row.name || ''}的报名记录吗?`, '删除确认', {
|
this.$confirm(`<i class="el-icon-warning-outline"></i>确定删除${row.name || ''}的报名记录吗?`, '删除确认', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
dangerouslyUseHTMLString: true,
|
dangerouslyUseHTMLString: true,
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
customClass: 'custom-confirm-dialog'
|
customClass: 'custom-confirm-dialog'
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
apicourseStudy.deleteSignUp(row.id, this.courseDetail.id)
|
apicourseStudy.deleteNewSignUp({
|
||||||
|
id: row.id,
|
||||||
|
courseId: this.courseDetail.id,
|
||||||
|
studentId: row.aid
|
||||||
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res && res.status === 200) {
|
if (res && res.status === 200) {
|
||||||
this.$showMessage("删除成功", 'success');
|
this.$showMessage("删除成功", 'success');
|
||||||
|
|||||||
@@ -100,9 +100,12 @@
|
|||||||
placeholder="资源归属"
|
placeholder="资源归属"
|
||||||
clearable
|
clearable
|
||||||
:props="resOwnerCascaderProps"
|
:props="resOwnerCascaderProps"
|
||||||
|
:options="resOwnerOptions"
|
||||||
:show-all-levels="false"
|
:show-all-levels="false"
|
||||||
@change="handleResOwnerChange"
|
@change="handleResOwnerChange"
|
||||||
@input.native="limitResOwnerInput"
|
@input.native="limitResOwnerInput"
|
||||||
|
@clear="handleResOwnerClear"
|
||||||
|
@visible-change="handleResOwnerVisibleChange"
|
||||||
filterable
|
filterable
|
||||||
:filter-method="resOwnerFilterMethod"
|
:filter-method="resOwnerFilterMethod"
|
||||||
></el-cascader>
|
></el-cascader>
|
||||||
@@ -227,7 +230,7 @@
|
|||||||
<span class="common-cell common-cell-right">{{ scope.row.openCourse == 1 ? '是' : '否' }}</span>
|
<span class="common-cell common-cell-right">{{ scope.row.openCourse == 1 ? '是' : '否' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="资源归属" prop="orgName" min-width="220" align="center" sortable="custom">
|
<el-table-column label="资源归属" prop="orgName" min-width="220" align="center" sortable="custom" show-overflow-tooltip>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tooltip :content="scope.row.orgFullName || scope.row.orgName" placement="top" effect="dark">
|
<el-tooltip :content="scope.row.orgFullName || scope.row.orgName" placement="top" effect="dark">
|
||||||
<span class="common-cell common-cell-right">{{ scope.row.orgName }}</span>
|
<span class="common-cell common-cell-right">{{ scope.row.orgName }}</span>
|
||||||
@@ -464,14 +467,23 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['resOwnerMap', 'sysTypeMap', 'userInfo', 'identity']),
|
...mapGetters(['resOwnerMap', 'sysTypeMap', 'userInfo', 'identity']),
|
||||||
resOwnerCascaderProps() {
|
resOwnerCascaderProps() {
|
||||||
|
// 搜索模式:关闭懒加载,直接使用全量 options
|
||||||
|
if (this.resOwnerSearchMode) {
|
||||||
|
return {
|
||||||
|
value: 'id',
|
||||||
|
label: 'name',
|
||||||
|
children: 'children',
|
||||||
|
checkStrictly: true, // 允许选择任意一级选项
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 非搜索模式:开启前端“伪懒加载”,数据从本地缓存树中按需取
|
||||||
return {
|
return {
|
||||||
value: 'id',
|
value: 'id',
|
||||||
label: 'name',
|
label: 'name',
|
||||||
children: 'children',
|
children: 'children',
|
||||||
lazy: true,
|
lazy: true,
|
||||||
lazyLoad: this.loadResOwnerNode,
|
lazyLoad: this.loadResOwnerNodeFromCache,
|
||||||
leaf: 'leaf',
|
checkStrictly: true, // 允许选择任意一级选项
|
||||||
checkStrictly: true // 允许选择任意一级选项
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
// 动态计算“授课教师”列的最小宽度,避免固定 260px
|
// 动态计算“授课教师”列的最小宽度,避免固定 260px
|
||||||
@@ -496,7 +508,11 @@ export default {
|
|||||||
sysTypeList: [],
|
sysTypeList: [],
|
||||||
resOwnerListMap: [],
|
resOwnerListMap: [],
|
||||||
resOwnerSelected: [],
|
resOwnerSelected: [],
|
||||||
resOwnerCascaderOptions: [],
|
// 资源归属全量树 & 级联选项
|
||||||
|
resOwnerTreeAll: [],
|
||||||
|
resOwnerOptions: [],
|
||||||
|
// 资源归属搜索模式开关(有关键字时为 true)
|
||||||
|
resOwnerSearchMode: false,
|
||||||
showSetTopFeature: false,
|
showSetTopFeature: false,
|
||||||
page: {
|
page: {
|
||||||
pageIndex: 1,//第几页
|
pageIndex: 1,//第几页
|
||||||
@@ -628,6 +644,8 @@ export default {
|
|||||||
//已经加载tree的情况下,不需要再单独的加载一次
|
//已经加载tree的情况下,不需要再单独的加载一次
|
||||||
this.loadResOwners();
|
this.loadResOwners();
|
||||||
this.loadSysTypes();
|
this.loadSysTypes();
|
||||||
|
// 加载资源归属全量树,供级联和搜索使用
|
||||||
|
this.loadAllResOwnerTree();
|
||||||
document.querySelector('#app').style.overflowX = 'hidden';
|
document.querySelector('#app').style.overflowX = 'hidden';
|
||||||
this.applyAppScrollbarStyle();
|
this.applyAppScrollbarStyle();
|
||||||
|
|
||||||
@@ -838,8 +856,36 @@ export default {
|
|||||||
if (event && event.target && event.target.value !== limited) {
|
if (event && event.target && event.target.value !== limited) {
|
||||||
event.target.value = limited;
|
event.target.value = limited;
|
||||||
}
|
}
|
||||||
if (this.$refs.resOwnerCascader) {
|
const keyword = (limited || '').trim();
|
||||||
this.$refs.resOwnerCascader.inputValue = limited;
|
// 根据是否有关键字切换搜索模式
|
||||||
|
this.resOwnerSearchMode = !!keyword;
|
||||||
|
if (this.resOwnerSearchMode) {
|
||||||
|
// 搜索模式:使用全量树作为 options,交给 filter-method 过滤
|
||||||
|
this.resOwnerOptions = this.resOwnerTreeAll;
|
||||||
|
} else {
|
||||||
|
// 非搜索模式:清空 options,交给 lazyLoad 从缓存树按需“懒加载”
|
||||||
|
this.resOwnerOptions = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 清空选择时,恢复到懒加载模式
|
||||||
|
handleResOwnerClear() {
|
||||||
|
this.resOwnerSearchMode = false;
|
||||||
|
this.resOwnerOptions = [];
|
||||||
|
// 清空输入框的文字,避免残留关键字
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.resOwnerCascader && this.$refs.resOwnerCascader.inputValue !== undefined) {
|
||||||
|
this.$refs.resOwnerCascader.inputValue = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 下拉面板打开时,如果当前没有关键字,也确保是懒加载模式
|
||||||
|
handleResOwnerVisibleChange(visible) {
|
||||||
|
if (!visible) return;
|
||||||
|
// 如果没有关键字,就强制回到懒加载模式
|
||||||
|
const keyword = (this.$refs.resOwnerCascader && this.$refs.resOwnerCascader.inputValue) || '';
|
||||||
|
if (!keyword) {
|
||||||
|
this.resOwnerSearchMode = false;
|
||||||
|
this.resOwnerOptions = [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resOwnerFilterMethod(node, keyword) {
|
resOwnerFilterMethod(node, keyword) {
|
||||||
@@ -1460,59 +1506,49 @@ export default {
|
|||||||
sessionStorage.setItem('courseDetail', JSON.stringify(row));
|
sessionStorage.setItem('courseDetail', JSON.stringify(row));
|
||||||
this.$router.push({ path: '/iframe/course/coursemanage-remote' });
|
this.$router.push({ path: '/iframe/course/coursemanage-remote' });
|
||||||
},
|
},
|
||||||
async loadResOwnerNode(node, resolve) {
|
// 前端“伪懒加载”:根据本地全量机构树按需返回子节点
|
||||||
const { level } = node;
|
// 为了让 el-cascader 的 loading 动画有可见效果,这里故意加入一个很小的延时再 resolve
|
||||||
let parentId = '';
|
async loadResOwnerNodeFromCache(node, resolve) {
|
||||||
|
try {
|
||||||
if (level === 0) {
|
const delayResolve = (nodes) => {
|
||||||
// 第一层:获取根节点
|
// 适当延时 150ms,让 loading 动画可见,但又不会让用户感觉明显卡顿
|
||||||
try {
|
setTimeout(() => resolve(nodes), 150);
|
||||||
const res = await apiUserbasic.findOrgsByKeyword('');
|
};
|
||||||
if (res && res.result) {
|
|
||||||
const nodes = res.result.map(item => ({
|
// 根节点(level === 0):返回所有一级机构
|
||||||
id: item.id,
|
if (node.level === 0) {
|
||||||
name: item.name,
|
return delayResolve(this.resOwnerTreeAll || []);
|
||||||
hrbpId: item.hrbpId,
|
|
||||||
leaf: false, // 懒加载模式下,先假设所有节点都可能有子节点
|
|
||||||
children: [] // 空数组表示需要懒加载
|
|
||||||
}));
|
|
||||||
resolve(nodes);
|
|
||||||
} else {
|
|
||||||
resolve([]);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('加载资源归属失败:', error);
|
|
||||||
resolve([]);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// 子节点:根据父节点ID加载
|
// 其他层级:根据当前节点 id 在树中查找对应节点,再返回其 children
|
||||||
parentId = node.value || (node.data && node.data.id);
|
const currentId = node.value || (node.data && node.data.id);
|
||||||
if (!parentId) {
|
if (!currentId) {
|
||||||
resolve([]);
|
return delayResolve([]);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
const res = await apiUserbasic.getOrgInfo(parentId);
|
const findNodeById = (list = [], id) => {
|
||||||
if (res && res.status === 200 && res.result) {
|
for (let i = 0; i < list.length; i++) {
|
||||||
let treeList = [];
|
const item = list[i];
|
||||||
if (res.result.directChildList && res.result.directChildList.length > 0) {
|
if (item.id === id) {
|
||||||
treeList = res.result.directChildList.map(item => ({
|
return item;
|
||||||
id: item.id,
|
}
|
||||||
name: item.name,
|
if (Array.isArray(item.children) && item.children.length > 0) {
|
||||||
hrbpId: item.hrbpId,
|
const found = findNodeById(item.children, id);
|
||||||
leaf: false, // 懒加载模式下,先假设所有节点都可能有子节点
|
if (found) return found;
|
||||||
children: [] // 空数组表示需要懒加载
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
resolve(treeList);
|
|
||||||
} else {
|
|
||||||
// 如果没有子节点,返回空数组,级联选择器会自动将其视为叶子节点
|
|
||||||
resolve([]);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
return null;
|
||||||
console.error('加载资源归属子节点失败:', error);
|
};
|
||||||
resolve([]);
|
|
||||||
|
const target = findNodeById(this.resOwnerTreeAll || [], currentId);
|
||||||
|
if (target && Array.isArray(target.children)) {
|
||||||
|
delayResolve(target.children);
|
||||||
|
} else {
|
||||||
|
delayResolve([]);
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('本地懒加载资源归属节点失败:', e);
|
||||||
|
resolve([]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleResOwnerChange(value) {
|
handleResOwnerChange(value) {
|
||||||
@@ -1536,6 +1572,39 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// 将后端机构节点转换为级联组件所需结构
|
||||||
|
mapOrgToCascaderNode(node = {}) {
|
||||||
|
const children = Array.isArray(node.childList)
|
||||||
|
? node.childList.map(child => this.mapOrgToCascaderNode(child))
|
||||||
|
: [];
|
||||||
|
return {
|
||||||
|
id: node.organizationId,
|
||||||
|
name: node.orgName,
|
||||||
|
children,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// 加载资源归属全量机构树
|
||||||
|
async loadAllResOwnerTree() {
|
||||||
|
try {
|
||||||
|
const res = await apiUserbasic.getAllOrgTree();
|
||||||
|
if (res && res.status === 200 && res.result && Array.isArray(res.result.orgTreeList)) {
|
||||||
|
this.resOwnerTreeAll = res.result.orgTreeList.map(item => this.mapOrgToCascaderNode(item));
|
||||||
|
// 默认进入非搜索模式,由懒加载从本地树按需返回节点
|
||||||
|
this.resOwnerOptions = [];
|
||||||
|
} else if (res && res.result && Array.isArray(res.result.orgTreeList)) {
|
||||||
|
// 兼容没有 status 字段但有 result 的情况
|
||||||
|
this.resOwnerTreeAll = res.result.orgTreeList.map(item => this.mapOrgToCascaderNode(item));
|
||||||
|
this.resOwnerOptions = [];
|
||||||
|
} else {
|
||||||
|
this.resOwnerTreeAll = [];
|
||||||
|
this.resOwnerOptions = [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载资源归属全量树失败:', error);
|
||||||
|
this.resOwnerTreeAll = [];
|
||||||
|
this.resOwnerOptions = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
showChooseCourse() {
|
showChooseCourse() {
|
||||||
this.courseChooseShow = true;
|
this.courseChooseShow = true;
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user