diff --git a/src/api/modules/courseStudy.js b/src/api/modules/courseStudy.js
index af906be0..f16a36b3 100644
--- a/src/api/modules/courseStudy.js
+++ b/src/api/modules/courseStudy.js
@@ -17,7 +17,7 @@ const hasSignup = function(courseId) {
* 课程报名,微课,录播课
* @param {Object} data
* {
- courseId:
+ courseId:
courseName:
courseType: 课程类型,对应微课,录播课
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}`);
}
+/*
+删除课程学习记录
+@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,
findSignup,
deleteSignup,
+ deleteNewSignUp,
importSignup,
countSignup,
studyIndex,
diff --git a/src/components/signup/AudienceModal.vue b/src/components/signup/AudienceModal.vue
index abec78ce..f58aebda 100644
--- a/src/components/signup/AudienceModal.vue
+++ b/src/components/signup/AudienceModal.vue
@@ -5,16 +5,37 @@
-
- 查询
- 重置
+ reserve-keyword
+ placeholder="姓名"
+ :multiple-limit="5"
+ :remote-method="remoteSearchMember"
+ :loading="memberLoading"
+ @input.native="limitMemberInput"
+ @visible-change="handleMemberVisibleChange"
+ @change="handleMemberChange"
+ @clear="handleMemberClear"
+ size="small"
+ >
+
+ {{ item.name }}
+ ({{ item.code }})
+
+
+ 查询
+ 重置
import { fetchAudienceList, saveStu } from "@/api/signup/commonStudent";
+import apiUserbasic from "@/api/boe/userbasic.js";
export default {
name: "AudienceModal",
@@ -74,6 +96,10 @@ export default {
total: 0,
pageNo: 1,
selectedRows: [],
+ // 成员远程搜索多选
+ memberSelected: [],
+ memberOptions: [],
+ memberLoading: false,
};
},
watch: {
@@ -89,15 +115,18 @@ export default {
},
methods: {
resetAndFetch() {
- this.keyword = "";
this.pageNo = 1;
this.selectedRows = [];
+ this.keyword = "";
+ this.memberSelected = [];
+ this.memberOptions = [];
this.fetchList();
},
fetchList() {
this.loading = true;
fetchAudienceList({
- keyword: this.keyword,
+ // memberList 为多选成员 ID 列表
+ memberList: this.memberSelected || [],
pageNo: this.pageNo,
pageSize: this.pageSize,
audienceIdList: this.audienceIds || [],
@@ -117,6 +146,8 @@ export default {
},
onReset() {
this.keyword = "";
+ this.memberSelected = [];
+ this.memberOptions = [];
this.onSearch();
},
onPageChange(page) {
@@ -126,6 +157,79 @@ export default {
onSelectionChange(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() {
this.visibleSync = false;
},
diff --git a/src/components/signup/SignupModal.vue b/src/components/signup/SignupModal.vue
index 51b12065..1295a05d 100644
--- a/src/components/signup/SignupModal.vue
+++ b/src/components/signup/SignupModal.vue
@@ -35,7 +35,7 @@
搜索
- 重置
+ 重置
@@ -43,8 +43,15 @@
@node-click="onOrgSelect" />
-
+
@@ -83,8 +90,15 @@
重置
-
+
@@ -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 = "";