赞
踩
目录
刚做完第一期的模拟题目,第二期又开始发布了,花了点时间做完了,分享下自己的解题思路。
请你编写一个名为 expectFn
的函数,用于帮助开发人员测试他们的代码。它可以通过参数 val
接受任何值,并返回一个对象,该对象包含下面两个函数:
toBe(val)
:接受另一个值并在两个值相等( ===
)时返回 true
。如果它们不相等,则返回 "Not Equal" 。notToBe(val)
:接受另一个值并在两个值不相等( !==
)时返回 true
。如果它们相等,则返回 "Equal" 。题目要求写的很清楚了,按照其要求做判断条件即可
- var expectFn = function (val) {
- // TODO
- return {
- toBe: function (value) {
- if (val === value) {
- return true
- } else {
- return 'Not Equal'
- }
- },
- notToBe: function (value) {
- if (val !== value) {
- return true
- } else {
- return 'Equal'
- }
- }
- }
- }
请完善 style.css
的 TODO 部分,具体要求如下:
.content span
标签中的文字单行显示,多余溢出显示省略号。-webkit-box
语法使得下面的文字即 .content p
标签里的内容显示三行,多余溢出显示省略号。这里主要是如果写过案例的话,应该就知道怎么写,需要注意的是span元素是单行元素,要想达到效果,需要将其变为块级元素。
- span {
- font-size: 20px;
- color: #837362;
- /* TODO:补充下面的代码 */
- /* 单行显示,多余溢出省略号 */
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- display: block;
- /* 使得溢出部分显示省略号 */
- }
-
- p {
- color: #837362;
- display: -webkit-box;
- -webkit-box-orient: vertical;
- -webkit-line-clamp: 3;
- /* 显示的行数 */
- overflow: hidden;
- }
axios
请求 ./data.json
(必须使用该路径请求,否则可能会请求不到数据)的数据。
name
渲染到 id 为 movie-name
的节点中。price
渲染到 id 为 movie-price
的节点中。seats
渲染到 id 为 seat-area
的节点中,二维数组中每一个子数组代表一行,0 代表没有被他人占位,1 代表已经被订购。selected
),并更新已选择的座位数和总价。- /* TODO:
- 1. 完成数据请求,生成电影名,价格以及座位情况
- 2. 绑定点击事件,实现订票功能
- */
-
- let data = {}
- axios
- .get('../data.json')
- .then((res) => {
- console.log(res)
- data = res.data
- movieNameNode.innerHTML = data.name
- moviePriceNode.innerHTML = data.price
- //创建节点渲染数据
- data.seats.forEach((item) => {
- let row = document.createElement('div')
- row.className = 'row'
- item.forEach((item) => {
- let seat = document.createElement('div')
- seat.className = 'seat'
- row.appendChild(seat)
- if (item) {
- seat.classList.add('occupied')
- }
- })
- seatAreaNode.appendChild(row)
- })
- })
- .catch((err) => {
- console.log(err)
- })
-
- // 获取座位区域节点
- const seatAreaNode = document.getElementById('seat-area')
- // 获取电影名节点
- const movieNameNode = document.getElementById('movie-name')
- // 获取电影票价节点
- const moviePriceNode = document.getElementById('movie-price')
- // 获取已订电影票数量节点
- const count = document.getElementById('count')
- // 获取已订电影票总价节点
- const total = document.getElementById('total')
-
- // 获取所有座位节点
- const seatNodes = document.querySelectorAll('.seat')
- // 初始化已选择座位数和总价
- let selectedSeatsCount = 0
- let totalPrice = 0
-
- // 监听座位点击事件
- seatAreaNode.addEventListener('click', (event) => {
- const clickedSeat = event.target
-
- // 检查是否点击的是座位
- if (clickedSeat.classList.contains('seat') && !clickedSeat.classList.contains('occupied')) {
- // 切换座位的选中状态
- clickedSeat.classList.toggle('selected')
-
- // 更新已选择座位数和总价
- if (clickedSeat.classList.contains('selected')) {
- selectedSeatsCount++
- totalPrice += data.price
- } else {
- selectedSeatsCount--
- totalPrice -= data.price
- }
-
- // 更新显示
- updateDisplay()
- }
- })
-
- // 更新显示函数
- function updateDisplay() {
- count.textContent = selectedSeatsCount
- total.textContent = totalPrice
- }
找到 js/index.js
中的 GetResult
函数,完成此函数,实现以下目标:
点击开始后,可以通过 GetResult
的三个参数 r1
、r2
、r3
计算出滚动后每一列图片的停留位置。当最后停留的图片都相同时,意味着玩家中了大奖!文字框(class = textPanel
)显示“恭喜你,中奖了”,否则显示:“很遗憾,未中奖”。
参数介绍:r1
、r2
、r3
表示的是三列元素下的 li
的最后停留位置,分别对应第一列(id=sevenFirst
)、第二列(id=sevenSecond
)、第三列(id=sevenThird
)。以第一列为例,最终显示的元素是 sevenFirst
下的第 r
个 li
元素。请使用显示的 li
元素的 data-point
属性判断三张图片是否相同。当 data-point
属性对应的值相同时,说明这三张图片相同。
这一题很明确的考察点就是获取元素身上的属性,需要用到getAttribute()方法,通过获取到的属性对比是否一样,如果三个相同则中奖。
- if (sevenFirst.children[r1 - 1].getAttribute('data-point') == sevenSecond.children[r2 - 1].getAttribute('data-point')
- && sevenFirst.children[r1 - 1].getAttribute('data-point') == sevenThird.children[r3 - 1].getAttribute('data-point')) {
- textPanel.innerHTML = '恭喜你,中奖了'
- } else {
- textPanel.innerHTML = '很遗憾,未中奖'
- }
完善 index.js
中的 translate
函数,完善其中的 TODO 部分:
translate
函数接收一个字符串参数 alienMessage
,其中包含一系列外星人的密文。函数根据特定的翻译规则将密文翻译成人类语言,并返回翻译后的结果字符串。外星人密文翻译规则存放在 codonTable
变量中。
这个题目就是js的切割 遍历
- // 密语规则
- const codonTable = {
- IIX: '人类',
- VII: '哈喽',
- III: '你好',
- IXI: '赞',
- XVI: '嗨',
- CUV: '打击',
- XII: '夜晚',
- IVI: '我',
- XIC: '想',
- XIV: '交个朋友',
- VIX: '月亮',
- XCI: '代码',
- XIX: '祈福',
- XVI: '和',
- XXI: 'stop'
- }
-
- /**
- * @param {string} alienMessage 外星人的密文
- * @return {string} 翻译结果
- */
- const translate = (alienMessage) => {
- // TODO:待补充代码
- // 检查密文是否为空
- if (!alienMessage) {
- return ''
- }
-
- // 切分密文
- const codons = []
- for (let i = 0; i < alienMessage.length; i += 3) {
- codons.push(alienMessage.slice(i, i + 3))
- }
- // 初始化翻译结果
- let translation = ''
-
- // 遍历密文
- for (const codon of codons) {
- // 检查是否为停止符号
- if (codon === 'XXI') {
- break
- }
-
- // 查找翻译表
- const translationResult = codonTable[codon]
-
- // 如果找到翻译结果,则添加到最终结果中
- if (translationResult) {
- translation += translationResult
- } else {
- // 未找到对应翻译结果,返回无效密语
- return '无效密语'
- }
- }
- return translation
- }
- // 请注意:以下代码用于检测,请勿删除。
- try {
- module.exports = translate
- } catch (e) {}
power
字段的值对所有学校进行排序,取出排在前 10 名的学校,从左到右降序排列。./mock/map.json
),map.json
中存放的数据为省市对应的学校数据根据要求获取数据,然后替换options中的配置即可
- const { createApp, ref, onMounted } = Vue
- const app = createApp({
- setup() {
- const chartsData = ref([])
- onMounted(() => {
- // TODO:待补充代码 请求数据,并正确渲染柱形图和地图
- axios
- .get('../mock/map.json')
- .then((res) => {
- chartsData.value = res.data
- showChartBar()
- showChinaMap()
- })
- .catch((err) => {
- console.log(err)
- })
- })
- // 展示柱状图
- const showChartBar = () => {
- const myChart = echarts.init(document.getElementById('chart'))
-
- let data = chartsData.value.map((item, index) => {
- return item.school_power
- })
- console.log(data)
- let result = data.flat(1).sort((a, z) => {
- return z.power - a.power
- })
- let arr = result.slice(0, 10)
- let school = arr.map((item) => {
- return item.name
- })
- let power = arr.map((item) => {
- return item.power
- })
- console.log(school)
- console.log(power)
- // 指定配置和数据
- const option = {
- xAxis: {
- type: 'category',
- axisLabel: { interval: 0, rotate: 40 },
- // TODO:待修改 柱状图 x 轴数据 -> 前 10 学校名称
- data: school
- },
- grid: {
- left: '3%',
- right: '4%',
- bottom: '3%',
- containLabel: true
- },
- yAxis: {
- type: 'value',
- boundaryGap: [0, 0.01]
- },
- series: [
- {
- // TODO:待修改 柱状图 y 轴数据->学校战力值
- data: power,
- type: 'bar',
- showBackground: true,
- backgroundStyle: {
- color: 'rgba(180, 180, 180, 0.2)'
- },
- itemStyle: {
- color: '#8c7ae6'
- }
- }
- ]
- }
-
- // 把配置给实例对象
- myChart.setOption(option)
- // 根据浏览器大小切换图表尺寸
- window.addEventListener('resize', function () {
- myChart.resize()
- })
- }
-
- // 展示地图
- const showChinaMap = () => {
- const chinaMap = echarts.init(document.getElementById('chinaMap'))
-
- // 进行相关配置
- const mapOption = {
- tooltip: [
- {
- backgroundColor: '#fff',
- subtext: 'aaa',
- borderColor: '#ccc',
- padding: 15,
- formatter: (params) => {
- return params.name + '热度值:' + params.value + '<br>' + params.data.school_count + '所学校已加入备赛'
- },
- textStyle: {
- fontSize: 18,
- fontWeight: 'bold',
- color: '#464646'
- },
- subtextStyle: {
- fontSize: 12,
- color: '#6E7079'
- }
- }
- ],
- geo: {
- // 这个是重点配置区
- map: 'china', // 表示中国地图
- label: {
- normal: {
- show: false // 是否显示对应地名
- }
- },
- itemStyle: {
- normal: {
- borderColor: 'rgb(38,63,168)',
- borderWidth: '0.4',
- areaColor: '#fff'
- },
- emphasis: {
- //鼠标移入的效果
- areaColor: 'rgb(255,158,0)',
- shadowOffsetX: 0,
- shadowOffsetY: 0,
- shadowBlur: 20,
- borderWidth: 0,
- shadowColor: 'rgba(0, 0, 0, 0.5)'
- }
- }
- },
- visualMap: {
- show: true,
- left: 'center',
- top: 'bottom',
- type: 'piecewise',
- align: 'bottom',
- orient: 'horizontal',
- pieces: [
- {
- gte: 80000,
- color: 'rgb(140,122,230)'
- },
- {
- min: 50000,
- max: 79999,
- color: 'rgba(140,122,230,.8)'
- },
- {
- min: 30000,
- max: 49999,
- color: 'rgba(140,122,230,.6)'
- },
- {
- min: 10000,
- max: 29999,
- color: 'rgba(140,122,230,.4)'
- },
- {
- min: 1,
- max: 9999,
- color: 'rgba(140,122,230,.2)'
- }
- ],
- textStyle: {
- color: '#000',
- fontSize: '11px'
- }
- },
- series: [
- {
- type: 'map',
- geoIndex: 0,
- // TODO:待修改 地图对应数据
- data: chartsData.value.map((item) => {
- return {
- name: item.name,
- school_count: item.school_count,
- value: item.value
- }
- })
- }
- ]
- }
-
- // 把配置给实例对象
- chinaMap.setOption(mapOption)
- }
-
- return {
- chartsData,
- showChartBar,
- showChinaMap
- }
- }
- })
-
- app.mount('#app')
题目要求和分析就不写了 ,代码中给了注释
- // 声明一个数组,包含了所有的拼图块数据
- var puzzlePieces = [
- { src: './images/img1.png', id: 1 },
- { src: './images/img2.png', id: 2 },
- { src: './images/img3.png', id: 3 },
- { src: './images/img4.png', id: 4 },
- { src: './images/img5.png', id: 5 },
- { src: './images/img6.png', id: 6 },
- { src: './images/img7.png', id: 7 },
- { src: './images/img8.png', id: 8 },
- { src: './images/img9.png', id: 9 }
- ]
-
- // 定义一个打乱数组的函数
- function shuffleArray(array) {
- for (let i = array.length - 1; i > 0; i--) {
- const j = Math.floor(Math.random() * (i + 1))
- ;[array[i], array[j]] = [array[j], array[i]]
- }
- return array
- }
-
- // 使用定义的函数打乱拼图块数组
- puzzlePieces = shuffleArray(puzzlePieces)
-
- // 获取拼图容器元素
- var container = document.getElementById('puzzle-container')
-
- // 遍历拼图块数据数组
- puzzlePieces.forEach(function (pieceData) {
- // 创建一个新的拼图块元素
- var piece = document.createElement('div')
- piece.classList.add('puzzle-piece')
- piece.setAttribute('draggable', 'true')
-
- // 创建一个新的图片元素
- var image = document.createElement('img')
- image.src = pieceData.src
- image.dataset.id = pieceData.id
-
- // 将图片元素添加到拼图块元素中
- piece.appendChild(image)
-
- // 将拼图块元素添加到父容器元素中
- container.appendChild(piece)
- })
-
- // 获取所有的拼图块元素,并转换为数组
- const puzzleArray = Array.from(document.querySelectorAll('.puzzle-piece'))
-
- // 获取成功消息元素
- const successMessage = document.getElementById('success-message')
-
- // 为每个拼图块元素添加拖拽事件监听器
- puzzleArray.forEach((piece) => {
- piece.addEventListener('dragstart', dragStart)
- piece.addEventListener('dragover', dragOver)
- piece.addEventListener('drop', drop)
- })
-
- // 声明一个变量用来保存正在拖动的拼图块
- let draggedPiece = null
-
- // 定义开始拖动事件的处理函数
- function dragStart(event) {
- draggedPiece = this
- event.dataTransfer.setData('text/plain', null)
- }
-
- // 定义在拖动过程中的处理函数,阻止默认行为
- function dragOver(event) {
- event.preventDefault()
- }
-
- // 定义拖放事件的处理函数
- function drop(event) {
- // 检查是否拖动的拼图块不是当前目标拼图块
- // draggedPiece 被拖动的拼图块元素。this 目标位置的拼图块元素。
- let num = 0
- if (draggedPiece !== this) {
- // TODO:待补充代码
- // 交换图片的 src 属性和 data-id 属性
- let tempSrc = draggedPiece.querySelector('img').src
- let tempDataId = draggedPiece.querySelector('img').dataset.id
-
- draggedPiece.querySelector('img').src = this.querySelector('img').src
- draggedPiece.querySelector('img').dataset.id = this.querySelector('img').dataset.id
-
- this.querySelector('img').src = tempSrc
- this.querySelector('img').dataset.id = tempDataId
-
- // 检查是否拼图成功
- puzzleArray.forEach((item, index) => {
- if (parseInt(item.children[0].getAttribute('data-id')) === index + 1) {
- num++
- }
- })
- if (num === 9) {
- successMessage.classList.remove('hide')
- successMessage.classList.add('show')
- } else {
- successMessage.classList.remove('show')
- successMessage.classList.add('hide')
- }
- // 重置正在拖动的拼图块
- draggedPiece = null
- }
- }
HeroList:
- // TODO:补全代码,实现目标效果
- const HeroList = {
- template: `
- <div class="hero-list">
- <h2>可选英雄</h2>
- <ul>
- <li class="hero-item" v-for="(item,index) in store.heroes" :key="item.id">
- <span>{{item.name}}</span>
- <span>{{item.ability}}</span>
- <span>{{item.strength}}</span>
- <button @click=store.add(item.id) :disabled="item.btn">{{ item.btn ? '已添加' : '添加至队伍' }}</button>
- </li>
- </ul>
- </div>
- `,
- setup() {
- //第一步获取数据
- const store = useHeroStore()
- axios
- .get('./js/heroes.json')
- .then((res) => {
- store.heroes = res.data
- })
- .catch((err) => {
- console.log(err)
- })
- return {
- store
- }
- }
- }
- // TODOEnd
TeamList:
- // TODO:补全代码,实现目标效果
- const TeamList = {
- template: `
- <div class="team-list">
- <h2>我的队伍</h2>
- <ul>
- <li class="team-item" v-for="(item,index) in store.team" :key="item.id">
- <span>{{item.name}}</span>
- <span>{{item.strength}}</span>
- <button @click=store.removeHero(item.id)>移除</button>
- </li>
- </ul>
- <button class="sort-button" @click=store.sort>按实力排序</button>
- <p class="total-strength">当前队伍战斗力:{{store.totalStrength}} </p>
- </div>
- `,
- setup() {
- const store = useHeroStore()
- return {
- store
- }
- }
- }
- // TODOEnd
store.js:
- const { defineStore } = Pinia
- const { ref } = Vue
-
- const useHeroStore = defineStore('hero', {
- state: () => ({
- heroes: [], //英雄列表
- team: [] // 队伍列表
- }),
- // TODO:补全代码,实现目标效果
- getters: {
- //计算出战力总和strength
- totalStrength() {
- return this.team.reduce((total, hero) => {
- return total + hero.strength
- }, 0)
- }
- },
- actions: {
- add(id) {
- this.heroes[id - 1].btn = true
- this.team.push(this.heroes[id - 1])
- },
- removeHero(id) {
- this.heroes[id - 1].btn = false
- //移出team中的元素
- this.team = this.team.filter((hero) => hero.id !== id)
- },
- sort() {
- //按照实力排序strength
- this.team.sort((a, b) => {
- return b.strength - a.strength
- })
- }
- }
- // TODOEnd
- })
这个题目我不知道为啥,明明在线测试基本上满足题目要求了,但是就是不能完全通过
node.js:
- /**
- * 请完成下面的 TODO 部分,其他代码请勿改动
- */
- const fs = require('fs')
- const http = require('http')
- const path = require('path')
- const dataUrl = path.resolve(__dirname, '../data.json')
- const loggerUrl = path.resolve(__dirname, '../logger.json')
- // 获取唯一的id
- function getLoggerId() {
- return Buffer.from(Date.now().toString()).toString('base64') + Math.random().toString(36).substring(2)
- }
-
- /**
- * 该方法统一了服务器返回的消息格式,并返回给客户端
- * @param {*} res 响应 response
- * @param {*} code 状态码,默认为 0 代表没有错误,如果有错误固定为 404
- * @param {*} msg 错误消息,固定为空字符串即可 ''
- * @param {*} data 响应体,为 js 对象,若 data 为 utf-8 编码时需要使用 eval(data) 处理
- */
- function send(res, code, msg, data) {
- const responseObj = {
- code,
- msg,
- data
- }
- const da = JSON.stringify(responseObj)
- res.setHeader('Content-Type', 'application/json;charset=utf-8')
- res.write(da)
- res.end()
- }
-
- function handleStatic(res, pathName, part) {
- const content = fs.readFileSync(path.resolve(__dirname, pathName))
- let contentType = 'text/html'
- switch (part) {
- case 'css':
- contentType = 'text/css'
- break
- case 'js':
- contentType = 'text/js'
- break
- }
- res.writeHead(200, 'Content-Type', contentType)
- res.write(content)
- res.end()
- }
-
- const server = http.createServer((req, res) => {
- res.setHeader('Access-Control-Allow-Origin', '*')
- if (req.url === '/') {
- handleStatic(res, '../index.html', '')
- } else if (req.url === '/css/index.css') {
- handleStatic(res, `..${req.url}`, 'css')
- } else if (req.url === '/js/index.js') {
- handleStatic(res, `..${req.url}`, 'js')
- } else if (req.url === '/js/axios.min.js') {
- handleStatic(res, `..${req.url}`, 'js')
- } else if (req.url === '/js/vue3.global.min.js') {
- handleStatic(res, `..${req.url}`, 'js')
- }
-
- if (req.method === 'GET' && req.url === '/users') {
- // TODO 处理获取文件内容的操作
- //读取data.json中的数据
- let fileContent = fs.readFileSync(dataUrl, 'utf-8')
- let data = JSON.parse(fileContent)
- if (fileContent) {
- //将读取到的数据转化为json格式
- //将json格式的数据响应给客户端
- send(res, 0, '', data)
- }
- } else if (req.method === 'PUT' && req.url === '/editUser') {
- let fileContent = fs.readFileSync(dataUrl, 'utf-8')
- let data = JSON.parse(fileContent)
- let body = ''
- req.on('readable', () => {
- let chunk = ''
- if (null !== (chunk = req.read())) {
- body += chunk
- }
- })
- req.on('end', () => {
- if (body) {
- // TODO 处理更改文件数据并将最新的文件数据响应给客户端
- //处理put请求
- let bodyData = JSON.parse(body)
- //修改data.json中的数据
- data.forEach((item) => {
- if (item.id == bodyData.id) {
- item.power = bodyData.power
- }
- })
- //存储文件数据到data.json中
- fs.writeFileSync(dataUrl, JSON.stringify(data))
- send(res, 0, '', data)
- }
- })
- } else if (req.method === 'POST' && req.url === '/logger') {
- let body = ''
- req.on('readable', () => {
- let chunk = ''
- if (null !== (chunk = req.read())) {
- body += chunk
- }
- })
- req.on('end', () => {
- let fileContentLog = fs.readFileSync(loggerUrl, 'utf-8')
- //判断是否有日志
- let dataLog = []
- if (fileContentLog) {
- dataLog = JSON.parse(fileContentLog)
- }
- let fileContentUser = fs.readFileSync(dataUrl, 'utf-8')
- let dataUser = JSON.parse(fileContentUser)
- if (body) {
- // TODO 处理新增日志
- let bodyData = JSON.parse(body)
-
- let dataJson = {
- id: getLoggerId(),
- msg: bodyData.data,
- // 时间格式为:2023/6/6 上午8:10:35
- time: `${getTime()}`
- }
- //存储日志
- dataLog.unshift(dataJson)
- // 并在该对象转化成 JSON 格式的末尾添加换行符(如不添加换行符会导致检测不通过)
- fs.writeFileSync(loggerUrl, JSON.stringify(dataLog, null, 2) + '\n')
- send(res, 0, '', dataJson)
- }
- })
- }
- })
-
- function getTime() {
- // 获取当前时间
- const currentDate = new Date()
- // 获取年、月、日、时、分、秒
- const year = currentDate.getFullYear()
- const month = currentDate.getMonth() + 1 // 月份是从 0 开始的,所以要加 1
- const day = currentDate.getDate()
- const hours = currentDate.getHours()
- //获取是上午还是下午
- const amPm = hours >= 12 ? '下午' : '上午'
- const minutes = currentDate.getMinutes()
- const seconds = currentDate.getSeconds()
- // 格式化时间
- const formattedTime = `${year}/${month}/${day} ${amPm}${hours}:${minutes}:${seconds}`
- return formattedTime
- }
-
- server.listen(8080, () => {
- console.log('Server running on port 8080')
- })
index.js:
- /**
- * 请完成下面的 TODO 部分,其他代码请勿改动
- */
-
- // 对响应进行统一处理,如果不调用该函数,可能导致判题出错
- // 参数为服务器的响应对象
- function parseRes(res) {
- return (res.json && res.json()) || res.data
- }
-
- const App = {
- setup() {
- const { onMounted } = Vue
- const data = Vue.reactive({
- userList: [], //用户数组
- loggerList: [] //日志数组
- })
- const getPowerText = (power) => {
- return power ? '可以登录' : '禁止登录'
- }
- const handleChange = async (e) => {
- if (e.target.tagName !== 'INPUT') {
- return
- }
- // TODO 处理发送请求修改当前用户的权限并更新一条日志记录
- //处理put请求
- let res = await axios.put(`/editUser`, {
- id: e.target.dataset.id,
- power: e.target.checked
- })
- if (res.status == 200) {
- data.userList = parseRes(res.data)
- } else {
- console.log('修改失败')
- }
- //调用post请求,添加一条修改日志
- //用id找出用户名
- let userName = data.userList.find((item) => item.id == e.target.dataset.id).name
- let postRes = await axios.post('/logger', {
- data: `超级管理员将用户${userName}设置为${getPowerText(e.target.checked)}权限`
- })
- if (postRes.status == 200) {
- //将数据放在数组首
- let a = parseRes(postRes.data)
- data.loggerList.unshift(a)
- } else {
- console.log('添加日志失败')
- }
- }
-
- // TODO 在页面挂载之前请求用户数据并修改对应的响应数据
- //利用axios获取数据
- const getUserData = async () => {
- let res = await axios.get('/users')
- if (res.status == 200) {
- data.userList = res.data.data
- } else {
- getUserData()
- }
- }
- onMounted(() => {
- getUserData()
- })
- return {
- data,
- handleChange,
- getPowerText,
- getUserData
- }
- }
- }
- const app = Vue.createApp(App)
- app.mount(document.querySelector('#app'))
- <!DOCTYPE html>
- <html>
-
- <head>
- <meta charset="utf-8" />
- <title>账户验证</title>
- <link rel="stylesheet" type="text/css" href="./css/index.css" />
- <link rel="stylesheet" href="./css/element-plus@2.3.7/index.css">
- <script src="./js/vue3.global.js"></script>
- <script src="./css/element-plus@2.3.7/index.full.js"></script>
- <script type="importmap">
- {
- "imports": {
- "vue-demi": "./js/index.mjs",
- "vue": "./js/vue.esm-browser.prod.js",
- "pinia": "./js/pinia.esm-browser.js"
- }
- }
- </script>
- <script src="./js/pinia.esm-browser.js" type="module"></script>
- </head>
-
- <body>
- <!-- app根组件开始 -->
- <div id="app">
- <div class="header">
- <img class="back-btn" src="images/arrow.png" />
- <span id="main_title">使用手机号登录</span>
- <span class="blank"></span>
- </div>
- <component :is="showName"></component>
- </div>
- <!-- app根组件结束 -->
-
- <!-- phone组件开始 -->
- <template id="phone">
- <div>
- <ul class="phone">
- <span>输入手机号码</span>
- <li>
- <input v-model="phoneVal" type="text" autofocus id="numberInput" />
- </li>
- <li>
- <input v-model="isSure" type="checkbox" name="" id="checkbox" />
- <span>已阅读并同意
- <a href="javascript:;">服务协议</a>
- 和
- <a href="javascript:;">隐私保护指引</a>
- </span>
- </li>
- <button id="btn" @click="nextStep">下一步</button>
- </ul>
- </div>
- </template>
- <!-- phone组件结束 -->
-
- <!-- check组件开始 -->
- <template id="check">
- <ul class="number">
- <span>输入短信验证码</span>
- <li class="hassend">已向
- <i>{{ handlePhoneVal }}</i>
- 发送验证码
- </li>
- <li class="code-container">
- <input v-for="(item, index) in verificationCodeInput" :key="index" v-model="item" @input="handleInput(index)"
- @keydown="handleKeyDown(index)" class="code" type="number" min="0" max="9" ref="codeInput{{index}}"
- required />
- </li>
- <a href="javascript:;" id="resend" @click="resendCode">重新发送</a>
- </ul>
- </template>
- <!-- check组件结束 -->
-
- <!-- success组件开始 -->
- <template id="success">
- <div class="success">
- <ul>
- <div>验证成功!</div>
- <div>5s后将自动跳转</div>
- </ul>
- </div>
- </template>
- <!-- success组件结束 -->
- </body>
-
- <script type="module">
- import { createPinia } from 'pinia';
- import { createApp, ref, reactive, provide, inject, onBeforeMount } from 'vue';
- const { ElNotification } = ElementPlus;
-
- const app = createApp({
- setup() {
- const data = reactive({
- showName: 'phone',
- });
-
- const code = ref([]);
- const phoneVal = ref('');
- const createCode = function () {
- let res = '';
- function* _create() {
- let count = 0;
- while (++count <= 6) {
- yield Math.floor(Math.random() * 10);
- }
- }
- for (const iterator of _create()) {
- res += iterator;
- }
- return res;
- };
-
- const handlePhone = (num) => {
- let res = '';
- for (let idx in num) {
- if (idx > 2 && idx < num.length - 2) {
- res += '*';
- } else {
- res += num[idx];
- }
- }
- return res;
- };
-
- provide('code', code);
- provide('phoneVal', phoneVal);
- provide('createCode', createCode);
- provide('data', data);
- provide('handlePhone', handlePhone);
-
- return {
- ...data,
- };
- },
- });
-
- app.use(ElementPlus);
- app.use(createPinia());
-
- app.component('phone', {
- template: '#phone',
- setup() {
- const isSure = ref('');
- const phoneVal = inject('phoneVal');
- const code = inject('code');
- const createCode = inject('createCode');
- const data = inject('data');
-
- function verifyPhone(num) {
- if (num.length !== 11) return false;
- return num[0] === '1' && num[1] === '8';
- }
-
- return {
- isSure,
- phoneVal,
- nextStep() {
- if (!isSure.value)
- return ElNotification({
- title: '发送失败',
- message: '请先阅读并同意下方协议',
- type: 'error',
- });
- if (!verifyPhone(phoneVal.value))
- return ElNotification({
- title: '发送失败',
- message: '无效的手机号码',
- type: 'error',
- });
- code.value = createCode();
- ElNotification({
- title: '发送成功',
- message: '您在验证码为' + code.value,
- type: 'success',
- });
- data.showName = 'check';
- },
- };
- },
- });
-
- app.component('check', {
- template: '#check',
- setup() {
- const phoneVal = inject('phoneVal');
- const handlePhoneVal = inject('handlePhone')(phoneVal.value);
- const data = inject('data');
- const code = inject('code');
- const createCode = inject('createCode');
- const verificationCodeInput = Array(6).fill('');
-
- onBeforeMount(() => {
- setTimeout(() => {
- const oCodeIptList = [...document.getElementsByClassName('code')];
-
- oCodeIptList[0].focus();
-
- oCodeIptList.map((item) => {
- item.oninput = function () {
- if (item.value) {
- item?.nextElementSibling && item?.nextElementSibling.focus();
- } else {
- item?.previousElementSibling && item?.previousElementSibling.focus();
- }
- trackVal();
- };
- });
-
- function trackVal() {
- const val = verificationCodeInput.join('');
- if (val.length === 6) {
- if (val === code.value) {
- ElNotification({
- title: '验证成功',
- message: '欢迎回来',
- type: 'success',
- });
- data.showName = 'success';
- } else {
- ElNotification({
- title: '验证失败',
- message: '您输入的验证码有误',
- type: 'error',
- });
- verificationCodeInput.fill('');
- oCodeIptList[0].focus();
- }
- }
- }
- });
- });
-
- return {
- handlePhoneVal,
- verificationCodeInput,
- handleInput(index) {
- if (index < 5 && verificationCodeInput[index].length === 1) {
- this.$refs[`codeInput${index + 1}`]?.focus();
- } else if (index > 0 && verificationCodeInput[index].length === 0) {
- this.$refs[`codeInput${index - 1}`]?.focus();
- }
- trackVal();
- },
- handleKeyDown(index) {
- if (event.key === 'Backspace' && index > 0) {
- this.$refs[`codeInput${index - 1}`]?.focus();
- }
- },
- trackVal() {
- const val = verificationCodeInput.join('');
- if (val.length === 6) {
- if (val === code.value) {
- ElNotification({
- title: '验证成功',
- message: '欢迎回来',
- type: 'success',
- });
- data.showName = 'success';
- } else {
- ElNotification({
- title: '验证失败',
- message: '您输入的验证码有误',
- type: 'error',
- });
- verificationCodeInput.fill('');
- this.$refs['codeInput0']?.focus();
- }
- }
- },
- resendCode() {
- code.value = createCode();
- ElNotification({
- title: '发送成功',
- message: '您的验证码为' + code.value,
- type: 'success',
- });
- },
- };
- },
- });
-
- app.component('success', {
- template: '#success',
- });
-
- app.mount('#app');
- </script>
-
- </html>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。