import { PropType, Teleport, defineComponent, nextTick, onMounted, onUnmounted, ref } from "vue"; import { Config, DriveStep, PopoverDOM, State, driver } from "driver.js"; import "driver.js/dist/driver.css"; import state, { IPlatform } from "/src/state"; import { getGuidance, setGuidance } from "../guide-page/api"; const endGuide = (guideInfo: any) => { try { // setGuidance({ guideTag: "guideInfo", guideValue: JSON.stringify(guideInfo) }); localStorage.setItem("guideInfo", JSON.stringify(guideInfo)); } catch (e) { console.log(e); } }; /** * 按钮状态 */ type ButtonStatus = { /** 是否显示播放按钮 */ playBtnStatus?: Boolean; /** 声部状态 */ subjectStatus?: Boolean; /** 是否显示模式切换 */ modelTypeStatus?: Boolean; /** 播放模式 演唱 演奏 */ playType?: Boolean; /** 返回和标题 */ backTitle?: Boolean; /** 返回显示的标题类型 文本 TEXT 按钮 IMG */ titleType?: String; /** 原声 true 范唱 false */ originPlayType?: Boolean; /** 是否显示原音 */ originBtnStatus?: Boolean; /** 是否显示切换曲谱列表 */ showSwitchList?: Boolean; }; /** 练习模式 */ export const PractiseDriver = defineComponent({ name: "PractiseDriver", props: { // 按钮状态 statusAll: { type: Object as PropType, default: () => {}, }, }, setup(props) { const driverNextStatus = ref(false); // 初始化部分引导位置 const driverInitialPosition = (popover: PopoverDOM, options: { config: Config; state: State }) => { options.config.stageRadius = 5; options.config.stagePadding = 8; try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 + 4 + "px"; } catch {} }; const driverOptions = (): Config => { let length = 10; if (!props.statusAll.playBtnStatus) { length -= 1; } if (!props.statusAll.originBtnStatus) { length -= 1; } // 显示指法 if (!state.setting.displayFingering) { length -= 1; } // 声部 if (!props.statusAll.subjectStatus) { length -= 1; } // 非midi if (!props.statusAll.playType && !state.isAppPlay) { length -= 1; } // pc端不显示标题和模式切换引导 if (state.platform === IPlatform.PC) { length -= 2; } else { // 判断是否有标题 if (!props.statusAll.backTitle || props.statusAll.titleType === "NONE") { length -= 1; } // 练习模式 if (!props.statusAll.modelTypeStatus) { length -= 1; } } console.log(props.statusAll, "statusAll", length, state.setting.displayFingering); let options: Config = { showProgress: false, allowClose: false, popoverOffset: 3, disableActiveInteraction: true, onCloseClick: () => { onDriverClose(); }, onHighlightStarted: () => { driverNextStatus.value = true; }, onHighlighted: () => { driverNextStatus.value = false; }, steps: [] as DriveStep[], }; if (props.statusAll.playBtnStatus) { options.steps?.push({ element: ".driver-1", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass1", align: "end", side: "top", nextBtnText: `下一步 (1/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { options.config.stageRadius = 1000; options.config.stagePadding = 0; }, }, }); } if (props.statusAll.playType) { options.steps?.push({ element: ".driver-2", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass2", align: "start", side: "top", nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }); } if (props.statusAll.originBtnStatus) { options.steps?.push({ element: ".driver-3", popover: { title: "", description: "", popoverClass: props.statusAll.originPlayType ? "popoverClass popoverClass3" : "popoverClass popoverClass11", align: "start", side: "top", nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }); } options.steps?.push( { element: ".driver-4", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass4", align: "start", side: "top", nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }, { element: ".driver-5", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass5", align: "start", side: "top", nextBtnText: `下一步 (${options.steps.length + 2}/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, } ); if (props.statusAll.subjectStatus) { options.steps?.push({ element: ".driver-10", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass10", align: "start", side: "top", nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }); } options.steps?.push({ element: ".driver-5-1", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass5-1", align: "start", side: "top", nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }); if (state.platform === IPlatform.PC) { options.steps?.push({ element: ".driver-6", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass6 popoverClose", align: "start", side: "top", prevBtnText: "再看一遍", doneBtnText: "完成", showButtons: ["next", "previous"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, onPrevClick: () => { driverObj.drive(0); }, onNextClick: () => { onDriverClose(); }, }, }); } else { // 判断设置之后是否还有引导 if (!state.setting.displayFingering && !props.statusAll.backTitle && !props.statusAll.modelTypeStatus) { options.steps?.push({ element: ".driver-6", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass6 popoverClose", align: "start", side: "top", prevBtnText: "再看一遍", doneBtnText: "完成", showButtons: ["next", "previous"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, onPrevClick: () => { driverObj.drive(0); }, onNextClick: () => { onDriverClose(); }, }, }); } else if (state.setting.displayFingering && !props.statusAll.backTitle && !props.statusAll.modelTypeStatus) { options.steps?.push({ element: ".driver-6", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass6", align: "start", side: "top", nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, //"下一步6/" + length, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }); } else if (props.statusAll.backTitle && !props.statusAll.modelTypeStatus) { options.steps?.push({ element: ".driver-6", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass6", align: "start", side: "top", nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, //"下一步6/" + length, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }); options.steps?.push({ //props.statusAll.titleType === "TEXT" ? ".driver-8 .van-notice-bar__content" : element: ".driver-8", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass8 popoverClose", align: "start", side: "bottom", prevBtnText: "再看一遍", doneBtnText: "完成", showButtons: ["next", "previous"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { if (props.statusAll.titleType === "TEXT") { options.config.stageRadius = 5; options.config.stagePadding = 5; } else { options.config.stageRadius = 1000; options.config.stagePadding = 0; } try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 - 4 + "px"; } catch {} }, onPrevClick: () => { driverObj.drive(0); }, onNextClick: () => { onDriverClose(); }, }, }); } else { options.steps?.push({ element: ".driver-6", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass6", align: "start", side: "top", nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, //"下一步6/" + length, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }); if (props.statusAll.backTitle) { options.steps?.push({ // .van-notice-bar__content // element: ".driver-8 .van-notice-bar__content", // props.statusAll.titleType === "TEXT" ? ".driver-8 .van-notice-bar__content" : element: ".driver-8", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass8", align: "start", side: "bottom", nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { if (props.statusAll.titleType === "TEXT") { options.config.stageRadius = 5; options.config.stagePadding = 5; } else { options.config.stageRadius = 1000; options.config.stagePadding = 0; } try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 - 4 + "px"; } catch {} }, }, }); } options.steps?.push({ element: ".driver-9", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass9 popoverClose", align: "end", side: "bottom", prevBtnText: "再看一遍", doneBtnText: "完成", showButtons: ["next", "previous"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { options.config.stageRadius = 1000; options.config.stagePadding = 0; try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = -((rect?.width || 0) / 2 - 8) + "px"; } catch {} }, onPrevClick: () => { driverObj.drive(0); }, onNextClick: () => { onDriverClose(); }, }, }); } } return options; }; let driverObj: any; const handleClickOutside = (event: any) => { // 如果高亮没有结束则下进行下一步 if (driverNextStatus.value) return; if (driverObj.isActive() && (event.target.nodeName === "path" || event.target.classList.contains("driver-popover") || event.target.classList.contains("driver-overlay"))) { if (driverObj.isLastStep()) { onDriverClose(); } else { driverObj.moveNext(); // 跳转到下一步 } } }; const guideInfo = ref({} as any); const showCloseBtn = ref(false); const getAllGuidance = async () => { try { // const res = await getGuidance({ guideTag: "guideInfo" }); const res = localStorage.getItem("guideInfo"); if (res) { guideInfo.value = JSON.parse(res) || null; } else { guideInfo.value = {}; } if (!(guideInfo.value && guideInfo.value.practiseDriver)) { document.addEventListener("click", handleClickOutside, true); driverObj = driver(driverOptions()); nextTick(() => { driverObj.drive(); showCloseBtn.value = true; state.hasDriverPop = true; }); } } catch (e) { console.log(e); } }; getAllGuidance(); // 结束关闭弹窗 const onDriverClose = () => { if (!guideInfo.value) { guideInfo.value = { practiseDriver: true }; } else { guideInfo.value.practiseDriver = true; } endGuide(guideInfo.value); driverObj.destroy(); document.querySelector(".driver-popover-close-btn-custom")?.remove(); document.removeEventListener("click", handleClickOutside, true); state.hasDriverPop = false; }; onUnmounted(() => { document.removeEventListener("click", handleClickOutside, true); }); return () => ( {showCloseBtn.value && (
{ onDriverClose(); }} >
)}
); }, }); /** 跟练模式 */ export const FollowDriver = defineComponent({ name: "FollowDriver", props: { // 按钮状态 statusAll: { type: Object as PropType, default: () => {}, }, }, setup(props) { const driverNextStatus = ref(false); // 初始化部分引导位置 const driverInitialPosition = (popover: PopoverDOM, options: { config: Config; state: State }) => { options.config.stageRadius = 5; options.config.stagePadding = 8; try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 + 4 + "px"; } catch {} }; // 声部 let length = props.statusAll.subjectStatus ? 5 : 4; const driverOptions: Config = { showProgress: false, allowClose: false, popoverOffset: 3, disableActiveInteraction: true, onCloseClick: () => { onDriverClose(); }, onHighlightStarted: () => { driverNextStatus.value = true; }, onHighlighted: () => { driverNextStatus.value = false; }, steps: [ { element: ".follow-1", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassF1", align: "end", side: "top", nextBtnText: `下一步 (1/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { options.config.stageRadius = 1000; options.config.stagePadding = 0; }, }, }, { element: ".driver-5", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassF2", align: "start", side: "top", nextBtnText: `下一步 (2/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }, ], }; if (props.statusAll.subjectStatus) { driverOptions.steps?.push({ element: ".driver-10", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass10", align: "start", side: "top", nextBtnText: `下一步 (${driverOptions.steps.length + 1}/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }); } driverOptions.steps?.push({ element: ".driver-5-1", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass5-1", align: "start", side: "top", nextBtnText: `下一步 (${driverOptions.steps.length + 1}/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }); driverOptions.steps?.push({ element: ".driver-6", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassF3 popoverClose", align: "start", side: "top", prevBtnText: "再看一遍", doneBtnText: "完成", showButtons: ["next", "previous"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, onPrevClick: () => { driverObj.drive(0); }, onNextClick: () => { onDriverClose(); }, }, }); let driverObj: any; const handleClickOutside = (event: any) => { if (driverNextStatus.value) return; console.log(driverObj.getActiveIndex(), "driverObj.getActiveIndex()"); if (driverObj.isActive() && (event.target.nodeName === "path" || event.target.classList.contains("driver-popover") || event.target.classList.contains("driver-overlay"))) { if (driverObj.isLastStep()) { onDriverClose(); } else { // driverObj.moveNext(); // 跳转到下一步 const index = driverObj.getActiveIndex(); driverObj.moveTo(index + 1); } } }; const guideInfo = ref({} as any); const showCloseBtn = ref(false); const getAllGuidance = async () => { try { const res = localStorage.getItem("guideInfo"); if (res) { guideInfo.value = JSON.parse(res) || null; } else { guideInfo.value = {}; } if (!(guideInfo.value && guideInfo.value.followDriver)) { document.addEventListener("click", handleClickOutside, true); nextTick(() => { driverObj = driver(driverOptions); driverObj.drive(0); showCloseBtn.value = true; state.hasDriverPop = true; }); } } catch (e) { console.log(e); } }; getAllGuidance(); // 结束关闭弹窗 const onDriverClose = () => { if (!guideInfo.value) { guideInfo.value = { followDriver: true }; } else { guideInfo.value.followDriver = true; } endGuide(guideInfo.value); driverObj.destroy(); document.querySelector(".driver-popover-close-btn-custom")?.remove(); document.removeEventListener("click", handleClickOutside, true); state.hasDriverPop = false; }; onUnmounted(() => { document.removeEventListener("click", handleClickOutside, true); }); return () => ( {showCloseBtn.value && (
{ onDriverClose(); }} >
)}
); }, }); // 评测模式 export const EvaluatingDriver = defineComponent({ name: "EvaluatingDriver", props: { // 按钮状态 statusAll: { type: Object as PropType, default: () => {}, }, }, setup(props) { const driverNextStatus = ref(false); // 初始化部分引导位置 const driverInitialPosition = (popover: PopoverDOM, options: { config: Config; state: State }) => { options.config.stageRadius = 5; options.config.stagePadding = 8; try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 + 4 + "px"; } catch {} }; // 声部 let length = props.statusAll.subjectStatus ? 6 : 5; const driverOptions: Config = { showProgress: false, allowClose: false, popoverOffset: 3, disableActiveInteraction: true, onCloseClick: () => { onDriverClose(); }, onHighlightStarted: () => { driverNextStatus.value = true; }, onHighlighted: () => { driverNextStatus.value = false; }, steps: [ { element: ".evaluting-1", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassE1", align: "end", side: "top", nextBtnText: `下一步 (1/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { options.config.stageRadius = 1000; options.config.stagePadding = 0; }, }, }, { element: ".driver-4", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassE2", align: "start", side: "top", nextBtnText: `下一步 (2/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }, { element: ".driver-5", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassE3", align: "start", side: "top", nextBtnText: `下一步 (3/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }, ], }; if (props.statusAll.subjectStatus) { driverOptions.steps?.push({ element: ".driver-10", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass10", align: "start", side: "top", nextBtnText: `下一步 (${driverOptions.steps.length + 1}/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }); } driverOptions.steps?.push({ element: ".driver-5-1", popover: { title: "", description: "", popoverClass: "popoverClass popoverClass5-1", align: "start", side: "top", nextBtnText: `下一步 (${driverOptions.steps.length + 1}/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }); driverOptions.steps?.push({ element: ".driver-6", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassE4 popoverClose", align: "start", side: "top", prevBtnText: "再看一遍", doneBtnText: "完成", showButtons: ["next", "previous"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, onPrevClick: () => { driverObj.drive(0); }, onNextClick: () => { onDriverClose(); }, }, }); let driverObj: any; const handleClickOutside = (event: any) => { if (driverNextStatus.value) return; console.log(driverObj.getActiveIndex(), "driverObj.getActiveIndex()"); if (driverObj.isActive() && (event.target.nodeName === "path" || event.target.classList.contains("driver-popover") || event.target.classList.contains("driver-overlay"))) { if (driverObj.isLastStep()) { onDriverClose(); } else { driverObj.moveNext(); // 跳转到下一步 } } }; const guideInfo = ref({} as any); const showCloseBtn = ref(false); const getAllGuidance = async () => { try { const res = localStorage.getItem("guideInfo"); if (res) { guideInfo.value = JSON.parse(res) || null; } else { guideInfo.value = {}; } console.log(guideInfo.value, "guideInfo.value", showCloseBtn.value); if (!(guideInfo.value && guideInfo.value.evaluatingDriver)) { document.addEventListener("click", handleClickOutside, true); nextTick(() => { driverObj = driver(driverOptions); driverObj.drive(); showCloseBtn.value = true; state.hasDriverPop = true; console.log(driverOptions, "driverOptions Evaluating", showCloseBtn.value); }); } else { driverObj?.destroy(); } } catch (e) { console.log(e); } }; getAllGuidance(); // 结束关闭弹窗 const onDriverClose = () => { if (!guideInfo.value) { guideInfo.value = { evaluatingDriver: true }; } else { guideInfo.value.evaluatingDriver = true; } endGuide(guideInfo.value); driverObj?.destroy(); document.querySelector(".driver-popover-close-btn-custom")?.remove(); document.removeEventListener("click", handleClickOutside, true); state.hasDriverPop = false; }; onUnmounted(() => { document.removeEventListener("click", handleClickOutside, true); }); return () => ( {showCloseBtn.value && (
{ onDriverClose(); }} >
)}
); }, }); // 评测模式 - 结果弹窗 export const EvaluatingResultDriver = defineComponent({ name: "EvaluatingResultDriver", props: { // 保存按钮状态 saveBtn: { type: Boolean, default: true, }, }, setup(props) { let length = 4; if (!props.saveBtn) { length -= 1; } console.log(props.saveBtn, "props.saveBtn"); const driverNextStatus = ref(false); // 初始化部分引导位置 const driverInitialPosition = (popover: PopoverDOM, options: { config: Config; state: State }, position = 1) => { options.config.stageRadius = 1000; options.config.stagePadding = 2; try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * position + 4 + "px"; } catch {} }; const driverOptionsFun = () => { const driverOptions: Config = { showProgress: false, allowClose: false, popoverOffset: 3, disableActiveInteraction: true, onCloseClick: () => { onDriverClose(); }, onHighlightStarted: () => { driverNextStatus.value = true; }, onHighlighted: () => { driverNextStatus.value = false; }, steps: [ { element: ".evaluting-result-1", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassER1", align: "start", side: "right", nextBtnText: `下一步 (1/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { options.config.stageRadius = 12; options.config.stagePadding = 10; }, }, }, { element: ".evaluting-result-2", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassER2", align: "start", side: "top", nextBtnText: `下一步 (2/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { options.config.stageRadius = 1000; options.config.stagePadding = 2; try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 - 4 + "px"; } catch {} }, }, }, ], }; if (props.saveBtn) { driverOptions.steps?.push({ element: ".evaluting-result-3", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassER3", align: "end", side: "top", nextBtnText: `下一步 (3/${length})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options, -1); }, }, }); } driverOptions.steps?.push({ element: ".evaluting-result-4", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassER4 popoverClose", align: "end", side: "top", prevBtnText: "再看一遍", doneBtnText: "完成", showButtons: ["next", "previous"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options, -1); }, onPrevClick: () => { driverObj.drive(); }, onNextClick: () => { onDriverClose(); }, }, }); return driverOptions; }; let driverObj: any; const handleClickOutside = (event: any) => { if (driverNextStatus.value) return; if (driverObj.isActive() && (event.target.nodeName === "path" || event.target.classList.contains("driver-popover") || event.target.classList.contains("driver-overlay"))) { if (driverObj.isLastStep()) { onDriverClose(); } else { driverObj.moveNext(); // 跳转到下一步 } } }; const guideInfo = ref({} as any); const showCloseBtn = ref(false); const getAllGuidance = async () => { try { const res = localStorage.getItem("guideInfo"); if (res) { guideInfo.value = JSON.parse(res) || null; } else { guideInfo.value = {}; } if (!(guideInfo.value && guideInfo.value.evaluatingResultDriver)) { setTimeout(() => { document.addEventListener("click", handleClickOutside, true); nextTick(() => { driverObj = driver(driverOptionsFun()); driverObj.drive(); showCloseBtn.value = true; state.hasDriverPop = true; }); }, 100); } } catch (e) { console.log(e); } }; onMounted(() => { getAllGuidance(); }); // 结束关闭弹窗 const onDriverClose = () => { if (!guideInfo.value) { guideInfo.value = { evaluatingResultDriver: true }; } else { guideInfo.value.evaluatingResultDriver = true; } endGuide(guideInfo.value); driverObj.destroy(); document.querySelector(".driver-popover-close-btn-custom")?.remove(); document.removeEventListener("click", handleClickOutside, true); state.hasDriverPop = false; }; onUnmounted(() => { document.removeEventListener("click", handleClickOutside, true); }); return () => ( {showCloseBtn.value && (
{ onDriverClose(); }} >
)}
); }, }); // 评测报告 export const EvaluatingReportDriver = defineComponent({ name: "EvaluatingReportDriver", props: { /** 视屏地址 */ videoFilePath: { type: String, default: "", }, }, setup(props) { const driverNextStatus = ref(false); // state.isPercussion 是否为打击乐 // 初始化部分引导位置 const driverInitialPosition = (popover: PopoverDOM, options: { config: Config; state: State }, position = 1) => { options.config.stageRadius = 12; options.config.stagePadding = 0; try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * position - 4 + "px"; } catch {} }; // 判断是否为打击乐 let steps: DriveStep[] = []; if (state.isPercussion) { if (props.videoFilePath) { steps = [ { element: ".evaluting-report-2", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassReport2", align: "end", side: "bottom", nextBtnText: "下一步 (1/2)", showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px"; } catch {} }, }, }, { element: ".evaluting-report-4", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassReport4 popoverClose", align: "end", side: "bottom", prevBtnText: "再看一遍", doneBtnText: "完成", showButtons: ["next", "previous"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { options.config.stageRadius = 8; options.config.stagePadding = 5; try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px"; } catch {} }, onPrevClick: () => { driverObj.drive(0); }, onNextClick: () => { onDriverClose(); }, }, }, ]; } else { steps = [ { element: ".evaluting-report-2", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassReport2 popoverClose", align: "end", side: "bottom", doneBtnText: "完成", showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { options.config.stageRadius = 12; options.config.stagePadding = 0; try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px"; } catch {} }, onPrevClick: () => { driverObj.drive(0); }, onNextClick: () => { onDriverClose(); }, }, }, ]; } } else { const count = props.videoFilePath ? 4 : 3; steps = [ { element: ".evaluting-report-1", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassReport1", align: "start", side: "bottom", nextBtnText: `下一步 (1/${count})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { driverInitialPosition(popover, options); }, }, }, { element: ".evaluting-report-2", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassReport2", align: "end", side: "bottom", nextBtnText: `下一步 (2/${count})`, showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px"; } catch {} }, }, }, ]; if (props.videoFilePath) { steps.push( { element: ".evaluting-report-3", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassReport3", align: "end", side: "bottom", nextBtnText: "下一步 (3/4)", showButtons: ["next"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px"; } catch {} }, }, }, { element: ".evaluting-report-4", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassReport4 popoverClose", align: "end", side: "bottom", prevBtnText: "再看一遍", doneBtnText: "完成", showButtons: ["next", "previous"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { options.config.stageRadius = 8; options.config.stagePadding = 5; try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px"; } catch {} }, onPrevClick: () => { driverObj.drive(0); }, onNextClick: () => { onDriverClose(); }, }, } ); } else { steps.push({ element: ".evaluting-report-3", popover: { title: "", description: "", popoverClass: "popoverClass popoverClassReport3 popoverClose", align: "end", side: "bottom", prevBtnText: "再看一遍", doneBtnText: "完成", showButtons: ["next", "previous"], onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => { try { const rect = options.state.activeElement?.getBoundingClientRect(); popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px"; } catch {} }, onPrevClick: () => { driverObj.drive(0); }, onNextClick: () => { onDriverClose(); }, }, }); } } const driverOptions: Config = { showProgress: false, allowClose: false, popoverOffset: 3, disableActiveInteraction: true, onCloseClick: () => { onDriverClose(); }, onHighlightStarted: () => { driverNextStatus.value = true; }, onHighlighted: () => { driverNextStatus.value = false; }, steps: steps, }; let driverObj: any; const guideInfo = ref({} as any); const handleClickOutside = (event: any) => { if (driverNextStatus.value) return; if (driverObj.isActive() && (event.target.nodeName === "path" || event.target.classList.contains("driver-popover") || event.target.classList.contains("driver-overlay"))) { if (driverObj.isLastStep()) { onDriverClose(); } else { driverObj.moveNext(); // 跳转到下一步 } } }; const showCloseBtn = ref(false); const getAllGuidance = async () => { try { const res = localStorage.getItem("guideInfo"); if (res) { guideInfo.value = JSON.parse(res) || null; } else { guideInfo.value = {}; } if (!(guideInfo.value && guideInfo.value.evaluatingReportDriver)) { // 监听点击事件以实现点击空白区域跳转到下一步 document.addEventListener("click", handleClickOutside, true); nextTick(() => { driverObj = driver(driverOptions); driverObj.drive(); state.hasDriverPop = true; showCloseBtn.value = true; }); } } catch (e) { console.log(e); } }; getAllGuidance(); // 结束关闭弹窗 const onDriverClose = () => { if (!guideInfo.value) { guideInfo.value = { evaluatingReportDriver: true }; } else { guideInfo.value.evaluatingReportDriver = true; } endGuide(guideInfo.value); driverObj.destroy(); document.querySelector(".driver-popover-close-btn-custom")?.remove(); document.removeEventListener("click", handleClickOutside, true); state.hasDriverPop = false; }; onUnmounted(() => { document.removeEventListener("click", handleClickOutside, true); }); return () => ( {showCloseBtn.value && (
{ onDriverClose(); }} >
)}
); }, });