mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/learning-system-portal.git
synced 2025-12-12 04:16:45 +08:00
还原
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,8 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="tag-container">
|
<div class="tag-container">
|
||||||
<el-select style="width: 100%;"
|
<el-select style="width: 100%;"
|
||||||
v-model="selectedTagIds"
|
v-model="selectedTags"
|
||||||
multiple
|
multiple
|
||||||
filterable
|
filterable
|
||||||
value-key="id"
|
value-key="id"
|
||||||
@@ -21,13 +22,13 @@
|
|||||||
v-for="item in searchResults"
|
v-for="item in searchResults"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:label="item.tagName"
|
:label="item.tagName"
|
||||||
:value="item.id"
|
:value="item"
|
||||||
:disabled="isTagDisabled(item)"
|
:disabled="isTagDisabled(item)"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
<!-- 添加标签计数显示 -->
|
<!-- 添加标签计数显示 -->
|
||||||
<div class="tag-count">
|
<div class="tag-count">
|
||||||
{{ selectedTagIds.length }}/5
|
{{ selectedTags.length }}/5
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -60,7 +61,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedTagIds: [], // 修改:存储标签ID数组
|
selectedTags: [],
|
||||||
searchResults: [],
|
searchResults: [],
|
||||||
loading: false,
|
loading: false,
|
||||||
tagMap: new Map(),
|
tagMap: new Map(),
|
||||||
@@ -73,13 +74,10 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['userInfo']),
|
...mapGetters(['userInfo']),
|
||||||
// 修改:计算属性,返回完整的标签对象数组用于显示
|
|
||||||
displayTags() {
|
displayTags() {
|
||||||
return this.selectedTagIds.map(tagId => this.tagMap.get(tagId)).filter(Boolean)
|
return this.selectedTags.map(tag =>
|
||||||
},
|
typeof tag === 'object' ? tag : this.tagMap.get(tag)
|
||||||
// 新增:计算标签ID字符串,用于传参
|
).filter(Boolean)
|
||||||
tagIdsString() {
|
|
||||||
return this.selectedTagIds.join(',')
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@@ -90,7 +88,14 @@ export default {
|
|||||||
// 添加:挂载时初始化标签数据
|
// 添加:挂载时初始化标签数据
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.initialTags && this.initialTags.length > 0) {
|
if (this.initialTags && this.initialTags.length > 0) {
|
||||||
this.initTags(this.initialTags);
|
this.selectedTags = this.initialTags;
|
||||||
|
this.searchResults = this.initialTags;
|
||||||
|
// 将初始标签添加到tagMap中,确保删除功能正常
|
||||||
|
this.initialTags.forEach(tag => {
|
||||||
|
if (tag.id) {
|
||||||
|
this.tagMap.set(tag.id, tag);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -100,13 +105,12 @@ export default {
|
|||||||
},
|
},
|
||||||
// 监听初始标签变化,重新加载
|
// 监听初始标签变化,重新加载
|
||||||
initialTags(newVal) {
|
initialTags(newVal) {
|
||||||
if (newVal && newVal.length > 0) {
|
this.selectedTags = newVal || [];
|
||||||
this.initTags(newVal);
|
this.searchResults = newVal || [];
|
||||||
} else {
|
this.tagMap.clear(); // 清空旧缓存
|
||||||
this.selectedTagIds = [];
|
newVal.forEach(tag => {
|
||||||
this.searchResults = [];
|
if (tag.id) this.tagMap.set(tag.id, tag);
|
||||||
this.tagMap.clear();
|
});
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// 监听分类变化,重新加载搜索结果
|
// 监听分类变化,重新加载搜索结果
|
||||||
sysTypeList: {
|
sysTypeList: {
|
||||||
@@ -117,37 +121,22 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
},
|
|
||||||
// 监听标签ID变化,触发change事件
|
|
||||||
tagIdsString(newVal) {
|
|
||||||
this.$emit('change', this.displayTags, newVal);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 新增:初始化标签方法
|
|
||||||
initTags(tags) {
|
|
||||||
this.selectedTagIds = tags.map(tag => tag.id);
|
|
||||||
this.searchResults = [...tags];
|
|
||||||
this.tagMap.clear();
|
|
||||||
tags.forEach(tag => {
|
|
||||||
if (tag.id) {
|
|
||||||
this.tagMap.set(tag.id, tag);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// 新增:检查标签是否应该被禁用
|
// 新增:检查标签是否应该被禁用
|
||||||
isTagDisabled(tag) {
|
isTagDisabled(tag) {
|
||||||
// 如果标签已经被选中,不应该禁用(允许取消选择)
|
// 如果标签已经被选中,不应该禁用(允许取消选择)
|
||||||
const isSelected = this.selectedTagIds.some(selectedTagId => selectedTagId === tag.id);
|
const isSelected = this.selectedTags.some(selectedTag => selectedTag.id === tag.id);
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 如果标签未被选中且已达到最大数量,则禁用
|
// 如果标签未被选中且已达到最大数量,则禁用
|
||||||
return this.selectedTagIds.length >= this.maxTags;
|
return this.selectedTags.length >= this.maxTags;
|
||||||
},
|
},
|
||||||
// 新增:处理输入框获得焦点事件
|
// 新增:处理输入框获得焦点事件
|
||||||
async handleFocus() {
|
async handleFocus() {
|
||||||
this.previousTags = [...this.selectedTagIds];
|
this.previousTags = [...this.selectedTags];
|
||||||
// 当输入框获得焦点时,加载默认的搜索结果
|
// 当输入框获得焦点时,加载默认的搜索结果
|
||||||
if (this.sysTypeList.length > 0) {
|
if (this.sysTypeList.length > 0) {
|
||||||
await this.doSearch('');
|
await this.doSearch('');
|
||||||
@@ -155,15 +144,15 @@ export default {
|
|||||||
},
|
},
|
||||||
// 新增:重置标签状态的方法
|
// 新增:重置标签状态的方法
|
||||||
resetTagState() {
|
resetTagState() {
|
||||||
this.selectedTagIds = [];
|
this.selectedTags = [];
|
||||||
this.searchResults = [];
|
this.searchResults = [];
|
||||||
this.tagMap.clear();
|
this.tagMap.clear();
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.params = {};
|
this.params = {};
|
||||||
},
|
},
|
||||||
handleTagRemove(tagId) {
|
handleTagRemove(tagId) {
|
||||||
this.selectedTagIds = this.selectedTagIds.filter(id => id !== tagId)
|
this.selectedTags = this.selectedTags.filter(id => id !== tagId)
|
||||||
this.$emit('change', this.displayTags, this.tagIdsString)
|
this.$emit('change', this.displayTags)
|
||||||
this.clearInput();
|
this.clearInput();
|
||||||
},
|
},
|
||||||
removeTag(tagId) {
|
removeTag(tagId) {
|
||||||
@@ -182,19 +171,17 @@ export default {
|
|||||||
handleEnterKey(event) {
|
handleEnterKey(event) {
|
||||||
const inputVal = event.target.value?.trim()
|
const inputVal = event.target.value?.trim()
|
||||||
if (!inputVal) return;
|
if (!inputVal) return;
|
||||||
|
|
||||||
// 检查是否与已选择的标签重复
|
// 检查是否与已选择的标签重复
|
||||||
const isDuplicate = this.displayTags.some(tag => tag.tagName === inputVal);
|
const isDuplicate = this.selectedTags.some(tag => tag.tagName === inputVal);
|
||||||
if (isDuplicate) {
|
if (isDuplicate) {
|
||||||
this.$message.warning('该标签已存在,无需重复创建');
|
this.$message.warning('该标签已存在,无需重复创建');
|
||||||
event.target.value = '';
|
event.target.value = '';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!this.searchResults.length && inputVal && this.selectedTags.length < this.maxTags) {
|
||||||
if (!this.searchResults.length && inputVal && this.selectedTagIds.length < this.maxTags) {
|
|
||||||
this.createNewTag(event.target.value.trim())
|
this.createNewTag(event.target.value.trim())
|
||||||
this.clearInput();
|
this.clearInput();
|
||||||
} else if (this.selectedTagIds.length >= this.maxTags) {
|
} else if (this.selectedTags.length >= this.maxTags) {
|
||||||
this.$message.warning('最多只能添加5个标签')
|
this.$message.warning('最多只能添加5个标签')
|
||||||
this.clearInput();
|
this.clearInput();
|
||||||
} else {
|
} else {
|
||||||
@@ -202,20 +189,20 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 修改:处理选择变化事件
|
// 新增:处理选择变化事件
|
||||||
handleSelectionChange(newValues) {
|
handleSelectionChange(newValues) {
|
||||||
// 检查数量限制
|
// 检查数量限制
|
||||||
if (newValues.length > this.maxTags) {
|
if (newValues.length > this.maxTags) {
|
||||||
this.$message.warning(`最多只能选择${this.maxTags}个标签`);
|
this.$message.warning(`最多只能选择${this.maxTags}个标签`);
|
||||||
// 回滚到之前的状态
|
// 回滚到之前的状态
|
||||||
this.selectedTagIds = [...this.previousTags];
|
this.selectedTags = [...this.previousTags];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新前保存当前状态
|
// 更新前保存当前状态
|
||||||
this.previousTags = [...newValues];
|
this.previousTags = [...newValues];
|
||||||
|
this.$emit('change', this.displayTags);
|
||||||
|
|
||||||
// 自动触发change事件,通过watch监听tagIdsString的变化
|
|
||||||
this.clearInput();
|
this.clearInput();
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -228,34 +215,30 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
//修改:创建新标签 - 修复显示问题
|
//创建新标签
|
||||||
async createNewTag(tagName) {
|
async createNewTag(tagName) {
|
||||||
// 标签不能超过八个字
|
// 标签不能超过八个字
|
||||||
if (tagName.length > 8) {
|
if (tagName.length > 8) {
|
||||||
this.$message.error('标签不能超过8个字')
|
this.$message.error('标签不能超过8个字')
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 首先检查是否与已选择的标签重复
|
// 首先检查是否与已选择的标签重复
|
||||||
const isDuplicate = this.displayTags.some(tag => tag.tagName === tagName);
|
const isDuplicate = this.selectedTags.some(tag => tag.tagName === tagName);
|
||||||
if (isDuplicate) {
|
if (isDuplicate) {
|
||||||
this.$message.warning('该标签已存在,无需重复创建');
|
this.$message.warning('该标签已存在,无需重复创建');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 标签格式验证:仅支持中文、英文、数字、下划线、中横线
|
// 标签格式验证:仅支持中文、英文、数字、下划线、中横线
|
||||||
const tagPattern = /^[\u4e00-\u9fa5a-zA-Z0-9_-]+$/;
|
const tagPattern = /^[\u4e00-\u9fa5a-zA-Z0-9_-]+$/;
|
||||||
if (!tagPattern.test(tagName)) {
|
if (!tagPattern.test(tagName)) {
|
||||||
this.$message.error('标签名称仅支持中文、英文、数字、下划线(_)和中横线(-),不支持空格、点和特殊字符');
|
this.$message.error('标签名称仅支持中文、英文、数字、下划线(_)和中横线(-),不支持空格、点和特殊字符');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加标签数量限制检查
|
// 添加标签数量限制检查
|
||||||
if (this.selectedTagIds.length >= this.maxTags) {
|
if (this.selectedTags.length >= this.maxTags) {
|
||||||
this.$message.warning('最多只能添加5个标签')
|
this.$message.warning('最多只能添加5个标签')
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
try {
|
try {
|
||||||
this.params.courseId = this.courseId;
|
this.params.courseId = this.courseId;
|
||||||
@@ -270,39 +253,23 @@ export default {
|
|||||||
if (this.sysTypeList.length > 2) {
|
if (this.sysTypeList.length > 2) {
|
||||||
this.params.sysType3 = this.sysTypeList[2]; //三级的id
|
this.params.sysType3 = this.sysTypeList[2]; //三级的id
|
||||||
}
|
}
|
||||||
|
|
||||||
const {result:newTag} = await apiCourseTag.createTag(this.params)
|
const {result:newTag} = await apiCourseTag.createTag(this.params)
|
||||||
this.$message.success('标签创建成功');
|
this.$message.success('标签创建成功',newTag);
|
||||||
|
this.searchResults.push(newTag)
|
||||||
// 修改:将新标签添加到选中列表和搜索结果中
|
console.log("----------newTag---------->",this.searchResults)
|
||||||
this.selectedTagIds.push(newTag.id);
|
this.tagMap.set(newTag.id, newTag)
|
||||||
|
this.$emit('change', this.displayTags)
|
||||||
// 创建完整的标签对象,包含id和tagName
|
|
||||||
const completeTag = {
|
|
||||||
id: newTag.id,
|
|
||||||
tagName: newTag.tagName
|
|
||||||
};
|
|
||||||
|
|
||||||
this.searchResults.push(completeTag);
|
|
||||||
this.tagMap.set(newTag.id, completeTag);
|
|
||||||
|
|
||||||
console.log("----------新创建标签---------->", completeTag)
|
|
||||||
console.log("----------当前选中标签ID---------->", this.selectedTagIds)
|
|
||||||
console.log("----------标签映射表---------->", this.tagMap)
|
|
||||||
|
|
||||||
// 触发change事件,传递标签对象数组和ID字符串
|
|
||||||
this.$emit('change', this.displayTags, this.tagIdsString);
|
|
||||||
|
|
||||||
// 清空输入框
|
|
||||||
this.clearInput();
|
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 修改doSearch方法,添加搜索结果为空时的提示
|
// 修改doSearch方法,添加搜索结果为空时的提示
|
||||||
async doSearch(query) {
|
async doSearch(query) {
|
||||||
|
// 不再在空查询时清空搜索结果
|
||||||
|
// if (!query.trim()) {
|
||||||
|
// this.searchResults = []
|
||||||
|
// return
|
||||||
|
// }
|
||||||
console.log("---- doSearch ------ query = " + query )
|
console.log("---- doSearch ------ query = " + query )
|
||||||
this.loading = true
|
this.loading = true
|
||||||
try {
|
try {
|
||||||
@@ -314,18 +281,12 @@ export default {
|
|||||||
const {result:tags} = await apiCourseTag.searchTags({tagName:query,typeId:typeId})
|
const {result:tags} = await apiCourseTag.searchTags({tagName:query,typeId:typeId})
|
||||||
console.log("-- searchTags 查询结果 tags = " + tags )
|
console.log("-- searchTags 查询结果 tags = " + tags )
|
||||||
|
|
||||||
// 确保每个标签对象都有完整的属性
|
tags.forEach(item => {
|
||||||
const completeTags = tags.map(tag => ({
|
|
||||||
id: tag.id,
|
|
||||||
tagName: tag.tagName
|
|
||||||
}));
|
|
||||||
|
|
||||||
completeTags.forEach(item => {
|
|
||||||
this.tagMap.set(item.id, item)
|
this.tagMap.set(item.id, item)
|
||||||
})
|
})
|
||||||
this.searchResults = completeTags
|
this.searchResults = tags
|
||||||
// 当搜索结果为空时,提示用户可以按回车键创建标签
|
// 当搜索结果为空时,提示用户可以按回车键创建标签
|
||||||
if (tags.length === 0 && query.trim()) {
|
if (tags.length === 0) {
|
||||||
this.$message.info('无此标签,按回车键创建')
|
this.$message.info('无此标签,按回车键创建')
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user