index.tsx 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445
  1. import { PropType, Teleport, defineComponent, nextTick, onMounted, onUnmounted, ref } from "vue";
  2. import { Config, DriveStep, PopoverDOM, State, driver } from "driver.js";
  3. import "driver.js/dist/driver.css";
  4. import state, { IPlatform } from "/src/state";
  5. import { getGuidance, setGuidance } from "../guide-page/api";
  6. const endGuide = (guideInfo: any) => {
  7. try {
  8. // setGuidance({ guideTag: "guideInfo", guideValue: JSON.stringify(guideInfo) });
  9. localStorage.setItem("guideInfo", JSON.stringify(guideInfo));
  10. } catch (e) {
  11. console.log(e);
  12. }
  13. };
  14. /**
  15. * 按钮状态
  16. */
  17. type ButtonStatus = {
  18. /** 是否显示播放按钮 */
  19. playBtnStatus?: Boolean;
  20. /** 声部状态 */
  21. subjectStatus?: Boolean;
  22. /** 是否显示模式切换 */
  23. modelTypeStatus?: Boolean;
  24. /** 播放模式 演唱 演奏 */
  25. playType?: Boolean;
  26. /** 返回和标题 */
  27. backTitle?: Boolean;
  28. /** 返回显示的标题类型 文本 TEXT 按钮 IMG */
  29. titleType?: String;
  30. /** 原声 true 范唱 false */
  31. originPlayType?: Boolean;
  32. /** 是否显示原音 */
  33. originBtnStatus?: Boolean;
  34. /** 是否显示切换曲谱列表 */
  35. showSwitchList?: Boolean;
  36. };
  37. /** 练习模式 */
  38. export const PractiseDriver = defineComponent({
  39. name: "PractiseDriver",
  40. props: {
  41. // 按钮状态
  42. statusAll: {
  43. type: Object as PropType<ButtonStatus>,
  44. default: () => {},
  45. },
  46. },
  47. setup(props) {
  48. const driverNextStatus = ref(false);
  49. // 初始化部分引导位置
  50. const driverInitialPosition = (popover: PopoverDOM, options: { config: Config; state: State }) => {
  51. options.config.stageRadius = 5;
  52. options.config.stagePadding = 8;
  53. try {
  54. const rect = options.state.activeElement?.getBoundingClientRect();
  55. popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 + 4 + "px";
  56. } catch {}
  57. };
  58. const driverOptions = (): Config => {
  59. let length = 10;
  60. if (!props.statusAll.playBtnStatus) {
  61. length -= 1;
  62. }
  63. if (!props.statusAll.originBtnStatus) {
  64. length -= 1;
  65. }
  66. // 显示指法
  67. if (!state.setting.displayFingering) {
  68. length -= 1;
  69. }
  70. // 声部
  71. if (!props.statusAll.subjectStatus) {
  72. length -= 1;
  73. }
  74. // 非midi
  75. if (!props.statusAll.playType && !state.isAppPlay) {
  76. length -= 1;
  77. }
  78. // pc端不显示标题和模式切换引导
  79. if (state.platform === IPlatform.PC) {
  80. length -= 2;
  81. } else {
  82. // 判断是否有标题
  83. if (!props.statusAll.backTitle || props.statusAll.titleType === "NONE") {
  84. length -= 1;
  85. }
  86. // 练习模式
  87. if (!props.statusAll.modelTypeStatus) {
  88. length -= 1;
  89. }
  90. }
  91. console.log(props.statusAll, "statusAll", length, state.setting.displayFingering);
  92. let options: Config = {
  93. showProgress: false,
  94. allowClose: false,
  95. popoverOffset: 3,
  96. disableActiveInteraction: true,
  97. onCloseClick: () => {
  98. onDriverClose();
  99. },
  100. onHighlightStarted: () => {
  101. driverNextStatus.value = true;
  102. },
  103. onHighlighted: () => {
  104. driverNextStatus.value = false;
  105. },
  106. steps: [] as DriveStep[],
  107. };
  108. if (props.statusAll.playBtnStatus) {
  109. options.steps?.push({
  110. element: ".driver-1",
  111. popover: {
  112. title: "",
  113. description: "",
  114. popoverClass: "popoverClass popoverClass1",
  115. align: "end",
  116. side: "top",
  117. nextBtnText: `下一步 (1/${length})`,
  118. showButtons: ["next"],
  119. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  120. options.config.stageRadius = 1000;
  121. options.config.stagePadding = 0;
  122. },
  123. },
  124. });
  125. }
  126. if (props.statusAll.playType) {
  127. options.steps?.push({
  128. element: ".driver-2",
  129. popover: {
  130. title: "",
  131. description: "",
  132. popoverClass: "popoverClass popoverClass2",
  133. align: "start",
  134. side: "top",
  135. nextBtnText: `下一步 (${options.steps.length + 1}/${length})`,
  136. showButtons: ["next"],
  137. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  138. driverInitialPosition(popover, options);
  139. },
  140. },
  141. });
  142. }
  143. if (props.statusAll.originBtnStatus) {
  144. options.steps?.push({
  145. element: ".driver-3",
  146. popover: {
  147. title: "",
  148. description: "",
  149. popoverClass: props.statusAll.originPlayType ? "popoverClass popoverClass3" : "popoverClass popoverClass11",
  150. align: "start",
  151. side: "top",
  152. nextBtnText: `下一步 (${options.steps.length + 1}/${length})`,
  153. showButtons: ["next"],
  154. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  155. driverInitialPosition(popover, options);
  156. },
  157. },
  158. });
  159. }
  160. options.steps?.push(
  161. {
  162. element: ".driver-4",
  163. popover: {
  164. title: "",
  165. description: "",
  166. popoverClass: "popoverClass popoverClass4",
  167. align: "start",
  168. side: "top",
  169. nextBtnText: `下一步 (${options.steps.length + 1}/${length})`,
  170. showButtons: ["next"],
  171. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  172. driverInitialPosition(popover, options);
  173. },
  174. },
  175. },
  176. {
  177. element: ".driver-5",
  178. popover: {
  179. title: "",
  180. description: "",
  181. popoverClass: "popoverClass popoverClass5",
  182. align: "start",
  183. side: "top",
  184. nextBtnText: `下一步 (${options.steps.length + 2}/${length})`,
  185. showButtons: ["next"],
  186. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  187. driverInitialPosition(popover, options);
  188. },
  189. },
  190. }
  191. );
  192. if (props.statusAll.subjectStatus) {
  193. options.steps?.push({
  194. element: ".driver-10",
  195. popover: {
  196. title: "",
  197. description: "",
  198. popoverClass: "popoverClass popoverClass10",
  199. align: "start",
  200. side: "top",
  201. nextBtnText: `下一步 (${options.steps.length + 1}/${length})`,
  202. showButtons: ["next"],
  203. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  204. driverInitialPosition(popover, options);
  205. },
  206. },
  207. });
  208. }
  209. options.steps?.push({
  210. element: ".driver-5-1",
  211. popover: {
  212. title: "",
  213. description: "",
  214. popoverClass: "popoverClass popoverClass5-1",
  215. align: "start",
  216. side: "top",
  217. nextBtnText: `下一步 (${options.steps.length + 1}/${length})`,
  218. showButtons: ["next"],
  219. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  220. driverInitialPosition(popover, options);
  221. },
  222. },
  223. });
  224. if (state.platform === IPlatform.PC) {
  225. options.steps?.push({
  226. element: ".driver-6",
  227. popover: {
  228. title: "",
  229. description: "",
  230. popoverClass: "popoverClass popoverClass6 popoverClose",
  231. align: "start",
  232. side: "top",
  233. prevBtnText: "再看一遍",
  234. doneBtnText: "完成",
  235. showButtons: ["next", "previous"],
  236. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  237. driverInitialPosition(popover, options);
  238. },
  239. onPrevClick: () => {
  240. driverObj.drive(0);
  241. },
  242. onNextClick: () => {
  243. onDriverClose();
  244. },
  245. },
  246. });
  247. } else {
  248. // 判断设置之后是否还有引导
  249. if (!state.setting.displayFingering && !props.statusAll.backTitle && !props.statusAll.modelTypeStatus) {
  250. options.steps?.push({
  251. element: ".driver-6",
  252. popover: {
  253. title: "",
  254. description: "",
  255. popoverClass: "popoverClass popoverClass6 popoverClose",
  256. align: "start",
  257. side: "top",
  258. prevBtnText: "再看一遍",
  259. doneBtnText: "完成",
  260. showButtons: ["next", "previous"],
  261. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  262. driverInitialPosition(popover, options);
  263. },
  264. onPrevClick: () => {
  265. driverObj.drive(0);
  266. },
  267. onNextClick: () => {
  268. onDriverClose();
  269. },
  270. },
  271. });
  272. } else if (state.setting.displayFingering && !props.statusAll.backTitle && !props.statusAll.modelTypeStatus) {
  273. options.steps?.push({
  274. element: ".driver-6",
  275. popover: {
  276. title: "",
  277. description: "",
  278. popoverClass: "popoverClass popoverClass6",
  279. align: "start",
  280. side: "top",
  281. nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, //"下一步6/" + length,
  282. showButtons: ["next"],
  283. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  284. driverInitialPosition(popover, options);
  285. },
  286. },
  287. });
  288. } else if (props.statusAll.backTitle && !props.statusAll.modelTypeStatus) {
  289. options.steps?.push({
  290. element: ".driver-6",
  291. popover: {
  292. title: "",
  293. description: "",
  294. popoverClass: "popoverClass popoverClass6",
  295. align: "start",
  296. side: "top",
  297. nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, //"下一步6/" + length,
  298. showButtons: ["next"],
  299. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  300. driverInitialPosition(popover, options);
  301. },
  302. },
  303. });
  304. options.steps?.push({
  305. //props.statusAll.titleType === "TEXT" ? ".driver-8 .van-notice-bar__content" :
  306. element: ".driver-8",
  307. popover: {
  308. title: "",
  309. description: "",
  310. popoverClass: "popoverClass popoverClass8 popoverClose",
  311. align: "start",
  312. side: "bottom",
  313. prevBtnText: "再看一遍",
  314. doneBtnText: "完成",
  315. showButtons: ["next", "previous"],
  316. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  317. if (props.statusAll.titleType === "TEXT") {
  318. options.config.stageRadius = 5;
  319. options.config.stagePadding = 5;
  320. } else {
  321. options.config.stageRadius = 1000;
  322. options.config.stagePadding = 0;
  323. }
  324. try {
  325. const rect = options.state.activeElement?.getBoundingClientRect();
  326. popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 - 4 + "px";
  327. } catch {}
  328. },
  329. onPrevClick: () => {
  330. driverObj.drive(0);
  331. },
  332. onNextClick: () => {
  333. onDriverClose();
  334. },
  335. },
  336. });
  337. } else {
  338. options.steps?.push({
  339. element: ".driver-6",
  340. popover: {
  341. title: "",
  342. description: "",
  343. popoverClass: "popoverClass popoverClass6",
  344. align: "start",
  345. side: "top",
  346. nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, //"下一步6/" + length,
  347. showButtons: ["next"],
  348. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  349. driverInitialPosition(popover, options);
  350. },
  351. },
  352. });
  353. if (props.statusAll.backTitle) {
  354. options.steps?.push({
  355. // .van-notice-bar__content
  356. // element: ".driver-8 .van-notice-bar__content",
  357. // props.statusAll.titleType === "TEXT" ? ".driver-8 .van-notice-bar__content" :
  358. element: ".driver-8",
  359. popover: {
  360. title: "",
  361. description: "",
  362. popoverClass: "popoverClass popoverClass8",
  363. align: "start",
  364. side: "bottom",
  365. nextBtnText: `下一步 (${options.steps.length + 1}/${length})`,
  366. showButtons: ["next"],
  367. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  368. if (props.statusAll.titleType === "TEXT") {
  369. options.config.stageRadius = 5;
  370. options.config.stagePadding = 5;
  371. } else {
  372. options.config.stageRadius = 1000;
  373. options.config.stagePadding = 0;
  374. }
  375. try {
  376. const rect = options.state.activeElement?.getBoundingClientRect();
  377. popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 - 4 + "px";
  378. } catch {}
  379. },
  380. },
  381. });
  382. }
  383. options.steps?.push({
  384. element: ".driver-9",
  385. popover: {
  386. title: "",
  387. description: "",
  388. popoverClass: "popoverClass popoverClass9 popoverClose",
  389. align: "end",
  390. side: "bottom",
  391. prevBtnText: "再看一遍",
  392. doneBtnText: "完成",
  393. showButtons: ["next", "previous"],
  394. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  395. options.config.stageRadius = 1000;
  396. options.config.stagePadding = 0;
  397. try {
  398. const rect = options.state.activeElement?.getBoundingClientRect();
  399. popover.wrapper.style.marginLeft = -((rect?.width || 0) / 2 - 8) + "px";
  400. } catch {}
  401. },
  402. onPrevClick: () => {
  403. driverObj.drive(0);
  404. },
  405. onNextClick: () => {
  406. onDriverClose();
  407. },
  408. },
  409. });
  410. }
  411. }
  412. return options;
  413. };
  414. let driverObj: any;
  415. const handleClickOutside = (event: any) => {
  416. // 如果高亮没有结束则下进行下一步
  417. if (driverNextStatus.value) return;
  418. if (driverObj.isActive() && (event.target.nodeName === "path" || event.target.classList.contains("driver-popover") || event.target.classList.contains("driver-overlay"))) {
  419. if (driverObj.isLastStep()) {
  420. onDriverClose();
  421. } else {
  422. driverObj.moveNext(); // 跳转到下一步
  423. }
  424. }
  425. };
  426. const guideInfo = ref({} as any);
  427. const showCloseBtn = ref(false);
  428. const getAllGuidance = async () => {
  429. try {
  430. // const res = await getGuidance({ guideTag: "guideInfo" });
  431. const res = localStorage.getItem("guideInfo");
  432. if (res) {
  433. guideInfo.value = JSON.parse(res) || null;
  434. } else {
  435. guideInfo.value = {};
  436. }
  437. if (!(guideInfo.value && guideInfo.value.practiseDriver)) {
  438. document.addEventListener("click", handleClickOutside, true);
  439. driverObj = driver(driverOptions());
  440. nextTick(() => {
  441. driverObj.drive();
  442. showCloseBtn.value = true;
  443. state.hasDriverPop = true;
  444. });
  445. }
  446. } catch (e) {
  447. console.log(e);
  448. }
  449. };
  450. getAllGuidance();
  451. // 结束关闭弹窗
  452. const onDriverClose = () => {
  453. if (!guideInfo.value) {
  454. guideInfo.value = { practiseDriver: true };
  455. } else {
  456. guideInfo.value.practiseDriver = true;
  457. }
  458. endGuide(guideInfo.value);
  459. driverObj.destroy();
  460. document.querySelector(".driver-popover-close-btn-custom")?.remove();
  461. document.removeEventListener("click", handleClickOutside, true);
  462. state.hasDriverPop = false;
  463. };
  464. onUnmounted(() => {
  465. document.removeEventListener("click", handleClickOutside, true);
  466. });
  467. return () => (
  468. <Teleport to="body">
  469. {showCloseBtn.value && (
  470. <div
  471. class="driver-popover-close-btn-custom"
  472. onClick={(e: any) => {
  473. onDriverClose();
  474. }}
  475. ></div>
  476. )}
  477. </Teleport>
  478. );
  479. },
  480. });
  481. /** 跟练模式 */
  482. export const FollowDriver = defineComponent({
  483. name: "FollowDriver",
  484. props: {
  485. // 按钮状态
  486. statusAll: {
  487. type: Object as PropType<ButtonStatus>,
  488. default: () => {},
  489. },
  490. },
  491. setup(props) {
  492. const driverNextStatus = ref(false);
  493. // 初始化部分引导位置
  494. const driverInitialPosition = (popover: PopoverDOM, options: { config: Config; state: State }) => {
  495. options.config.stageRadius = 5;
  496. options.config.stagePadding = 8;
  497. try {
  498. const rect = options.state.activeElement?.getBoundingClientRect();
  499. popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 + 4 + "px";
  500. } catch {}
  501. };
  502. // 声部
  503. let length = props.statusAll.subjectStatus ? 5 : 4;
  504. const driverOptions: Config = {
  505. showProgress: false,
  506. allowClose: false,
  507. popoverOffset: 3,
  508. disableActiveInteraction: true,
  509. onCloseClick: () => {
  510. onDriverClose();
  511. },
  512. onHighlightStarted: () => {
  513. driverNextStatus.value = true;
  514. },
  515. onHighlighted: () => {
  516. driverNextStatus.value = false;
  517. },
  518. steps: [
  519. {
  520. element: ".follow-1",
  521. popover: {
  522. title: "",
  523. description: "",
  524. popoverClass: "popoverClass popoverClassF1",
  525. align: "end",
  526. side: "top",
  527. nextBtnText: `下一步 (1/${length})`,
  528. showButtons: ["next"],
  529. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  530. options.config.stageRadius = 1000;
  531. options.config.stagePadding = 0;
  532. },
  533. },
  534. },
  535. {
  536. element: ".driver-5",
  537. popover: {
  538. title: "",
  539. description: "",
  540. popoverClass: "popoverClass popoverClassF2",
  541. align: "start",
  542. side: "top",
  543. nextBtnText: `下一步 (2/${length})`,
  544. showButtons: ["next"],
  545. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  546. driverInitialPosition(popover, options);
  547. },
  548. },
  549. },
  550. ],
  551. };
  552. if (props.statusAll.subjectStatus) {
  553. driverOptions.steps?.push({
  554. element: ".driver-10",
  555. popover: {
  556. title: "",
  557. description: "",
  558. popoverClass: "popoverClass popoverClass10",
  559. align: "start",
  560. side: "top",
  561. nextBtnText: `下一步 (${driverOptions.steps.length + 1}/${length})`,
  562. showButtons: ["next"],
  563. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  564. driverInitialPosition(popover, options);
  565. },
  566. },
  567. });
  568. }
  569. driverOptions.steps?.push({
  570. element: ".driver-5-1",
  571. popover: {
  572. title: "",
  573. description: "",
  574. popoverClass: "popoverClass popoverClass5-1",
  575. align: "start",
  576. side: "top",
  577. nextBtnText: `下一步 (${driverOptions.steps.length + 1}/${length})`,
  578. showButtons: ["next"],
  579. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  580. driverInitialPosition(popover, options);
  581. },
  582. },
  583. });
  584. driverOptions.steps?.push({
  585. element: ".driver-6",
  586. popover: {
  587. title: "",
  588. description: "",
  589. popoverClass: "popoverClass popoverClassF3 popoverClose",
  590. align: "start",
  591. side: "top",
  592. prevBtnText: "再看一遍",
  593. doneBtnText: "完成",
  594. showButtons: ["next", "previous"],
  595. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  596. driverInitialPosition(popover, options);
  597. },
  598. onPrevClick: () => {
  599. driverObj.drive(0);
  600. },
  601. onNextClick: () => {
  602. onDriverClose();
  603. },
  604. },
  605. });
  606. let driverObj: any;
  607. const handleClickOutside = (event: any) => {
  608. if (driverNextStatus.value) return;
  609. console.log(driverObj.getActiveIndex(), "driverObj.getActiveIndex()");
  610. if (driverObj.isActive() && (event.target.nodeName === "path" || event.target.classList.contains("driver-popover") || event.target.classList.contains("driver-overlay"))) {
  611. if (driverObj.isLastStep()) {
  612. onDriverClose();
  613. } else {
  614. // driverObj.moveNext(); // 跳转到下一步
  615. const index = driverObj.getActiveIndex();
  616. driverObj.moveTo(index + 1);
  617. }
  618. }
  619. };
  620. const guideInfo = ref({} as any);
  621. const showCloseBtn = ref(false);
  622. const getAllGuidance = async () => {
  623. try {
  624. const res = localStorage.getItem("guideInfo");
  625. if (res) {
  626. guideInfo.value = JSON.parse(res) || null;
  627. } else {
  628. guideInfo.value = {};
  629. }
  630. if (!(guideInfo.value && guideInfo.value.followDriver)) {
  631. document.addEventListener("click", handleClickOutside, true);
  632. nextTick(() => {
  633. driverObj = driver(driverOptions);
  634. driverObj.drive(0);
  635. showCloseBtn.value = true;
  636. state.hasDriverPop = true;
  637. });
  638. }
  639. } catch (e) {
  640. console.log(e);
  641. }
  642. };
  643. getAllGuidance();
  644. // 结束关闭弹窗
  645. const onDriverClose = () => {
  646. if (!guideInfo.value) {
  647. guideInfo.value = { followDriver: true };
  648. } else {
  649. guideInfo.value.followDriver = true;
  650. }
  651. endGuide(guideInfo.value);
  652. driverObj.destroy();
  653. document.querySelector(".driver-popover-close-btn-custom")?.remove();
  654. document.removeEventListener("click", handleClickOutside, true);
  655. state.hasDriverPop = false;
  656. };
  657. onUnmounted(() => {
  658. document.removeEventListener("click", handleClickOutside, true);
  659. });
  660. return () => (
  661. <Teleport to="body">
  662. {showCloseBtn.value && (
  663. <div
  664. class="driver-popover-close-btn-custom"
  665. onClick={(e: any) => {
  666. onDriverClose();
  667. }}
  668. ></div>
  669. )}
  670. </Teleport>
  671. );
  672. },
  673. });
  674. // 评测模式
  675. export const EvaluatingDriver = defineComponent({
  676. name: "EvaluatingDriver",
  677. props: {
  678. // 按钮状态
  679. statusAll: {
  680. type: Object as PropType<ButtonStatus>,
  681. default: () => {},
  682. },
  683. },
  684. setup(props) {
  685. const driverNextStatus = ref(false);
  686. // 初始化部分引导位置
  687. const driverInitialPosition = (popover: PopoverDOM, options: { config: Config; state: State }) => {
  688. options.config.stageRadius = 5;
  689. options.config.stagePadding = 8;
  690. try {
  691. const rect = options.state.activeElement?.getBoundingClientRect();
  692. popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 + 4 + "px";
  693. } catch {}
  694. };
  695. // 声部
  696. let length = props.statusAll.subjectStatus ? 6 : 5;
  697. const driverOptions: Config = {
  698. showProgress: false,
  699. allowClose: false,
  700. popoverOffset: 3,
  701. disableActiveInteraction: true,
  702. onCloseClick: () => {
  703. onDriverClose();
  704. },
  705. onHighlightStarted: () => {
  706. driverNextStatus.value = true;
  707. },
  708. onHighlighted: () => {
  709. driverNextStatus.value = false;
  710. },
  711. steps: [
  712. {
  713. element: ".evaluting-1",
  714. popover: {
  715. title: "",
  716. description: "",
  717. popoverClass: "popoverClass popoverClassE1",
  718. align: "end",
  719. side: "top",
  720. nextBtnText: `下一步 (1/${length})`,
  721. showButtons: ["next"],
  722. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  723. options.config.stageRadius = 1000;
  724. options.config.stagePadding = 0;
  725. },
  726. },
  727. },
  728. {
  729. element: ".driver-4",
  730. popover: {
  731. title: "",
  732. description: "",
  733. popoverClass: "popoverClass popoverClassE2",
  734. align: "start",
  735. side: "top",
  736. nextBtnText: `下一步 (2/${length})`,
  737. showButtons: ["next"],
  738. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  739. driverInitialPosition(popover, options);
  740. },
  741. },
  742. },
  743. {
  744. element: ".driver-5",
  745. popover: {
  746. title: "",
  747. description: "",
  748. popoverClass: "popoverClass popoverClassE3",
  749. align: "start",
  750. side: "top",
  751. nextBtnText: `下一步 (3/${length})`,
  752. showButtons: ["next"],
  753. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  754. driverInitialPosition(popover, options);
  755. },
  756. },
  757. },
  758. ],
  759. };
  760. if (props.statusAll.subjectStatus) {
  761. driverOptions.steps?.push({
  762. element: ".driver-10",
  763. popover: {
  764. title: "",
  765. description: "",
  766. popoverClass: "popoverClass popoverClass10",
  767. align: "start",
  768. side: "top",
  769. nextBtnText: `下一步 (${driverOptions.steps.length + 1}/${length})`,
  770. showButtons: ["next"],
  771. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  772. driverInitialPosition(popover, options);
  773. },
  774. },
  775. });
  776. }
  777. driverOptions.steps?.push({
  778. element: ".driver-5-1",
  779. popover: {
  780. title: "",
  781. description: "",
  782. popoverClass: "popoverClass popoverClass5-1",
  783. align: "start",
  784. side: "top",
  785. nextBtnText: `下一步 (${driverOptions.steps.length + 1}/${length})`,
  786. showButtons: ["next"],
  787. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  788. driverInitialPosition(popover, options);
  789. },
  790. },
  791. });
  792. driverOptions.steps?.push({
  793. element: ".driver-6",
  794. popover: {
  795. title: "",
  796. description: "",
  797. popoverClass: "popoverClass popoverClassE4 popoverClose",
  798. align: "start",
  799. side: "top",
  800. prevBtnText: "再看一遍",
  801. doneBtnText: "完成",
  802. showButtons: ["next", "previous"],
  803. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  804. driverInitialPosition(popover, options);
  805. },
  806. onPrevClick: () => {
  807. driverObj.drive(0);
  808. },
  809. onNextClick: () => {
  810. onDriverClose();
  811. },
  812. },
  813. });
  814. let driverObj: any;
  815. const handleClickOutside = (event: any) => {
  816. if (driverNextStatus.value) return;
  817. console.log(driverObj.getActiveIndex(), "driverObj.getActiveIndex()");
  818. if (driverObj.isActive() && (event.target.nodeName === "path" || event.target.classList.contains("driver-popover") || event.target.classList.contains("driver-overlay"))) {
  819. if (driverObj.isLastStep()) {
  820. onDriverClose();
  821. } else {
  822. driverObj.moveNext(); // 跳转到下一步
  823. }
  824. }
  825. };
  826. const guideInfo = ref({} as any);
  827. const showCloseBtn = ref(false);
  828. const getAllGuidance = async () => {
  829. try {
  830. const res = localStorage.getItem("guideInfo");
  831. if (res) {
  832. guideInfo.value = JSON.parse(res) || null;
  833. } else {
  834. guideInfo.value = {};
  835. }
  836. console.log(guideInfo.value, "guideInfo.value", showCloseBtn.value);
  837. if (!(guideInfo.value && guideInfo.value.evaluatingDriver)) {
  838. document.addEventListener("click", handleClickOutside, true);
  839. nextTick(() => {
  840. driverObj = driver(driverOptions);
  841. driverObj.drive();
  842. showCloseBtn.value = true;
  843. state.hasDriverPop = true;
  844. console.log(driverOptions, "driverOptions Evaluating", showCloseBtn.value);
  845. });
  846. } else {
  847. driverObj?.destroy();
  848. }
  849. } catch (e) {
  850. console.log(e);
  851. }
  852. };
  853. getAllGuidance();
  854. // 结束关闭弹窗
  855. const onDriverClose = () => {
  856. if (!guideInfo.value) {
  857. guideInfo.value = { evaluatingDriver: true };
  858. } else {
  859. guideInfo.value.evaluatingDriver = true;
  860. }
  861. endGuide(guideInfo.value);
  862. driverObj?.destroy();
  863. document.querySelector(".driver-popover-close-btn-custom")?.remove();
  864. document.removeEventListener("click", handleClickOutside, true);
  865. state.hasDriverPop = false;
  866. };
  867. onUnmounted(() => {
  868. document.removeEventListener("click", handleClickOutside, true);
  869. });
  870. return () => (
  871. <Teleport to="body">
  872. {showCloseBtn.value && (
  873. <div
  874. class="driver-popover-close-btn-custom"
  875. onClick={(e: any) => {
  876. onDriverClose();
  877. }}
  878. ></div>
  879. )}
  880. </Teleport>
  881. );
  882. },
  883. });
  884. // 评测模式 - 结果弹窗
  885. export const EvaluatingResultDriver = defineComponent({
  886. name: "EvaluatingResultDriver",
  887. props: {
  888. // 保存按钮状态
  889. saveBtn: {
  890. type: Boolean,
  891. default: true,
  892. },
  893. },
  894. setup(props) {
  895. let length = 4;
  896. if (!props.saveBtn) {
  897. length -= 1;
  898. }
  899. console.log(props.saveBtn, "props.saveBtn");
  900. const driverNextStatus = ref(false);
  901. // 初始化部分引导位置
  902. const driverInitialPosition = (popover: PopoverDOM, options: { config: Config; state: State }, position = 1) => {
  903. options.config.stageRadius = 1000;
  904. options.config.stagePadding = 2;
  905. try {
  906. const rect = options.state.activeElement?.getBoundingClientRect();
  907. popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * position + 4 + "px";
  908. } catch {}
  909. };
  910. const driverOptionsFun = () => {
  911. const driverOptions: Config = {
  912. showProgress: false,
  913. allowClose: false,
  914. popoverOffset: 3,
  915. disableActiveInteraction: true,
  916. onCloseClick: () => {
  917. onDriverClose();
  918. },
  919. onHighlightStarted: () => {
  920. driverNextStatus.value = true;
  921. },
  922. onHighlighted: () => {
  923. driverNextStatus.value = false;
  924. },
  925. steps: [
  926. {
  927. element: ".evaluting-result-1",
  928. popover: {
  929. title: "",
  930. description: "",
  931. popoverClass: "popoverClass popoverClassER1",
  932. align: "start",
  933. side: "right",
  934. nextBtnText: `下一步 (1/${length})`,
  935. showButtons: ["next"],
  936. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  937. options.config.stageRadius = 12;
  938. options.config.stagePadding = 10;
  939. },
  940. },
  941. },
  942. {
  943. element: ".evaluting-result-2",
  944. popover: {
  945. title: "",
  946. description: "",
  947. popoverClass: "popoverClass popoverClassER2",
  948. align: "start",
  949. side: "top",
  950. nextBtnText: `下一步 (2/${length})`,
  951. showButtons: ["next"],
  952. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  953. options.config.stageRadius = 1000;
  954. options.config.stagePadding = 2;
  955. try {
  956. const rect = options.state.activeElement?.getBoundingClientRect();
  957. popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 - 4 + "px";
  958. } catch {}
  959. },
  960. },
  961. },
  962. ],
  963. };
  964. if (props.saveBtn) {
  965. driverOptions.steps?.push({
  966. element: ".evaluting-result-3",
  967. popover: {
  968. title: "",
  969. description: "",
  970. popoverClass: "popoverClass popoverClassER3",
  971. align: "end",
  972. side: "top",
  973. nextBtnText: `下一步 (3/${length})`,
  974. showButtons: ["next"],
  975. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  976. driverInitialPosition(popover, options, -1);
  977. },
  978. },
  979. });
  980. }
  981. driverOptions.steps?.push({
  982. element: ".evaluting-result-4",
  983. popover: {
  984. title: "",
  985. description: "",
  986. popoverClass: "popoverClass popoverClassER4 popoverClose",
  987. align: "end",
  988. side: "top",
  989. prevBtnText: "再看一遍",
  990. doneBtnText: "完成",
  991. showButtons: ["next", "previous"],
  992. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  993. driverInitialPosition(popover, options, -1);
  994. },
  995. onPrevClick: () => {
  996. driverObj.drive();
  997. },
  998. onNextClick: () => {
  999. onDriverClose();
  1000. },
  1001. },
  1002. });
  1003. return driverOptions;
  1004. };
  1005. let driverObj: any;
  1006. const handleClickOutside = (event: any) => {
  1007. if (driverNextStatus.value) return;
  1008. if (driverObj.isActive() && (event.target.nodeName === "path" || event.target.classList.contains("driver-popover") || event.target.classList.contains("driver-overlay"))) {
  1009. if (driverObj.isLastStep()) {
  1010. onDriverClose();
  1011. } else {
  1012. driverObj.moveNext(); // 跳转到下一步
  1013. }
  1014. }
  1015. };
  1016. const guideInfo = ref({} as any);
  1017. const showCloseBtn = ref(false);
  1018. const getAllGuidance = async () => {
  1019. try {
  1020. const res = localStorage.getItem("guideInfo");
  1021. if (res) {
  1022. guideInfo.value = JSON.parse(res) || null;
  1023. } else {
  1024. guideInfo.value = {};
  1025. }
  1026. if (!(guideInfo.value && guideInfo.value.evaluatingResultDriver)) {
  1027. setTimeout(() => {
  1028. document.addEventListener("click", handleClickOutside, true);
  1029. nextTick(() => {
  1030. driverObj = driver(driverOptionsFun());
  1031. driverObj.drive();
  1032. showCloseBtn.value = true;
  1033. state.hasDriverPop = true;
  1034. });
  1035. }, 100);
  1036. }
  1037. } catch (e) {
  1038. console.log(e);
  1039. }
  1040. };
  1041. onMounted(() => {
  1042. getAllGuidance();
  1043. });
  1044. // 结束关闭弹窗
  1045. const onDriverClose = () => {
  1046. if (!guideInfo.value) {
  1047. guideInfo.value = { evaluatingResultDriver: true };
  1048. } else {
  1049. guideInfo.value.evaluatingResultDriver = true;
  1050. }
  1051. endGuide(guideInfo.value);
  1052. driverObj.destroy();
  1053. document.querySelector(".driver-popover-close-btn-custom")?.remove();
  1054. document.removeEventListener("click", handleClickOutside, true);
  1055. state.hasDriverPop = false;
  1056. };
  1057. onUnmounted(() => {
  1058. document.removeEventListener("click", handleClickOutside, true);
  1059. });
  1060. return () => (
  1061. <Teleport to="body">
  1062. {showCloseBtn.value && (
  1063. <div
  1064. class="driver-popover-close-btn-custom"
  1065. onClick={(e: any) => {
  1066. onDriverClose();
  1067. }}
  1068. ></div>
  1069. )}
  1070. </Teleport>
  1071. );
  1072. },
  1073. });
  1074. // 评测报告
  1075. export const EvaluatingReportDriver = defineComponent({
  1076. name: "EvaluatingReportDriver",
  1077. props: {
  1078. /** 视屏地址 */
  1079. videoFilePath: {
  1080. type: String,
  1081. default: "",
  1082. },
  1083. },
  1084. setup(props) {
  1085. const driverNextStatus = ref(false);
  1086. // state.isPercussion 是否为打击乐
  1087. // 初始化部分引导位置
  1088. const driverInitialPosition = (popover: PopoverDOM, options: { config: Config; state: State }, position = 1) => {
  1089. options.config.stageRadius = 12;
  1090. options.config.stagePadding = 0;
  1091. try {
  1092. const rect = options.state.activeElement?.getBoundingClientRect();
  1093. popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * position - 4 + "px";
  1094. } catch {}
  1095. };
  1096. // 判断是否为打击乐
  1097. let steps: DriveStep[] = [];
  1098. if (state.isPercussion) {
  1099. if (props.videoFilePath) {
  1100. steps = [
  1101. {
  1102. element: ".evaluting-report-2",
  1103. popover: {
  1104. title: "",
  1105. description: "",
  1106. popoverClass: "popoverClass popoverClassReport2",
  1107. align: "end",
  1108. side: "bottom",
  1109. nextBtnText: "下一步 (1/2)",
  1110. showButtons: ["next"],
  1111. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  1112. try {
  1113. const rect = options.state.activeElement?.getBoundingClientRect();
  1114. popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px";
  1115. } catch {}
  1116. },
  1117. },
  1118. },
  1119. {
  1120. element: ".evaluting-report-4",
  1121. popover: {
  1122. title: "",
  1123. description: "",
  1124. popoverClass: "popoverClass popoverClassReport4 popoverClose",
  1125. align: "end",
  1126. side: "bottom",
  1127. prevBtnText: "再看一遍",
  1128. doneBtnText: "完成",
  1129. showButtons: ["next", "previous"],
  1130. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  1131. options.config.stageRadius = 8;
  1132. options.config.stagePadding = 5;
  1133. try {
  1134. const rect = options.state.activeElement?.getBoundingClientRect();
  1135. popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px";
  1136. } catch {}
  1137. },
  1138. onPrevClick: () => {
  1139. driverObj.drive(0);
  1140. },
  1141. onNextClick: () => {
  1142. onDriverClose();
  1143. },
  1144. },
  1145. },
  1146. ];
  1147. } else {
  1148. steps = [
  1149. {
  1150. element: ".evaluting-report-2",
  1151. popover: {
  1152. title: "",
  1153. description: "",
  1154. popoverClass: "popoverClass popoverClassReport2 popoverClose",
  1155. align: "end",
  1156. side: "bottom",
  1157. doneBtnText: "完成",
  1158. showButtons: ["next"],
  1159. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  1160. options.config.stageRadius = 12;
  1161. options.config.stagePadding = 0;
  1162. try {
  1163. const rect = options.state.activeElement?.getBoundingClientRect();
  1164. popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px";
  1165. } catch {}
  1166. },
  1167. onPrevClick: () => {
  1168. driverObj.drive(0);
  1169. },
  1170. onNextClick: () => {
  1171. onDriverClose();
  1172. },
  1173. },
  1174. },
  1175. ];
  1176. }
  1177. } else {
  1178. const count = props.videoFilePath ? 4 : 3;
  1179. steps = [
  1180. {
  1181. element: ".evaluting-report-1",
  1182. popover: {
  1183. title: "",
  1184. description: "",
  1185. popoverClass: "popoverClass popoverClassReport1",
  1186. align: "start",
  1187. side: "bottom",
  1188. nextBtnText: `下一步 (1/${count})`,
  1189. showButtons: ["next"],
  1190. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  1191. driverInitialPosition(popover, options);
  1192. },
  1193. },
  1194. },
  1195. {
  1196. element: ".evaluting-report-2",
  1197. popover: {
  1198. title: "",
  1199. description: "",
  1200. popoverClass: "popoverClass popoverClassReport2",
  1201. align: "end",
  1202. side: "bottom",
  1203. nextBtnText: `下一步 (2/${count})`,
  1204. showButtons: ["next"],
  1205. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  1206. try {
  1207. const rect = options.state.activeElement?.getBoundingClientRect();
  1208. popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px";
  1209. } catch {}
  1210. },
  1211. },
  1212. },
  1213. ];
  1214. if (props.videoFilePath) {
  1215. steps.push(
  1216. {
  1217. element: ".evaluting-report-3",
  1218. popover: {
  1219. title: "",
  1220. description: "",
  1221. popoverClass: "popoverClass popoverClassReport3",
  1222. align: "end",
  1223. side: "bottom",
  1224. nextBtnText: "下一步 (3/4)",
  1225. showButtons: ["next"],
  1226. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  1227. try {
  1228. const rect = options.state.activeElement?.getBoundingClientRect();
  1229. popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px";
  1230. } catch {}
  1231. },
  1232. },
  1233. },
  1234. {
  1235. element: ".evaluting-report-4",
  1236. popover: {
  1237. title: "",
  1238. description: "",
  1239. popoverClass: "popoverClass popoverClassReport4 popoverClose",
  1240. align: "end",
  1241. side: "bottom",
  1242. prevBtnText: "再看一遍",
  1243. doneBtnText: "完成",
  1244. showButtons: ["next", "previous"],
  1245. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  1246. options.config.stageRadius = 8;
  1247. options.config.stagePadding = 5;
  1248. try {
  1249. const rect = options.state.activeElement?.getBoundingClientRect();
  1250. popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px";
  1251. } catch {}
  1252. },
  1253. onPrevClick: () => {
  1254. driverObj.drive(0);
  1255. },
  1256. onNextClick: () => {
  1257. onDriverClose();
  1258. },
  1259. },
  1260. }
  1261. );
  1262. } else {
  1263. steps.push({
  1264. element: ".evaluting-report-3",
  1265. popover: {
  1266. title: "",
  1267. description: "",
  1268. popoverClass: "popoverClass popoverClassReport3 popoverClose",
  1269. align: "end",
  1270. side: "bottom",
  1271. prevBtnText: "再看一遍",
  1272. doneBtnText: "完成",
  1273. showButtons: ["next", "previous"],
  1274. onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
  1275. try {
  1276. const rect = options.state.activeElement?.getBoundingClientRect();
  1277. popover.wrapper.style.marginLeft = ((rect?.width || 0) / 2) * -1 + 4 + "px";
  1278. } catch {}
  1279. },
  1280. onPrevClick: () => {
  1281. driverObj.drive(0);
  1282. },
  1283. onNextClick: () => {
  1284. onDriverClose();
  1285. },
  1286. },
  1287. });
  1288. }
  1289. }
  1290. const driverOptions: Config = {
  1291. showProgress: false,
  1292. allowClose: false,
  1293. popoverOffset: 3,
  1294. disableActiveInteraction: true,
  1295. onCloseClick: () => {
  1296. onDriverClose();
  1297. },
  1298. onHighlightStarted: () => {
  1299. driverNextStatus.value = true;
  1300. },
  1301. onHighlighted: () => {
  1302. driverNextStatus.value = false;
  1303. },
  1304. steps: steps,
  1305. };
  1306. let driverObj: any;
  1307. const guideInfo = ref({} as any);
  1308. const handleClickOutside = (event: any) => {
  1309. if (driverNextStatus.value) return;
  1310. if (driverObj.isActive() && (event.target.nodeName === "path" || event.target.classList.contains("driver-popover") || event.target.classList.contains("driver-overlay"))) {
  1311. if (driverObj.isLastStep()) {
  1312. onDriverClose();
  1313. } else {
  1314. driverObj.moveNext(); // 跳转到下一步
  1315. }
  1316. }
  1317. };
  1318. const showCloseBtn = ref(false);
  1319. const getAllGuidance = async () => {
  1320. try {
  1321. const res = localStorage.getItem("guideInfo");
  1322. if (res) {
  1323. guideInfo.value = JSON.parse(res) || null;
  1324. } else {
  1325. guideInfo.value = {};
  1326. }
  1327. if (!(guideInfo.value && guideInfo.value.evaluatingReportDriver)) {
  1328. // 监听点击事件以实现点击空白区域跳转到下一步
  1329. document.addEventListener("click", handleClickOutside, true);
  1330. nextTick(() => {
  1331. driverObj = driver(driverOptions);
  1332. driverObj.drive();
  1333. state.hasDriverPop = true;
  1334. showCloseBtn.value = true;
  1335. });
  1336. }
  1337. } catch (e) {
  1338. console.log(e);
  1339. }
  1340. };
  1341. getAllGuidance();
  1342. // 结束关闭弹窗
  1343. const onDriverClose = () => {
  1344. if (!guideInfo.value) {
  1345. guideInfo.value = { evaluatingReportDriver: true };
  1346. } else {
  1347. guideInfo.value.evaluatingReportDriver = true;
  1348. }
  1349. endGuide(guideInfo.value);
  1350. driverObj.destroy();
  1351. document.querySelector(".driver-popover-close-btn-custom")?.remove();
  1352. document.removeEventListener("click", handleClickOutside, true);
  1353. state.hasDriverPop = false;
  1354. };
  1355. onUnmounted(() => {
  1356. document.removeEventListener("click", handleClickOutside, true);
  1357. });
  1358. return () => (
  1359. <Teleport to="body">
  1360. {showCloseBtn.value && (
  1361. <div
  1362. class="driver-popover-close-btn-custom"
  1363. onClick={(e: any) => {
  1364. onDriverClose();
  1365. }}
  1366. ></div>
  1367. )}
  1368. </Teleport>
  1369. );
  1370. },
  1371. });