mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/learning-system-portal.git
synced 2025-12-10 19:36:43 +08:00
还原提示
This commit is contained in:
@@ -1,203 +0,0 @@
|
||||
<template>
|
||||
<div v-if="visible" class="guide-overlay">
|
||||
<!-- 高亮区域 -->
|
||||
<div class="highlight-area" :style="highlightStyle"></div>
|
||||
|
||||
<!-- 蒙层 -->
|
||||
<div class="overlay-mask"></div>
|
||||
|
||||
<!-- 提示内容区域 -->
|
||||
<div class="tip-content" :style="tipStyle">
|
||||
<div class="tip-header">
|
||||
<h3>{{ currentStep.title }}</h3>
|
||||
<div class="step-indicator">{{ currentStepIndex + 1 }}/{{ steps.length }}</div>
|
||||
</div>
|
||||
<div class="tip-body">
|
||||
<p>{{ currentStep.content }}</p>
|
||||
</div>
|
||||
<div class="tip-footer">
|
||||
<el-button size="small" @click="skipAll">跳过</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="nextStep">
|
||||
{{ isLastStep ? '完成' : '下一步' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
steps: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentStepIndex: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentStep() {
|
||||
return this.steps[this.currentStepIndex] || {}
|
||||
},
|
||||
isLastStep() {
|
||||
return this.currentStepIndex === this.steps.length - 1
|
||||
},
|
||||
highlightStyle() {
|
||||
const step = this.currentStep
|
||||
if (!step.targetElement) return {}
|
||||
|
||||
const rect = this.getElementRect(step.targetElement)
|
||||
return {
|
||||
width: `${rect.width}px`,
|
||||
height: `${rect.height}px`,
|
||||
top: `${rect.top}px`,
|
||||
left: `${rect.left}px`,
|
||||
borderRadius: step.borderRadius || '4px'
|
||||
}
|
||||
},
|
||||
tipStyle() {
|
||||
const step = this.currentStep
|
||||
const rect = this.getElementRect(step.targetElement)
|
||||
|
||||
// 根据高亮区域位置智能调整提示框位置
|
||||
let top = rect.top + rect.height + 10
|
||||
let left = rect.left
|
||||
|
||||
// 如果下方空间不足,显示在上方
|
||||
if (top + 200 > window.innerHeight) {
|
||||
top = rect.top - 210
|
||||
}
|
||||
|
||||
// 如果右侧空间不足,左对齐
|
||||
if (left + 300 > window.innerWidth) {
|
||||
left = window.innerWidth - 320
|
||||
}
|
||||
|
||||
return {
|
||||
top: `${top}px`,
|
||||
left: `${left}px`
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getElementRect(selector) {
|
||||
const el = document.querySelector(selector)
|
||||
if (!el) return { width: 0, height: 0, top: 0, left: 0 }
|
||||
|
||||
const rect = el.getBoundingClientRect()
|
||||
return {
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
top: rect.top + window.pageYOffset,
|
||||
left: rect.left + window.pageXOffset
|
||||
}
|
||||
},
|
||||
|
||||
nextStep() {
|
||||
if (this.isLastStep) {
|
||||
this.complete()
|
||||
} else {
|
||||
this.currentStepIndex++
|
||||
}
|
||||
},
|
||||
|
||||
skipAll() {
|
||||
this.$emit('skip')
|
||||
this.complete()
|
||||
},
|
||||
|
||||
complete() {
|
||||
this.$emit('complete')
|
||||
this.currentStepIndex = 0
|
||||
|
||||
// 保存引导完成状态到本地存储
|
||||
localStorage.setItem('courseTagGuideCompleted', 'true')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.guide-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.overlay-mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.highlight-area {
|
||||
position: absolute;
|
||||
border: 2px solid #409EFF;
|
||||
background: transparent;
|
||||
box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5),
|
||||
0 0 20px rgba(64, 158, 255, 0.5);
|
||||
z-index: 10000;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.tip-content {
|
||||
position: absolute;
|
||||
width: 300px;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
z-index: 10001;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.tip-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.tip-header h3 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.step-indicator {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.tip-body {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.tip-body p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.tip-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
</style>
|
||||
@@ -75,13 +75,6 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="标签" required>
|
||||
<courseTag ref="courseTag" :courseId="curCourseId" :sysTypeList="sysTypeList" :initialTags="courseTags" @change="handleTagsChange"></courseTag>
|
||||
<!-- 标签提示对话框 -->
|
||||
<div v-if="tagTipDialogVisible && isFirstTime"
|
||||
class="tag-tip-dialog"
|
||||
@click.stop="closeTagTip">
|
||||
<p>请选择适合课程内容的标签,最多可选择5个</p>
|
||||
<p>点击任意处关闭此提示</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="资源归属" required>
|
||||
<el-input placeholder="请选择" v-model="orgName" >
|
||||
@@ -265,13 +258,6 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="标签" required>
|
||||
<courseTag ref="courseTag" :courseId="curCourseId" :sysTypeList="sysTypeList" :initialTags="courseTags" @change="handleTagsChange"></courseTag>
|
||||
<!-- 标签提示对话框 -->
|
||||
<div v-if="tagTipDialogVisible && isFirstTime"
|
||||
class="tag-tip-dialog"
|
||||
@click.stop="closeTagTip">
|
||||
<p>请选择适合课程内容的标签,最多可选择5个</p>
|
||||
<p>点击任意处关闭此提示</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="关键字">
|
||||
<el-input v-model.trim="keywords" maxlength="100" @keyup.enter.native="changeKeywords" placeholder="请输入关键字"></el-input>
|
||||
@@ -419,14 +405,6 @@
|
||||
<!--选择图片-->
|
||||
<filecloud :show="dlgFileChoose.show" @choose="changeCourseImage" @close="choseChoose"></filecloud>
|
||||
<chooseOrg ref="refChooseOrg" @confirm="confirmChooseOrg"></chooseOrg>
|
||||
|
||||
<!-- 蒙层引导 -->
|
||||
<guide-overlay
|
||||
:visible="showGuide"
|
||||
:steps="guideSteps"
|
||||
@skip="handleSkipGuide"
|
||||
@complete="handleCompleteGuide"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -454,44 +432,11 @@ import { courseType, getType } from '../../utils/tools.js';
|
||||
import { mapGetters, mapActions } from 'vuex';
|
||||
import filecloud from '@/components/FileCloud/index.vue';
|
||||
import chooseOrg from '@/components/System/chooseOrg.vue';
|
||||
import GuideOverlay from '@/components/Course/GuideOverlay.vue';
|
||||
export default {
|
||||
props: {},
|
||||
components: { courseTag, weikeContent, catalogCourseware, imageUpload, WxEditor, catalogSort,agreement,filecloud,choice,chooseOrg,GuideOverlay},
|
||||
components: { courseTag, weikeContent, catalogCourseware, imageUpload, WxEditor, catalogSort,agreement,filecloud,choice,chooseOrg},
|
||||
data() {
|
||||
return {
|
||||
showGuide: false,
|
||||
guideSteps: [
|
||||
{
|
||||
title: '课程名称',
|
||||
content: '请输入课程名称,这将帮助系统智能推荐相关标签',
|
||||
targetElement: '.el-input__inner', // 课程名称输入框
|
||||
borderRadius: '4px'
|
||||
},
|
||||
{
|
||||
title: '课程分类',
|
||||
content: '选择课程分类,系统会根据分类自动推荐合适的标签',
|
||||
targetElement: '.el-cascader__search-input', // 分类选择框
|
||||
borderRadius: '4px'
|
||||
},
|
||||
{
|
||||
title: '智能标签',
|
||||
content: '系统会根据课程名称和分类智能推荐标签,点击即可添加',
|
||||
targetElement: '.smart-tag-hint', // 智能提示区域
|
||||
borderRadius: '4px'
|
||||
},
|
||||
{
|
||||
title: '标签管理',
|
||||
content: '您可以手动输入标签或选择推荐标签,最多可添加5个标签',
|
||||
targetElement: '.el-select__tags', // 标签显示区域
|
||||
borderRadius: '4px'
|
||||
}
|
||||
],
|
||||
courseForm: {
|
||||
name: '',
|
||||
categories: [],
|
||||
tags: []
|
||||
},
|
||||
keywords:'',//关键字的定义
|
||||
tips:[],
|
||||
addOrder:1,
|
||||
@@ -591,9 +536,7 @@ export default {
|
||||
dlgShow: false
|
||||
},
|
||||
rightTypeId: {},
|
||||
catalogSortDialogShow: false,
|
||||
tagTipDialogVisible: false,
|
||||
isFirstTime: true,
|
||||
catalogSortDialogShow: false
|
||||
};
|
||||
},
|
||||
created() {
|
||||
@@ -645,84 +588,8 @@ export default {
|
||||
this.loadResOwners();
|
||||
this.loadSysTypes();
|
||||
this.loadUserGroup();
|
||||
|
||||
// 初始化标签提示
|
||||
this.$nextTick(() => {
|
||||
// 监听 courseTag 组件的焦点事件
|
||||
if (this.$refs.courseTag && this.$refs.courseTag.$el) {
|
||||
this.$refs.courseTag.$el.addEventListener('focus', this.showTagTip, true);
|
||||
}
|
||||
});
|
||||
this.checkAndShowGuide()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
// 清理事件监听器
|
||||
document.removeEventListener('click', this.handleGlobalClick);
|
||||
if (this.$refs.courseTag && this.$refs.courseTag.$el) {
|
||||
this.$refs.courseTag.$el.removeEventListener('focus', this.showTagTip, true);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
checkAndShowGuide() {
|
||||
// 检查是否为新用户或首次使用标签功能
|
||||
const guideCompleted = localStorage.getItem('courseTagGuideCompleted')
|
||||
if (!guideCompleted && this.isNewUser()) {
|
||||
// 延迟显示引导,确保DOM已渲染
|
||||
setTimeout(() => {
|
||||
this.showGuide = true
|
||||
}, 1000)
|
||||
}
|
||||
},
|
||||
|
||||
isNewUser() {
|
||||
// 根据业务逻辑判断是否为新用户
|
||||
return !this.curCourseId || this.courseTags.length === 0
|
||||
},
|
||||
|
||||
handleSkipGuide() {
|
||||
this.showGuide = false
|
||||
this.$message.info('已跳过引导,您可以在设置中重新查看')
|
||||
},
|
||||
|
||||
handleCompleteGuide() {
|
||||
this.showGuide = false
|
||||
this.$message.success('引导完成,开始使用智能标签功能吧!')
|
||||
},
|
||||
|
||||
// 手动触发引导(供用户重新查看)
|
||||
showTagGuide() {
|
||||
this.showGuide = true
|
||||
},
|
||||
|
||||
// 显示标签提示对话框
|
||||
showTagTip() {
|
||||
if (this.isFirstTime) {
|
||||
this.tagTipDialogVisible = true;
|
||||
// 添加全局点击监听器
|
||||
document.addEventListener('click', this.handleGlobalClick);
|
||||
}
|
||||
},
|
||||
|
||||
// 关闭标签提示对话框
|
||||
closeTagTip() {
|
||||
this.tagTipDialogVisible = false;
|
||||
this.isFirstTime = false;
|
||||
document.removeEventListener('click', this.handleGlobalClick);
|
||||
},
|
||||
|
||||
// 处理全局点击事件
|
||||
handleGlobalClick(event) {
|
||||
// 如果点击的不是标签提示框内部,则关闭提示框
|
||||
if (this.tagTipDialogVisible) {
|
||||
const tipDialog = document.querySelector('.tag-tip-dialog');
|
||||
if (tipDialog && !tipDialog.contains(event.target)) {
|
||||
this.closeTagTip();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 关键字的更改
|
||||
changeKeywords(option){
|
||||
if(option.target.value){
|
||||
@@ -1949,32 +1816,4 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tag-tip-dialog {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
z-index: 2000;
|
||||
width: 300px;
|
||||
margin-top: 5px;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
p:first-child {
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -27,19 +27,6 @@
|
||||
:disabled="isTagDisabled(item)"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<!-- 添加引导提示图标 -->
|
||||
<el-tooltip content="点击查看标签使用引导" placement="top">
|
||||
<el-button
|
||||
class="guide-trigger"
|
||||
type="text"
|
||||
icon="el-icon-question"
|
||||
@click="showGuide"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
|
||||
<smart-tag-hint ref="smartHint" />
|
||||
|
||||
<!-- 添加标签计数显示 -->
|
||||
<div class="tag-count">
|
||||
{{ selectedTags.length }}/5
|
||||
@@ -138,9 +125,6 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showGuide() {
|
||||
this.$emit('show-guide')
|
||||
},
|
||||
// 新增:检查标签是否应该被禁用
|
||||
isTagDisabled(tag) {
|
||||
// 如果标签已经被选中,不应该禁用(允许取消选择)
|
||||
@@ -378,6 +362,7 @@ export default {
|
||||
}
|
||||
|
||||
::v-deep(.el-tag) {
|
||||
flex: 0 0 calc(50% - 8px);
|
||||
max-width: calc(50% - 8px);
|
||||
box-sizing: border-box;
|
||||
margin-right: 8px;
|
||||
@@ -391,17 +376,4 @@ export default {
|
||||
flex: 1;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.tag-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.guide-trigger {
|
||||
position: absolute;
|
||||
right: -30px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #409EFF;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user