Tutorial.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. <template>
  2. <div class="tutorial">
  3. <el-row style="padding: 5px; font-size: larger">Developer使用指南
  4. <el-button size="small" class="closeButton" @click="closeTutorial"></el-button>
  5. </el-row>
  6. <el-divider style="margin: 4px; height: 2px"/>
  7. <div id="taskContainer" class="introduction" v-if="showTask">
  8. <div v-for="(task, index) in taskList" :key="index" class="taskLine" @click="beginTask(index)">
  9. <el-tag type="info" size="mini" effect="light" round v-if="task.status === 0">未开始</el-tag>
  10. <el-tag type="danger" size="mini" effect="light" round v-if="task.status === 1">进行中</el-tag>
  11. <el-tag type="success" size="mini" effect="light" round v-if="task.status === 2">已完成</el-tag>
  12. {{task.description}}
  13. </div>
  14. </div>
  15. <div id="stepContainer" class="introduction" v-if="showStep">
  16. <div style="float: left; padding: 6px; left: 5px">{{stepIndex+1}}.</div>
  17. <div style="padding: 4px; margin-left:20px; margin-bottom: 8px">{{ currentSteps[stepIndex].description }}</div>
  18. <div style="padding: 4px; margin-left:20px; margin-bottom: 8px">请按照下列指示进行操作:</div>
  19. <div class="actionDisplay" v-show="!stepFinish">{{currentSteps[stepIndex].action}}</div>
  20. <div class="actionDisplaySuccess" v-show="stepFinish">{{currentSteps[stepIndex].action}}</div>
  21. <el-button size="small" type="primary" plain
  22. :disabled="!stepFinish" style="float: right; right: 5px; margin-top: 10px" @click="nextStep">
  23. 下一步
  24. </el-button>
  25. </div>
  26. </div>
  27. <div class="shade" style="height: 60px; width: 100%"></div>
  28. <div class="shade" style="top: 60px; height: 100%; width: 100%;"></div>
  29. </template>
  30. <script>
  31. export default {
  32. name: 'Tutorial',
  33. data() {
  34. return {
  35. showTask: true,
  36. showStep: false,
  37. // status 表示某一个任务是否被完成,0表示未开始,1表示进行中,2表示已完成
  38. taskList: [
  39. { name: 'display', description: 'Developer界面介绍', status: 0 },
  40. { name: 'taskList', description: '学习使用任务列表模块', status: 0 },
  41. { name: 'git', description: '学习使用提交记录模块', status: 0 },
  42. { name: 'pipeline', description: '学习使用流水线模块', status: 0 },
  43. { name: 'database', description: '学习使用数据库模块', status: 0 },
  44. { name: 'apitest', description: '学习使用测试模块', status: 0 },
  45. { name: 'bugList', description: '学习使用缺陷模块', status: 0 },
  46. { name: 'codereview', description: '学习开展分支评审任务', status: 0 },
  47. ],
  48. instructions: {
  49. display: [],
  50. taskList: [
  51. {
  52. id: 'taskList', popUpId: 'sidebar', description: 'Developer系统提供了任务列表模块,用户可以管理项目开发过程中的所有任务。', action: '点击左边栏中的"任务列表"按钮', type: 'click',
  53. },
  54. {
  55. id: 'taskListTable', popUpId: 'taskListTable', description: '在此模块中可以看到所有存在的任务,以及其预计耗时、优先级等信息', action: '查看表中的任务信息', type: 'display',
  56. },
  57. ],
  58. git: [
  59. {
  60. id: 'git', popUpId: 'sidebar', description: 'Developer系统的模块选择位于最左侧的选择栏中', action: '点击左边栏中的"提交记录"按钮', type: 'click',
  61. },
  62. {
  63. id: 'gitCommitTree', popUpId: 'gitCommitTree', description: '提交记录模块中展示了项目的所有git commit记录', action: '查看当前分支的commit信息', type: 'display',
  64. },
  65. {
  66. id: 'gitBranchSelect', popUpId: 'gitSelectRow', description: '提交记录模块允许选择分支来单独展示分支上的变更', action: '选择master分支', type: 'select', value: 'master',
  67. },
  68. {
  69. id: 'gitFilterButton', popUpId: 'gitSelectRow', description: '', action: '点击\'过滤\'按钮确认筛选', type: 'click',
  70. },
  71. {
  72. id: 'gitAuthorSelect', popUpId: 'gitSelectRow', description: '提交记录模块允许在分支的基础上通过提交人进行筛选', action: '选择任意的提交者', type: 'select',
  73. },
  74. {
  75. id: 'gitFilterButton', popUpId: 'gitSelectRow', description: '', action: '点击\'过滤\'按钮确认筛选', type: 'click',
  76. },
  77. {
  78. id: 'gitTitleFilter', popUpId: 'gitSelectRow', description: '提交记录模块允许根据commit信息以及哈希码进行过滤', action: '输入需要筛选的message或者哈希码', type: 'input',
  79. },
  80. {
  81. id: 'gitFilterButton', popUpId: 'gitSelectRow', description: '', action: '点击\'过滤\'按钮确认筛选', type: 'click',
  82. },
  83. ],
  84. pipeline: [
  85. {
  86. id: 'pipeline', popUpId: 'sidebar', description: 'Developer系统提供了流水线模块,用户可以创建并触发部署流水线,查看部署产物。', action: '点击左边栏中的"流水线"按钮', type: 'click',
  87. },
  88. {
  89. id: 'pipelineCreateButton', popUpId: 'pipelineElTable', description: '为了使用流水线模块的功能,我们首先创建一个新的流水线', action: '点击创建按钮', type: 'click',
  90. },
  91. {
  92. id: 'pipelineCreateTitle', popUpId: 'pipelineCreateTitle', description: '', action: '填写流水线标题为"springboot"', type: 'input', input: 'springboot',
  93. },
  94. {
  95. id: 'pipelineCreateTemplate', popUpId: 'pipelineCreateTemplate', description: '', action: '选择流水线模版"SpringBoot"', type: 'select', value: 'SPRINGBOOT_JAVA8',
  96. },
  97. {
  98. id: 'pipelineCreateConfirm', popUpId: 'pipelineCreateConfirm', description: '', action: '点击确认创建流水线', type: 'select',
  99. },
  100. {
  101. id: 'pipelineTable', popUpId: 'pipelineTabs', description: '在此表中可以看到所有的流水线信息', action: '查看流水线列表', type: 'display',
  102. },
  103. {
  104. id: 'pipelineEditButton-springboot', popUpId: 'pipelineElTable', description: '为了使用流水线任务,我们还需要配置一些必要信息,比如代码仓库地址、端口等', action: '点击编辑按钮', type: 'click',
  105. },
  106. {
  107. id: 'pipelineEditInput-branchOrHash', popUpId: 'pipelineEditInput-branchOrHash', description: '代码检查镜像会在构建前检查指定的分支或提交的代码', action: '输入需要生成检查镜像的分支或hash', type: 'input',
  108. },
  109. {
  110. id: 'pipelineEditNextStep', popUpId: 'pipelineEditNextStep', description: '', action: '点击按钮进行后续配置', type: 'click',
  111. },
  112. {
  113. id: 'pipelineEditInput-repoUrl', popUpId: 'pipelineEditInput-repoUrl', description: '在触发流水线任务时,Developer系统会在指定仓库、指定分支拉取代码并进行构建', action: '输入需要构建的代码仓库地址', type: 'input',
  114. },
  115. {
  116. id: 'pipelineEditInput-branchName', popUpId: 'pipelineEditInput-branchName', description: '', action: '输入需要构建的代码分支', type: 'input',
  117. },
  118. {
  119. id: 'pipelineEditNextStep', popUpId: 'pipelineEditNextStep', description: '', action: '点击按钮进行后续配置', type: 'click',
  120. },
  121. {
  122. id: 'pipelineEditInput-port', popUpId: 'pipelineEditInput-port', description: '此处需要填写springboot后端项目将要占用的端口', action: '填写8080', type: 'input', value: '8080',
  123. },
  124. {
  125. id: 'pipelineEditNextStep', popUpId: 'pipelineEditNextStep', description: '', action: '点击按钮进行后续配置', type: 'click',
  126. },
  127. {
  128. id: 'pipelineEditInput-testSelect', popUpId: 'pipelineEditInput-testSelect', description: '此处可以选择需要进行的自动化接口测试,可以在测试模块中创建API测试', action: '选择需要进行的API测试任务,可以不选择', type: 'display',
  129. },
  130. {
  131. id: 'pipelineEditFinish', popUpId: 'pipelineEditFinish', description: '', action: '点击按钮完成配置', type: 'click',
  132. },
  133. {
  134. id: 'pipelineActivateButton-springboot', popUpId: 'pipelineActivateButton-springboot', description: '点击触发按钮后,系统会根据配置拉取代码并进行构建', action: '点击触发按钮', type: 'click',
  135. },
  136. ],
  137. database: [
  138. {
  139. id: 'pipeline', popUpId: 'sidebar', description: '在使用数据库模块之前需要先通过流水线部署一个数据库实例', action: '点击左边栏中的"流水线"按钮', type: 'click',
  140. },
  141. {
  142. id: 'pipelineCreateButton', popUpId: 'pipelineElTable', description: '', action: '点击按钮新建流水线', type: 'click',
  143. },
  144. {
  145. id: 'pipelineCreateTitle', popUpId: 'pipelineCreateTitle', description: '', action: '填写流水线标题为"mysql"', type: 'input', input: 'mysql',
  146. },
  147. {
  148. id: 'pipelineCreateTemplate', popUpId: 'pipelineCreateTemplate', description: '', action: '选择流水线模版"MYSQL"', type: 'select', value: 'MYSQL',
  149. },
  150. {
  151. id: 'pipelineCreateConfirm', popUpId: 'pipelineCreateConfirm', description: '', action: '点击确认创建流水线', type: 'select',
  152. },
  153. {
  154. id: 'pipelineActivateButton-mysql', popUpId: 'pipelineElTable', description: '默认的数据库占用3306端口,root账户的密码默认为root,可以在编辑中进行修改。', action: '点击确认触发数据库部署', type: 'click',
  155. },
  156. {
  157. id: 'database', popUpId: 'sidebar', description: 'Developer系统提供了数据库模块,用户可以在此模块中执行SQL语句,直观的对数据库进行操作', action: '点击左边栏中的"数据库"按钮', type: 'click',
  158. },
  159. {
  160. id: 'databaseSelect', popUpId: 'projectContainer', description: '用户在此处需要选择要操作的数据库,必须在流水线模块中部署后才可以选择', action: '选择mysql数据库实例', type: 'select', value: 'mysql',
  161. },
  162. {
  163. id: 'databasePassword', popUpId: 'projectContainer', description: '用户在此处需要输入数据库的密码', action: '输入root用户的密码', type: 'input',
  164. },
  165. {
  166. id: 'databaseSQL', popUpId: 'projectContainer', description: '用户在此处输入要执行的SQL语句', action: '输入SQL语句', type: 'input',
  167. },
  168. {
  169. id: 'databaseExec', popUpId: 'projectContainer', description: '', action: '点击按钮执行SQL语句', type: 'click',
  170. },
  171. {
  172. id: 'databaseHistory', popUpId: 'databaseHistory', description: '', action: '在此处可以看到SQL语句执行历史以及结果', type: 'display',
  173. },
  174. ],
  175. apitest: [
  176. {
  177. id: 'apitest', popUpId: 'sidebar', description: '', action: '点击左边栏中的"测试"', type: 'click',
  178. },
  179. {
  180. id: 'testCreateButton', popUpId: 'testElTable', description: '测试模块包括接口测试与黑盒测试两个部分,首先使用接口测试部分', action: '点击按钮新建接口测试任务', type: 'click',
  181. },
  182. {
  183. id: 'testCreateTitle', popUpId: 'testCreateTitle', description: '此处填写测试的名称,在构建时可以根据此名称选择需要进行的自动化测试', action: '输入"tutorial"', type: 'input', value: 'tutorial',
  184. },
  185. {
  186. // eslint-disable-next-line max-len
  187. id: 'testCreateUrl', popUpId: 'testCreateUrl', description: '此处填写接口测试使用的URL, 触发测试时会想此处发送请求', action: '输入"http://backend.todolist-backend-877.devcloud.seec.seecoder.cn/hello"', type: 'input', value: 'http://backend.todolist-backend-877.devcloud.seec.seecoder.cn/hello',
  188. },
  189. {
  190. id: 'testCreateMethod', popUpId: 'testCreateMethod', description: '此处填写接口使用的Http方法类型', action: '选择GET', type: 'select', value: 'GET',
  191. },
  192. {
  193. id: 'testCreateParam', popUpId: 'testCreateParam', description: '此处填写Http需要填写的参数,POST方法中是指RequestBody', action: '在此方法中无需填写', type: 'display',
  194. },
  195. {
  196. id: 'testCreateConfirm', popUpId: 'testCreateConfirm', description: '', action: '点击按钮创建测试', type: 'click',
  197. },
  198. {
  199. id: 'testExec-tutorial', popUpId: 'testElTable', description: '触发测试后,系统会按照配置发送Http请求并返回结果', action: '点击按钮触发测试', type: 'click',
  200. },
  201. {
  202. id: 'testDetail-tutorial', popUpId: 'testElTable', description: '用户可以查看测试的执行历史等信息', action: '点击按钮查看详情', type: 'click',
  203. },
  204. {
  205. id: 'testExecHistory', popUpId: 'testExecHistory', description: '', action: '查看接口测试的执行历史,点击前面的按钮可以查看测试执行返回结果', type: 'display',
  206. },
  207. ],
  208. bugList: [
  209. {
  210. id: 'bugList', popUpId: 'sidebar', description: 'Developer系统提供了缺陷管理模块用于管理开发过程中发现的各种问题', action: '点击左边栏中的"缺陷列表"', type: 'click',
  211. },
  212. {
  213. id: 'generalTableCreateButton', popUpId: 'projectContainer', description: '', action: '点击按钮创建新的缺陷', type: 'click',
  214. },
  215. {
  216. id: 'bugAddTitle', popUpId: 'bugAddTitle', description: '', action: '填写缺陷的名称', type: 'input',
  217. },
  218. {
  219. id: 'bugAddDescription', popUpId: 'bugAddDescription', description: '此处需要描述缺陷出现的场景,可能出现的原因,方便其余人员进行修复', action: '填写缺陷描述(非必填)', type: 'display',
  220. },
  221. {
  222. id: 'bugAddTime', popUpId: 'bugAddTime', description: '此处填写预计解决缺陷需要花费的事件,以"人月"作为单位', action: '选择需要的时间', type: 'display',
  223. },
  224. {
  225. id: 'bugAddPriority', popUpId: 'bugAddPriority', description: '此处需要选择缺陷需要处理的优先级', action: '选择优先级', type: 'select',
  226. },
  227. {
  228. id: 'bugAddProcessor', popUpId: 'bugAddProcessor', description: '此处可以指定项目中的开发人员负责修复这个缺陷', action: '选择经办人', type: 'select',
  229. },
  230. {
  231. id: 'bugAddConfirm', popUpId: 'bugAddConfirm', description: '', action: '点击按钮创建缺陷', type: 'click',
  232. },
  233. {
  234. id: 'bugTable', popUpId: 'projectContainer', description: '在此处展示了当前项目的缺陷列表,点击其中一列可以查看缺陷的详情', action: '点击任意一列', type: 'click',
  235. },
  236. {
  237. id: 'bugEditSwitch', popUpId: 'bugEditSwitch', description: '在此处展示了某一个缺陷的详情,点击上方的开关按钮可以对缺陷进行编辑', action: '查看缺陷详情,对缺陷进行编辑', type: 'display',
  238. },
  239. ],
  240. codereview: [
  241. {
  242. id: 'codereview', popUpId: 'sidebar', description: '分支评审任务属于代码评审模块的一部分', action: '点击左边栏中的"代码评审"按钮', type: 'click',
  243. },
  244. {
  245. id: 'addBranchReview', popUpId: 'codeReviewButtonRow', description: '', action: '点击新建分支评审任务', type: 'click',
  246. },
  247. {
  248. id: 'selectSourceBranch', popUpId: 'branchSelectDrawer', description: '分支评审基于项目的不同分支进行,在创建分支评审时需要首先选择分支,目标分支与源分支不能相同', action: '选择master分支', type: 'select', value: 'master',
  249. },
  250. {
  251. id: 'selectTargetBranch', popUpId: 'branchSelectDrawer', description: '当分支评审任务结束时,会将源分支上的改动合并至目标分支中', action: '选择dev分支', type: 'select', value: 'dev',
  252. },
  253. {
  254. id: 'confirmSelectBranch', popUpId: 'branchSelectDrawer', description: '', action: '点击继续按钮', type: 'click',
  255. },
  256. {
  257. id: 'branchAddCodeDiff', popUpId: 'branchReviewDrawer', description: '在此处可以预览分支间的代码差异', action: '查看分支代码差异预览', type: 'display',
  258. },
  259. {
  260. id: 'branchReviewTitle', popUpId: 'branchReviewDrawer', description: '', action: '填写评审任务的的标题', type: 'input',
  261. },
  262. {
  263. id: 'branchReviewer', popUpId: 'branchReviewDrawer', description: '分支评审任务只可以选择项目内部的开发人员作为评审人', action: '选择任意的评审人', type: 'select',
  264. },
  265. {
  266. id: 'confirmCreateBranchReview', popUpId: 'branchReviewDrawer', description: '', action: '点击确认创建新的分支评审任务', type: 'click',
  267. },
  268. ],
  269. },
  270. currentSteps: [],
  271. eventListeners: [],
  272. stepFinish: false,
  273. stepIndex: -1,
  274. taskIndex: 1,
  275. };
  276. },
  277. methods: {
  278. beginTask(index) {
  279. this.currentSteps = this.instructions[this.taskList[index].name];
  280. this.taskList[index].status = 1;
  281. this.taskIndex = index;
  282. this.nextStep();
  283. this.showTask = false;
  284. this.showStep = true;
  285. },
  286. nextStep() {
  287. if (this.stepIndex !== -1) {
  288. // 存在前一个步骤,需要先消除之前的闪烁边框以及z-index提前
  289. document.getElementById(this.currentSteps[this.stepIndex].id).classList.remove('border-glow');
  290. document.getElementById(this.currentSteps[this.stepIndex].popUpId).classList.remove('pop-up');
  291. // 去除事件监听器
  292. if (this.eventListeners[this.stepIndex] !== null) {
  293. document.getElementById(this.currentSteps[this.stepIndex].id).removeEventListener(this.eventListeners[this.stepIndex].type, this.eventListeners[this.stepIndex].func);
  294. }
  295. }
  296. if (this.stepIndex === this.currentSteps.length - 1) {
  297. // 所有的步骤都被遍历完,可以直接推出步骤引导,返回任务列表
  298. this.stepIndex = -1;
  299. this.taskList[this.taskIndex].status = 2;
  300. this.showStep = false;
  301. this.showTask = true;
  302. this.eventListeners = [];
  303. this.currentSteps = [];
  304. return;
  305. }
  306. this.stepIndex += 1;
  307. this.stepFinish = false;
  308. // 更改元素的样式,增加闪烁边框以及增加z-index
  309. document.getElementById(this.currentSteps[this.stepIndex].id).classList.add('border-glow');
  310. document.getElementById(this.currentSteps[this.stepIndex].popUpId).classList.add('pop-up');
  311. const { type } = this.currentSteps[this.stepIndex];
  312. let event;
  313. const that = this;
  314. if (type === 'display') {
  315. // 操作类型为仅展示,不需要操作
  316. this.stepFinish = true;
  317. event = null;
  318. this.eventListeners.push(event);
  319. } else if (type === 'click') {
  320. event = function () {
  321. that.stepFinish = true;
  322. document.getElementById(that.currentSteps[that.stepIndex].popUpId).classList.remove('pop-up');
  323. };
  324. document.getElementById(this.currentSteps[this.stepIndex].id).addEventListener('click', event);
  325. this.eventListeners.push({ type: 'click', func: event });
  326. } else if (type === 'select') {
  327. event = function () {
  328. const expectedV = that.currentSteps[that.stepIndex].value;
  329. const actualV = document.getElementById(that.currentSteps[that.stepIndex].id).value;
  330. if (expectedV === null || expectedV === undefined) {
  331. that.stepFinish = true;
  332. } else {
  333. that.stepFinish = expectedV === actualV;
  334. }
  335. };
  336. document.getElementById(this.currentSteps[this.stepIndex].id).addEventListener('focus', event);
  337. this.eventListeners.push({ type: 'focus', func: event });
  338. } else if (type === 'input') {
  339. event = function () {
  340. const expectedV = that.currentSteps[that.stepIndex].value;
  341. const actualV = document.getElementById(that.currentSteps[that.stepIndex].id).value;
  342. if (expectedV === null || expectedV === undefined) {
  343. that.stepFinish = true;
  344. } else {
  345. that.stepFinish = expectedV === actualV;
  346. }
  347. };
  348. document.getElementById(this.currentSteps[this.stepIndex].id).addEventListener('change', event);
  349. this.eventListeners.push({ type: 'change', func: event });
  350. } else if (type === 'row-click') {
  351. event = function () {
  352. that.stepFinish = true;
  353. document.getElementById(that.currentSteps[that.stepIndex].popUpId).classList.remove('pop-up');
  354. };
  355. document.getElementById(this.currentSteps[this.stepIndex].id).addEventListener('row-click', event);
  356. this.eventListeners.push({ type: 'row-click', func: event });
  357. }
  358. },
  359. closeTutorial() {
  360. this.currentSteps = [];
  361. this.showStep = false;
  362. this.showTask = true;
  363. if (this.stepIndex !== -1 && this.eventListeners[this.stepIndex] !== null) {
  364. document.getElementById(this.currentSteps[this.stepIndex].id).removeEventListener(this.eventListeners[this.stepIndex].type, this.eventListeners[this.stepIndex].func);
  365. }
  366. this.eventListeners = [];
  367. this.stepIndex = -1;
  368. this.stepFinish = false;
  369. this.$emit('close');
  370. },
  371. },
  372. emits: ['close'],
  373. };
  374. </script>
  375. <style scoped>
  376. .shade {
  377. position: fixed;
  378. top: 0px;
  379. left: 0px;
  380. background-color: rgba(0,0,0,0);
  381. z-index: 2000;
  382. }
  383. .tutorial {
  384. width: 300px;
  385. height: 100%;
  386. z-index: 5000;
  387. padding: 5px;
  388. background-color: rgba(255,255,255,1);
  389. }
  390. .introduction {
  391. padding: 5px;
  392. margin-top: 5px;
  393. color: #444444;
  394. }
  395. .taskLine {
  396. padding: 8px 5px;
  397. margin-bottom: 10px;
  398. border-bottom: solid 1px #eeeeee;
  399. }
  400. .taskLine:hover {
  401. cursor: pointer;
  402. }
  403. .actionDisplay {
  404. margin-left: 20px;
  405. border-left: 5px solid #909090;
  406. margin-bottom: 8px;
  407. background-color: whitesmoke;
  408. padding: 5px;
  409. font-size: smaller;
  410. }
  411. .actionDisplaySuccess {
  412. margin-left: 20px;
  413. margin-bottom: 8px;
  414. border-left: 5px solid #67C23A;
  415. background-color: #F0F9EB;
  416. padding: 5px;
  417. font-size: smaller;
  418. }
  419. .closeButton {
  420. background-image: url("../assets/icon/close.svg");
  421. background-size: 25px 25px;
  422. background-repeat: no-repeat;
  423. border: none;
  424. margin-left: 70px;
  425. }
  426. </style>
  427. <style>
  428. .border-glow {
  429. animation: glow 800ms ease-out infinite alternate;
  430. }
  431. @keyframes glow {
  432. 0% {
  433. border-color: yellow;
  434. box-shadow: 0 0 1px 3px yellow inset;
  435. }
  436. 100% {
  437. border-color: yellow;
  438. box-shadow: 0 0 1px 5px yellow inset;
  439. }
  440. }
  441. .pop-up {
  442. z-index: 3000;
  443. }
  444. </style>