student-guide.tsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import { NButton } from 'naive-ui';
  2. import {
  3. defineComponent,
  4. nextTick,
  5. onMounted,
  6. onUnmounted,
  7. reactive,
  8. ref,
  9. watch
  10. } from 'vue';
  11. import styles from './index.module.less';
  12. import { getImage } from './images';
  13. import {px2vw,px2vwH} from '@/utils/index'
  14. export default defineComponent({
  15. name: 'coai-guide',
  16. emits: ['close'],
  17. setup(props, { emit }) {
  18. const data = reactive({
  19. box: {
  20. height:'0px',
  21. } as any,
  22. show: false,
  23. /**
  24. *
  25. width: px2vw(840),
  26. height: px2vw(295)
  27. left: '-80px',
  28. width: '518px',
  29. height: '256px'
  30. */
  31. steps: [
  32. {
  33. ele: '',
  34. eleRect: {} as DOMRect,
  35. img: getImage('student1.png'),
  36. handStyle: {
  37. top: '0.91rem'
  38. },
  39. imgStyle: {
  40. top:px2vw(-4),
  41. left: px2vw(-64),
  42. width: px2vw(518),
  43. height: px2vw(256)
  44. },
  45. btnsStyle: {
  46. bottom: px2vw(30),
  47. left: px2vw(-74),
  48. },
  49. eleRectPadding:{
  50. left:7,
  51. top:7,
  52. width:14,
  53. height:14
  54. }
  55. },
  56. {
  57. ele: '',
  58. img: getImage('student2.png'),
  59. imgStyle: {
  60. top: px2vw(-4),
  61. left: px2vw(-261),
  62. width: px2vw(515),
  63. height:px2vw(227)
  64. },
  65. btnsStyle: {
  66. bottom:px2vw(30),
  67. left: px2vw(-120),
  68. },
  69. eleRectPadding:{
  70. left:7,
  71. top:7,
  72. width:14,
  73. height:14
  74. }
  75. },
  76. ],
  77. step: 0
  78. });
  79. const tipShow = ref(false);
  80. const guideInfo = localStorage.getItem('teacher-guideInfo');
  81. if (guideInfo && JSON.parse(guideInfo).studentGuide) {
  82. tipShow.value = false;
  83. } else {
  84. tipShow.value = true;
  85. }
  86. const getStepELe = () => {
  87. const ele: HTMLElement = document.getElementById(`student-${data.step}`)!;
  88. if (ele) {
  89. const eleRect = ele.getBoundingClientRect();
  90. const left = data.steps[data.step].eleRectPadding?.left || 0;
  91. const top = data.steps[data.step].eleRectPadding?.top || 0;
  92. const width = data.steps[data.step].eleRectPadding?.width || 0;
  93. const height = data.steps[data.step].eleRectPadding?.height || 0
  94. data.box = {
  95. left: eleRect.x - left+ 'px',
  96. top: eleRect.y - top +'px',
  97. width: eleRect.width + width+'px',
  98. height: eleRect.height +height+ 'px'
  99. };
  100. console.log(`coai-${data.step}`,data.box);
  101. }else{
  102. handleNext()
  103. }
  104. };
  105. onMounted(() => {
  106. getStepELe();
  107. window.addEventListener("resize", resetSize);
  108. });
  109. const resetSize = ()=>{
  110. getStepELe();
  111. }
  112. onUnmounted(()=>{
  113. window.removeEventListener("resize", resetSize);
  114. })
  115. const handleNext = () => {
  116. if (data.step >= 2) {
  117. endGuide();
  118. return;
  119. }
  120. data.step = data.step + 1;
  121. getStepELe();
  122. };
  123. const endGuide = () => {
  124. let guideInfo =
  125. JSON.parse(localStorage.getItem('teacher-guideInfo') || '{}') || null;
  126. if (!guideInfo) {
  127. guideInfo = { studentGuide: true };
  128. } else {
  129. guideInfo.studentGuide = true;
  130. }
  131. localStorage.setItem('teacher-guideInfo', JSON.stringify(guideInfo));
  132. tipShow.value = false;
  133. // localStorage.setItem('endC')
  134. };
  135. return () => (
  136. <>
  137. {tipShow.value ? (
  138. <div
  139. v-model:show={tipShow.value}
  140. class={['n-modal-mask', 'n-modal-mask-guide']}>
  141. <div class={styles.content} onClick={() => handleNext()}>
  142. <div
  143. class={styles.backBtn}
  144. onClick={(e: Event) => {
  145. e.stopPropagation();
  146. endGuide();
  147. }}>
  148. 跳过
  149. </div>
  150. <div
  151. class={styles.box}
  152. style={{...data.box}}
  153. id={`modeType-${data.step}`}>
  154. {data.steps.map((item: any, index) => (
  155. <div
  156. onClick={(e: Event) => e.stopPropagation()}
  157. class={styles.item}
  158. style={ item.type=='bottom'? {
  159. display: index === data.step ? '' : 'none',
  160. left: `${item.eleRect?.left}px`,
  161. top:`-${item.imgStyle?.height}`
  162. }:{
  163. display: index === data.step ? '' : 'none',
  164. left: `${item.eleRect?.left}px`,
  165. top: `${data.box?.height}`,
  166. }}>
  167. <img
  168. class={styles.img}
  169. style={item.imgStyle}
  170. src={item.img}
  171. />
  172. {/* <img
  173. class={styles.iconHead}
  174. style={item.handStyle}
  175. src={getImage('indexDot.png')}
  176. /> */}
  177. <div class={styles.btns} style={item.btnsStyle}>
  178. {data.step + 1 == data.steps.length ? (
  179. <>
  180. <div
  181. class={[styles.endBtn]}
  182. onClick={() => endGuide()}>
  183. 完成
  184. </div>
  185. <div
  186. class={styles.nextBtn}
  187. onClick={() => {
  188. data.step = 0;
  189. getStepELe();
  190. }}>
  191. 再看一遍
  192. </div>
  193. </>
  194. ) : (
  195. <div class={styles.btn} onClick={() => handleNext()}>
  196. 下一步 ({data.step + 1}/{data.steps.length})
  197. </div>
  198. )}
  199. </div>
  200. </div>
  201. ))}
  202. </div>
  203. </div>
  204. </div>
  205. ) : null}
  206. </>
  207. );
  208. }
  209. });