feat: 增强报名管理功能,新增删除课程学习记录API,优化受众选择弹窗的多选逻辑和搜索功能

(cherry picked from commit 5f518b713a)
This commit is contained in:
huweihang
2025-12-17 17:44:58 +08:00
parent be730deef2
commit b2654f5501
3 changed files with 239 additions and 19 deletions

View File

@@ -35,7 +35,7 @@
<el-button type="primary" size="small" @click="onSearchStu">
搜索
</el-button>
<el-button type="primary" size="small" @click="resetStu">重置</el-button>
<el-button size="small" @click="resetStu">重置</el-button>
</div>
<div class="split">
<div class="left-tree">
@@ -43,8 +43,15 @@
@node-click="onOrgSelect" />
</div>
<div class="table-area">
<el-table class="use-table" border :data="stuTable.list"
@selection-change="onStuSelectionChange" :row-key="row => row.id || row.userId">
<el-table
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 prop="realName" label="姓名" width="120" />
<el-table-column prop="userNo" label="工号" width="120" />
@@ -83,8 +90,15 @@
</el-button>
<el-button size="small" @click="resetAudienceInfo">重置</el-button>
</div>
<el-table class="use-table" border :data="audienceTable.list" @selection-change="onAudienceSelectionChange"
:row-key="row => row.id">
<el-table
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 prop="audienceName" label="受众名称" min-width="220" />
<el-table-column prop="totalMember" label="总人数" width="100" />
@@ -309,6 +323,8 @@ export default {
visible(val) {
if (val) {
this.initData();
} else {
this.resetState();
}
},
},
@@ -318,6 +334,30 @@ export default {
}
},
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() {
this.courseDetail = JSON.parse(sessionStorage.getItem("courseDetail") || "{}");
this.projectParams = {
@@ -374,6 +414,10 @@ export default {
console.log("res", res);
this.stuTable.list = res.data?.list || [];
this.stuTable.total = res.data?.total || 0;
// 根据右侧已选,恢复当前页的勾选状态
this.$nextTick(() => {
this.syncStuTableSelection();
});
});
},
onStuPageChange(page) {
@@ -381,7 +425,22 @@ export default {
this.onSearchStu();
},
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() {
this.nameSearch = { keyword: "", departId: "" };
@@ -444,6 +503,10 @@ export default {
console.log('searchAudience', res);
this.audienceTable.list = res.data?.list || [];
this.audienceTable.total = res.data?.total || 0;
// 根据右侧已选,恢复当前页的受众勾选状态
this.$nextTick(() => {
this.syncAudienceTableSelection();
});
});
},
onAudiencePageChange(page) {
@@ -451,7 +514,50 @@ export default {
this.searchAudience();
},
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() {
this.audienceName.keyword = "";